mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-19 00:02:03 +00:00
change-e93fb9ed
13520 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
adaf8c389e |
fix(frontend): surface schedule args missing from the runnable schema
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
5508f1da9c |
feat(frontend): View Diff and in-place Load for other users' drafts (#9621)
* feat(frontend): replace other-user draft "View JSON" with "View Diff" Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(frontend): replace other-user draft "Fork" with in-place "Load" Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(frontend): detect first overlay edit by value divergence, not a timer Replaces the 700ms arming timer (which leaked across sessions and silently swallowed sub-window edits) with a deterministic check: a blocked save opens the overwrite prompt only once the cell value diverges from the loaded value. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): overlay leak on revisit, diff z-index, home-popover edit affordances - Clear a stale "editing another user's draft" overlay when its editor is reloaded without a fresh Load, so returning to the item edits our own draft. - Open View Diff above the others-drafts modal (close it first) instead of rendering the drawer behind it. - Add an Edit button to our own row in the home draft popover; use a pencil icon (not a download) for Load. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: admin "Migrate" action for legacy drafts (delete / assign to self) Adds an admin-gated `POST /drafts/migrate_legacy/{kind}/{path}` endpoint to resolve pre-migration workspace-level drafts (email NULL): delete the row, or move its value onto the admin's own row. Surfaces a "Migrate" button on legacy rows in the home-page draft popover and the in-editor others-drafts modal (workspace admins / superadmins only), opening a modal with Delete and Assign to self. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): close home draft popover before opening View Diff / Migrate The hover popover sits above the diff drawer and migrate modal (z-index), so it covered them. Close it first so they render on top. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): remount the flow builder on "Reset to draft" from an overlay FlowBuilder captures the flow at mount, so reloading the value alone left the foreign graph on screen — reset appeared to do nothing. Force a remount (renderEditor=false → loadFlow) like navigation does. Scripts (imperative setCode) and apps (redraw++) already remount, so only flows needed this. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): refresh the home row after migrating a legacy draft invalidateAll() didn't refetch the home list (it loads items client-side), so the legacy badge entry lingered after delete / assign-to-self. Bubble an onMigrated callback up to the row's `change` event, reusing the same reload chain (Item → ItemsList loadScripts/Flows/Apps) as delete/archive. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * nit * nit * fix(frontend): match app overlay baseline to the migrated value AppEditor migrateApp()s the app on mount, so the draft cell settles to the migrated value. The overlay used the raw loaded value as the divergence baseline, so a post-mount mirror write could trip "Overwrite your current draft?" before any edit. Migrate the baseline too (like the deployed-baseline and raw_app bundle do) so it matches the settled cell. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): address review on legacy-draft migrate + overlay - Legacy "Assign to self" now confirms before replacing an existing own draft (MigrateLegacyDraftModal gains an `ownDraftExists` step, threaded from the home badge and the in-editor others-drafts modal). - Gate overlay mode on a per-response `hasOwnDraft` instead of the sticky `loadedFromDraft`, so navigating to a no-own-draft item in the same editor route can't wrongly enter overlay. Fixed in all 4 editor routes. - Raw-app "View Diff" now projects the deployed app into the flat draft-bundle shape (via a shared `extractDataConfig`) instead of diffing `.value` against the bundle, so the drawer shows a real diff. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
3eeccaf968 |
feat: add ducklake schema support to the database manager (#9633)
* feat: add ducklake schema support to the database manager Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: support schema in wmill.ducklake("name:schema") template helper Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: preserve schema when parsing ducklake asset/favorite paths Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: regenerate system prompts for ducklake schema syntax doc Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
25a891041d |
wire DB-backed autosave into the whitelabel flow SDK (#9637)
* fix(frontend): wire DB-backed autosave into the whitelabel flow SDK FlowWrapper (the @windmill-labs/components flow editor entry) was never updated after DB-backed user drafts moved autosave wiring to the page layer, so the SDK editor had no autosave and never rendered the AutosaveIndicator. Back the bound store with a per-user UserDraft handle (workspace-guarded so it no-ops before a workspace exists) and pass liveEditorDraftStoragePath so the indicator and Ctrl/Cmd+S flush engage. Also set $workspaceStore on the /test_dev/sdk_flow harness page, which lives outside the (logged) layout and so had an empty workspace store (mirrors the sibling sdk_resource page). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(frontend): shared test_dev header to log in + set the SDK token Add a common TestDevHeader (rendered by a test_dev/+layout) that logs in (email/password → bearer token), lets a token be pasted/set manually, picks the workspace, loads the user, and persists the session across reloads — mirroring the React SDK's initializeClients. test_dev routes live outside the (logged) layout, so this is the single place that wires OpenAPI.TOKEN + workspaceStore + userStore for the SDK demo pages. Drop the now-redundant per-page workspace/user wiring from sdk_flow. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(frontend): reuse usePageDraftSync in the flow SDK instead of a parallel copy FlowWrapper hand-rolled UserDraft.useMany + a manual seed effect, duplicating the core of usePageDraftSync but dropping recordRemoteSync/seedBaseline/discardIf — a divergence that would drift. The only reason it couldn't reuse the helper was that useReactive passes workspace straight into useMany, whose reconcile called resolveWorkspace() (which throws) before the detached-handle check. Make reconcile resolve the workspace without throwing and treat an absent workspace like an empty path — handing out a detached, local-only handle that re-keys into a real entry once the workspace resolves. FlowWrapper then reuses usePageDraftSync directly, keeping one code path for the page and SDK editors. Seed via the spec's defaultValue (threaded through usePageDraftSync -> useReactive -> useMany, captured once on first acquire and swallowed by the syncer's seed guard) rather than a manual first-write effect, dropping the fragile skipNextWrite assumption and the seededPath bookkeeping. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): wire DB-backed autosave into the whitelabel script SDK ScriptWrapper had the same gap FlowWrapper did: ScriptBuilder delegates its draft handle to the page (it only stop/restart-syncs and flushes by userDraftPath), so the SDK's plain `bind:script` never reached a UserDraft handle — no autosave, no indicator. Back it with usePageDraftSync<script> (bind:script={draftSync.draft}, userDraftPath), seeded from the consumer's script via defaultValue. Same one-code-path reuse as the flow SDK. AppWrapper needs no change: AppEditor already self-acquires its handle (UserDraft.use('app', ...)), so apps autosave already — and now also tolerate mounting before login via the reconcile change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): gate SDK editors on a resolved workspace Before a workspace exists the draft handle is detached (local-only); editing into it and then having the workspace resolve re-keys to a fresh real entry seeded from the original value, silently dropping those edits. Gate the flow, script, and app SDK editors on `$workspaceStore` so no editing happens until the real draft key exists. Embedders set the workspace before rendering (React SDK initializeClients); the test_dev header sets it on mount. AppEditor additionally acquires its handle at init from a non-reactive workspace, so gating AppWrapper also ensures it mounts with the workspace already set rather than permanently detached. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(frontend): add sdk_app test_dev page for the app editor SDK Exercises AppWrapper the same way sdk_flow/sdk_script exercise their editors, under the shared TestDevHeader. Confirms the app editor's self-managed autosave + AutosaveIndicator work via the SDK wrapper. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
3c0e38b589 |
fix(git-sync): bump default sync script to hub/28719 (windmill-cli 1.728.1) for WAC modules (#9649)
Points LATEST_GIT_SYNC_SCRIPT_PATH at the republished sync-script-to-git-repo (windmill-labs/windmill-integrations#155) pinning windmill-cli@1.728.1, which carries the gitSyncIncludePattern __mod/** fix (#9606). On-deploy git-sync was running windmill-cli@1.713.2 and filtered workflow-as-code (WAC v2 / module) scripts stored under <path>__mod/ out of the deploy pull, so they never reached the repo. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
e26a9239a6 |
feat: zero-setup oauth client credentials for registry providers (#9559)
* feat: zero-setup oauth client credentials for registry-declared providers Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: support client-credentials-only custom oauth providers Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add coupa client credentials provider to oauth registry Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: clarify oauth resource connect auth-method selection Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: support shared instance-level oauth client credentials Admins can designate an instance OAuth entry's credentials as client credentials; the connect dialog then runs the exchange server-side with them instead of asking each user for their own. Replaces the per-provider "Support Client Credentials Flow" toggle with a grant-type selector. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore: update ee-repo-ref to be9f23b2c06b8b6ee0cd3e4d9f16bcd9e90129fb This commit updates the EE repository reference after PR #613 was merged in windmill-ee-private. Previous ee-repo-ref: 05643cbbc8c1bebf3509c691c5811b4057d96485 New ee-repo-ref: be9f23b2c06b8b6ee0cd3e4d9f16bcd9e90129fb Automated by sync-ee-ref workflow. * feat: allow both grant types on an instance oauth entry Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: bring-your-own oauth credentials from the others section Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: segmented oauth grant-type selector, always show grant Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: enable client credentials for 5 more oauth providers Verified against official docs: bitbucket, linkedin, spotify, xero and zoho support the standard client_credentials grant with a plain client_id + client_secret, compatible with Windmill's token exchange. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: hide create-manually link on the managed oauth connect path Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: enable client credentials for salesforce and servicenow Salesforce CC requires the org's My Domain token endpoint (login.salesforce.com is unsupported for that grant), so add an optional cc_token_url registry field that the connect form prefills for the client-credentials path instead of the shared token_url. ServiceNow uses the same instance host for both grants, so it only needs its token URL and req_body_auth surfaced at the top level. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: add instance-level client-credentials token url override Some providers use a per-org/instance-specific token endpoint for the client-credentials grant that differs from the authorization-code URL. Add an optional cc_token_url on the instance OAuth entry, surfaced in instance settings (prefilled from the registry template) when client credentials is selected, and used for the CC exchange and refresh while auth-code keeps its own token URL. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * style: remove redundant grant-type tags from oauth auth cards Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor: extract reusable RadioCard component for the oauth auth chooser A token-based selectable card (label, description, selected, onSelect, optional icon) replacing the inline cards in the connect dialog. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: hide sign-in option on the bring-your-own oauth path Picking a provider from "Others" means bring your own credentials, so the auth-code "Sign in" card (which uses the instance client) no longer shows there — it goes straight to the client-credentials form. The two-flow chooser stays on the instance-configured path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: restrict client-credentials token url to caller-supplied creds Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: resolve client-credentials id and secret all-or-nothing Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: host-pin client-credentials token url via instance-name input For registry providers whose CC token URL is instance-templated (Coupa, Salesforce My Domain, ServiceNow), the connect dialog and instance settings collect an instance name and the backend substitutes it into the fixed-host template, validating it as a hostname label. A free-form token URL is no longer accepted for these providers, so the exchange host cannot be redirected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: client-credentials token url always comes from the registry Bring-your-own CC is registry-only: the token URL is resolved server-side from the built-in registry (host-pinned via an instance name for templated providers, the fixed registry URL otherwise) and rejected for custom resource types. The caller-supplied token URL field is removed from the connect dialog and the API. Adds unit tests for the resolver. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: address CC review - sandbox CC config and instance-templated providers Resolve `_sandbox` provider keys to the parent registry entry in the instance settings and connect-dialog helpers, so salesforce_sandbox (and future sandbox entries) can enable client credentials. Use the effective CC token URL template (cc_token_url or token_url) so the instance-name field works for Coupa/ServiceNow, and hide that field when a connect_config_template already owns the instance input (ServiceNow). Document the authorization contract on resolve_instance_cc_credentials. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor: unify instance-templated oauth onto connect_config_template Remove the separate cc_token_url and cc_instance config fields. An instance- templated provider now declares one connect_config_template (auth_url optional for client-credentials-only providers like Coupa); the CC flow reads its token URL, label and strip_suffix to host-pin the exchange. Coupa and ServiceNow move to connect_config_template; Coupa stays drawer-only (no auth_url -> excluded from instance settings). Salesforce CC is removed for now (its auth-code/CC host split needs the endpoint-profiles model). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: cc_scopes defaults and instance config for client credentials Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: store empty auth_url for cc-only templated oauth providers Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: address review nits - sandbox key lookup, template doc, deref specs Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: default shared client-credentials connect to cc_scopes Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: support bring-your-own client credentials for instance-configured providers Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor: move oauth grant-type help into per-option tooltips Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: keep instance-configured oauth providers selectable from Others Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: preserve admin-configured scopes for custom client-credentials providers Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: use cc scopes on cc refresh and enforce cc grant for bring-your-own Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: require {instance} in leftmost host label for cc token url templates Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: drop token_url from unauthenticated get_connect response Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: fill byo templated resource args from the entered instance Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to 136f4634aca61e74ccb045372358a1e3f6b23e75 This commit updates the EE repository reference after PR #616 was merged in windmill-ee-private. Previous ee-repo-ref: b5083e266492e908456e39401778a9cdcea46e94 New ee-repo-ref: 136f4634aca61e74ccb045372358a1e3f6b23e75 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> |
||
|
|
ba69d8147b |
fix(frontend): show AI sessions when AI unconfigured, with disabled chat (#9644)
Previously the AI sessions sidebar section was hidden entirely when AI was not configured at the workspace level. Now the section stays visible and the per-session chat input is disabled with an explanatory message, mirroring the sidebar AI chat behavior. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
e87ff79ecf |
fix(ai_evals): adapt global eval harness to DB-backed user drafts (#9641)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
e80c62b958 |
docs(cli): improve generate-metadata guidance, fix description parser (#9635)
* docs(cli): improve generate-metadata guidance, fix description parser Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(cli): surface dependency version bumps after generate-metadata Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(cli): explain generate-metadata scope, import cascade, and --dry-run troubleshooting Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
8021775f5f |
fix(drafts): preserve original timestamp when migrating localStorage drafts (#9638)
The localStorage→DB user-draft migration upserted via /drafts/update, whose SQL always stamped created_at = now(). Every migrated draft therefore resurfaced to the top as freshly created, regardless of its real age. Add an optional created_at override to the update_draft request, threaded into the upsert as COALESCE($8, now()) / created_at = EXCLUDED.created_at. Normal saves omit it and still stamp now(); the migration passes the draft's original write time (or epoch 0 when unknown) so migrated drafts keep their age. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
1d87ca5958 |
address codex review (app draft no-op, view-only diff, comment) (#9639)
Three issues from the Codex PR review of the low-code app deploy + summary work: - [P1] The summary mirror onto the autosaved App value broke the autosave's no-op detection for deployed apps: `discardIf` compares the live value against the deployed baseline, but the baseline (the deployed App value) carried no summary while the live value now always does — so a draft reverted to the deployed state never compared equal and a no-op draft was persisted instead of deleted. Carry the deployed summary onto the baseline so the comparison matches (a summary-only edit still counts as a real change). - [P2] "Show diff" stayed enabled for view-only (`mine=false`) rows in the "Show all drafts" view, but the diff only fetches the current user's draft overlay — wrong diff for another user's deployed-row draft, 404 for their draft-only row. Hide it for foreign rows; own/legacy rows keep it. - [P2] Reword the `rawAppDraftValue` doc comment to state the current invariant (must read a draft's top-level `files`) instead of referencing past drafting history, per AGENTS.md. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
e09cd5862c |
feat: per-user draft review & deploy page (gating, badges, rename, raw-app deploy fixes) (#9625)
* feat: per-user draft gating, badges and rename display on deploy page Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): don't strike the path when a draft adds a summary to a summary-less item Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): don't strike draft-only items' auto-generated path against the pretty path Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): deploy raw-app drafts from top-level files so the bundle isn't dropped Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(frontend): share raw-app source→draft-value projection across chat and deploy page Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): deploy renamed/new flow, app and raw-app drafts at draft_path, not the temp storage path Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(frontend): add a design-system Checkbox and use it for deploy-page row/select-all checkboxes Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: "Show all drafts" toggle on the deploy-drafts page Replace the deploy-drafts page's legacy-hiding "Only my drafts" toggle with a "Show all drafts" toggle that switches the listing scope between the current user's own drafts (+ legacy no-owner rows) and every user's drafts in the workspace. Backend (`drafts.rs`, `openapi.yaml`): - `/drafts/list` gains an `all_users` query param that drops the owner filter, and a per-row `mine` flag (own draft or legacy no-owner row). `DISTINCT ON` now prefers the user's own row, then the legacy row, then another user's, so `mine`/`legacy_draft` describe the kept row. Frontend (`CompareDrafts.svelte`, `workspaceDrafts.svelte.ts`): - "Show all drafts" toggle (default off). The all-users superset is fetched lazily via the shared resource only while the toggle is on, so the page's fork draft-count (own drafts) is unaffected. - Other users' drafts are view-only: disabled checkbox + Discard with a "belongs to another user" tooltip; Show diff stays enabled. Selection, select-all and the deploy count only ever include the user's own drafts. The multi-user warning triangle shows on owned rows only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(backend): gate all_users draft listing by read permission Addresses the PR review on the per-user deploy-drafts page: - `/drafts/list?all_users=true` previously had only `WHERE workspace_id = $1` with no read-permission check, so any non-operator could enumerate every draft's path, summary and authors — including items they can't read. Now rows the caller doesn't own (`mine = false`) are gated through `require_can_read_path` (the same gate `/drafts/get` uses) and dropped when unreadable; both its `NotFound` and `NotAuthorized` denials are treated as "not visible". - Skip the per-row `require_can_write_path` probe on those non-owned rows (they're never selectable — `isSelectable` requires `mine`): set `can_write = false` directly, removing a redundant N RLS write-probes when `all_users` is on. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): only confirm destructive draft discards on the deploy page Discarding a draft is non-destructive in every case except removing the last draft of a never-deployed item (`draft_only` with no other user's draft), which permanently deletes it. Confirm only that case; reverting a draft over a deployed item, or discarding your copy while another user still holds a draft, now runs immediately (the ⚠️ already signals the multi-user case). Drops the redundant "other users still have a draft" / "deployed version unaffected" confirmation branches. Harden the destructive check: it keyed off `otherDraftUsers()`, which subtracts `currentUsername`; while `$userStore.username` is unhydrated, your own draft looked like another user's, flipping a draft-only item to "non-destructive" and deleting it with no confirmation. Now: deployed counterpart → never destructive; `draft_only` with unknown `currentUsername` → treated as destructive (confirm). The delete modal also shows the friendly `draft_path` instead of the raw `draft_{uuid}` storage path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): deploy low-code app drafts (value + summary persistence) A visual (low-code) app draft is autosaved as the *bare* App value (grid/theme/... plus a draft-only `draft_path`), not wrapped in { value, summary, policy } like script/flow drafts. The Review & Deploy page read `requestBody.value = d.value` — undefined for that shape — so deploying any low-code app draft (created or edited) sent no value and failed. Read the value from the draft object itself, strip the draft-only `draft_path` from it, and use that as the deploy path. Also persist the app summary, which was dropped entirely: the autosave stores the bare App value (the summary normally lives only in the `app` table column, set on deploy), so a draft never carried it — reopening a draft or deploying it lost the summary. Mirror the summary onto the autosaved App (like `draft_path`), read it back when loading a draft, and on deploy send it as the summary column while stripping it (and `draft_path`) from the deployed value so the value stays clean. Verified end-to-end: a new low-code app with a summary deploys at its pretty path with the summary set, content intact, and no draft_path/summary leaked into the deployed value; the draft is cleaned up. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
b67c8cf42b |
fix(frontend): render Modal2 dialogs above the AI chat panel (#9636)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
f4425fca9f |
feat(ai-chat): self-hosted docs tools via windmill.dev llms.txt + ask benchmark (#9578)
* feat(ai-chat): add self-hosted docs tools fetching from windmill.dev llms.txt Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(ai-evals): add ask benchmark mode comparing inkeep vs llms.txt docs tools Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(ai-chat): fix docs link sanitizer tests to match skip-all-`../` guard Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(ai-chat): add hybrid full-text docs search tool and ask variant Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(ai-chat): expose docs search tools in the global workspace assistant Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor(ai-chat): drop inkeep/llmstxt arms, keep only hybrid docs search Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(ai-chat): remove docs-tool benchmark write-up Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor(ai-evals): remove ask mode, cover docs search via global mode Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * nits * refactor(ai-chat): swap navigator + api copilots from inkeep to search_docs Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ai-chat): point read_docs_page empty-path hint at search_docs Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
51bd8692a4 |
feat: queue messages typed while ai chat is streaming (#9525)
* feat(frontend): queue messages typed while ai chat is streaming * fix(frontend): avoid losing queued chat messages on send early-return * test(frontend): cover queued chat message semantics in AIChatManager * fix(frontend): complete ChatLoopResult mock in queued message tests * feat(frontend): single appendable queued message, send on cancel * fix(frontend): only auto-send queued message on a user cancel, not programmatic * chore(frontend): remove queued-message dev preview page * fix(frontend): clear queued chat message on conversation switch |
||
|
|
2523465009 |
fix(frontend): don't save drafts on leave when auto-save is off, warn instead (#9630)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
e6b45c4eee |
chore(main): release 1.728.1 (#9628)
* chore(main): release 1.728.1 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>v1.728.1 |
||
|
|
86d1d160f0 |
fix(cli): fall back to esbuild-wasm on native host/binary mismatch (#9629)
* fix(cli): fall back to esbuild-wasm on native host/binary mismatch Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(cli): guard tarball extraction, extend esbuild-wasm fallback to script bundling Address CI review: prevent tar-slip in esbuild-wasm package extraction, route codebase/script and inline-rawscript bundling through getEsbuild() too, and move the loader to utils. Add a unit test for the tar-slip guard. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(cli): make esbuild-wasm fallback concurrency-safe Address CI review (P1): memoize getEsbuild() on an in-flight promise so concurrent first callers (parallel wmill sync push) share one probe/download instead of racing, and give each extraction a unique temp dir so concurrent extractions can't clobber each other. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
8a3f69dda8 |
fix(backend): purge workspace_diff cache on workspace delete (#9627)
* fix(backend): purge workspace_diff cache on workspace delete Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(backend): add sqlx cache for workspace_diff regression test queries Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(backend): clear stale fork diff state on fork creation and backfill Purge inherited workspace_diff/skip_workspace_diff_tally rows when a fork is created (reused ids would otherwise leak a prior occupant's cached diff state), and extend the cleanup migration to drop live-pointing stale skip rows that short-circuit compare_workspaces before the has_changes reset. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
e4bfeb29bc |
fix(frontend): persist session-editor draft path/summary edits + per-line diff tooltips (#9622)
* fix(frontend): persist raw-app draft path edits in the session editor Renaming a raw app's path in the session preview editor never triggered a draft save: the header surfaced the typed path as `pendingDraftPath`, but RawAppEditorView ignored it (it never reached runtime.rawApp.val), and the RawAppDraft codec didn't serialize a path field — so the autosave signature (JSON.stringify(draft)) was unchanged and nothing was written. The rename was lost and the home/review/Drafts lists kept the original `draft_path`. - appDraftCodec: make `draft_path` a real draft + runtime field, serialized by runtimeRawAppToDraft and round-tripped by applyDraftToRuntimeRawApp, so a path change moves the sig and fires a save. - sessionRuntime.loadRawApp (+ inline rawApp.val type): seed `draft_path` from the loaded draft so it survives reloads. - RawAppEditorView: bind the header's `pendingDraftPath`, mirror it into runtime.rawApp.val.draft_path (guarded so the initial undefined can't clobber the seed or fire a spurious save), and seed the path widget from `draft_path ?? path`. Mirrors the full-page /apps_raw/edit route. - appDraftCodec.test: add a draft_path round-trip test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): per-line tooltips in workspace item diff rows The summary line now shows the full summary on hover and the path line the full path, instead of one row-level title surfacing the path everywhere. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): persist flow/script draft path edits in the session editor The session sync dedups on a per-kind signature that omitted the path, so a rename never moved the signature and never autosaved. Add path/draft_path to the flow signature, and derive draft_path in the script codec (scripts bind the Path widget to script.path directly) so the rename both autosaves and shows the typed name in the home/Drafts lists. Mirrors the raw-app fix. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): commit editor summary edits live instead of on blur EditableInput only fired onSave on Enter/blur, so the summary in the shared editor header only updated when the field lost focus. Add an opt-in commitOnInput that fires onSave per keystroke and enable it for the header summary, so flow/script/raw-app summaries autosave as you type. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): preserve renamed never-deployed script path on session re-seed loadScript seeded a draft-only script's baseline path from the storage key, so re-running it with the draft still in memory (e.g. a script→script switch) reset the path to draft_<uuid> and the next autosave dropped draft_path, clobbering the rename. Seed from the draft's own draft_path/path instead. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): clear raw-app draft_path when the path rename is reverted The mirror effect only ever set draft_path, so reverting/clearing the path field left a stale friendly name in the draft (persisted by the codec and shown in the home/Drafts lists). Track whether a real typed path was surfaced so a revert clears draft_path while the initial pre-bind undefined still can't clobber the loadRawApp-seeded value. Mirrors the script codec's drop-on-revert. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
f9cfeb0dba |
chore(main): release 1.728.0 (#9613)
* chore(main): release 1.728.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>v1.728.0 |
||
|
|
a2ce44645f | feat(frontend): dedup user drafts against the deployed baseline (#9618) | ||
|
|
651fa13ee8 |
fix: show folder labels in the folder list table (#9620)
Surface folder labels in the /folders table via a new "Labels" column between Name and Scripts, rendered as blue badges with a +N overflow indicator (first 3 shown), matching the script row pattern. Previously labels were only visible inside the folder editor drawer. Fixes WIN-2056 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
46288b6143 |
fix(frontend): session Drafts drawer uses raw_app kind for the raw-app diff (#9617)
* fix(frontend): session Drafts drawer uses raw_app kind for the raw-app diff Follow-up to #9601. DraftDiffDrawer mapped a raw_app row back to `app` before calling getDraftDiffValues(), but that helper sends `rawApp:true` only for the exact kind `raw_app` (which a never-deployed raw app needs). With `app` it hit the normal app endpoint and 404'd instead of rendering the added diff. `raw_app` isn't in the deploy-kind maps anyway, so just pass the row kind through. Caught by the Codex auto-review on #9601, which posted after that PR had already merged (locked conversation), so the fix lands separately here. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): show friendly draft path + summary for all kinds in session Drafts drawer A never-deployed app/raw_app is parked at a synthetic `u/.../draft_<uuid>` storage path with the user's typed name in the draft JSON's `draft_path`; the Drafts drawer rendered that UUID path. The list endpoint already returns `draft_path` and `summary` for every kind, but `fetchDrafts` dropped them and the drawer only had the lazily-derived summary. Thread both through the shared row: `WorkspaceDiffDrawer` gains optional `displayPath` (shown in tree/header/search, while `path` stays the storage key for value-loading, item keys and edit links) and `summary` (preferred over the value-derived one, shown before the diff loads). `DraftDiffDrawer` populates them from the draft list (`draft_path ?? path`, `summary`). Both fields are opt-in via `?? path` / lazy fallback, so ForkDiffDrawer — the other consumer of the component — is unchanged. The symptom only surfaced for apps/raw apps because their storage path diverges from the friendly name; scripts already kept a readable path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): use friendly display path for single-segment draft tree nodes buildTree splits displayPathOf(d), but the `< 2 parts` branch still named the file node from the storage `path` — a draft whose friendly path is a bare name (no `/`) would show `…/draft_<uuid>` in the sidebar tree. Name it from displayPathOf(d) too, consistent with the rest of the tree/header/search. Addresses Codex and claude review nits on #9617. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
7cb5c6e749 |
fix(frontend): reset deleteWorkspaceForkModal on confirm in SidebarContent (#9619)
The on:confirmed handler for the delete-fork ConfirmationModal never reset deleteWorkspaceForkModal to false. Since SidebarContent persists across workspace switches, the stale true state caused the delete-fork modal to immediately reappear when a new fork workspace was created. Reset the state before calling deleteFork(), matching the on:canceled handler and the pattern in forks/compare/+page.svelte and SessionWrapper.svelte. Fixes WIN-2057 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
46345e9ee7 |
backfill legacy draft emails from usr table (#9616)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
f6104ce05c |
fix: show last updated date per user in other-users-drafts modal (#9614)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
611c70acd2 |
feat(frontend): adapt AI-chat/sessions drafts to DB-backed model (#9601)
* feat(frontend): adapt AI-chat/sessions drafts to DB-backed model PR #9351 dropped UserDraft's localStorage layer; the chat adapter's synchronous save->read-back threw "Could not read written draft". The adapter now treats the backend as source of truth (in-tab cell used opportunistically for live-preview coherence) with conflict-on-save, and read tools fall back to the backend. Collapses the six writeXDraft functions onto one generic writeDraft + typed per-kind WriteSpec constants. Terminology: "local draft" -> "draft" (drafts are server-side). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(frontend): autosave indicator + draft-only diff guard in session editors Thread an explicit (workspace, path) autosave target to the cloud AutosaveIndicator in the Script/Flow/RawApp session previews so it watches the same key saves land on (it previously watched an empty path and never animated). Disable the Diff button with a hint for draft-only (no_deployed) items consistently across the three editors. Adjust the script topbar compact breakpoint/layout so the cloud icon is part of the bar, and stop splitpanes over-constraining session panes on reload. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): session draft diff viewer for schedule/resource/variable Canonicalize both sides of the draft diff onto one field set and strip runtime-only fields so rows aren't spuriously marked all-changed; mask secret values. Map draft itemKinds to deploy-style kinds so the DiffRow shows the correct icon/label. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): uniform diff-viewer row height regardless of summary Diff-viewer leaf rows (WorkspaceItemRow) drew two lines when an item had a summary and one line otherwise, giving unequal heights. Add an opt-in `uniformHeight` prop that gives the text wrapper a shared min-height and vertically centers the one-line case; enable it only from the diff viewer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(frontend): address review nits on the drafts diff/guard changes - Reuse the exported TRIGGER_RUNTIME_IGNORE from utils_deployable instead of a verbatim copy, so the runtime-field ignore list has one source of truth. - Drop the now-redundant `(savedApp as any)` cast in RawAppEditorHeader; the prop type already carries `no_deployed`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): add description parameter to the write_flow chat tool write_flow had no way to set a flow's top-level description (the sibling of summary in OpenFlow); patch_flow_json only edits the compact value, so the field was unreachable from the AI chat. Thread an optional description end-to-end: tool schema -> persisted draft -> read-back -> deploy body. Structural patches (patch_flow_json/set_flow_module_code) pass no description, so a previously-set description is preserved. Adds a deployRequests regression test asserting a draft description reaches the deploy body, overriding the deployed one. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): round-trip top-level fields in session preview draft sync The session preview's two-way draft sync dedups on a per-kind signature and mirrors fields between the editor store and the shared UserDraft cell. Both omitted fields the chat can set, so with the preview open a change to only that field was swallowed (identical signature) and then clobbered by the editor's outbound save: - flow: the signature and applyDraftToStore ignored top-level `description`. - script: the signature keyed on `content` alone, dropping `summary`/`language`. Add the missing fields to flowDraftSig and the script codec signature, and copy `description` in the flow codec's applyDraftToStore (mirroring `summary`). Raw-app already stringifies the whole draft, so it was unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): deploy draft-only flow from the session preview Deploying a draft-only flow (a draft with no deployed row) from the session preview hit two gaps the full-page flow editor already handled: - create vs update: newFlow keyed on `!savedFlow.val`, but a draft-only flow has a synthesized savedFlow (no_deployed=true), so deploy took updateFlow against the draft path and 404'd "Flow not found". Key it on no_deployed too. - friendly name: a brand-new flow is stored under a `draft_<uuid>` path with its intended name in `draft_path`. Seed the builder's initialPath from `draft_path` (as the full-page editor does) so the Path widget and deploy use the friendly name instead of creating a flow named draft_<uuid>. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): deploy draft-only raw app from the session preview Same create-vs-update bug as the flow session preview: newApp keyed on `!savedRawApp.val`, but a draft-only app has a truthy synthesized savedApp (getAppByPath with rawApp:true resolves to the draft kind instead of 404ing, carrying no_deployed=true), so deploy took updateApp against a path with no deployed row and 404'd "not found". Key newApp on no_deployed too so a never-deployed app deploys via createApp. More reachable than the flow case: it hit any never-deployed app, including chat-created ones at friendly paths. Keying newApp on no_deployed also exposed that newEditedPath (the breadcrumb path AND the createApp target) used newApp to mean "brand-new, generate a random name". A draft-only app is newApp=true but already has a real path (empty newPath at init, but appPath is set), so it showed and would deploy a random `*_app` name. Prefer the real appPath before the random fallback, so only a genuinely new app (appPath === '') still gets a generated suggestion; the full-page editor is unaffected (it always sets newPath). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): don't re-save a draft after deploying from the session preview Deploying from a session preview reloaded the editor (expected) but then immediately POSTed a fresh draft. The full-page editor guards deploy with discardDraftAfterDeploy (stopSync + arm-restart-on-first-interaction), but the shared editor header skips that in a session pane (inSessionPane) and routes post-deploy cleanup through sessionRuntime.syncPreviewWithDeployed, which did discard + reload without the stopSync guard. UserDraft.discard keeps the cell entry, so the reload's UserDraft.save fired the cell's reactive effect and re-POSTed the just-deployed value as a draft. Wrap the discard + reload in the same UserDraft.stopSync + armRestartOnFirst- Interaction bracket. One place fixes all three kinds (script/flow/raw_app), since they all funnel through syncPreviewWithDeployed; autosave resumes on the next genuine edit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(frontend): address review findings on the session-preview drafts work - Type `no_deployed` via the GetXByPathResponse/UserDraftOverlay types instead of `(result as any)`/`(saved as any)` casts at the sites this branch added (sessionRuntime, ScriptBuilder, FlowBuilder, + widened the script/flow builder prop types). Pre-existing trigger/variable/resource-editor casts left untouched. - Drop a history-narrating comment parenthetical per the AGENTS.md comment policy (RawAppEditorView). - Add a unit test covering persistGlobalDraft's conflict-on-save / override path (conflict-capable updateDraft mock; inert for existing tests). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): keep the friendly generated path for a brand-new raw app The earlier draft-only newApp fix made newEditedPath prefer `appPath` before the random suggestion, but a brand-new app is parked at the storage placeholder `u/{user}/draft_{uuid}` (the /apps_raw/add redirect target), so it surfaced that uuid instead of a friendly `<adjective>_app` suggestion. Reject a `draft_` placeholder segment when choosing the path: a real named/draft-only path is still kept, a placeholder falls through to the generated suggestion. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): show the Diff-button tooltip when it's disabled A disabled <button> fires no pointer events and browsers suppress its native title, so the "deploy once to compare" explanation never showed on hover for a draft-only item's Diff button. Wrap the button in a titled element and set pointer-events-none on the button when disabled, so the hover reaches the wrapper. Applied in ScriptBuilder, FlowBuilder, and RawAppEditorHeader (covers both the full-page editors and the session preview). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): surface draft save failures and conflicts in the AI chat tools Addresses Codex + Pi review findings on PR #9601 (three P1s, all in the DB-backed draft adapter reporting success when the write didn't land): - persistGlobalDraft reported {status:'saved'} even when UserDraftDbSyncer.save failed (it records network/5xx into a failure map instead of throwing). Check getState().state==='failed' after the save and return a new 'error' status; finishDraftWrite now emits success:false with a retry hint. - saveGlobalAppDraft dropped the conflict/error status (returned only the item), so write_app_file/patch_app_file/write_app_runnable reported every stale or failed write as saved. It now returns the full DraftPersistResult, and the six app write tools route through a shared finishAppDraftWrite helper. - fetchBackendDraftValue's catch{} swallowed non-404 errors (403/500/network), collapsing them to "no draft" so the write merged from the deployed item and lost in-progress draft edits. Narrow the catch to status===404; propagate the rest. Adds unit coverage: save-failure -> 'error', non-404 read -> propagates, raw-app stale write -> 'conflict'. 71/71 pass, check:fast + full build clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): surface failed draft deletes + strip tool-only override from schedule drafts Addresses Codex's second-round review on PR #9601: - [P1] deleteGlobalDraft reported success even when the server delete failed or conflicted (UserDraftDbSyncer.save records failure state instead of throwing) — so discard_local_draft / deploy_workspace_item / delete_workspace_item / the /global_drafts delete could report a draft removed while the DB still had it. Check getState().state and getConflict() after the awaited null save and throw, mirroring the write-path guard. - [P2] writeScheduleDraft persisted the tool-only `override` conflict flag into the schedule draft value (mergeDraftConfig cloned every arg field). Strip `override` in SCHEDULE_SPEC.buildDraft before merging. Tests: failed server delete -> throws; schedule draft no longer contains `override`. 73/73 pass, check:fast + full build clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): /global_drafts "Clear all" deletes persisted drafts, not just cells Codex review nit (P2): the dev-only global-drafts inspector's "Clear all" called clearGlobalDrafts(), which only iterates in-tab UserDraft cells — any persisted backend draft row not currently mounted as a cell survived, so the list re-showed it after refresh. Iterate the listed drafts and delete each via the backend-aware deleteGlobalDraft() (continue past per-row failures), matching the per-row delete, then clear local cells + ephemeral secrets. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
41562c7d7c |
fix(nativets): respect custom CA certs in in-process fetch runtime (#9615)
* fix(nativets): respect custom CA certs in in-process fetch runtime Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(nativets): dedupe CA file paths and clarify DENO_TLS_CA_STORE semantics Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(nativets): resolve CA env vars from worker-group config too Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
bc0d5bf241 |
feat(frontend): consolidate draft-migration errors into a single toast + modal (#9612)
* Draft migration error modal * nits |
||
|
|
5a2405743b |
fix(ResourceForm): initialize JSON editor when resource type schema is unavailable (#9611)
When editing a resource whose type definition does not exist in the workspace (e.g. custom types not yet synced), the JSON fallback editor rendered empty. The pre-refactor ResourceEditor seeded rawCode from the resource args in its loadResourceType() catch block; the new ResourceForm only populated rawCode when the user toggled viewJsonSchema. Add a reactive effect that seeds rawCode from args when the resource type schema is unavailable, restoring the old behavior so the resource data is visible in the JSON editor. Fixes WIN-2045 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev> |
||
|
|
6b62b1d832 |
chore(main): release 1.727.0 (#9605)
* chore(main): release 1.727.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>v1.727.0 |
||
|
|
a44fc89eba |
fix(frontend): open draft-only apps in editor from home list (#9610)
A draft-only app (one that exists only in the `draft` table and was never deployed) failed to load when opened from the home list: the row linked to the viewer `/get/` route, whose `get_app_lite` backend handler 404s when there is no deployed version. Route `draft_only` apps to the `/edit/` route instead, matching the existing behavior in ScriptRow and FlowRow. Covers both raw and regular draft-only apps. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
51e82d7c6d |
fix(frontend): make UserDraft read-after-write work without live entry (#9609)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
9e3c0decf9 |
fix(frontend): seed detached user-draft handles so new-item drawers render (#9608)
The "Add a variable" drawer (and other editors built on `UserDraft.useMany`)
opened empty: for a brand-new item `editPath` is undefined so the spec path is
empty, which routes through `useMany`'s empty-path branch. That branch handed
out a `makeDetachedHandle()` whose cell was initialized to `undefined`,
ignoring the spec's `defaultValue`. The editor binds its form behind
`{#if current}` where `current = states[ws]?.draft`, so an undefined cell left
the drawer with just the title and a Save button.
Seed the detached handle with `defaultValue`, and re-seed it when the caller
supplies a fresh `defaultValue` reference (reopening the drawer clones a new
default) so a reopened editor starts clean instead of replaying the previous
session's edits — the reference is stable within a session, so live edits are
never clobbered. Also drop detached handles that fall out of the specs so they
don't leak.
Regression from #9351 (db-backed user drafts).
Fixes WIN-2054
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
cd098700c2 |
fix(cli): harden legacy flow lock migration ordering and collision guard (#9557)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
8500435e82 |
fix(frontend): allow same-origin redirects in isValidLogoutRedirect (#9568)
Self-hosted instances that embed their own UI (Windmill as backend, custom
app at the instance root) can't be redirected back to their app after OAuth
login: isValidLogoutRedirect rejects same-origin absolute URLs, so the login
callback falls back to a client-side goto('/') into Windmill's own dashboard.
Same-origin redirects are never open redirects (and toSameOriginRelativePath
already treats them as safe), so accept them.
Also make the test-setup window global configurable so vitest's stubGlobal
can redefine it across the window-stubbing test suites.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
252c1b35fc |
fix(cli): include __mod/ folder in gitSyncIncludePattern for scripts (#9606)
* fix(cli): include __mod/ folder in gitSyncIncludePattern for scripts
Scripts with companion modules use a `__mod/` folder layout on disk
(`path__mod/script.ts`, `path__mod/script.yaml`, ...). The default case of
`gitSyncIncludePattern` returned only `${path}.*`, which does not match files
inside `__mod/`. During git-sync deployment the `extraIncludes` filter then
excluded all module files from the pull, and the subsequent
`git add '${path}**'` failed with "pathspec did not match any files" because
nothing was written to disk.
Add the `${path}__mod/**` pattern so module files are pulled, mirroring the
existing dual-layout handling for flows (`.flow/*,__flow/*`) and apps.
Fixes WIN-2052
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(cli): e2e guard that module scripts' __mod/ files land on git-sync deploy branch
Add a promotion test mirroring the existing trigger/schedule cases: deploy a
script WITH companion modules (one flat, one nested) under use_individual_branch
and assert the `__mod/` entry point and module files land on the wm_deploy
branch. Without the gitSyncIncludePattern `__mod/**` fix the extra-includes
filter matches none of those files and the branch is created without them.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
33ac287065 |
feat: support temp_script_refs in wmill dev for local relative imports (#9554)
* feat: support temp_script_refs in wmill dev for local relative imports Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test: add unit tests for getAllTempScriptRefs Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
c213801b5a |
fix(frontend): strip server-managed fields from value diffs (#9599)
* fix(frontend): strip server-managed fields from value diffs The script editor's "Deployed <> Current" diff rendered spurious metadata changes (created_at, created_by, extra_perms, lock_error_logs, ...) the user never touched. Since #9351 the edit loader fetches the full Script row via getScriptByPath (instead of the trimmed NewScript-shaped getScriptByPathWithDraft), so the editing object carries these DB-managed fields. The deployed side is trimmed in syncWithDeployed, so the two sides no longer match. Normalize both sides at the shared chokepoint: cleanValueProperties now also strips created_at, created_by, extra_perms, workspace_id, parent_hashes, lock and lock_error_logs. These are never user-editable, so this also fixes the draft<>current diff and unsaved-change detection, and benefits the flow/app diff viewers that share the helper. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(frontend): cover cleanValueProperties; keep lock in diffs Add unit tests for cleanValueProperties asserting the server-managed bookkeeping keys are stripped while user-editable keys survive. Keep `lock` out of the stripped set: it was part of the value comparison before the full-DB-row loader (#9351) and version-to-version diff viewers (WorkspaceItemDiffViewer) legitimately surface lockfile changes. Only the fields that the full Script row newly introduced as diff noise are stripped. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): keep extra_perms in shared diff, strip script noise at source Address review: stripping `extra_perms` in the shared `cleanValueProperties` hid folder sharing-permission changes in workspace/fork diffs (the backend's compare_two_folders treats folder extra_perms as a real change). Remove it from the global skip-list so folder diffs surface it again. The script-editor noise it (and `lock`) would otherwise cause is now stripped at the source instead: `ScriptBuilder.openDiffDrawer` nulls `lock`/`extra_perms` on the current side to match the existing deployed-side strip in `syncWithDeployed`. Also strip the draft-overlay bookkeeping fields the full DB row carries (`draft_saved_at`, `draft_created_at`, `is_draft`, `other_drafts_users`) — they leaked into the current side and showed as spurious metadata diffs. Verified in browser: no-edit diff shows "No changes detected"; a summary edit surfaces only that change, with no lock/extra_perms/draft metadata noise. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
1cf402a9be |
chore(main): release 1.726.1 (#9603)
* chore(main): release 1.726.1 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>v1.726.1 |
||
|
|
24f32596e9 |
fix(apps): prevent decision tree graph editor crash on missing graph context (#9602)
NodeWrapper destructured `moveManager` from `getGraphContext()` unconditionally,
but FlowGraphContext is only set by the flow graph. The app decision-tree editor
reuses NodeWrapper without setting that context, so opening its Graph Editor threw
"Cannot destructure property 'moveManager' of getGraphContext(...) as it is undefined".
Guard the context with `?? {}` since `moveManager` is already used optionally.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
4e4b2247ef |
fix: db-backed draft fixes — review-page UX, legacy drafts, session restore (#9600)
* fix(frontend): session-pane draft seeding + restore actions Seed per-tab last_sync from the server draft's draft_saved_at in the loadFlow/loadScript "no local draft" branches (mirroring loadRawApp) so the seeding save attaches a matching last_sync and the server no longer clobbers an existing server draft with a fresh created_at. Replace the no-op loadFlow/loadRawApp-based diff-drawer restore handlers with proper restoreDeployed/restoreDraft that reset the live UserDraft cell (the inbound sync then updates the preview) and delete the per-user server draft, mirroring ScriptEditorView. Add rawAppValueToDraft to project a deployed raw-app value into the draft shape. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(api): move UserDraftOverlay/UserDraftItemKind out of openflow inline block These two schemas were defined between the python-client's "# -- INLINE START/END --" markers, whose contents build.sh replaces with the openflow legacy wildcard $ref. That deleted both definitions during bundling while ~19 path responses still referenced them, failing the python-client build. Relocated them after the marker block. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(frontend): explain legacy drafts in the draft badge popover The home-page draft badge lists each draft owner; a workspace-level row from before the per-user drafts migration shows as "Legacy workspace draft". Add an info tooltip next to it explaining that a legacy draft isn't tied to any user (email NULL) so everyone with access to the path sees it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(compare): show friendly draft path on the review & deploy page list_drafts now surfaces the draft JSON's `draft_path` (when set and different from the storage path) alongside summary, mirroring the home-page list endpoints. CompareDrafts displays it instead of the `u/{user}/draft_{uuid}` storage path, while all fetch/deploy/discard calls keep using the storage path (the draft's server-side key). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(compare): delete the storage-path draft when deploying a renamed draft Deploying a draft from the review page replays the editor's create/update at the draft's friendly path, which deletes the draft server-side only at that path. A never-deployed item parked at `u/{user}/draft_{uuid}` therefore left its storage-path draft behind on deploy and kept listing. Delete the storage-path draft for every kind after a successful deploy, mirroring the editors' discardDraftAfterDeploy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(compare): badge legacy drafts on the review & deploy page list_drafts now reports `legacy_draft` (true when the listed row is a workspace-level NULL-email draft and no per-user row exists at the path). CompareDrafts shows a "Legacy draft" badge with a hover tooltip explaining these predate the per-user drafts migration and aren't tied to a user. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(compare): allow discarding a legacy draft from the review page Legacy drafts (workspace-level, email NULL) aren't owned by the authed user, so the email-scoped draft delete in update_draft never matched them and the discard was a silent no-op. Add a delete-only `legacy` flag that retargets the DELETE (and the conflict re-read) to the NULL-email row, and route the review page's discard of a legacy draft through it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(backend): prune orphaned sqlx offline cache entries Re-ran the canonical update_sqlx.sh after rebasing windmill-ee-private onto origin/main and re-running substitute_ee_code.sh. Compiling the full workspace with all features recorded every live query and pruned 55 stale cache entries no longer produced by any query (22 are the removed `draft_only`-on-app lookups dropped by the db-backed user drafts work; the rest pre-existing orphans). Orphan entries don't break offline builds — this is cleanup only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(drafts): stop migrated draft-only items flooding the home list 20260609165313_remove_draft_only inserted the legacy (email IS NULL) draft stubs without an explicit created_at, so every row defaulted to the migration's now() (transaction_timestamp, constant for the whole transaction) and they all bunched at the migration instant — flooding the top of the newest-first home list. Add a corrective migration that resets those rows' created_at to the epoch so they sort to the bottom (their real per-item timestamps are unrecoverable — the source rows were deleted and the draft value carries no timestamp; editing one bumps created_at to now() and floats it back up). The rows are identified exactly via _sqlx_migrations.installed_on, which sqlx writes in the same transaction as the migration so it is byte-identical to the inserted rows' created_at; rows edited since no longer match and are left alone. Leaving remove_draft_only intact (rather than neutralizing it) keeps its essential schema work running everywhere; this migration runs right after and corrects the timestamps. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(migration): note both timestamps are timestamptz in draft created_at repair Pre-empt a misread: draft.created_at became TIMESTAMPTZ in 20260514233244, so `created_at = installed_on` is an exact instant comparison, not a tz-sensitive timestamp/timestamptz cast. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(compare): resolve friendly draft path per kind + strip email from u/ path list_drafts read the friendly path only from value->>'draft_path', which is empty for scripts — the script editor binds the Path widget to script.path, so the typed path round-trips through the draft JSON's own `path` (flows/apps/raw -apps use draft_path). Read the right field per kind, matching the home-page list endpoints, so renamed never-deployed scripts show their friendly name. Also truncate the user segment at `@` when displaying a `u/{user}/…` path: auto-generated draft slots are `u/{user}/draft_{uuid}`, and in the admins workspace (or email-as-username setups) `{user}` is the full email (`u/admin@windmill.dev/…` → `u/admin/…`). Display only — the path/key used for fetch/deploy/discard is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(raw-app): make diff-drawer "restore to deployed" reset like the autosave indicator The diff drawer's restoreDeployed ran the same runResetToDeployed as the AutosaveIndicator's "Reset to deployed", but its onResetToDeployed callback also did `redraw++`, remounting RawAppEditor mid-reset (inside the stopSync bracket); the fresh mount's draft write resurrected the draft, so the restore appeared to do nothing. Extract a single `reloadDeployed` callback (drop the draft handle + reload without the draft overlay) and use it for the diff drawer, the conflict modal, and the AutosaveIndicator so all three reset the same way. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(compare): don't show auto-generated draft path as the bold title A never-named draft lives at a synthetic `u/{user}/draft_{uuid}` slot. When it had no summary and no friendly draft path, that uuid showed as the row's bold title. Return '' from displayPath for auto-generated paths so they aren't bolded — the row still shows the storage path in its secondary (grey) line. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(diff-drawer): remove obsolete draft-vs-current tab selector The "Latest saved draft <> Current" comparison is obsolete. Remove the whole diff-type tab selector; normal-mode diffs now always show deployed-vs-current, simple-mode shows its single custom diff. Drop the now-unreachable restore-to-draft button and the `restoreDraft` prop (plus the dead handlers in the session editor views). The content/metadata selector is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(compare): make "Reset to deployed" work from the diff drawer Route the raw-app session preview and the low-code app editor diff-drawer restore through the same reset-to-deployed callback the AutosaveIndicator uses. - Raw-app session: add a deployedOnly path to loadRawApp that bypasses the draft (cell + server overlay) and reloads the deployed value; the diff drawer's restore now runs it via runResetToDeployed instead of rebuilding the draft shape in place (which hung and never reset). Also wires the in-session AutosaveIndicator reset. - Low-code app editor: drop the goto in the diff-drawer restoreDeployed that re-ran the page load with the draft overlay on and resurrected the draft; share one reloadDeployed across the diff drawer, AutosaveIndicator and the load-latest-deploy modal. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
abe442bf42 |
chore(main): release 1.726.0 (#9598)
* chore(main): release 1.726.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>v1.726.0 |
||
|
|
9de5708608 |
feat(audit): record workspace archive/unarchive/delete in instance audit log (#9596)
Archiving a workspace sets `deleted = true`, hiding it from the workspace switcher for everyone (the `user_workspaces` query filters `workspace.deleted = false`). The archive/delete actions were audited only inside that same workspace's audit log, which then becomes inaccessible — so there was no durable, discoverable record of who archived or deleted a workspace, or when. Also write these lifecycle events under the instance-level `admins` workspace, the canonical instance-audit scope (a superadmin querying `admins` with `all_workspaces=true` sees entries across all workspaces). The target workspace id is carried in the audit `resource` field and the actor in the author. For delete, the per-workspace rows are removed in the same transaction, so the instance-level entry is the sole durable record. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
6a6295921d |
fix(embeddings): retry HuggingFace model downloads with backoff (#9597)
Caching the gte-small embedding model fetched config.json / tokenizer.json /
model.safetensors from HuggingFace with no retry, so a single transient
network error ("error sending request for url ...") failed the whole image
build. Wrap each download in a retry loop (up to 5 attempts, exponential
backoff capped at 8s) that logs each retry and surfaces the error only after
the final attempt. No new dependency.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
5ccaae8ab3 |
fix: resolve release CI failures (pypi bundle, flow serde test, cli windows) (#9595)
Three independent failures on the latest release commit: - pypi (Publish python-client): the `UserDraftOverlay`/`UserDraftItemKind` schema definitions were placed inside the `# -- INLINE START/END --` markers in openapi.yaml. The python-client build replaces that whole block with a wildcard import of `openflow.openapi.yaml`'s schemas, which do not define these two, so every `$ref` to them became unresolvable and the redocly bundle aborted. Move both definitions outside the markers — they are windmill-api schemas, not openflow-mirrored ones. - flows::tests::flowmodule_serde: the expected JSON still carried `"error_message": null` in three `stop_after_if` blocks, but StopAfterIf.error_message is now skipped when None. Drop those keys. - CLI Tests (test-windows): preservePendingScriptLocks mixed the OS path separator (SEP) into map keys that are always forward-slash normalized, so on Windows the multi-module suffix match and the lock-file lookup both failed. Use forward slashes consistently; this also fixes real Windows git-sync deploys, not just the test. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
5709a564fb |
feat(frontend): add user-level toggle to disable Windmill AI (#9585)
* feat(frontend): add user-level toggle to disable Windmill AI Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(frontend): hide AI sessions sidebar section when AI is disabled Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
8643e68891 |
chore(main): release 1.725.1 (#9589)
* chore(main): release 1.725.1 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>v1.725.1 |
||
|
|
6b916ac688 |
fix(cli): preserve committed script.lock on transient NULL lock during git-sync deploy (#9593)
* fix(cli): preserve committed script.lock on transient NULL lock during git-sync deploy (#9588) A script's `lock` is NULL on the server only while a relock is mid-flight (an importer relock after a relative-import dependency changed, or the script's own first lock job). The git-sync deploy mirror reads the workspace inside that window, sees no lock, and mirrors the transient NULL as a deletion of the committed `.script.lock` plus a strip of the `lock: '!inline …'` line — corrupting the git mirror until the relock writes the identical lock back seconds later. When pulling (remote -> local), carry the local committed lock onto the remote map when the remote lock is NULL, so the diff is a no-op for both the lock file and the metadata line. An empty-string lock ('') — the real "no dependencies" state — is left untouched, so genuine lock removals still propagate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(cli): cover __mod multi-module scripts in pending-lock preservation Address auto-review on #9593: the lock-file key was reconstructed from the metadata path (`.script.yaml` -> `.script.lock`), so a multi-module script whose lock lives at `…__mod/script.lock` fell through unprotected. Derive the key from the committed `!inline` reference instead (covers both the dotted and `__mod` folder layouts) and detect the folder-layout metadata file. The reference is always forward-slash; convert to the OS separator so the local map lookup matches on Windows. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |