mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-21 08:02:38 +00:00
d46de0179ce9275070bc72e440b68df65ffbf8bf
9052
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d46de0179c |
fix(chat): word every tool row from the tool that ran
A tool row said one of four things depending on how its call ended, and two of those wordings were the error itself. The row's text is the one thing every reader of a conversation has — the transcript, the chat SDK, anything reading the API — so it should say the same kind of thing every time, and the reason a call failed belongs where every other call's result already lives. All four now word the row from the tool, and a failure puts what it failed with in the row's result. Only where the row is the sole copy: a tool that ran has a job holding both its arguments and its error, and that job is still what the card reads them from. The card shows a failed tool's result rather than discarding it, falling back to the row's text for the rows already written the old way, which keep rendering as they always did. A tool whose job ran and failed streamed success where it stored failure, so the card read as a successful call for the length of the turn and corrected itself on the next reload. The stream now carries what the row is worded from. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
0332ffdb45 |
style(chat): run prettier over the agent chat input tests
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
769e7eebbe |
fix(chat): list a flow's chats under the path its runs record
The editor's chat asked for conversations under the path the flow was opened at, while a preview run recorded them under the path being edited. On a flow that has never been deployed those differ from the first keystroke, so every test chat was written somewhere the sidebar never looked and vanished as soon as the list refreshed. `path` is now the path a run records, and what makes the panel a different panel moves to `identity`. They are not the same question: a chat holds conversations, a running turn and the rows it is writing, so it is replaced rather than re-pointed — but replacing it on every keystroke in the path field would throw away the turn being typed alongside. `chatFlowKey` is the flow half of that identity and `chatIdentity` the whole of it, so the panel key and anything filed under the flow cannot drift apart. A conversation keeps the path it was created under, so renaming a flow that already has chats leaves those behind under the old path. That is the trade: the sidebar follows what runs record, and what ran before a rename recorded something else. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
404419588c |
fix(chat): let a turn own every hold it takes on a chat
Three of the last five review rounds were the same defect with a different trigger: some path decided a chat was free, or stuck, without the run having said so. `Turn` gave that question an owner, but the holds taken before a turn exists were left outside it, and the two that were are what these fix. The read that opens a conversation now starts a turn before it awaits. That read is how the chat finds out whether a run owns the conversation, so it holds the chat while it is out — and Stop, the panel going away, and a later send all have to be able to reach it. Each ends the turn, and a read whose turn is over writes nowhere: it can no longer drop the rows a live turn is writing, nor resume on top of the turn that replaced it. `#resumeRunningTurn` carries that turn on rather than starting a second, which would end the read that produced the rows it reasons over. A read that fails leaves the chat held, since whether a run owns the agent memory is exactly what could not be read. `#holdUnreadableChat` is the one place that happens, and it holds only a turn that still holds the chat — a read outruns a Stop and fails after it, and taking the hold back then would shut a composer the reader was just handed. The run request is not tied to the turn's handle, so the whole of it is a window in which Stop can land, on a turn with no job to cancel yet. The run it returns is then nobody's: it is cancelled, and the send reports that nothing ran. Which turn is running is asked of the server rather than read back to through the transcript. The kind is checked again here, because the caller takes that row's job as the turn's: every other kind names the agent step's own job, and a turn named with that has Stop cancel the step while the rest of the flow runs on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
dda7ab2f30 |
refactor(chat): give a flow chat turn a module of its own
A turn was not a thing. What one is made of lived in three places — a reactive status record, a non-reactive runtime map, and locals inside the function following the job — so the question every piece of a turn's work has to answer, "am I still the turn this chat is on?", had no owner. Each await site answered it again from whatever abort flag it had in scope, and each new await needed another answer; the counter this replaces was the eighth such answer in as many review rounds. `Turn` holds the run, the handle that stops it, the cursor its stream resumes from, the rows it is writing and the timers it armed, and the chat keys one per conversation. Work carries its turn and passes `isCurrent` before writing, so a frame buffered before a Stop, a poll dispatched a tick ago, or a settle that outlived its own turn all land nowhere instead of in whatever replaced it. Ending a turn is one call rather than an abort, two timers and a pair of reveals that every caller had to remember, and the sites that release one say which turn they mean. The chat itself is keyed on its flow and workspace, so changing flow builds a new panel rather than re-pointing the old one. That is what makes the guards removable: nothing survives a flow change to need them. Fixes found while doing this, each of which the old shape allowed: a two-minute polling deadline that outlived its turn and stopped the next one's reading; a run launched into a stopped turn that nothing could name; a conversation-list refresh on every poll tick of a new chat's first turn; a failed page walk that freed a chat whose run it never got to ask about; and a Stop during a launch that tore down the turn that came after it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
d3344eb3cd |
fix(chat): read a conversation forward from the start, and clear the polling deadline
A poll with no row to resume from sent no cursor at all, and the messages endpoint answers that with the newest page rather than the oldest, so the rows before it were never read and the sweep dropped the temp rows covering them. Sequences start at 1, so reading from 0 puts every request on the forward branch. A read that stops at the request cap is now kept: each batch is a run of rows from the cursor, so the next tick carries on from where it stopped. The last poll of a turn has no tick after it, and there its prefix is dropped instead, since it would sit beside the temp rows showing the turn's start twice. `startPolling` armed a two-minute timeout it never held onto, and `stopPolling` cleared only the interval. A turn ending inside two minutes left the timeout armed to fire into the next turn on the same conversation and stop its polling part-way, which a non-streaming turn feels as intermediate rows drying up. The handle now lives on the turn's runtime and is cleared with the interval. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
b76485b0a1 |
fix(chat): count requests, not loop indices, in the partial-read warning
The counter was the loop variable, which leaves the cap exit one past the last request and the stall exit on it — so the same expression printed 21 pages for a cap of 20, in the one message whose job is to say which exit stopped it. It counts requests that completed. The constants shared a doc comment that described the cap while sitting on the page size, and credited it with catching a cursor that stops advancing, which is a separate check. Each says what it is. The partial-read rationale is four lines rather than ten, and points at `loadMessages` for why a reload is the recovery. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
0f2e7a3865 |
docs(chat): say what a partial read actually costs
The comment offered the next turn's poll as a recovery route. It is not one: the cursor comes from the last persisted row, and applying none of them is exactly what leaves it where it was, so the next poll reads the same window against a conversation that has only grown. A reload is what recovers, and the comment says so — it changes how the trade-off reads. The warning blamed the page cap for both exits, so a cursor that stalled on the second request reported twenty pages. It names which one stopped it and where it got to. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
3e90c8f5d9 |
fix(chat): a partial read of a conversation changes nothing
Keeping the temp rows on a capped read was half the answer: the rows that were read got appended anyway, so the reader would have seen the same range twice with the tail still missing. Reading that stops before the conversation does is not a picture of it, so none of it is applied — the transcript keeps what it has, the next turn's poll resumes from it, and a reload refetches. A cursor that stops advancing takes the same route. It was marked a whole read, which is the opposite of what it is: a full page came back, so rows almost certainly remain. Unreachable against a backend that filters on the cursor, but the two guards should not disagree about what they mean. The warning carries how far it got, since the conversation id alone does not say how far behind the transcript is. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
ad847bfa78 |
fix(chat): make the page cap a state the transcript can survive
Stopping at the cap left the conversation looking fully read, and the sweep then dropped the temp rows standing in for everything beyond it — the same vanished answer the paging was added to prevent, one order of magnitude up. The cap is a guard against a cursor that stops advancing, not evidence the conversation ends there, so a poll that hit it keeps its temp rows and says so. The paging test now pins the cursor as well as the rows: a second read that asked for the same page again would have looked right from the rows alone. Moves the attachment test out of the middle of another test's comment, which it had split across two unrelated cases. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
81d843a24c |
fix(chat): give each attachment its own object, and read a long turn whole
Two attachments can arrive under one name — a reader picking `report.pdf` from two folders. Keyed on the name alone they raced to a single object, so the agent read whichever landed last twice and never saw the other. Each gets a segment of its own inside the turn's prefix; the name stays the last segment, so anything reading a name off the key still sees what was attached. The messages endpoint answers oldest-first with a limit, so one request only ever reached the start of a turn that wrote more rows than a page — an agent calling several tools a round. Its answer was among the rows left behind, and the sweep then dropped the temp rows standing in for it, so the answer vanished until the conversation was next loaded. The poll reads on until a page comes back short. Leaving uploaded objects behind when a send does not run is deliberate, and now says so: deleting them is a request that can fail on a path already failing, and a resend uploads its own, so a lost send costs one prefix rather than a growing number. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
4ee585e07d |
fix(chat): guard every write-back behind the re-point, and order the conversation locks
The streaming path had the same unguarded gap the settle path was fixed for: its final poll is awaited and then `endTurn(settled)` runs regardless. Settling releases the conversation's queue, so a message typed before a re-point was started against the flow now loaded, writing it into the previous flow's conversation and agent memory — the thing the forgetting exists to prevent. The poller and the sidebar's loader were unguarded too. Both are guarded at their own await now, which covers every caller rather than each call site. The editor chats keyed off `$initialPathStore || $pathStore`, which still falls back to the typed path on a flow that was never deployed — and there the summary field rewrites the path on every keystroke, so naming a new flow emptied the composer as you typed. They take the editor's stable identity instead, which is also what a preview run records. `FOR UPDATE` over several rows takes them in whatever order the plan plans, so two purges could acquire two conversations in opposite orders. Both sites order by id. The transaction the lock depends on is now stated on `delete_jobs`, which takes a bare connection and would silently lose the serialisation on one that autocommits. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
53bb9ce99a |
fix(chat): make forgetting a flow hold against work already in flight
Clearing the state was not enough: a transcript fetch, a latest-conversation lookup or a settle tail started before the chat was re-pointed resolved after it and wrote the previous flow's rows, selection or status straight back — the bug the clearing exists to prevent, reached through the gap instead. Each of those now carries the generation it started in and drops what it fetched if the chat has moved on since. The re-point test was asserting two things that could not fail — an empty rows map and an empty conversation list, both empty either way — so it pinned half the fix. It loads rows now and checks they are gone. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
89a797d498 |
fix(chat): follow the saved flow path, and serialise the second purge path too
Widening `cleanup()` made it destructive on a prop the editor changes far more often than the flow does: both editor chats were passed `$pathStore`, which is bound to the rename field, so the teardown that forgets a flow could run while someone renamed one. They take the saved path instead, as the preview drawer's other two call sites already do, so forgetting happens when the flow does. The conversation cleanup in `jobs_export` is the same logic as retention's and had the same race: it now takes the conversation rows before asking whether they are empty. One lock order across both paths — messages, then conversation. The lock reads rather than executes because a checked `SELECT` has no `execute`; the discarded ids are the cost of the compile-time check. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
ec9c4054f3 |
fix(chat): release a stuck chat, forget a flow on re-point, serialise conversation cleanup
Three separate holes, all in code this PR added. `endTurn` cleared every flag but `isDispatchingTurn`, so Stop could not release the hold a failed transcript load leaves behind. That flag gates the whole surface, so a conversation whose rows never load took New chat and every other chat with it. The route component is reused between two flows, so the chat is re-pointed rather than rebuilt, and `cleanup()` only ended turns. The selection survived, so `selectLatestConversation` found one already open and the new flow rendered — and would have sent into — the previous flow's conversation and agent memory. Cleanup now forgets what it holds about a flow. Two `delete_jobs` calls each removing one of a conversation's last messages could not see each other's uncommitted deletes, so neither collected the conversation and nothing tried again, stranding the row and its `ai_agent_memory`. The conversation rows are taken before the emptiness check, which serialises them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
c820961dcc |
Merge origin/main into glm/update-chat-mode-ui
#11134 landed squashed, so main carries its changes while this branch carries its commits. The flow chat components resolve to this branch's, as they did when the branch was stacked on it: the SDK keeps serving external frontends and raw apps, and the in-app chat runs on these components. `agentFormFields` takes main's version — it grew `seed` and the `enabled_tools` rule there, and this branch never edited it — with `agentStreamingEnabled` and its tests grafted back, since FlowInput, FlowPreviewContent and the flow page all call it. `runInput` stays removed; nothing reads it. Brings the EE pin main already moved to, which is what the backend checks were failing to compile against. |
||
|
|
8b4f6220dc |
refactor: run the flow chat UI on the windmill-chat sdk (#11134)
* refactor: run the flow chat UI on the windmill-chat sdk Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix: structural answer check, poll option and latest run in the chat sdk Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix: count jobless tool rows and the loaded license in the flow chat Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
3b2eb1485c |
fix(chat): name the run before offering Stop, and hold a chat whose rows failed to load
Two holes in the window between opening a chat and its job answering. Stop is on offer for that whole window, and it cancels whatever `status.jobId` holds — which was not set until the answer came back. Pressing it then cancelled nothing, ended the turn and freed the chat while the run carried on. The run is named before the question, and unnamed again if the turn is not taken over. A load that failed used to release the hold, on the reasoning that an empty transcript has nothing to interleave with. It does: the run owns the conversation's agent memory whatever the browser managed to fetch. The hold stays; selecting the chat again retries the load, and Stop is the way out. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
19af05b213 |
fix(chat): never free a chat on a guess about its run
The same rule the streaming path already follows, applied to the three places that still decided for themselves: - Non-streaming turns waited on `waitJob`, which stops answering without settling: on its fifth failed status request it cancels and returns, leaving its promise pending, and the chat busy for the session. They wait on the job the same way a stream-less turn does, and `pollJobResult` goes with it. - A Stop whose cancel request failed still ended the turn, freeing the composer while the run it could not reach carried on. The turn is left to its job. - Loading a conversation's rows was not covered: between opening a chat and the job answering, a send was accepted. The hold now spans the load and the question, and a failed question is asked again rather than taken as a no. A turn with more rows than a page still has no user row on the page to name its job, so it is not picked up. That needs the server to say which turn is running. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
de8fd34334 |
feat(chat): pick a conversation's turn back up when its run is still going
The client was deciding whether a turn had ended from whether its own stream was alive, which it cannot know. It asks the run instead. Nothing in the browser survives a reload, so a chat opened while its flow was running read as idle and the composer took a message — two turns writing one agent memory. The row the server writes when a turn starts carries its flow job; that job is asked whether it is over, and if not the turn is picked back up and followed. The chat is held from the moment the question is asked rather than from the answer, since a send accepted during that round trip is the thing this prevents. A stream resumed this way replays the rounds an agent has already persisted, and the transcript cannot tell a replayed round from a second one, so the turn's own rows are dropped before re-attaching; the final poll brings them back. With that, a turn whose stream dies no longer needs a rule for giving up: it polls its job until the run says it is over. The retry cap, the cancel fallback and the settled/unsettled split go — a run that cannot be reached has said nothing, and Stop is on screen throughout for the reader who wants out. A turn with more rows than a page has no user row on the page to name its job and is not picked up; finding it needs the server to say which turn is running. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
3de5a283fa |
fix(chat): cancel a run nothing can reach, and settle only a turn known to be over
An API that stops answering says the status is unknown, not that the run stopped, and the run holds the conversation's agent memory. Marking the turn settled there both freed the composer and flushed the queued message into a flow that might still be writing. The run is cancelled instead, which is what makes the chat safe to use again. If even that cannot be delivered the turn ends unsettled: the chat is usable, but its queue waits for the reader rather than going out beside a live run. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
de876bbd86 |
fix(chat): settle a turn whose stream is gone, rather than waiting forever
The fallback awaited `waitJob`, which stops answering without settling: on its fifth failed status request it cancels the run and returns from its inner poll, leaving the outer promise pending. A turn handed to it never reached `endTurn`, so the chat and its queued message stayed locked for the rest of the session. The turn now waits on the job through the client it already has, and always settles — either the run completes, or it stops answering enough times to call it unreachable. `waitJob` itself is left alone; its other callers are outside this change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
3d60bf6e04 |
fix(chat): hand a turn whose stream is gone to its job, not to the composer
Running out of stream attempts freed the composer while the flow kept going, so the next turn wrote the same agent memory — the thing the retry was added to prevent, only deferred. The turn goes to `pollJobResult` instead, which keeps the chat busy until the run reaches a terminal state and settles it on the rows; `waitJob` cancels the run rather than waiting forever if the API stays down. The budget is counted since the last attempt that delivered something, so a long turn that blips once an hour is not treated like an endpoint that has gone. An abort is checked inside the consumer loop: the SSE reader drains the frames it has already buffered, and `endTurn` has by then reset the transcript state they would be applied to. The give-up toast truncates what it quotes — a 502 body is often a whole HTML error page. Drops the `flow_stream_job_id` scaffolding from the re-attach test: `followJob` never surfaces that id, so the assertion could not fail for the reason its comment claimed. Stop cancelling the flow rather than the streaming step is verified against a running backend instead. Also drops the EventSource stub the test no longer needs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
ec1c01d1bd |
fix(chat): re-open a failed stream rather than freeing the composer
`followJob` absorbs the server ending a stream on its own clock, but not the request to open one failing — a restarting server, a 502. Ending the turn there unlocked the composer while the flow kept running, and the next turn would write the same agent memory. Those attempts are retried from the offset already read, so the answer resumes rather than replaying, and the turn stays busy across the gap. Bounded, so a genuinely gone endpoint still reports itself instead of retrying forever under a chat that looks live. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
a6ec3914ed |
refactor(chat): follow a flow chat turn with the SDK's followJob
The flow chat kept its own EventSource loop: re-attach on the server's stream timeout, resume from `stream_offset`, drop the offset when a retried step gets a new stream job. `windmill-chat` does the same thing in `followJob`, which this PR's base makes importable, so the transport moves there and ~190 lines go. `followJob` is scoped to one job and holds no chat state, so turns still run in several conversations at once — each drives its own generator, with an AbortController in TurnRuntime where the EventSource was. Three things it does that the loop did not: it buffers a chunk that ends mid-line, where ours parsed the halves separately and dropped the token; it reconnects on a close that carried no timeout frame, where ours ended the turn; and it starts a fresh parser when the streaming step changes. Stop now cancels the flow job rather than the streaming step. `followJob` never surfaces `flow_stream_job_id`, so the line that overwrote `status.jobId` with it goes — which is what the comment on the line that sets it always said should happen, and what keeps the steps after the agent from running on. `poll_delay_ms` is sent only with an enterprise licence; a CE server ignores it and warns on every poll. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
0e20a5d751 |
feat(ai-chat): render flow chat mode through the AI session chat components
The flow chat ran on its own components; this points it at the ones the AI session chat already uses, so the two surfaces share a transcript, a composer and a sidebar instead of keeping two of each. The seam is `ChatViewHost` (copilot/chat/chatViewHost.ts): the view components read the host rather than `AIChatManager` directly, and `getChatViewHost()` falls back to the session manager, so the copilot's call sites are unchanged. `FlowChatViewHost` is the second adapter, over `FlowChatManager`. What the flow chat gains from the move: - turns running in several conversations at once, with a status, a queue and a Stop per chat, and an unread count on the rail - attachments, uploaded to the workspace's object storage for the worker to read - a composer that speaks for the agent steps a message is fed to: the model, the thinking effort, and the flow inputs the agent reads straight out of `flow_input`; everything else is asked for in a Configure-inputs modal - tool cards with the call and the result, the model's reasoning, and a step name per answer once a conversation holds more than one agent - Retry, which replays the failed turn's own run arguments read back from its job - named and renamable conversations, and test chats kept out of the deployed flow's list Backend: conversation rows carry an MCP tool's call and result and the model's reasoning, which live nowhere else; every row gets a job so retention can empty it; and the providers parse a non-streaming answer's reasoning. Stacked on #11134, which keeps the windmill-chat SDK for external frontends and raw apps while the in-app flow chat runs on these components. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
9fe493311d |
chore(main): release 1.812.0 (#11111)
* chore(main): release 1.812.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com> |
||
|
|
a78beff743 |
feat: dynamic AI agent toolsets (#11050)
* feat: dynamic ai agent toolsets, and memory as a step input Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: address review round 1 on dynamic ai agent toolsets Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor: tag enabled_tools and drop the memory step input Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: let an mcp server entry be named by the path the roster shows Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: keep $res: out of the tool names the enabled tools picker offers Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: name an mcp server by its bare path on the one side that can hold it Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: count the enabled tool names that matched nothing instead of logging them Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor: narrow an agent's roster in one pass, by whole entries Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * test: pin that an mcp summary is rejected against a name that is not Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * chore: regenerate the copilot flow schema after the merge Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: shorten the enabled tools list hint Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor: take enabled_tools back to a plain list of tool names Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: keep the enabled tools add-menu hint describing the unset field Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: name a websearch tool that carries no summary of its own Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: reserve the name web search is enabled by so no tool can share it Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor: spell the reserved web search name with a hyphen Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor: reserve __wm_web_search as the name web search is enabled by Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * chore: advance ee-repo-ref past the git sync ci check work Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: shorten the enabled tools description the run form shows Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to e4c1b794d6c5e6e390987341b2840587bbb40348 This commit updates the EE repository reference after PR #785 was merged in windmill-ee-private. Previous ee-repo-ref: af668462f0f06b02a5f4e0c22e6156858487a518 New ee-repo-ref: e4c1b794d6c5e6e390987341b2840587bbb40348 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
42f489685b |
feat: store resource type display names and label hub integrations (#11113)
* feat: label resource types and integrations with hub display names Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: load hub integration names in the app and flow pickers Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: load hub resource type names where drawers title a type Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: store resource type display names and drop the hardcoded list Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: leave display_name out of the fork comparison Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: ignore over-long synced display names, move name loaders Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: share the hub integration list cache, backfill admins only Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: keep a name over a nameless duplicate, retry failed hub reads Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
69e6efd875 |
fix(git-sync): run auto-pull as the admin who enabled it (#11121)
* fix(git-sync): run auto-pull as the admin who enabled it Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(git-sync): audit the admin grant fork pulls make Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore: bump ee ref for the post-commit fork grant audit Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(git-sync): address review nits on the auto-pull stamp Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore: update ee-repo-ref to ccada062c072d7b74894b63863728fd1ef9bdffd This commit updates the EE repository reference after PR #799 was merged in windmill-ee-private. Previous ee-repo-ref: 7cee30f0cf12721cba551cd754dc817444810470 New ee-repo-ref: ccada062c072d7b74894b63863728fd1ef9bdffd Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
082d897328 |
stop the variables page opening a drawer for the instance settings hash (#11129)
Claude-Session: https://claude.ai/code/session_01LCt167dnWJ2EVnLpkHATh4 Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
3895e1d579 |
fix: count jobless tool rows and the loaded license in the flow chat
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
dd7ee0cdbb |
fix: structural answer check, poll option and latest run in the chat sdk
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
77740b278e |
refactor: run the flow chat UI on the windmill-chat sdk
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
57a134e2de |
feat(ai-sessions): share session artifacts with the workspace by link (#11115)
* feat(ai-sessions): share session artifacts with the workspace by link Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pyjp67oR269QAx3b4yf4oH * chore: cache the shared artifact queries for offline sqlx Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pyjp67oR269QAx3b4yf4oH * fix: replace a literal NUL byte in the shared artifact body limit comment Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pyjp67oR269QAx3b4yf4oH * test: pin that a shared artifact is confined to its workspace's path Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pyjp67oR269QAx3b4yf4oH * fix: sanitize shared artifact markdown and validate the artifact id on every route The shared page renders another member's markdown, so ArtifactBody now runs the repo's rehype-raw + rehype-sanitize chain with the chat's link renderer on top; only the session viewer opts into the chat code block (mermaid, apply button). The link renderer keeps a link's text when its href is empty or unsafe, and the scheme check moves to a tested helper. The status route checks artifact_id like share does, so a NUL is a 400 rather than a 500. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pyjp67oR269QAx3b4yf4oH * fix(ai-sessions): say which way re-sharing moves an artifact link The popover offered "Update to v1" when a v2 link was open on a pinned v1, which reads as if v1 were newer. Each direction now has its own sentence and action: a newer version on screen updates the link, an older one shares that version instead, a rename updates the name. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
e8c02c04cd |
feat: windmill-chat sdk for chat-mode flows in external frontends and raw apps (#11117)
* feat: windmill-chat sdk for chat-mode flows in external frontends and raw apps Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018aQiZNAU8g17kWkyTryS5J * fix: keep streamed answers until persisted, finish turns after history fallback Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018aQiZNAU8g17kWkyTryS5J * feat: ai sdk transport and assistant-ui runtime for windmill-chat Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix: finish a turn from the flow result until its answer row lands, hash chat ids without crypto.subtle Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix: judge a turn answered by a persisted assistant row, wherever it was fetched Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix: attribute a turn's answer to its own jobs, keep a local turn when switching conversations Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix: mirror local history on every change, attribute failure-handler answers to the turn Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix: new chat per token string in the React hook, idle after destroy, no reorder on view Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix: recreate the hook's chat on any credential change, namespace local history per user Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix: send the latest inputs from the React hook Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
a95e950529 |
feat(cli): list, get and restore trashed items with wmill trash (#11125)
* feat(cli): list, get and restore trashed items from the CLI * docs(cli): tell agents a sync push deletion is restorable with wmill trash * refactor(cli): share the ApiError formatting and type trash flags as integers |
||
|
|
91e6dc39ce |
feat: pre-approved cloud accounts: login links, OAuth adoption, setup, and the trial bridge (#10875)
* feat: single-use login links and oauth-claimable pending accounts * docs: capture the auth surface facts behind login links * fix: accept stringified email_verified from oauth userinfo * docs: describe the oauth claim rule in the auth surface notes * fix: harden login-link redirects and sweep expired links * chore: bump ee-repo-ref * fix: keep expired login links a day so an open still reads as expired * fix: refuse login links for superadmin and devops accounts * fix: re-check the account's roles when a login link is opened * feat: pre-approved cloud accounts finish their setup and start their trial from Windmill * feat: dev-only localStorage opt-in to the cloud UI on localhost * feat: finish-setup entry in the desktop settings menu * style: pulse the settings row while account setup is pending; shorter, blue finish-setup entry * fix: list the configured providers in the finish-setup modal * fix: open the finish-setup modal after the menu has closed * feat: finish-setup provider sign-in keeps the session when the provider asserts another address * chore: pin the EE companion commit * fix: plain toast for the finish-setup refusal * style: format the dev cloud override Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * feat: onboarding skips the source question an invite already answered Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * fix: type the finish-setup icons and login_type as the frontend uses them Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * feat: invited accounts get a workspace name, hub picks and starter prompts from their invite Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * fix: the workspace form reads the invite's name itself, so the picker prefills it too Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * feat: an empty workspace offers the projects its invite picked, one click from importing Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * style: picked projects get identical import buttons Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * feat: a pinned sidebar banner until an invited account has credentials of its own Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * style: the account-setup row speaks the rail's language, tinted not filled Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * chore: pin ee-repo-ref to the import fix Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * refactor: picked projects live in the template picker only; account-setup row moves to the rail footer Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * fix: review round — no portal login for job tokens, finish-setup failures keep the session, prompt labels deduped Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * fix: CI round — trial start is a POST, profile cache follows the session, setup row on MenuButton Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * fix: CI round — no password road where password login is off, cache note on the login form, trial refusal surfaced Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * fix: CI round — set_password guarded on its read, refusal stays on the page, docs and formatting Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * fix: CI round — popup OAuth clears the profile cache, portal helper crate-private, refusal toast stays Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * fix: a refused trial is recorded inline in the rail, not in a day-long toast Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * fix: the refusal notice uses the rail's button and has a collapsed form Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * fix: CI round — SSO can finish account setup, with the same mismatch refusal as OAuth Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * fix: SSO finish-setup rides in RelayState and the refusal notice is a status region Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * fix: keep the finish-setup cookie beside RelayState, hoist the status region, pin session-keyed profile cache Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * fix: empty live region for the trial refusal, drop the setup cookie once adopted, telemetry inventory Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * fix: the trial refusal survives the responsive sidebar swap Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * fix: the trial refusal is shown to the account it answers, modal open prop is required Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * feat: an invited account skips the whole onboarding survey Its source is the invite and its use case was researched before the invite went out, so neither question is asked: the known source is recorded and onboarding opens on naming the workspace. Accounts without an invite profile see the survey exactly as before. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * fix: an invited account with a workspace leaves onboarding before anything paints Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * fix: account-setup state resets on sign-out, onboarding shows a loading state while it settles Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * style: keep the refresh doc comment on refresh Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * fix: profile lists are distinct, and the offer table notes what a users-import does to it Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011HMniEf5hapoKEB6TEBcGy * chore: update ee-repo-ref to 1ba6fe83451f0a1f8fafe04b7187087d51e0f769 This commit updates the EE repository reference after PR #750 was merged in windmill-ee-private. Previous ee-repo-ref: be42722d09832ffff709a1f710f3e97e34d513b2 New ee-repo-ref: 1ba6fe83451f0a1f8fafe04b7187087d51e0f769 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
a4ddbd733b |
lower the workspace creation handover floor to 500ms (#11109)
Claude-Session: https://claude.ai/code/session_015hBkusKsmiRiZ9VZVE314G Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
5d32b61067 |
feat: run a flow step test through the chat's argument form (#11114)
test_run_step was the last run tool still starting a job on whatever the model sent. Route it through runThroughForm, as test_run_script, run_script and test_run_flow already are. A step's arguments are its own, not the flow's: it is normally fed by its input transforms, so the form is built from the step's target rather than the flow's schema. loadSchemaFromModule resolves script and subflow steps against the deployed version, which would offer the fields of code this path is not about to run, so the schema comes from the same read the job uses — inferred from a rawscript body, the draft script's content, or the subflow's own schema. The preprocessor's _ENTRYPOINT_OVERRIDE is declared by no schema, so it is added inside the resolved startJob: proposed into the form instead, the argument conforming would drop it and the preprocessor would silently run its main. Its schema is inferred rather than read off the target for the same reason a stored one cannot describe it: a schema speaks for the one entrypoint it was inferred from. executeFlowStepTestRun splits into resolveFlowStepRun plus a thin wrapper, so the flow editor's own test_run_step keeps its behaviour but for one fix it inherits: a deployed subflow step now runs with skipPreprocessor. The flow editor's step test passes it too, and a parent flow pushes a subflow step the same way (apply_preprocessor: false) — a preprocessor would take the subflow's own inputs for a trigger event. Claude-Session: https://claude.ai/code/session_018PBB2gw8FK4YmGPxu5Drbn Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
94c548cd5d |
fix: re-attach flow chat to the same job on SSE timeout instead of re-running it (#11122)
* fix: re-attach flow chat to the same job on SSE timeout instead of re-running it Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S4xKKyrBTs35MEScYucgZW * fix: restart the flow chat stream when the streaming sub-job changes across a reconnect Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S4xKKyrBTs35MEScYucgZW --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
244ec13291 |
fix(ai-chat): hide other users' MCP servers from the chat unless shared (#11112)
* fix(ai-chat): hide other users' MCP servers from the chat unless shared An admin's database role lets the resource listing return every user's u/ MCP resource, so the chat's "+" menu and the assistant settings tab offered servers that carry someone else's credentials. Both lists, and the tool loader behind them, now keep a u/ server only when it belongs to the current user or its extra_perms name them or one of their groups. The Resources page is unchanged. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0131DsyTiBR6Q54qPXbTX5sC * fix(ai-chat): resolve the MCP viewer for the workspace being listed Username and groups are per workspace, and a session chat can operate on a workspace other than the one being browsed, so the filter now takes its identity from that workspace's whoami rather than from userStore. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0131DsyTiBR6Q54qPXbTX5sC * fix(ai-chat): list the whole MCP catalog before filtering, one predicate The visibility filter runs after the server's LIMIT, so a 100-row page could drop the viewer's own servers behind foreign u/ rows. The three call sites now ask for 1000 and call the tested predicate directly. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0131DsyTiBR6Q54qPXbTX5sC --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> |
||
|
|
56dd940e34 |
fix: keep a script draft's password marking through the chat's run form (#11110)
* fix: keep a script draft's password marking through the chat's run form Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dx9oMWHnKywoqooZBeaPCy * docs: describe what the inferArgs test mock actually lets the suite pin Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dx9oMWHnKywoqooZBeaPCy --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
80eba80d6e |
feat(git-sync): gate GitHub PRs on Windmill CI test results (WIN-2051) (#10096)
* docs: add design doc for automatic git-to-windmill pull sync
* docs: add migration plan and implementation phases to git-sync pull design
* feat(git-sync): add auto_pull settings schema and pull enqueue primitive
Adds AutoPullSettings/AutoPullMode/AutoPullStatus on GitRepositorySettings
(workspace_settings.git_sync JSONB), the GIT_SYNC_PULL_SCRIPT_PATH constant,
and should_pull/effective_poll_interval_s helpers with unit tests. Exports the
EE enqueue_git_pull_job primitive. Foundation for repo→Windmill auto-pull.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(git-sync): poll repos and auto-pull new commits into the workspace
Phase 1 of automatic repo → Windmill sync. A monitor task (EE-licensed,
single-replica via advisory lock) git ls-remotes each auto-pull-enabled
repository ~every minute and enqueues a pull when the tracked branch moves,
reusing the {workspace_id}:git_sync concurrency key so pulls serialize with
in-flight push commits.
- windmill-store: background (no-authed) resolver get_git_repo_head_for_autopull
that resolves the repo resource (incl. $var: refs) and ls-remotes; GitHub-App
repos are skipped here and will sync via webhooks (phase 2).
- monitor.rs: poll/reconcile/persist with optimistic sha advance and failure
status; targeted jsonb update so concurrent settings edits aren't clobbered.
- edit_git_sync_repository: preserve server-owned auto_pull state on UI save.
- openapi: AutoPullSettings/AutoPullMode/AutoPullStatus + auto_pull field.
- frontend: per-repo "Automatically deploy changes from Git" toggle with last
sync status; demote the GitHub Actions link to an advanced CI option.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(git-sync): wire webhook lifecycle + receiver; share reconcile logic
OSS side of phase 2 auto-pull webhooks:
- edit_git_sync_repository creates/removes the repo webhook on save (EE-gated,
best-effort → falls back to polling).
- monitor poller now delegates to the shared windmill_git_sync reconcile/persist
helpers (also used by the webhook receiver), removing duplicated logic.
- export the shared reconcile/persist/failure helpers; bump EE ref.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore(git-sync): bump EE ref for phase 3 in-app PR creation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(git-sync): show webhook vs polling status on the auto-pull toggle
When a repo has an active webhook (auto_pull.webhook_id set), the status line
reads "instant via webhook"; otherwise it reads the ~1-minute polling cadence.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(git-sync): post PR diff check on dry-run completion (phase 4)
Worker completion hook in process_completed_job: when a DeploymentCallback job
carrying the __git_sync_pr_check marker finishes, parse the dry-run SyncResponse
and patch the GitHub check run with the diff summary (success/neutral/failure).
Export enqueue_git_pull_dry_run; bump EE ref.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore(git-sync): bump EE ref (drop unused GHES webhook_secret)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* revert(git-sync): defer phase 4 PR diff checks (OSS side)
Remove the worker completion hook that posted the PR check run, drop the
enqueue_git_pull_dry_run re-export and the orphaned sqlx cache, bump EE ref.
Phases 1-3 (polling, webhooks, in-app PR creation) are unaffected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Revert "revert(git-sync): defer phase 4 PR diff checks (OSS side)"
This reverts commit
|
||
|
|
d8d7332eb6 |
feat: add per-route CORS origin allowlist for HTTP triggers (#10833)
* feat: add per-route CORS origin allowlist for HTTP triggers Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: fail closed on cold router cache and invalid origin input Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: resolve CORS route from the decoded path like the request handler Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * feat: add instance-wide default allowed origins for HTTP routes Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: let non-superadmins read the default allowed origins setting Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * feat: badge the advanced section when a route's origins are restricted Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: state inherited origins on the control and use one hint row Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: trim the origins tooltip and relabel the toggle when a default exists Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: keep the origins format hint visible until an entry is wrong Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: state the at-least-one requirement in the origins hint Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: import the origins validator in the trigger-http tests Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: make an empty allowlist deny rather than fall back to the default Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: address review nits on origin validation and the CORS editor * fix: derive the origins error from the stored list and tighten host validation * fix: parse real IPv6 hosts and refuse a newly emptied allowlist * refactor: make origin validation advisory except for null and non-ascii * feat: let an empty allowlist be saved as deny every origin * docs: document the empty allowlist as deny every origin * fix: bound allowlists, reject commas, and decide cors after the handler * chore: revert unrelated rustfmt churn in windmill-common tests * chore: revert unrelated rustfmt churn in windmill-common * chore: drop the route types the cors restructure replaced * fix: take the stricter cors decision from before and after the handler * fix: strip runnable cors headers when the routers are unavailable * docs: document the allowlist bounds in the openapi schema * fix: let an unavailable cors read defer to one that resolved * refactor: carry the resolved cors policy from the handler to the middleware * docs: describe why an unavailable read fails closed on the paths that reach it * fix: validate the default origins on the declarative settings path * test: keep the webhook doc comment with the test it describes * fix: warn on impossible schemes and ports, and validate the instance setting * feat: treat an empty allowlist as unset at both levels * perf: decode the cors path only when the fallback needs it * docs: document the empty allowlist as unset in the api schema * docs: describe an empty allowlist as unset in the frontend comments * docs: say what a null allowlist resolves to, not what it meant before the default existed * docs: state what the validator refuses and why methods stay broad * feat: exempt static asset routes from the origin allowlist * fix: hide the origin control for every static target, not just websites * fix: exempt only static websites, not single-file static assets * fix: warn on an unclosed ipv6 host in the origins advisory * fix: require assets present, not just the static website flag --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
7b89e37322 |
chore(main): release 1.811.1 (#11107)
* chore(main): release 1.811.1 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com> |
||
|
|
62d4632fad |
chore(main): release 1.811.0 (#11098)
* chore(main): release 1.811.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com> |
||
|
|
2a21efa11b |
fix: stop a resource delete from taking variables it does not own (#11102)
* fix: stop a resource delete from taking variables it does not own Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nb6mKJWUACuPKA3wZRuyy7 * fix: key the ws_specific cleanup on what the delete actually removed Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nb6mKJWUACuPKA3wZRuyy7 * fix: attribute a cascaded variable to the resource that actually referenced it Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nb6mKJWUACuPKA3wZRuyy7 * docs: state the real constraint behind the pre-transaction referrer scan Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nb6mKJWUACuPKA3wZRuyy7 --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
c90d1d95c2 |
refactor: make the app policy's principal the authority for its identity (#10440)
* refactor: make the app policy's principal the authority for its identity * fix: align the app backfill with the sibling migration and audit the uncached address * chore: refresh the sqlx cache after rebasing onto the merged base * fix: resolve the app execution address uncached, it decides the job's authorization * chore: cache the EE queries at the ref this branch pins * chore: cache the EE queries at the ref this branch pins * fix: derive the app draft's on-behalf-of address on read * chore: cache the query the draft derivation test added * fix: derive the app identity on the draft-table and version reads too * docs: state the draft resolver's authorization contract * fix: resolve a draft's principal against workspace membership only * chore: cache the membership lookup the draft resolver added * fix: drop an unresolvable draft's address instead of leaving it stale * perf: evict the address cache on change so app dispatch can read it * fix: evict on superadmin role changes, not only address changes * refactor: make the app policy's address optional instead of derived on read * fix: follow an external superadmin's rename into the apps that name them * docs: state the removal gate once, and correctly * refactor: drop the app-policy version constant that gated nothing * docs: drop the last reference to the removed constant * perf: read the address cache everywhere now that eviction reaches every replica * fix: keep persisted addresses off the cache the poller evicts asynchronously * docs: state where the cached address is accepted and where it is not * docs: keep the cache rule in one place and drop the stale premise * docs: sort the two lookups by how long a wrong answer lives * fix: resolve the schedule address uncached where it is written to the row * docs: name the release this actually ships in * perf: evict a superadmin's key per workspace instead of the whole cache * fix: evict every alias a superadmin principal can be spelled as * docs: describe the trigger as it is * docs: cover the round-tripped read in the cache rule * docs: record why a stale dispatch address cannot escalate * fix: validate a dispatch address against the principal's live binding * fix: carry the validated address through to the job row and token * fix: record the validated address on the job row, not the one handed in * test: run the substep tag check as the non-superadmin it means to test Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc * fix: rewrite a stored app address that disagrees with its principal Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc * docs: record the accepted staleness window of the cached dispatch address Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc * fix: record the validated address on the job's audit row Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc * docs: record the accepted rename race of pre-transaction identity resolution Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc * docs: separate the app's stored address from the derived one in the resolver doc Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc * docs: describe the job identity fast path the push comments skipped Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc * fix: backfill a legacy group-prefixed username as the group it names Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc * fix: resolve a schedule edit's identity before opening its transaction Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc * fix: never resolve a disabled member to a same-named superadmin Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc * docs: state what the email-change notify buys, and rewrap two comment lines Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc * fix: keep a group's runnables when offboarding a legacy group-prefixed member Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc * fix: read the app author from the stored address, as execution does Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc * docs: record the rename race's full consequence as a known, accepted limitation Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc * docs: record the keep-target group address case as a known, accepted limitation Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY4bBCR1q2c5XB8s2r7Ysc --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
e877b5f2e8 |
fix: clear a stale git auto-pull failure and show the status time (#11100)
* fix: show when the last git auto-pull status was recorded * chore: bump ee-repo-ref for the auto-pull status fix * fix: show the git auto-pull status age with TimeAgo instead of a year-less date * test: pin that a stale auto-pull recovery cannot overwrite a newer state * chore: bump ee-repo-ref for the conditional auto-pull recovery * fix: keep TimeAgo counting past the first hour in noSeconds mode * chore: bump ee-repo-ref for the clear_auto_pull_failure contract note * fix: guard TimeAgo's boundary scheduler against invalid dates and pin same-head newer failures * chore: bump ee-repo-ref for the timestamp-guarded auto-pull recovery * test: cover a same-second newer failure surviving a stale auto-pull recovery * chore: bump ee-repo-ref for the whole-failure recovery match * test: name the recovery helper after its input, not its staleness * chore: update ee-repo-ref to c6df9fdd9826efb40d3586a9f97d17dee98ac6ef This commit updates the EE repository reference after PR #793 was merged in windmill-ee-private. Previous ee-repo-ref: 6aff80b80cae4944a4a78a6b9244019bc37f368b New ee-repo-ref: c6df9fdd9826efb40d3586a9f97d17dee98ac6ef Automated by sync-ee-ref workflow. --------- Co-authored-by: Ruben Fiszel <ruben@windmill.dev> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |