mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-20 08:01:35 +00:00
workflow-execution-time-display
13405 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
2fe81b2445 | Merge branch 'main' into workflow-execution-time-display | ||
|
|
cfe5119035 |
feat(ai): add list_runs and get_job_logs tools to global chat mode (#9488)
* feat(ai): add list_runs and get_job_logs tools to global chat mode Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(ai): always suppress ansi hint in get_job_logs, drop misnamed param Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(ai_evals): add global list_runs and get_job_logs eval cases Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * style(ai): trim get_job_logs description and format global core Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ai): surface list_runs/get_job_logs output as tool result The tools set showDetails but never set message.result, so the details panel rendered "No result yet" even on success. Set result in setToolStatus (logs go in result for get_job_logs). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
4c22e3b712 |
fix: inherit container NO_PROXY into MITM tracing proxy job exclusions (#9492)
When HTTP request tracing is enabled, the NO_PROXY injected into traced jobs was built solely from the no_proxy_hosts instance setting, ignoring the worker container's own NO_PROXY. Enabling tracing therefore silently dropped every exclusion an operator had already configured at the container level, funneling those hosts into the MITM proxy (and on to any upstream corporate proxy). The upstream-relay side already honored the container NO_PROXY; this makes the injected-into-jobs side symmetric by merging both sources. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
136c88a231 |
docs(skills): decouple safe local commands from destructive sync push (#9467)
* docs(skills): decouple safe local commands from destructive sync push The schedules, triggers, and resources skill templates lumped every CLI command under a blunt "do NOT run them yourself" directive. This conflated two very different risk profiles and forbade the agent from running even read-only/local commands, creating needless friction. Align these three with the nuanced policy flow-cli.md already uses: keep `wmill sync push` defensive (it deploys and can be destructive to remote state — only run when the user explicitly asks to deploy/publish/push), while letting read-only commands (`sync pull`, `schedule`, `resource list`) be run freely. Regenerated auto-generated skills + skills.gen.ts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(cli): warn that sync push is destructive in dry-run output Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(skills): clarify sync pull mutates local files, not read-only Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: centdix <farhadg110@gmail.com> |
||
|
|
66c0334e70 |
chore(main): release 1.721.0 (#9480)
* chore(main): release 1.721.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>v1.721.0 |
||
|
|
c258928ab6 |
fix(cli): reconcile case-only path drift during sync on case-insensitive filesystems (WIN-2020) (#9485)
* fix(cli): reconcile case-only path drift during sync on case-insensitive filesystems Windmill paths are case-sensitive, but Windows (and the default macOS setup) use case-insensitive filesystems. The real-world failure behind WIN-2020 is not a user authoring both f/Caps and f/caps — it is a single capitalized folder whose on-disk casing silently drifts (Windows stores and reports whatever case the directory was first created with, regardless of the server's path). The diff then sees the drifted local path as a brand-new item and emits a destructive "delete f/Caps + add f/caps" pair, so a capitalized folder appears to vanish and a lowercase clone shows up out of nowhere — and a push can clobber the real server item. Fix: on a case-insensitive filesystem, reconcile case-only drift before diffing. The server's path casing is authoritative, so compareDynFSElement now rewrites local keys that differ from a remote key only by case to the server's casing (canonicalizeCaseInsensitiveKeys), making the diff treat them as the same item. Case-insensitivity is auto-detected by probing the sync directory, with a WMILL_CASE_INSENSITIVE_FS=true/false override to force Windows behaviour (or emulate it for tests / cross-platform repos) on any host. Reconciled paths are summarized in a single info line. Genuinely unrepresentable collisions — two DISTINCT server paths that differ only by case — cannot be canonicalized to one target; those are detected and warned about on every platform so a case-sensitive-Linux author learns their tree won't round-trip for a Windows/macOS teammate. Tests: - Pure unit tests for findCaseInsensitiveCollisions, canonicalizeCaseInsensitiveKeys and summarizeCaseRewrites (platform independent). - An end-to-end drift test that runs on BOTH CI jobs: on the Windows runner it exercises the real case-insensitive NTFS + auto-probe; on Linux it reproduces the drift via rename, asserts the destructive phantom appears without the fix, and asserts a clean no-op push with the fix forced on. Fixes WIN-2020 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(cli): canonicalize local-only descendants of drifted folders; dedupe nested case collisions Address two review findings on the WIN-2020 case-insensitive sync fix: P1 (correctness): canonicalizeCaseInsensitiveKeys previously only rewrote local keys with an exact full-path remote match. A brand-new local file under a drifted folder (e.g. adding f/caps/New.ts when the server has f/Caps but no f/caps/New.ts) had no exact match, so it kept its lowercase casing and push uploaded it as-is — recreating f/caps beside f/Caps and reintroducing the very collision the fix prevents. Canonicalization is now segment-by-segment against a trie of remote paths, so local-only descendants inherit the longest unambiguous server folder casing. A segment is only adopted when the server casing is unambiguous; at the first ambiguous/unknown segment the remainder keeps local casing. The original key's separator style is preserved so rewritten keys still round-trip. P2 (nit): findCaseInsensitiveCollisions reported the folder group AND a nested per-file group when case-variant folders held same-named files, inflating the "Found N path(s)" count. It now reports only the shallowest clash (drops a group whose ancestor prefix is itself a collision). Tests: add unit coverage for the new-file-under-drifted-folder rewrite, the stop-at-first-unguided-segment behavior, and shallowest-only collision reporting; extend the e2e drift test to assert a new item added under the drifted folder is pushed under the server's folder casing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
370c7439fe | Merge branch 'main' into workflow-execution-time-display | ||
|
|
92c21bbe65 |
fix: drop archived items from fork compare (spurious 'not visible' warning) (#9481)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
5f41ddd3a5 |
fix: require auth to view approval details when user_auth_required (#9482)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
b0b330c786 |
feat: deployed↔draft compare + AI-session draft bar (#9435)
* feat: deployed↔draft compare for current workspace + session draft bar Add a "Deployed ↔ draft" comparison alongside the existing fork-vs-parent compare flow, and surface drafts in the AI session UI. - Merge the fork-direction toggle (Deploy to parent / Update current) and the new deployed↔draft mode into one 3-way CompareModeToggle, rendered inside the comparison card. Hidden in non-fork workspaces (draft only). - CompareDrafts: list/deploy/discard server drafts (scripts, flows, apps incl. raw apps) via shared WorkspaceDeployLayout. - Session draft bar (SessionDraftBar) mirrors the fork bar, only visible when drafts exist; its diff button opens the shared read-only diff drawer extracted as WorkspaceDiffDrawer (ForkDiffDrawer + DraftDiffDrawer are thin wrappers over it). - WorkspaceDraftsBanner: home banner linking to draft review. - Backend: GET /drafts/count endpoint for the draft-count badge. - Raw app draft deploy (rawAppDeploy.ts) + vite /ui_builder proxy headers so the bundler iframe loads cross-origin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat: refine draft/fork compare toggle UX Follow-up polish on the merged deploy/draft compare control: - Relabel the draft toggle to "Deploy draft (N)" and show per-direction counts on all three toggle buttons (deployable / updateable / drafts), suppressed when zero. Counts are computed page-side so they persist in draft mode too. - Warn before deploying to the parent when the fork has undeployed drafts ("Only deployed versions in this fork can be sent to {parent} …") with a one-click link to the draft view; milder note in the update direction. - Show an empty-state message per direction ("Nothing to update — this fork is up to date with {parent}") instead of a table of greyed, non-actionable rows; hide the deploy/update button in that case. - Drop the standalone "Pending drafts" info alert from the draft list. - Align the fork "Show diff" button to the non-deprecated Button API (unifiedSize, onClick, startIcon) so it matches the draft one; mark "Discard draft" destructive. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat: link compare row titles to the item editor - Render each compare row title (fork and draft) as a link that opens the item in a new tab, scoped to the current workspace (raw apps route to /apps_raw/edit), matching the AI-session diff drawer: target=_blank, hover underline + ExternalLink icon, click stops row-selection propagation. Kinds without an editor stay plain; the fork rename markup is preserved. - Drop the "Kind → name" prefix from draft rows — that arrow reads as the rename visual and the kind is already shown by the row icon. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat: clickable rows + multi-select in deploy layout - Make deploy-layout row cards selectable on click via an opt-in `selectOnRowClick` prop on the shared Row (default off, other tables unaffected); clicks on the checkbox, title link and action buttons are ignored. Adds role/tabindex + Enter/Space keyboard support. - Support multi-select with modifier keys like classic list pickers: Shift+click selects the contiguous range from the anchor row; Cmd/Ctrl (and plain) click toggles a single row. select-none avoids text highlighting on shift-click. - Turn the "Select all" text into a <label> associated with its checkbox so clicking the text toggles it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat: select all drafts by default in draft compare Drafts now load pre-selected (deploy-all is the common intent); guarded so a reload after a deploy doesn't re-select the items left behind. Mirrors CompareWorkspaces' default auto-selection. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: show diff for draft-only items stored without a draft row A draft_only flow/script/app whose content lives in the entity row itself (created via create*(draft_only: true), no separate draft-table row — like u/admin/new) returns draft == null from get*ByPathWithDraft. getDraftDiffValues passed that null through, so the diff "after" side was empty and nothing rendered. Fall back to the row's own value as the draft content when draft is null (deployDraft already did this), fixing both the compare-page DiffDrawer and the session bars' WorkspaceDiffDrawer. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat: shared diff button across session bars + bar spacing - Extract SessionDiffButton (variant=default, ± DiffIcon, count, "Open diff" title) and use it for the diff-drawer trigger in both the fork bar and the draft bar, so they're identical. Drop the icons from both "Review" buttons. - Add gap-1 (4px) between the fork bar and draft bar when both are visible (flex wrapper; single in-flow root per bar, drawer is portalled — no stray gap when only one shows). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: deploying a new (draft-only) flow or app A draft_only flow/app already has an entity row (created via create*(draft_only: true)), so deployDraft's createFlow/createApp rejected it with 400 "already exists". Use updateFlow/updateApp instead — a listed draft always has a row, and update promotes a draft_only entity to a real deployed version (clearing the flag), like the editor does. Scripts were unaffected (createScript + parent_hash makes a new version). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: refresh fork comparison after deploying/discarding a draft Deploying a draft promotes it to the workspace's deployed version, changing the fork comparison (ahead/behind vs parent) — but the compare page only re-fetched it on workspace change, so the deploy/update toggle counts and the CompareWorkspaces tab went stale. CompareDrafts now fires onChanged after a successful deploy/discard; the page rewires it to refresh the comparison and draft count. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: stop draft-count effect from freezing the AI session page ensureDraftCount cleared its dedupe key on error; since the caller is a reactive $effect (SessionDraftBar), a persistently-failing countDrafts spun the effect into an infinite retry loop that flooded the console and froze the tab. Claim the key before awaiting and keep it set on failure; refresh*() still forces a re-fetch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: correct draft count and refresh compare counts after actions count_drafts now counts deployable drafts (draft_only OR has-a-draft-row across script/flow/app), matching the CompareDrafts list, instead of raw draft-table rows which miss new draft-only items. CompareWorkspaces and CompareDrafts fire onChanged so the compare page re-fetches the comparison and draft count after deploy/update/discard, keeping the toggle badges in sync. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: session draft bar shows a fresh count on every (re)open The runtime persists across client-side navigation, so the deduped ensureDraftCount() kept a stale count (e.g. a 0 cached before a draft was created) when a session was re-opened — the bar stayed hidden even though the server count was >0. Force one fresh fetch per mount from a non-reactive onMount via refreshDraftCount(workspace) (which now takes the workspace so it works before the dedupe key is set). The reactive $effect keeps using ensureDraftCount: refreshDraftCount reads loadingDraftCount ($state), so calling it from an effect would track-and-mutate that state into an infinite fetch loop — ensureDraftCount's plain-key early-return avoids it. ensureDraftCount also now releases its key after a 5s backoff on failure so a transient countDrafts error retries instead of leaving the bar stuck. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor: make the draft count a single deep Workspace Drafts module The Draft Count was computed four ways (backend count_drafts SQL, the CompareDrafts list filter, a bespoke sessionRuntime cache, and the compare page state) that drifted — the root cause of the unreliable count, the stale-on-reopen bug, and the effect-loop freeze. Introduce one module (workspaceDrafts.svelte.ts): - getDraftItems(ws) lists the deployable Draft Items once; count ≡ list length, never a separate query. - useWorkspaceDrafts(() => ws) is a component-scoped runed resource (fetches on mount + ws change, no persistent cache → fresh on every (re)open). - invalidateWorkspaceDrafts(ws) refreshes mounted consumers; deployDraft/ discardDraft self-invalidate, so callers never reason about staleness. Rewire every reader to it (SessionDraftBar, CompareDrafts, DraftDiffDrawer, WorkspaceDraftsBanner, compare page) and delete the sessionRuntime draftCount apparatus (key + loading flag + 4 methods + effects + backoff). With no caller left, remove the count_drafts endpoint (handler, route, openapi, sqlx cache, generated client) — drafts.rs/openapi return to their main state. Record the draft vocabulary in CONTEXT.md. A single GET /w/{ws}/drafts/items endpoint can later replace getDraftItems' three list calls behind the unchanged seam. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat: warn before deploying a draft based on an outdated version When a newer version is deployed while a draft exists (git-sync/CLI deploys preserve drafts via skip_draft_deletion), the compare/deploy-drafts page now flags the draft as Outdated and gates deploy behind an override confirmation with a diff — instead of silently clobbering the newer version. Staleness is read from the draft's base version: scripts already store parent_hash; flows/apps now record a draft_base_version sidecar on save. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: drop redundant /ui_builder proxyRes hack (superseded by #9433) main's global configure-response-headers plugin now runs with enforce:'pre' and sets COOP/COEP/CORP on dev responses (#9433), so the per-proxy proxyRes override is no longer needed. Revert the /ui_builder block to main's headers form — vite.config.js now matches main with no branch-specific change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(sessions): keep draft count reactive to preview/chat deploys Invalidate the Workspace Drafts resource at every frontend deploy seam (ScriptEditorView / FlowEditorView / RawAppEditorView onDeploy + onSaveDraft) so user-driven deploys from the Preview panel update the count immediately, and refresh SessionDraftBar on the same coarse signals SessionForkBar uses (AI turn-end + tab refocus) to cover chat-driven deploys that happen server-side and never surface as frontend calls. Also: always show the draft toggle count including (0) on the compare page, drop the header/content separator line in both compare cards, and derive the "Deploy N drafts" footer count so it stays reactive after discard. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor: address branch review findings - WorkspaceDraftsBanner: use the modern Button API (variant/unifiedSize/onclick) instead of the deprecated size/color/on:click triad; drop "pending" from the banner copy to match CONTEXT.md vocabulary. - WorkspaceDeployLayout: make Cmd/Ctrl-click distinct from a plain click. Plain row click now selects only that row (classic file-picker), Cmd/Ctrl toggles, Shift extends the range, and the checkbox still plain-toggles. Adds an onSelectOnly callback wired in CompareDrafts/CompareWorkspaces. - WorkspaceDiffDrawer: document why the file filter is a raw input (bespoke keyboard-nav integration the design-system inputs can't express). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * revert: drop draft version-gating (stale-draft warning) Remove the "deploying an outdated draft would override a newer version" guard. It's a rare edge case and will be handled properly by conflict resolution in a follow-up PR. - CompareDrafts: drop staleMap/computeStaleness, the TOCTOU pre-deploy re-check, the "Outdated" badge, the override-in-diff button, and the "Newer version deployed" confirmation modal; deploySelected is now the plain deploy. - utils_draft_deploy: remove getDraftStaleness/DraftStaleness and the draft_base_version strip. - FlowBuilder / AppEditorHeader / RawAppEditorHeader / AppJsonEditor: stop injecting draft_base_version into draft saves — these editor paths are back to matching main, shrinking the PR's blast radius. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * style: unify home banner CTAs on the modern Button API Both the Workspace Drafts banner and the sibling Fork banner now use variant="default" unifiedSize="sm" onclick, so the two CTAs on the home page render identically and neither uses the deprecated size/color/on:click props. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(compare): show draft deploy direction badge inside forks Mirror the fork compare header's "from → into" badges on the Deploy-draft tab: "deploy: draft → into: <fork>". Makes it explicit that deploying a draft promotes it within the fork (deployed↔draft), not up to the parent. Only rendered inside forks, where the parent could otherwise be confused with the deploy target. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(compare): address PR review — dedup drafts resource + shared link - De-dupe the compare page Workspace Drafts fetch: the page owns the single resource and passes draftItems/draftsLoading into CompareDrafts (was mounting a second resource → 6 list calls; now 3). - Prune transient deploymentStatus for items dropped from the list (no unbounded growth, no stale 'deployed' suppressing a re-drafted row). - Type getDraftItems' list fields via a narrow DraftListEntry (drop Array<any>). - Clear comparison catch-up timers on unmount (onDestroy). - Extract shared ExternalEditLink.svelte; use it in CompareDrafts, CompareWorkspaces, WorkspaceDiffDrawer (was a near-verbatim <a> block x3). - Note conflicts intentionally count in both toggle directions; drop a stray blank line in sessionRuntime. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(compare): show draft summary renames via shared item-summary component Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(compare): address round-2 PR review - Point the fork-compare edit link at the workspace the item actually lives in: a parent-only row (absent in the fork) would 404 if linked into the fork, so link it into the parent instead. - Replace the bespoke raw <button class="underline">Deploy drafts</button> in the undeployed-drafts alert with a design-system Button (variant=subtle). - Drop the stray Prettier reflow in sessionRuntime (restore to match main). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(compare): warn on fork items with a pending draft In the fork compare list, items that are deployed *and* have a pending draft (has_draft) now: - show a yellow "+Draft" badge (AlertTriangle), rendered before the New/status badges, with a per-direction tooltip explaining that deploying/updating moves the deployed version, not the draft; - are excluded from the default selection (still manually selectable); - trigger a confirmation modal if explicitly selected and deployed/updated, listing the affected paths. The signal comes from the page's existing fork drafts resource (a kind:path Set passed down) — no new fetch, no backend change. Also rename the undeployed-drafts alert CTA from "Deploy drafts" to "See drafts". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(compare): rename page to "Compare & Deploy" Update both the page heading (PageHeader) and the browser-tab title. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(compare): multi-select rows by default (no modifier) In the shared WorkspaceDeployLayout (fork + draft lists), a plain row click now toggles the item in/out of the selection instead of replacing the whole selection with it. Removed the modifier-based selection entirely: the now-dead onSelectOnly path and its two call sites, plus shift+click range selection (and its anchor/isPickable helpers). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(table): don't toggle row selection on keyboard child activation Row's onkeydown selection handler lacked the interactive-child guard that handleRowClick already had, so pressing Enter/Space on a checkbox, action button, or title link both activated the child and toggled the row's selection. Extract a shared fromInteractiveChild() guard and apply it in handleRowKeydown, mirroring the click path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(fork-banner): show draft CTA when fork is up to date When a fork has no changes vs its parent ("Everything is up to date") but has pending drafts, the banner now mirrors the non-fork drafts banner: the status text becomes "This workspace has N draft(s)" and the button becomes "Review & deploy drafts", linking to the compare page in draft mode. When the fork has real ahead/behind diffs, the existing status and buttons are unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(compare): honor renamed draft paths + raw-app draft fixes Address the Codex review: - Draft deploy now uses the draft payload's path for scripts, flows and raw apps (keeping the URL path as the existing item key), so a rename in a draft deploys to the new path instead of silently staying at the old one. - DraftDiffDrawer maps raw apps to the `raw_app` kind so their row edit links open the raw-app editor, not the legacy app editor. - ScriptEditorView.restoreDeployed invalidates the workspace drafts after deleting the draft, so the session draft-bar count drops immediately. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(compare): guard showDiff race, tree label, mode fallback Address the cubic review: - CompareDrafts.showDiff uses a monotonic request token so two quick "Show diff" clicks can't let a slow earlier fetch overwrite a faster later one. - WorkspaceDiffDrawer.buildTree labels a 2-segment path with its leaf name (parts[1]) instead of the full scope key. - The compare page only resolves ?mode=draft immediately; ?mode=fork (and an absent mode) defer to the isFork-aware effect, which falls back to draft for non-fork workspaces instead of stranding them on the fork UI. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore: remove CONTEXT.md from the PR Drop the root CONTEXT.md domain glossary and the lone comment pointer to it in workspaceDrafts.svelte.ts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(compare): send custom_path on raw-app draft deploy A raw-app draft that changes or clears its custom route was silently dropped on deploy from the compare page: updateAppRaw omitted custom_path, so the backend preserved the old route. Send the draft's custom_path on update — matching the fork deploy path (which spreads the full app, custom_path included) and the createAppRaw branch. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(sessions): refresh draft count on raw-app session save-draft The script/flow session editors invalidate the workspace drafts on save-draft, but the raw-app editor only did so on deploy. Thread an onSaveDraft callback through RawAppEditor → RawAppEditorHeader and call invalidateWorkspaceDrafts from RawAppEditorView, so saving a raw-app draft in an AI session updates the SessionDraftBar count immediately (and the bar appears when the count was zero). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(compare): honor renamed paths, draft triggers & paginate inventory Address the Codex review: - Draft deploy honors the draft's renamed path for scripts/flows/raw apps (keeping the URL path as the existing item key). - Script/flow draft deploy now deploys draft_triggers via the shared deployTriggers, instead of silently dropping them with the draft. - rawAppDeploy sends custom_path admin-gated on update (admin: value/'' to clear; non-admin: undefined) so non-admins don't hit RequireAdmin. - getDraftItems pages through listScripts/listFlows/listApps so drafts past the first page are included in the count, banners, drawer and deploy list. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(compare): admin-gate custom_path on visual-app draft deploy The visual-app branch of deployDraft sent custom_path unconditionally on updateApp, so a non-admin deploying an app draft for an app with a custom route hit RequireAdmin. Mirror AppEditorHeader and the raw-app path: admins send the draft's custom_path ('' clears), non-admins send undefined so the backend preserves the existing route. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(raw-app): save initial draft directly when path is known In the AI-session preview, a never-deployed raw app has newApp=true but a known path, so saveDraft opened the "Initial draft save" path-picker drawer — which is gated on `appPath == ''` and therefore never rendered, making Save draft silently do nothing. Branch the new-app case on appPath: pick a path via the drawer only when none is chosen yet; otherwise call saveInitialDraft() directly. saveInitialDraft now also toasts and fires onSaveDraft so the session draft-bar count refreshes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(compare): preserve deployed custom_path on visual-app draft deploy The visual-app draft value usually omits custom_path, so the admin branch's `d.custom_path ?? ''` sent an empty string, which the backend treats as "clear the route" — an admin deploying a content-only draft would wipe the app's existing custom route. Fall back to the deployed route (`r.custom_path`) when the draft omits it; an explicit '' still clears. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
a3740d571a |
chore(main): release 1.720.0 (#9464)
* chore(main): release 1.720.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>v1.720.0 |
||
|
|
e8e0701a36 |
feat(api): add endpoint to update token label (#9474)
* feat(api): add endpoint to update token label Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(api): prevent renaming the session token label Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(api): restrict token-label edits to user tokens, not just session Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): edit token label in the edit modal instead of inline Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(api): reject relabeling tokens to reserved system-token names Centralize the is_user_token classifier in windmill-common and reuse it to reject labels colliding with system-token namespaces (ephemeral*, debugger-token, mcp-oauth-*), not just session. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(api): match ephemeral label case-insensitively and cap label length Align the canonical is_user_token, the SQL guard and the frontend mirror on a case-insensitive `ephemeral` match (so a token can't be relabeled to a casing the backend allows but the UI hides), reject labels over the VARCHAR(1000) column limit with a 400, and add unit tests for is_user_token. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
5d0ef7dfd9 |
fix: center auth0/okta icons and respect currentColor (#9457)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev> |
||
|
|
6d522b3989 |
fix: refresh session editor preview on breadcrumb target switch (#9475)
* fix: refresh session editor preview on breadcrumb target switch
Consolidate the three session editor views into a SessionEditorTarget deep module that remounts the heavy editor on a data-ready target swap ({#key slot.loadedPath}), so stale mount-time state (e.g. Path.svelte's settings-panel path) re-derives. Adds LoadSlot to the runtime and a useUserDraftSync composable + per-kind codecs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: flush pending session draft write on target switch
A breadcrumb target swap (or unmount) within the 150ms outbound debounce window cleared the pending UserDraft write instead of flushing it, dropping the last edits. Scripts previously saved immediately so this was a regression from the new uniform debounce; flow/raw_app already had the latent drop. A dedicated path/workspace-scoped effect now flushes the pending write on switch/unmount without disturbing the debounce during a typing burst. Also refreshes a stale loadScript comment that named removed symbols (addresses PR review nits).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
192574ab8f |
fix(forks): keep trigger/schedule operational state owned by the parent - WIN-2019 (#9476)
* fix(forks): defer trigger/schedule state to parent for clean git merge Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(forks): read parent trigger/schedule state on non-RLS pool for complete substitution Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(forks): read schedule fork-ness on non-RLS pool; clarify mutator-rule wording Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
76c0d970a1 |
fix(oauth): persist refreshed token through configured secret backend (#9471)
The lazy on-fetch OAuth token refresh persisted the new access token with a raw
`UPDATE variable SET value = <db-encrypted>`, bypassing the secret-backend
abstraction. With an external secret backend (AWS Secrets Manager / Azure Key
Vault / Vault), secret reads resolve through the backend and ignore
`variable.value` entirely, so refresh advanced `account.expires_at` and updated
Postgres but never wrote the new token to the external store. Every read that
did not itself trigger a mint kept serving the frozen connect-time token, which
expired ~1h after connect (RefreshError on Google clients).
`windmill-oauth` can't depend on `windmill-store` (circular), so variable
persistence moves out of `refresh_token{,_for_account}` (which now only exchange
the token + update the `account` row and return the new token) into the
`windmill-store` callers, via a new `store_oauth_token_value` helper that writes
through the configured backend and stores the returned value (encrypted blob for
the DB backend, `$...:` marker for external backends) in `variable.value`.
If persisting the refreshed token fails (more likely now that it can be a
network write to an external backend) after the account was committed fresh,
`store_oauth_token_value` resets `expires_at` to the past and records
`refresh_error` — looking the account up via `variable.account` — so the next
fetch retries instead of serving the stale token for the whole token lifetime.
Also add `windmill-store/tests/oauth_refresh_secret_backend.rs`, an opt-in e2e
regression suite (RUN_SECRET_BACKEND_E2E / RUN_AWS_SM_TESTS) covering database
and external (AWS SM via LocalStack) backends plus the self-healing reset.
Verified against Postgres + LocalStack: 3 passed.
EE companion (oauth_refresh_ee.rs: 3 refresh paths) merged via #607; this OSS
half completes the fix (ee-repo-ref already at EE main 481ea7f).
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
fa86c62b66 |
fix(frontend): use ban icon for canceled jobs instead of hourglass (#9478)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
3bc5800197 |
feat: allow private MCP server URLs (#9470)
* feat: allow private MCP server URLs * docs: remove private MCP server URL doc * fix: apply MCP URL opt-in to OAuth handlers * fix: update EE ref for MCP OAuth redirects * fix: preserve MCP OAuth client timeout * chore: update ee-repo-ref to 481ea7f28dc5af6b72390c82f494f34cb9809546 This commit updates the EE repository reference after PR #608 was merged in windmill-ee-private. Previous ee-repo-ref: 6c7da03fb994be23ed6aca59bece94d257a641b5 New ee-repo-ref: 481ea7f28dc5af6b72390c82f494f34cb9809546 Automated by sync-ee-ref workflow. --------- Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
82cb7bf375 |
whitelabel default timeout + test-job callbacks (#9469)
Add a configurable `defaultTimeout` to the script/flow editor whitelabel customUi (replaces the hardcoded 300s default) and an `onTestJob` callback on ScriptBuilder/FlowBuilder that fires with the preview job id when a test run starts. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
dbc80e671c |
fix: show wall-clock execution time for WAC roots in the UI, keep duration_ms as worker time
Reworks the workflow-as-code (WAC) execution-time fix. The earlier approach persisted wall-clock into `v2_job_completed.duration_ms`, but that column is read as worker *service time* by cloud-usage accounting and EE workspace fairness — so a WAC root that suspends while its task jobs run would bill and be throttled for idle wall-clock, and counting it any other way (e.g. excluding it) would let arbitrary user code in the root go uncounted. Instead, keep `duration_ms` as the worker-measured value (revert the backend change entirely) and compute the wall-clock total in the UI from `completed_at - started_at` for WAC roots only. WAC roots are identified by the `_checkpoint` in `workflow_as_code_status` (present in the completed-job API payload; AI-agent jobs populate the column but have no `_checkpoint`). - frontend/src/lib/utils.ts: add `isWorkflowAsCodeRoot` + `jobDisplayDurationMs` - JobStatus.svelte / JobPreview.svelte: render the WAC-aware display duration Reverts the duration_ms/test/sqlx/ee-repo-ref changes from the prior commits so the backend is unchanged vs main; no EE companion change is needed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
0985d6b7b4 |
fix(backend): account worker-measured duration for WAC roots, not wall-clock
The display fix made WAC roots persist wall-clock `duration_ms` (they suspend while their task jobs run). That column also feeds cloud usage accounting, so a suspended WAC root was billing idle wall-clock on top of its child task jobs. Account the worker-measured `$9` duration instead (captured before it is shadowed by the persisted value); behaviour is unchanged for all non-WAC jobs. Bumps ee-repo-ref.txt for the companion EE change excluding WAC roots from workspace fairness service-time sampling. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
64b089cd23 |
feat(frontend): use unified drill picker for AI chat @-mention dropdown (#9159)
* feat(frontend): use unified drill picker for AI chat @-mention dropdown * fix(frontend): chat picker review followups + overlay alignment - AIChatDisplay: migrate @-badge popover to ChatContextPicker (was still importing the deleted AvailableContextList after the rebase onto #9034, causing a build break). - DrillPicker: handle Tab as Enter so the inline @<word> mention completes without losing focus. Tweak leaf-row weight to font-normal; secondary text uses text-hint. - ContextTextarea: drop px-0.5 from the highlight span — extra horizontal padding made every glyph typed after a mention drift right of the invisible textarea below. box-decoration-clone keeps the rounded corners. - ContextElementBadge: explicit font-normal label, hoist label into a {@const} and pass to title= so the truncated badge shows the full title on hover. - workspaceTree: drop orphaned doc-comment left dangling by the rebase. - Add unit tests for drillPicker.ts and workspaceTree.ts (51 tests cover resolveScope/scopeChain/collectLeavesGrouped/leafHaystack, buildWorkspaceTree shape + loading + dir forest + leaf shape, withCurrent rename suppression, extraItemsByKind dedup, legacyScopeToPath, relativizeWorkspacePath). * fix(flow-editor): ignore keyboard shortcuts when focus is outside the flow root Menus, modals, drawers etc. live outside the flow root and capture focus explicitly. Flow nodes aren't focusable, so the unfocused default (activeElement === body) means "flow is the canvas" and we should react; anything else means another surface has the user's attention and our shortcuts would steal it. * fix(frontend): inline @ mention picker + chat layout polish - ContextTextarea: swap manual Portal+caret-math positioning for svelte-floating-ui anchored at the `@` character (virtual reference, middleware [offset, flip(crossAxis:false), shift]). Picker stays pinned to `@` while the user types the query, slides leftward when hitting the right edge instead of flipping alignment, and floating-ui handles above-vs-below + edge clamping automatically. Drops the 60vh-worst-case reservation that left a big gap above the caret in sessions, and the now-unused isFirstMessage prop is marked deprecated. - AIChatDisplay: the `@`-button Popover now opens with placement bottom-start (was the default `bottom`), aligning its left edge with the button instead of centering under it. - ChatContextPicker: when no Diffs/Modules/Databases branches are present (e.g. global chat), return the Workspace tree's children at the root instead of wrapping them under a redundant "Workspace" row. handleScopeChange handles both the wrapped and unwrapped layouts and the single-kind `dir:` top segment. * chore(frontend): address review suggestions on chat picker PR - DrillPicker: clamp width to viewport on narrow screens — w-[420px] → w-[min(420px,calc(100vw-20px))]. - workspaceTree.buildWorkspaceTree: make loadingKind optional (defaults to {}). Chat picker still passes it; callers that don't track loading no longer need to thread an empty object. - ChatContextPicker.handleScopeChange: name the WRAPPED vs UNWRAPPED layouts in a comment block so the dir:/kind: branches are obvious. - ContextTextarea: drop deprecated isFirstMessage prop (floating-ui handles direction); drop defensive Math.max on the @ index now that the invariant is documented; comment the floatingRef(anchorRef) call as the supported virtual-reference path in svelte-floating-ui. - AIChatInput: stop forwarding isFirstMessage to ContextTextarea. * feat(frontend): sync selectedContext with @-mentions in textarea Both picker entry points now insert a visible `@title` token in the textarea, and deleting that token drops the matching entry from selectedContext. - AIChatInput: new insertMention(title) export. Appends `@title ` to instructions, prefixing a space only if the existing text doesn't already end in whitespace. - AIChatDisplay: the `@`-button popover calls insertMention after addContextToSelection so its picks match the inline-mention path's textarea state. - ContextTextarea: new onRemoveContext callback. A $effect compares the set of `@title` tokens in `value` (derived) against the previous snapshot; titles that disappeared trigger onRemoveContext for any selectedContext entry with `deletable !== false`. The diff lives in an effect (not handleInput) so it catches both keystroke deletions AND programmatic value updates from updateInstructionsWithContext. - AIChatInput: passes onRemoveContext that filters selectedContext by type+title — mirrors the existing badge X-button handler. * chore(frontend): narrow ChatContextPicker `inner` from `any` to `DrillPicker | undefined` The previous `let inner: any` worked around svelte-check rejecting `DrillPicker<ChatLeafData>` (the imported component is seen as the non-generic `Comp`). Dropping the type parameter keeps the workaround without `any`, so handleKeydown / pickHighlighted are at least typed at the call site. Addresses May-14 PR review. * fix(frontend): address PR #9159 bot-review findings (eager preload, focus, dedup, icon types) - [P1] ChatContextPicker.handleScopeChange: stop preloading workspace kinds at the wrapped picker root. New `isWorkspaceOnly` $derived (true when no Diffs/Modules/Databases branches are present) gates the at- root preload, so the chat root no longer fires two list requests before the user enters Workspace. Reported by Codex. - [P2] AIChatDisplay @-button popover: call aiChatInput.focusInput() after close() so the textarea is focused for immediate typing — mirrors the inline-mention path's setTimeout(textarea.focus, 0). Reported by Claude. - [P2] AIChatInput.insertMention: no-op when the `@title` token is already present in instructions, so re-picking a workspace item doesn't leave duplicate visible tokens for a single selectedContext entry. Reported by Codex. - [P2] drillPicker.ts: introduce `DrillIcon = ComponentType | Component<any, {}, ''>` and replace `icon: any` on DrillLeaf, DrillBranch, and ChatContextPicker.buildContextBranch. Mirrors the ComponentType | Component pattern used in TriggersBadge.svelte for the same Svelte 4/5 compatibility window. Reported by Pi. * fix(frontend): preserve workspace context on refresh + load all kinds for internal search - [P1, Codex] ContextManager.updateAvailableContextForScript/Flow: preserve workspace_script and workspace_flow entries through the selectedContext filter on editor refresh. They're user-picked refs that don't appear in availableContext, so the previous filter was silently dropping them whenever the script/flow editor refreshed options (e.g. on any code change). - [P2, cubic-dev-ai] WorkspaceItemDrillPicker: in internal-search mode (externalFilter === undefined, DrillPicker renders its own search box), preload all kinds on mount. Without this, typing in the picker's search before clicking a kind branch produced incomplete results since DrillPicker can't reach back through the adapter to trigger fetches on internalFilter change. Cached items keep the effective cost near-zero on warm sessions. * fix(frontend): preserve workspace refs through script-mode context refresh The script-mode updateAvailableContext overwrites newSelectedContext with a fresh [code] entry, defeating the workspace_script / workspace_flow preservation in the later filter — the entries are already gone by the time the filter runs. Seed newSelectedContext with the refreshed code block AND the user- picked workspace_script / workspace_flow / code_piece entries from currentlySelectedContext, so editor refreshes don't wipe @-mention badges in script chat. The existing line-271 filter still validates each entry against newAvailableContext + the per-type allowlist. Reported by Codex on PR #9159 — completes the prior workspace-context- on-refresh fix (b02d1f2d35) which only patched the filter, not the rebuild step that runs before it. * fix(frontend): preserve all previously-selected contexts on script refresh The prior c2775fe0c5 fix only carried over workspace_script / workspace_flow / code_piece entries from currentlySelectedContext. That preserved the workspace P1 path but still dropped previously- selected diff / error / db / runtime-context badges, which cubic flagged in its 16:55 review. Spread the full currentlySelectedContext (minus `code`, which we just rebuilt). The downstream filter validates each entry against newAvailableContext + the per-type allowlist, so auto-derived types like diff / error / db survive when still applicable, and unrelated items are dropped automatically. Reported by cubic-dev-ai on PR #9159. * fix(frontend): rehydrate auto-derived context + sync badge X with textarea - [P2, cubic] ContextManager.updateAvailableContext: when the rebuild carries over previously-selected diff/error/db entries, swap each one for the matching freshly-built entry from newAvailableContext in the final .map() step. Preserves the user's `deletable` override on top of the fresh content/diff/schema, so refreshes don't keep stale payloads while still surviving the badge across edits. - [P2, Pi/Codex] AIChatInput: new `removeMention(title)` export that strips `@title` tokens from `instructions` (whitespace-bounded so substring matches don't bleed). The badge X-button now calls it after filtering selectedContext, mirroring the inverse textarea-to- badge sync. No double-remove: ContextTextarea's $effect-driven onRemoveContext is a no-op once selectedContext no longer holds the entry. * fix(frontend): retype ChatContextPicker.inner to DrillPicker<ChatLeafData> `npm run check:fast` (TypeScript-only) and `npm run check` (svelte-check) disagree on whether the imported DrillPicker is generic — `check:fast` sees it as `Comp` and rejects the type parameter, while `svelte-check` sees the real generic component and requires it. CI runs `check`, so follow that: `DrillPicker<ChatLeafData> | undefined`. This also fully replaces the prior `inner: any` workaround called out in multiple bot reviews — handleKeydown / pickHighlighted now type-check at the call site against the correct component instance. * fix(frontend): scope removeMention's whitespace collapse to the mention site The trailing `.replace(/ +/g, ' ')` in `removeMention` was global, collapsing any pre-existing double-spaces in the prompt — e.g. a user typing `"hello world @foo bar"` lost their intentional formatting when they deleted the `@foo` badge. Rework the regex to match `(^|\s)@title(\s|$)` and decide per-match: - Mention at a boundary (no lead or no trail): drop entirely. - Mention in the middle: keep ONE bordering whitespace char (the leading one verbatim, so newlines/tabs aren't downgraded to spaces). No global pass over `instructions`. Unrelated whitespace stays intact. Reported by cubic-dev-ai on PR #9159 (07:27 review of 9e07eac4). * fix(frontend): expose DrillPicker.onFilterChange + lazy-load workspace kinds Both Codex P1s came from over-eager preload heuristics on my prior fixes: the workspace picker cold-loaded every configured kind on mount in internal-filter mode, and the chat badge popover never observed its own internal filter so workspace results were missing from search until the user drilled into Workspace. Replace both ad-hoc effects with a single `onFilterChange` callback on DrillPicker that fires whenever the EFFECTIVE filter (external or internal) changes: - [P1] WorkspaceItemDrillPicker: drop the "cold-load on mount when externalFilter === undefined" effect. Workspace kinds now load only once the user actually types something — closer to the pre-refactor behavior where the breadcrumb / "Open editor" pickers only fetched the drilled-into kind plus all kinds on search. - [P1] ChatContextPicker: handleFilterChange replaces the prior externalFilter-only effect. Badge-popover search (internal filter) now triggers the same preload as inline-mention search (external filter), so workspace results appear without needing to drill first. Both fixes reported by Codex on PR #9159. * fix(frontend): skip mention-removal sync when textarea is programmatically cleared sendRequest() sets `instructions = ''` immediately after dispatching to AIChatManager. The mention-removal effect treated this as user-initiated deletion and cleared selectedContext BEFORE AIChatManager.beforeSend snapshotted it — selected `@` contexts disappeared from the outgoing request. Skip the sync when value is empty; user-initiated mention deletes happen in-place against non-empty content. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(frontend): scope post-send wipe protection to the send path only Replace the blanket `if (value !== '')` guard on the mention-removal effect with an explicit `clearForSend()` export. `sendRequest()` now calls it instead of `instructions = ''`, so a user manually clearing the whole textarea still drops the corresponding context badges while the post-dispatch programmatic wipe is silent. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(frontend): extract useWorkspaceItemsLoader composable shared by both drill picker adapters WorkspaceItemDrillPicker and ChatContextPicker each duplicated the same machinery: loaded/loadingKind state seeded from the module cache, a stale-while-revalidate ensureLoaded coroutine with an untrack guard, a kind:/dir: scope-segment decoder, and the "load every kind once the user starts searching" filter callback. Move that to a single useWorkspaceItemsLoader() returning {loaded, loadingKind, ensureLoaded, ensureAll, ensureForScopeSegment, onFilterChange}. Adapters keep their own scope-walking policy (chat collapses an optional 'workspace' wrapper, workspace handles single-kind mode) but delegate kind decoding and lazy fetch to the composable. Net: -135 +28 LOC in the two adapters; +109 LOC in the new composable. The cache-version race, untrack discipline, and stale-while-revalidate semantics now live in one place. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(frontend): address Codex P1+P2s — non-context clear, same-title cross-removal, single-kind cold load P1: sendRequest() now clears `instructions` unconditionally after the optional `clearForSend()` so APP/NAVIGATOR/ASK/API modes (which don't mount ContextTextarea) still reset the input after send. P2: removeMention() now calls a new `unsyncMention(title)` on the textarea before stripping `@title` from `value`, so the mention-removal effect doesn't fire a second onRemoveContext on a same-title sibling (e.g. workspace_script + workspace_flow sharing a path). P2: single-kind WorkspaceItemDrillPicker loads its kind at mount even when scope is empty — buildWorkspaceTree collapses to the kind's children, so there's no kind row to drill into to trigger the load. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
6156e2372a |
fix: gate native integration pickers behind non-operator check (#9465)
Operators are read-only and cannot create native triggers, yet the google/github/nextcloud integration picker routes had no authorization gate, letting any workspace member drive the admin-configured integration's upstream API and enumerate its data (Drive files, repo names, calendars, events). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
44f5dd6636 | fix(frontend): respect forced column order for numeric column names (#9463) | ||
|
|
004339032e |
chore(main): release 1.719.0 (#9459)
* chore(main): release 1.719.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>v1.719.0 |
||
|
|
fbdf81ba5f |
fix: authenticate slack callback payload with per-workspace hmac (#9461)
* fix: authenticate slack callback payload with per-workspace hmac Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: regression tests for unauthenticated slack callback decryption Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: verify slack submission signature before resume + close workspace oracle Addresses review: verify private_metadata HMAC before handle_resume_action so a tampered/unsigned submission is rejected up front, and map get_workspace_key failure to the generic 401 so the status code is not a workspace-existence oracle. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: domain-separate slack payload hmac from resume-secret hmac Both MAC families key Hmac<Sha256> on the same per-workspace key; resume secrets are distributed to approvers in resume URLs, so add a fixed domain tag (slack_payload_v1) to the slack payload MAC to make the two non-interchangeable by construction rather than by byte-layout coincidence. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
6a15a9b152 |
fix(python): escape reserved-keyword step ids in wrapper codegen (#9460)
A flow inline step whose id is a Python keyword (e.g. `in`) crashed with a
`SyntaxError`: the wrapper emits `from {pkg} import {step_id} as inner_script`,
and `from x import in as y` is invalid Python.
The codegen already prefixes `_` to path segments that start with a digit
(`1234` → `_1234`); this extends that guard to Python hard keywords (`in` →
`_in`) in `compute_python_module_dir` and on the leaf in `compute_py_codegen`
and `prepare_wrapper`. The relative-imports write path inherits it for free.
Fixes #8893
|
||
|
|
e1e7af6a25 |
fix: prevent token label collision bypassing job read access control (#9462)
* fix: prevent token label collision bypassing job read access control Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: regression tests for token label collision job read access Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: bind job-read override fast-path to permissioned_as_email Replaces the reserved-label / label-* exclusion approach: webhook-/http-/email- labels are created through the public token API by the trigger panels, so they cannot be reserved, and blocking label-* regressed legitimate re-reads. Instead the username_override fast-path now requires the job's permissioned_as_email (non-forgeable, never derived from the label) to equal the caller's email. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
fad1a549d9 |
feat(otel): connect jobs to the inbound distributed trace (#9456)
* feat(otel): propagate inbound W3C traceparent to job spans Capture the inbound traceparent header at the run endpoints (WebhookArgs::to_args_from_format) into a reserved _wm_traceparent arg key (gated on OTEL_TRACING_ENABLED), riding the args jsonb like _ENTRYPOINT_OVERRIDE. At pickup, create_span_with_name attaches a span link from the job's worker span to the originating distributed trace, so a job triggered by an instrumented service is connected to the caller's trace while keeping its UUID-derived trace id (trace-by-job-id unaffected). The link/parse logic lives in the EE otel modules; this OSS side only captures the header and calls the (no-op outside EE) hook. Companion EE PR required. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: bump ee-repo-ref to inbound-trace-propagation EE branch Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(agents): don't attribute work to specific customers in repo content Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(otel): relocate job + script spans into the inbound trace Builds on the captured _wm_traceparent: the worker job span is re-parented on the inbound caller context, the script subprocess's TRACEPARENT env is the inbound context (so its spans join the caller's trace), and the context is propagated to flow steps so the whole flow relocates. Carried to the worker via a new LogContext.inbound_traceparent field. Non-inbound jobs are unchanged. Adds a relocation integration test. Companion EE PR required. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: bump ee-repo-ref to inbound-trace-propagation relocate commit Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(otel): harden inbound traceparent capture Address review feedback: - strip any caller-supplied _wm_traceparent from args/extra before stashing the header-captured value, so the reserved key is Windmill-controlled only - valid_w3c_traceparent: reject version ff and require lowercase hex, so we don't forward an inbound header that downstream OTel parsers would reject - clarify that the capture helper does not validate the W3C format (done at use) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to 2c7964460327fab5e3a27c0f74b8d6f26ab7f79a This commit updates the EE repository reference after PR #604 was merged in windmill-ee-private. Previous ee-repo-ref: 8fc04fb105dc49769205f7174d551a0d134d1bec New ee-repo-ref: 2c7964460327fab5e3a27c0f74b8d6f26ab7f79a Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
3887bf67dc |
chore(main): release 1.718.0 (#9450)
* chore(main): release 1.718.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>v1.718.0 |
||
|
|
90677872f6 |
fix: distinguish canceled jobs in runs (#9452)
* fix: distinguish canceled jobs in runs
* fix: order status=failure|canceled by completed_at to use partial index
The new `status` query param replaced the legacy `success=false` filter on
the Runs page, but the ORDER BY switch in list_completed_jobs_query only
flipped to v2_job_completed.completed_at for success==Some(false). With
status=failure|canceled (and success=None), the query fell back to ordering
by v2_job.created_at, which the partial index
ix_v2_job_completed_failure_workspace (workspace_id, completed_at DESC WHERE
status IN ('failure','canceled')) cannot serve.
EXPLAIN ANALYZE on 500k rows (1% failure/canceled): ordering by completed_at
uses the partial index (~150 buffers, 0.3ms); ordering by created_at scans
the v2_job created_at index and probes/discards 99% of rows via the join
(~49k buffers, 31ms). Switch the ordering to completed_at for
failure/canceled so the partial index serves both filtering and ordering.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test: trim order-by regression test to the failure/canceled case
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: only treat canceled as a terminal status icon for completed jobs
Guard the canceled branch in JobStatusIcon and getJobStatusKind with
`'success' in job` so a job that is still running while being canceled keeps
its running icon/favicon until it completes, instead of immediately showing
the gray Canceled state. Also clarify the openapi `status` param is an exact
match (status=success excludes skipped, unlike success=true).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
7590b28108 |
feat(sandbox): pull/extract images with crane instead of podman (#9455)
* feat(sandbox): pull/extract images with crane instead of podman (+ add to image)
The sandboxed container runtime (`# sandbox <image>`) only ever pulls + flattens an
image (nsjail does the run), so a full container engine is overkill — and podman was
never actually in any Dockerfile, so the merged feature couldn't run in the shipped
image. Switch to crane (google/go-containerregistry): a single ~25MB static binary,
no daemon/store/root/privileged.
- docker_v2.rs: crane export -> flattened rootfs tar, crane config -> OCI config,
crane digest -> content-addressed rootfs+config cache (cross-job dedup + automatic
freshness), crane manifest -> pre-download size guard. DOCKER_CONFIG authfile dir.
Cache eviction prunes the rootfs-tar cache by mtime (LRU). Pull policy honored via a
ref->digest cache (missing/never reuse without a registry hit).
- Dockerfile + docker/DockerfileSlim{,Ee}: install the crane binary (Full/FullEe and
the EE image inherit it via FROM the base image).
- docs + UI text + instance-setting descriptions updated (download size is compressed;
cache is the rootfs-tar cache).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(sandbox): address CI review — digest-pinned fetch, size cap on every job, eviction race
Codex P1s:
- Fetch by the resolved digest (name@digest), not the mutable tag, so content can't
diverge from the digest the cache is keyed under if a tag moves mid-fetch.
- Enforce the size cap on EVERY job via a cached {digest}.size sidecar (no registry call
on cache reuse), so lowering the limit rejects already-cached oversized images.
- Eviction race: hardlink the cache tar into the job dir before tar -xf (pins the inode
against concurrent eviction) and re-fetch if it was evicted first.
Claude P2s: atomic config sidecar (tmp+rename) + tolerate torn parse; soften the LRU
comment (mtime = creation order); sweep orphaned *.tmp.* and .size on eviction.
+digest_key/ref_key unit tests.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(sandbox): P1 cross-fs cache staging (EXDEV), Dockerfile arch fail-fast
CI re-review (Claude + Codex P1): the eviction-race hardlink crosses filesystems in the
shipped deployments — the cache is its own volume (/tmp/windmill/cache) while the job dir
is on the container fs — so hard_link returns EXDEV (not NotFound) and every sandbox job
fails. Fall back to tokio::fs::copy on a non-NotFound link error; copy reads through the
source inode so it still survives a concurrent eviction.
Also: Dockerfiles fail fast with a clear error on an unsupported arch instead of building
a 404 crane URL; ref->digest file written via tmp+rename (no torn read under missing/never).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(sandbox): say 'oldest by creation time' not 'LRU' for cache eviction
Codex P2: the code evicts by tar creation time (cache hits don't touch mtime), so the
user-facing docs + instance-setting text shouldn't claim true LRU.
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
9a609bf08a |
feat: make C# dotnet target framework configurable via DOTNET_TARGET_FRAMEWORK (#9454)
* feat: make C# dotnet target framework configurable via DOTNET_TARGET_FRAMEWORK Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: include dotnet target framework in C# binary cache key Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
1727271e19 |
feat: sandboxed daemonless container runtime via '# sandbox <image>' (#9453)
* feat: add sandboxed docker v2 runtime via '# docker <image>' Run a container image as a subprogram of the job's own nsjail sandbox: extract the image rootfs with podman (rootless) and run it chrooted inside the job's nsjail, so the container inherits the job's confinement and is safe under nsjail / for untrusted code. Selected by '# docker <image>'; a bare '# docker' keeps the v1 (dind) path untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: default to daemonless docker (drop dind from compose, allow docker on cloud) docker-compose no longer ships the dind sidecar (v2 is daemonless: podman + nsjail in the worker); removed the dind service, DOCKER_HOST env, depends_on and volume. Removed the language-picker guard that blocked Docker scripts on the multi-tenant platform, now that v2 makes docker safe to run sandboxed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: select sandboxed container via # sandbox <image>; add pull policy + size guards - Surface moved from '# docker <image>' to '# sandbox <image>' (groups under the sandbox annotation; '# docker' stays v1-only, '# sandbox' stays nsjail-bash). - SANDBOX_IMAGE_PULL_POLICY (default 'newer') so moving tags don't go stale. - SANDBOX_IMAGE_MAX_SIZE_MB rejects oversized images before extraction. - SANDBOX_IMAGE_CACHE_MAX_MB best-effort LRU eviction of podman's image store. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sandbox): support # volume, honor nsjail tmp instance settings, v2 docker template - Thread shared_mount into the sandbox container nsjail config so '# volume' mounts (and the same-worker /tmp/shared folder) apply inside the container. - Use resolve_nsjail_tmp_mount_block for the container's /tmp so it honors the same nsjail_tmp_backing / nsjail_tmpfs_size_mb instance settings as other nsjail jobs. - docker-compose comment + the editor's Docker template now use '# sandbox <image>'. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sandbox): make image size/cache/pull-policy UI instance settings Convert SANDBOX_IMAGE_* from worker env vars to DB-backed instance settings (sandbox_image_max_size_mb, sandbox_image_cache_max_mb, sandbox_image_pull_policy), hot-reloaded via the same mechanism as nsjail_tmpfs_size_mb and configurable in #superadmin-settings. No worker restart needed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sandbox): windmill-managed registry — default registry + private auth Two new instance settings: - sandbox_image_default_registry: prepended to unqualified image refs (alpine -> <registry>/alpine); fully-qualified refs untouched. - sandbox_registry_auth: docker/podman auth.json blob written to a per-job authfile (0600, removed with the job) and passed to podman --authfile for private registries. Both hot-reloaded and configurable in #superadmin-settings. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sandbox): protobuf-safe proto_str escaper, atomic 0600 authfile, registry tests Addresses local-review P2s: proto_str now emits valid protobuf octal escapes for control/non-ASCII bytes (not Rust \u{..} that nsjail would reject); the registry authfile is created 0600 atomically (no world-readable window); add a registry_qualified table test + a non-ASCII proto_str case. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sandbox): P0 — deliver image env via nsjail envar:, never the launcher process env CI review (P0): the image's OCI Env (attacker-controlled keys+values) was applied to the nsjail launcher process via .envs(), so a hostile image could set LD_PRELOAD/ LD_LIBRARY_PATH/LD_AUDIT on nsjail itself and execute code as the worker outside the jail. Now the image env is rendered as proto-escaped 'envar:' directives (child-only) and nsjail's process env carries only windmill-trusted keys (reserved vars + proxy). Also: warn instead of silently bypassing the size guard on inspect failure; reset the eviction guard via a Drop guard (no stuck flag on panic/early-return). +render_envars test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sandbox): P0 symlink-write escape via rootfs script; P1 redact registry-auth logging CI review: - P0 (Codex): the body was written into the image-controlled rootfs as .windmill_docker_main.sh via write_file (follows symlinks) — a hostile image could plant that path as a symlink to a host file and capture the worker's write before nsjail starts. Now the body is passed straight to 'sh -c <body> sh <args>'; no file is written into the rootfs at all. - P1 (Codex): sandbox_registry_auth flowed through the generic setting loader which logs the value (raw auth.json credentials). Replaced with a secret-aware reload that loads directly and logs only a redacted 'configured=' message. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sandbox): redact sandbox_registry_auth in instance-settings write log too The settings API also logs 'Set global setting <key> to <value>' via format_setting_value; add sandbox_registry_auth to SENSITIVE_SETTINGS so the credential is redacted there as well as on reload. * fix(sandbox): don't silently disable cache eviction on podman images parse error Re-review (cubic/Claude P2): serde_json::from_slice(...).unwrap_or_default() meant any parse hiccup (e.g. podman omitting Size/Created via omitempty for a zero value, or schema drift) silently degraded to an empty Vec and disabled eviction with no log. Now Size/Created are #[serde(default)] (a missing omitempty key -> 0, not a whole-array parse failure) and a real parse error warns + breaks instead of being swallowed. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
fb175e1c9d |
fix ee repo ref dynamic oauth urls (#9451)
* ee repo ref * fix(ee-ref): pin to EE commit that includes read_only create_session_token fix The previous pin (f7a83d9) carried only the connect_config_template change and dropped Ruben's read_only=false fix (EE 3742e06). CE #9371 made create_session_token require 6 args, so the EE overlay fails check_ee_full with an arity error without it. Bump the pin to 9be38de, which includes both fixes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to fb106b89cdf4088b004dac6062adb029f3923887 This commit updates the EE repository reference after PR #603 was merged in windmill-ee-private. Previous ee-repo-ref: 9be38def879f702cd0b134d9e71bbb17fbb9cfa4 New ee-repo-ref: fb106b89cdf4088b004dac6062adb029f3923887 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
fee23a5185 | threat_model v0 | ||
|
|
00a96b82f3 |
add databricks icon (#9445)
Adds DatabricksIcon.svelte (brand mark, #FF3621) and registers it under `databricks` in the shared APP_TO_ICON_COMPONENT map, so both the app and hub frontends pick it up for the new Databricks hub integration. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev> |
||
|
|
dad2bd0b93 |
add adobe acrobat sign icon (#9447)
Adds AdobeAcrobatSignIcon.svelte and registers `adobe_acrobat_sign` in APP_TO_ICON_COMPONENT, for the Adobe Acrobat Sign hub integration (windmill-labs/windmill-integrations#143). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
93a74f229a |
oauth: add ServiceNow + make per-instance OAuth providers registry-driven (#9449)
* oauth: add ServiceNow provider; make per-instance OAuth registry-driven
ServiceNow's OAuth endpoints are per-instance
(https://<instance>.service-now.com/oauth_auth.do + /oauth_token.do), like
Snowflake's. Rather than add another bespoke special-case, generalize:
a registry entry may carry a `connect_config_template` (label/placeholder/
help_url + {instance}-templated auth_url/token_url + req_body_auth +
optional extra_params_key/strip_suffix). The instance-settings UI renders
one generic instance-name input for any such provider and substitutes
{instance} to build the per-client connect_config — a new per-instance
provider needs only a JSON entry, no frontend code.
- oauth_connect.json: servicenow + snowflake_oauth now carry a
connect_config_template (snowflake keeps its account_identifier
extra_params key for backward compatibility).
- windmill-oauth: add the ConnectConfigTemplate struct (frontend-only
metadata; the backend's existing connect_config override resolves the
concrete URLs generically — no other backend change).
- AuthSettings/InstanceSettings: replace the Snowflake + ServiceNow
special-cases with one registry-driven path (instanceInputs map,
setupTemplatedOauthUrls, loadInstanceInputs); per-instance providers are
derived from the registry for the builtins list + dropdown.
Pairs with windmill-integrations#139 (ServiceNow hub integration).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: point ee-repo-ref at servicenow-oauth EE branch (revert at merge)
Temporary CI pointer so check_ee_full / cargo_test build against the EE
slack-literal fix (windmill-ee-private#602). Revert to a pinned SHA once
that EE PR is merged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
eb55356018 |
add wiz icon (#9448)
Wiz star logomark (brand blue #0254EC) for the shared icon map (APP_TO_ICON_COMPONENT), for windmill-integrations#144. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
f2f0812a04 |
feat(flows): opt-in to include the stopping step's result in early-stop errors (#9446)
* feat(flows): early stop can include the stopping step's result in the raised error
When a step uses Early Stop with "Raise an error message if stopped", the
flow result was entirely replaced with a static error object
({"error": {"name": "EarlyStopError", "message": "..."}}), discarding the
stopping step's own output. This made it impossible to stop+fail a flow
while preserving the data the step produced (e.g. an API that returns
HTTP 200 with a userErrors payload).
Add an opt-in `error_include_result` flag on StopAfterIf. When enabled on
the raise-error path, the raised payload becomes
{"error": {...}, "result": <step result>} instead of dropping the result.
Default is false, so existing behavior is unchanged. The option is threaded
through the worker's stop-after-if handling (including stop_after_all_iters_if
for loops/branchall) and exposed in the flow editor's Early Stop panel.
Fixes WIN-2012
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(flows): cover early-stop error_include_result payload shaping
Add a regression test asserting that a step using Early Stop with a raised
error message and error_include_result=true fails the flow while preserving
the step output as {"error": {..}, "result": <step result>}, and that with
the flag off the result is the bare {"error": {..}} object.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(flows): nest early-stop step result inside the error object
Embed the stopping step's result under `error.result` rather than as a
top-level sibling of `error`. This keeps the flow result shape as
`{ "error": { .. } }` — identical to a normal error — so consumers that
key off the top-level shape (single `error` key) keep working, while the
data is still preserved for those that look inside the error object.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(flows): always include the stopping step's result in early-stop errors
Drop the opt-in `error_include_result` gate. Since the step result is nested
inside the error object (`error.result`), the top-level result shape stays
`{ "error": .. }` — identical to a normal error — so consumers that detect or
parse failures by the top-level shape are unaffected. Gating it added schema
surface, plumbing, and a UI toggle for no real compatibility benefit.
Now, whenever a step early-stops with a raised error message, the flow fails
and the raised error embeds the stopping step's own result under
`error.result` (aggregated iteration results for loops/branchall). This
reverts the `StopAfterIf.error_include_result` field, its threading, the
OpenAPI/generated-client surface, and the editor toggle; the "Raise an error
message" tooltip now notes that the step result is included.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(flows): gate early-stop result inclusion behind opt-in flag
Re-introduce the per-step `error_include_result` flag (default off) instead
of always embedding the step result. Although nesting the result under
`error.result` keeps the result *shape* backward-compatible, it does not
address data exposure: a failed flow's result is propagated to synchronous
webhook callers, the flow's failure module, and the workspace/global error
handler (commonly a Slack/email/outbound-webhook notifier). Always including
the step output would surface previously-redacted intermediate data to all of
those sinks for every existing error-stop flow.
Gating keeps the existing behavior (bare `{ "error": .. }`) as the default and
only embeds `error.result` when the flow author explicitly opts in, matching
the original issue's intent.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(flows): omit error_include_result when false; refresh generated prompts
- Add `skip_serializing_if = "is_false"` to `StopAfterIf.error_include_result`
so serialized flows are byte-identical when the flag is off. Fixes the
`flowmodule_serde` round-trip test (cargo_test) and avoids churn on existing
flows.
- Regenerate `system_prompts/auto-generated/` and `cli/src/guidance/skills.gen.ts`
for the new OpenFlow `error_include_result` property. Fixes check-freshness.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(flows): cover error_include_result for the loop "stop after all iters" path
Add a regression test for the stop_after_all_iters_if branch, where `nresult`
already holds the aggregated iteration results — confirming `error.result`
carries each iteration's output (distinct from the per-step fallback path).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
c1a8250340 | Merge branch 'main' into workflow-execution-time-display | ||
|
|
24fa61d3c0 |
chore(main): release 1.717.1 (#9444)
* chore(main): release 1.717.1 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>v1.717.1 |
||
|
|
f595787409 |
fix: invalidate relative-import cache when imported script changes (#9443)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
6b6c16e6bc |
chore(main): release 1.717.0 (#9439)
* chore(main): release 1.717.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>v1.717.0 |
||
|
|
b5a6a1eeab |
fix(cli): push whole raw app instead of treating frontend files as scripts (#9442)
* fix(cli): push whole raw app instead of treating frontend files as scripts Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(cli): shorten raw-app handleFile comment Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
819ba5e150 |
fix: read latest db draft for scripts/flows in global mode read tool (#9441)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
83cd26ee2e |
fix(backend): report wall-clock duration for workflow-as-code roots
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
468aa230e5 |
refactor: resolve workspace imports via /f/,/u/ not $f/,$u/ aliases (#9438)
* refactor: resolve workspace imports via /f/,/u/ not $f/,$u/ aliases Keep the CLI managed tsconfig.wmill.json / `refresh tsconfig` / Deno import-map QoL from #9378, but re-key it on the existing /f/,/u/ workspace paths instead of the new $f/,$u/ specifiers. Verified /f/,/u/ resolves in tsc, Bun, Deno, the in-app ATA editor, and the worker, so the $-prefixed alias added no value. Drop the $f/,$u/ handling from the parser, dep-map, deno_executor, bun loaders, ATA, relative_imports and monaco paths; revert the windmill-parser-wasm-ts bump (1.714.0 -> 1.695.0). Also fold in the cli/package-lock.json sync for the already-committed pg-gateway dependency. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: drop duplicate relative-path check and restore rustfmt formatting Follow-up cleanups to the previous commit's full-file reverts, which restored pre-#9378 state that main had since improved: - relative_imports.ts: remove the redundant duplicate d.startsWith('/') (pre-#9378 had it; #9378 had repurposed that line, so main has no dup). - windmill-parser-ts/src/lib.rs: restore the multi-line new_source_file(...) formatting required by backend/rustfmt.toml (the single-line revert would fail `cargo fmt --check`). Now differs from main only by the $f//$u/ removal. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
e4e0984e55 |
feat: let flow AI chat create and edit sticky notes (#9412)
* feat: let flow AI chat create and edit sticky notes Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: strengthen flow AI guidance to prefer groups for organizing flows Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: harden flow note validation (validate position/size, document color default and group acceptance) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: make AI-created free notes draggable by seeding default position and size Free notes need explicit geometry to be draggable/resizable in the editor; UI-created notes always set position+size but agent-created notes omitted both, so they couldn't be moved until resized. Seed defaults in validateFlowNotes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |