mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-07 00:01:49 +00:00
8343203ec2cea28a2ffd5b4ac636497e861fa3ce
13851
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
8343203ec2 |
feat(mcp): add multi-workspace MCP tokens via the gateway endpoint (#10043)
* feat(mcp): add multi-workspace MCP tokens via the gateway endpoint A single MCP token with no bound workspace (workspace_id NULL + mcp scope) now works across every workspace the token owner can access, served through the existing /api/mcp/gateway endpoint. This avoids having to register one MCP server entry per workspace in clients like Claude/Cursor. In multi-workspace mode the runner exposes a synthetic `list_workspaces` tool plus the generic API endpoint tools, each workspace-scoped one gaining a required `workspace_id` argument (mirroring the proxy pattern users built externally). Per-workspace scripts/flows are not enumerated to avoid flooding the tool list — they are run via runScriptByPath/runFlowByPath with an explicit workspace_id. Auth is resolved per tool call: the gateway middleware detects a workspace-less mcp token and marks the request MultiWorkspaceMcp, and the runner resolves a per-workspace ApiAuthed from the raw token via the AuthCache (validating membership; superadmins may act in any workspace). Single-workspace tokens are unchanged. Frontend: the MCP token creation flow gains an "All workspaces" option that produces a workspace-less token and the gateway URL. Fixes WIN-2153 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(mcp): cover multi-workspace endpoint tool transformation Unit tests for endpoint_tool_to_mcp_tool_multi and list_workspaces_tool: workspace-scoped tools gain a required workspace_id arg, global tools are left unchanged, workspace_id is not duplicated, and list_workspaces takes no arguments. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(mcp): forward script/flow args for runScriptByPath/runFlowByPath These endpoints have an additionalProperties body (no declared properties), so build_request_body previously returned an empty body and dropped every script/flow argument. This was latent for the per-path run endpoints and became load-bearing in multi-workspace mode, where scripts/flows can only be run via runScriptByPath/runFlowByPath — parameterized runs silently lost their arguments. build_request_body now forwards all arguments not consumed by a path/query parameter for pass-through (additionalProperties) bodies, keeping the strict declared-only behavior for endpoints with explicit properties. The runner strips the synthetic workspace_id argument before dispatch so it can't leak into the forwarded body. Reported by Codex review on #10043. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(mcp): note workspace_id requirement in multi-workspace tool descriptions Workspace-scoped tools already gain a required workspace_id parameter (with its own schema description) in multi-workspace mode, but the tool's prose description was unchanged. Append a note so models/clients that read the description text know to pass workspace_id (and to call list_workspaces first). Global tool descriptions are left untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(mcp): trim multi-workspace tool/arg descriptions The workspace_id note repeats across every workspace-scoped tool in each tools/list, so keep it terse: description suffix "Requires `workspace_id`." and arg description "Target workspace id (from list_workspaces)." to avoid spending tokens on repeated boilerplate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(mcp): enforce script/flow path scopes for multi-workspace run-by-path In multi-workspace mode runScriptByPath/runFlowByPath are the only way to run scripts/flows, but they were authorized against the endpoint scope only — never the caller's mcp:scripts:/mcp:flows: path scopes. A granular token could run items outside its allowed paths (e.g. mcp:scripts:f/team/* + mcp:endpoints:* running f/other/secret), and a mcp:endpoints:* token could run arbitrary scripts. Now these two endpoints are authorized by the script/flow scope of the requested path (matching single-workspace mode's per-item tools): exposed in list_tools only when the token grants some script/flow (McpScopeConfig::has_any), and at call time the path is checked via is_allowed("script"/"flow", path). Verified e2e: mcp:scripts:f/team/* runs f/team/* but is denied f/other/*; mcp:endpoints:* alone no longer exposes or runs run-by-path. Reported by Codex + Pi review on #10043. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(mcp): deny run-by-path for mcp:favorites multi-workspace tokens mcp:favorites sets granular=false, so the previous run-by-path scope check (gated on `granular`) was skipped entirely — a default "Favorites only" all-workspaces token could run any script/flow by naming its path, bypassing the favorites restriction. Favorites are an enumerated set reachable only through per-item tools, not by arbitrary path, so they grant nothing for run-by-path. has_any() now returns true only for mcp:all (not favorites), and the call-time check drops the `granular` gate and relies on is_allowed() directly (already false for favorites, true for mcp:all, pattern-matched for granular). Verified e2e: mcp:favorites no longer exposes or runs run-by-path; mcp:all still runs; granular script scopes still path-enforced. Reported by Codex review on #10043. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
3b0781761b |
fix(frontend): show nested restart button for subflows nested in containers (#10042)
* fix(frontend): show nested restart button for subflows nested in containers Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): keep nested-restart flat fallback anchored to the leaf Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
40f93cee87 | unblock EE CUDA image build on trixie by allowing SHA1 for NVIDIA repo (#10040) | ||
|
|
1c88242849 |
fix(frontend): show optimistic user message and fork-creation label before beforeSend (#10037)
* fix(frontend): show optimistic user message and fork-creation label before beforeSend In AI chat, `sendRequest` previously set `loading` and pushed the user message only after the `beforeSend()` hook completed. For forked sessions `beforeSend` runs several sequential API calls (materialize session, flush files, create workspace fork, load copilot config) that take seconds, while the composer clears its textarea immediately. The result: the message text vanished into a void with no bubble and no loading indicator until the fork finished. Now the user bubble and loading indicator are shown optimistically before `beforeSend`, with context elements and the snapshot attached afterwards. A general-purpose `loadingLabel` lets any `beforeSend` hook describe its pre-flight work; the session hook sets "Creating workspace fork..." around `commitSessionWorkspace`. If `beforeSend` throws, the optimistic bubble and loading state are rolled back. Fixes WIN-2150 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): make Stop/Escape cancel the send during the beforeSend pre-flight Showing the loading indicator before beforeSend also exposed the Stop button and Escape handler during "Creating workspace fork...", but the abort controller was created after beforeSend, so cancel() had nothing to abort and the request still fired once the pre-flight resolved. Create the abort controller before beforeSend and check `signal.aborted` after it: a Stop/Escape during the pre-flight now rolls back the optimistic turn and skips the request. Factor the rollback into a shared helper reused by the beforeSend-failure and cancel paths, and refresh the now-stale beforeSend doc comment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): restore prompt and hand off queued message on pre-flight cancel The pre-flight abort check rolled back the optimistic turn and returned early, skipping the recovery the main cancel path runs. Because the input clears its composer on send, a Stop/Escape during "Creating workspace fork..." lost the typed prompt from both the bubble and the composer, and bypassed the queued-message handoff. Mirror the main "cancelled before usable output" path: restore the prompt to the composer via the same restoreInstructions helper, or auto-send a queued message when one is taking over, and return true so a parent queued-flush doesn't re-queue the cancelled turn. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
38a190b53a |
chore(main): release 1.754.0 (#10017)
* chore(main): release 1.754.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>v1.754.0 |
||
|
|
c5060a1e9a |
fix: scope AI-session flow/script editors to the session workspace (#10025)
* fix: scope flow script-edit drawer to session workspace and fix scroll Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: scope flow schema inference to session workspace Thread an optional workspace through loadSchemaFromPath/loadSchemaFlow/ loadSchemaFromModule/loadFlowModuleState/initFlowState/pickScript/pickFlow and pass the op (session) workspace at fork-context call sites, so a flow opened in an AI session resolves path-referenced scripts/subflows against the session workspace instead of the nav workspace. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: scope script editor log panel and git-repo pickers to op workspace LogPanel and the ansible git-repo viewer/picker read the nav workspace directly; pass the script editor's op workspace so past-test results/logs and git-repo resource/file lookups target the session workspace in a fork. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: correct session pipeline trigger-editor workspace comment The comment claimed session activation syncs $workspaceStore; SessionPicker intentionally does not, so trigger create/edit/delete from a fork session's pipeline canvas writes to the nav workspace. Document the known limitation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: forward op workspace to git-repo S3 file browser GitRepoViewer scoped its own calls to the op workspace but rendered the nested S3FilePickerInner without workspace={ws}, so the file list/preview/ metadata still queried the nav workspace with a session-workspace prefix. Addresses Codex review on #10025. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
15f9e9b48f |
perf: skip redundant retry-chain job query for successful top-level scripts (#10035)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
03535691d6 |
fix(frontend): open new script/flow/app in AI session (not-found + friendly tab) (#10028)
* fix(frontend): open new script/flow/app in AI session without "not found" "Open in AI session" on a never-deployed item opened the session preview against the friendly live-edited path (script.path / $pathStore) instead of the URL draft path the editor loads and saves by, so get-by-path 404'd. It also flushed only queued autosaves, so an untouched new item — which never triggered autosave — had no draft row to load at all. Target the URL draft path (userDraftPath / liveEditorDraftStoragePath; raw-app already used appPath), and add UserDraft.forcePersist to materialize a brand-new draft in beforeOpen, gated to never-deployed items where there is no deployed baseline to discard against. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): label a new session preview tab by its friendly name A never-deployed item's preview tab read draft_<uuid> instead of the typed/ auto name. The sessions page can't reactively read a runtime cell's state across reactive roots, so the live editor (SessionEditorTarget, handed the runtime as a prop) now stamps a transient friendlyLabel onto the tab model — which the page does observe — via a pure draftFriendlyLeaf helper. Unifies scripts, flows and raw apps through one path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): address review nits on AI-session open - Flow drawer (FlowEditorDrawer) mounts FlowBuilder with no liveEditorDraftStoragePath, so gating the AI button solely on it hid the session entry point there; fall back to $pathStore (the pre-PR behavior for those deployed-flow drawers) while the main editor still prefers the URL draft path. - Clear a tab's stamped friendlyLabel when it is retargeted, so a draft tab's friendly name no longer lingers after navigating to a plain page. - Trim the repeated persist-hook comments to satisfy the AGENTS.md comment rule. 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: Ruben Fiszel <ruben@windmill.dev> |
||
|
|
6c521e9d87 |
fix(backend): propagate script timeout when restarting perpetual scripts (#10029)
Perpetual scripts (restart_unless_cancelled) re-pushed their restart job with custom_timeout = None, so every rerun ignored the script's configured timeout and fell back to the instance-level job_default_timeout. Only the first run honored the script timeout. Fetch the script timeout alongside restart_unless_cancelled (both cached by the immutable script hash) and pass it as custom_timeout when re-pushing the perpetual job. Fixes WIN-2149 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
c029d6dcde |
fix(security): drop --allow-run from Deno sandbox (GHSA-gj6h-vw66-mr8f) (#10039)
The `// sandbox` annotation (and global nsjail sandboxing) restricted Deno to `--allow-run=git,/usr/bin/chromium`. Both binaries can be coerced into spawning `/bin/sh`, escaping Deno's permission model: - git via hook configs, e.g. `git -c core.fsmonitor='/bin/sh -c <cmd>' status` - chromium via subprocess-launcher flags, e.g. `--renderer-cmd-prefix` / `--gpu-launcher`, pointed at a launcher the script writes into `./` Because the subprocess is spawned by git/chromium — not Deno — it is invisible to Deno's permission checks, giving any user with script-execution permission arbitrary OS command execution (root, in the default worker container). Critically, the Deno runtime is the ONE language never wrapped in nsjail (there is no run.deno.config.proto; every other language has one). So for deno the Deno permission model is the *entire* sandbox — there is no OS-level containment to fall back on, and handing it any subprocess-spawning binary is an unconditional escape regardless of the nsjail setting. Fix: emit no `--allow-run` in the restricted path, denying all subprocess execution. The advisory's alternative (inject `-c core.fsmonitor=false ...`) doesn't apply — the user controls the git/chromium argv, so any injected hardening is overridden. Admins who accept the risk (e.g. puppeteer) can still re-add specific binaries via `DENO_FLAGS`. Verified with both PoCs on a running worker: git and chromium invocations now return `Requires run access to "<bin>"`; the sandbox escapes are closed. Fixes WIN-2151 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
689b20a470 |
fix(security): remove git from Deno sandbox allow-run (GHSA-gj6h-vw66-mr8f) (#10038)
The `// sandbox` annotation restricts Deno to `--allow-run=git,/usr/bin/chromium`. git can be coerced into spawning `/bin/sh` via hook configs such as `git -c core.fsmonitor=<cmd> status`, and that subprocess is spawned by git — not Deno — so it is invisible to Deno's permission model. This let any user with script-execution permission run arbitrary OS commands as root inside the worker, fully defeating the sandbox. The advisory's alternative (injecting `-c core.fsmonitor=false -c core.hooksPath=/dev/null`) does not apply here: the user's own script invokes git directly via `Deno.Command`, so Windmill cannot inject hardening flags into that call. Removing git from the allowlist is the only complete fix. git was originally allowed for git-sync-adjacent use, which no longer needs it. Verified with the advisory PoC: git invocation now returns `Requires run access to "git"` and the sandbox escape is closed. chromium (puppeteer) support is preserved. Fixes WIN-2151 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
9feda57c15 |
perf: index v2_job(parent_job) to speed up run child-job listing (#10034)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
5a460dbec6 |
fix: accept bunnative language in AI chat flow step validation (#10030)
* fix: accept bunnative language in AI chat flow step validation Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: regenerate copilot flow schema from openflow spec Run gen_openflow_schema.sh + minifiedOpenflowJson.sh instead of hand-patching. Also syncs three fields the checked-in generated files had drifted from since the last regen (reasoning_effort, reasoning_token_delta streaming event, aiagent tag). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: regenerate system prompts for bunnative openflow schema Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
5387076c1c |
fix(frontend): persist per-session preview panel resize width (#10031)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
3704d00956 | fix: sync theme into session page preview iframes on toggle (#10018) | ||
|
|
d7a9b46ab9 | fix(sessions): open test pane when enabling debug so the debug UI is visible (#9998) | ||
|
|
9036ac789f |
fix(frontend): name the draft in AI chat test-run confirmation (#10024)
* fix(frontend): name the draft in AI chat test-run confirmation
The confirmation card shown before an AI-chat test run displayed a
static, generic header ("Run script test"). Make it name the target
and clarify it runs the user's draft.
- Tool.confirmationMessage now accepts a function of the parsed args;
shared.ts resolves it before setting the tool status.
- test_run_script/flow/step (global chat) build a dynamic header
naming the script/flow/step, e.g. "Run a test of your draft of X".
- In-editor script/flow test-run tools say "Run a test of your draft".
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(frontend): fall back to tool name in YOLO tooltip for function messages
The auto-accept ("bypassed in current mode") tooltip rendered
confirmationMessage directly. Now that it can be a function of the call
args, render the tool name instead of the function source there.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(frontend): use neutral wording in test-run confirmations
The global test-run tools fall back to deployed content when no draft
exists, so "your draft" could contradict what actually runs. Drop the
draft claim and just name the target: "Run a test of X".
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
368fd2d9e4 |
fix: resolve fork family/picker for superadmin visiting a non-member workspace (#10023)
* fix: populate fork base picker for superadmin visiting a non-member workspace Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: resolve fork family for superadmin across sidebar picker and scope header Extract the superadmin-visited-workspace fallback into a shared useForkableWorkspaces composable and apply it to WorkspaceFamilyPicker and WorkspaceScopeHeader so the sidebar fork picker and its fork-count trigger resolve the family for a superadmin viewing a non-member workspace. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: resolve superadmin-visited workspace name in the scope trigger chip The sidebar scope trigger next to the fork picker read $userWorkspaces directly, so a superadmin viewing a non-member workspace saw its raw id instead of the resolved name/family. Thread the folded-in forkable list into WorkspaceScopeTrigger, and trim the now-duplicated per-site rationale comments to a pointer at the composable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
c537d45e49 |
fix(frontend): persist forked "Copy of X" script drafts (#10021)
* fix(frontend): persist forked "Copy of X" script drafts
Forking a script ("Copy of X"), hub-forking, or seeding a new draft from
a URL/YAML/JSON import opened the editor with pre-filled content, but the
saved draft never appeared in the scripts list.
The edit route suspends autosave for every `?new_draft=true` load
(`UserDraft.stopSync`) so the seed write doesn't post as the user's first
edit, expecting ScriptBuilder to lift it. ScriptBuilder's `restartSync`
only ran inside `if (script.content == '')`, so a non-empty seed (fork /
hub / import) skipped it and left autosave suspended for the session —
both autosave and explicit Ctrl+S then silently no-op'd, so the draft was
never written and never listed.
Add an `else if` branch for pre-filled `new_draft` seeds that runs the
same stores-gated restart cascade (restart only, no template seeding),
restoring parity with the empty-new-script flow. The empty-seed block is
unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs: condense scheduleRestartSync comments to ≤4 lines
Address Codex review P2: trim the helper and new-branch comments to the
core invariant per AGENTS.md's comment-length rule.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
c139eed631 |
fix: session preview tab labels, splitter hover, and diff-drawer sizing (#10008)
* fix: show pending friendly path in new raw app session tab Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: reveal a subtle rounded grabber on the sessions chat/preview splitter on hover Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: cap session diff blocks so each item's card fits the drawer viewport Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: floor flow diff cap at its min height and tidy diff/splitter comments Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
756979852c |
feat: add multi-select mode to copilot askUserQuestion (#10016)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
c000bbca28 |
fix(frontend): scope raw-app, flow and script editors to the session workspace (#10015)
* fix(frontend): scope raw-app/flow/script editors to the session workspace Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): scope flow and script editor operations to the session workspace Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): scope flow preview, inline-script creation and datatable schema to the session workspace Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): address Codex review — thread session workspace through flow resource pickers, script fetch, preview cancel/recording and path collision check Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): address Claude review — pass session workspace to preview FlowStatusViewer and align FlowChatManager guards Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): address Pi review — show acting workspace in script-not-found message and fetch picked script from it in EditorBar Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): address Codex review round 2 — thread session workspace into flow step test, raw-app inline runnable, inline editor toolbars and MCP OAuth path Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): address Codex review round 3 — thread session workspace into dynamic-input helpers and the flow-preview argument side panel (history/saved-inputs/captures) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): address Codex review round 4 — thread session workspace into nested flow/script drawers, flow chat inputs and the flow input side tabs Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): address Codex review round 5 — thread session workspace into script-module fork/reload and key the raw-app schema cache by workspace Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): address Codex review round 6 — key the DB manager schema cache by acting workspace Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): address Codex review round 7 — thread session workspace into resource-valued arg pickers and the editor variable/resource helper drawers Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(frontend): scope the flow asset explorer's ResourceEditorDrawer to the acting workspace Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: thread acting workspace through flow asset explore controls Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: thread acting workspace through SQL REPL, secret args, helper forms, S3 inputs, saved inputs Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
9ad6927231 |
chore(main): release 1.753.0 (#9997)
* chore(main): release 1.753.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>v1.753.0 |
||
|
|
f28ea9cb99 |
feat(db-health): add connection sizing guidance (#10014)
* feat(db-health): add connection sizing guidance The Database Connections panel showed current/max connections but gave no guidance on how to size max_connections for the deployment. Derive an estimate from the live worker fleet: each worker instance shares a pool sized DEFAULT_MAX_CONNECTIONS_WORKER + (workers - 1), and each server opens up to DEFAULT_MAX_CONNECTIONS_SERVER (both overridable via DATABASE_CONNECTIONS). The endpoint now returns live worker/instance counts, the default per-server and per-worker pool sizes, the estimated peak worker connections, the reserved superuser connections, and a recommended max_connections floor (workers + one server + 25% headroom). Servers do not ping worker_ping, so the recommendation assumes one server and exposes the per-server increment. The panel renders this as a sizing breakdown and warns when max_connections is below the recommended floor. Fixes WIN-2147 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(db-health): single source for pool-size constants + sizing tests Address review: db_connect.rs kept its own copies of DEFAULT_MAX_CONNECTIONS_* that duplicate the windmill_common constants the sizing guidance reads, so tuning the runtime pool size would silently leave the guidance stale. Re-export the windmill_common constants from db_connect.rs so there is one source of truth. Add unit tests for compute_connection_sizing covering the zero-fleet, single worker, multi-instance, and reserved-clamp cases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(db-health): 20% headroom and 200-connection minimum floor Lower the sizing headroom from 25% to 20% and never recommend below 200 connections (postgres defaults to 100; cheap headroom for growth/bursts/psql). Update the guidance message and unit tests accordingly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(db-health): honor DATABASE_CONNECTIONS in sizing recommendation Address Codex P1: the runtime caps every process's pool at DATABASE_CONNECTIONS when set (db_connect.rs), but the sizing guidance always used the default 50/5 pools. For a tuned deployment this under-estimated worker demand and could hide a genuine under-provisioning (e.g. DATABASE_CONNECTIONS=100 with 5 instances is 500 worker connections, not 25). compute_connection_sizing now takes the effective DATABASE_CONNECTIONS override (read the same way db_connect.rs reads it): when set, each worker instance and server pool is that value and the worker estimate is override * instances. The response exposes server_pool_size / worker_pool_size (effective) and database_connections_override; the panel renders both pool rows and labels them (default) vs (DATABASE_CONNECTIONS), and the message states which source is used. Adds a unit test for the override path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(db-health): exclude agent workers from connection sizing Agent workers reach the API over HTTP (MODE=agent, Connection::Http) and hold no postgres pool, but their pings still land in worker_ping (written server-side by /api/agent_workers/update_ping). Counting them inflated the connection estimate. Filter the fleet query by the worker-name prefixes: DB-connected workers use "wk-" (WORKER_NAME_PREFIX), agent workers use "ag-" (AGENT_WORKER_NAME_PREFIX). Only wk- workers/instances feed the estimate; ag- workers are counted separately and surfaced as context ("N agent workers excluded — they use HTTP, not postgres connections"). Adds a unit test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
735f2b20c4 |
docs(cli): clarify workspace fork naming and parent-workspace context (Fixes WIN-2148) (#10012)
* docs(cli): clarify workspace fork naming and parent-workspace context Expand `wmill workspace fork`'s help and interactive prompts so the two positional arguments are self-explanatory: - Command description now explains that the fork is created from the currently active (parent) workspace, that `workspace_name` is a friendly display name that may contain spaces (quote it), and that `workspace_id` is a bare slug auto-prefixed with `wm-fork-` which also determines the git branch name. - Interactive name/id prompts reworded to match. Regenerated system_prompts CLI guidance to reflect the new description. Fixes WIN-2148 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(cli): default fork name to "<parent>'s fork", make it optional The fork's display name is no longer effectively required — it now defaults to "<parent workspace name>'s fork" (fetched via get_workspace_name, falling back to the local profile name / id) and stays fully overridable via the positional argument or interactive prompt. To produce this default, `setClient` and the parent-name lookup are moved ahead of the name/id resolution. The id default is decoupled from the possessive display name: when auto-naming, the id/branch slug is derived from "<parent>-fork" (e.g. wm-fork-acme-fork) rather than the awkward "<parent>-s-fork". Branch-rename forks keep their branch-derived id. Regenerated system_prompts CLI guidance. Fixes WIN-2148 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(cli): fix workspace fork help — parent is branch-resolved, not active profile Addresses the codex/pi review: the fork help said the parent is the "currently active" workspace and told users to `wmill workspace switch`, but createWorkspaceFork resolves the parent from the current git branch's wmill.yaml mapping (tryResolveBranchWorkspace) and ignores the active profile. Reword to describe the actual branch-based resolution. Regenerated system_prompts CLI guidance. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(cli): note branch-derived fork id default in rename workflows Addresses the codex review: the `[workspace_id]` help and the interactive prompt said the default id is derived from the name, but rename workflows (non-base branch / --from-branch) keep the branch-derived default (`branchDefaultId ?? branchToForkId(idBasis)`) to keep the id/branch aligned with the branch being converted. Document that special case rather than changing the intentional behavior. Regenerated system_prompts CLI guidance. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(cli): cap auto fork name at 50 chars for long parent names Addresses the codex review: the "<parent>'s fork" default appended "'s fork" to a parent name that can itself be up to 50 chars (varchar(50)), so a parent name over 43 chars produced a default exceeding the limit and tripped the effectiveName.length > 50 guard — failing `wmill workspace fork --yes` (or accepting the interactive default) for a valid parent. Truncate the parent portion so the generated default stays within 50. Verified end-to-end: a 48-char parent name now yields a 49-char default ("... Team's fork") and the fork is created successfully. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
99d0047515 |
fix: name the offending item when a fork fails on a NUL escape (#10013)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
f65fe7bf58 |
fix: replicate external secret backend secrets when forking a workspace (#10007)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
b847ca2bc7 |
feat: condensed top bar for session preview editors (#10011)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
c4cb2f373b |
fix: preserve worker group tag override on 'Run again' (#10004)
* fix: preserve worker group tag override on 'Run again' Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: keep tag override in sharable hash on args change Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: disambiguate reserved __tag hash key from args named __tag Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: prefix carried tag in sharable hash and react to tag changes Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: re-resolve dynamic tags on 'Run again' with an explanatory note Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: treat only $args-templated tags as dynamic on 'Run again' Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: let a carried tag coexist with an arg named __tag via duplicate keys Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
32c398f27d |
feat(sessions): scoped preview refresh + multi-target live editors + pipeline preview (#10006)
* perf(sessions): scope preview-tab refresh to items a chat tool touched Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(sessions): drop dead editor pane, scope raw-app reload by path Multi-target migration P0. SessionWrapper's inline editor pane was dead (the sessions page always mounts it with hideEditor); remove it and the single-target machinery (setSessionTarget/pickEditorTarget/target-keyed editor views). Scope the raw-app file/runnable preview reload to args.path (the app's workspace path) instead of the session target. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(sessions): back editor state with per-(kind,path) cells Multi-target migration P1. Replace the three per-kind singleton stores/slots with per-(kind,path) cell maps, created on demand and kept (eviction deferred to P3). The runtime's public interface is unchanged: the flowStore/scriptStore/savedScript/rawApp/... getters and slot(kind) now forward to the 'active cell' per kind (a single-target shim, tracked by activePath, removed in P2 when the UI mounts one editor per tab). loadFlow/loadScript/loadRawApp and syncPreviewWithDeployed operate on the resolved cell; load logic and semantics are otherwise unchanged, so loading one item no longer clobbers another's state. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sessions): mount every editable preview tab as its own live editor Multi-target migration P2 — the behavioral flip. resolvePreviewTab no longer takes a target: any editable route (script/flow/raw_app) resolves to an in-process editor, so several items are live at once (iframes remain only for real pages and regular non-raw apps). Each editor binds its own per-(kind,path) cell; the draft codecs close over that cell's store so two editors never cross-write. The single-target shim (activePath + the flowStore/scriptStore/... getters + slot(kind)) is removed; runtime exposes flowCell/scriptCell/rawAppCell(path). Tab open/navigate dedupe by (kind,path) and no longer setTarget. setLiveEditorDraft is gated on the visible tab (isActiveTab) so N editors don't clobber the one-per-(workspace,kind) live-draft slot (path re-key deferred to P4). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * perf(sessions): evict unreferenced editor cells; drop dead warm-editor LRU Multi-target migration P3. Bound the per-(kind,path) editor cell maps: pruneEditorCells drops every cell no open preview tab still references, wired to a new onTabsChanged adapter callback fired on each tab-set change — so closing or navigating a tab away from an item reclaims its cell (dedupe keeps <=1 editor tab per item, so a pruned item has no live editor to strand). Also remove the now-dead editorWarmIds/promoteEditorWarm/MAX_WARM_EDITORS warm-editor LRU: its only reader (SessionWrapper.mountEditor) was removed in P0, and mounted editors are already capped per-tab by mountedTabKeys. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(sessions): retire session.target; preview is fully tab-driven Multi-target migration P4 (final). Remove the session.target field and setSessionTarget: the preview is driven entirely by the tab model now (P2). hydratePreviewTabs no longer seeds a tab from target (saved previewTabs only); openEditorInSession seeds the preview via resetSessionPreviewTabs; normalizeLegacySession drops the retired target field from old records. The setLiveEditorDraft focus gate (isActiveTab, one-per-(workspace,kind)) is kept as-is; a per-path re-key is a possible future refinement, not needed for correctness. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(sessions): describe editor cells as-is, not by their refactor history Address standards review: AGENTS.md requires comments describe the code as it is, not its drafting history. Drop the 'used to be per-kind singletons' / 'pre-refactor empty editor' / 'now' phrasings from the cell comments. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(sessions): update stale runtime.rawApp.val comments to cell.store Address spec review: two comments still referenced the removed runtime.rawApp.val accessor; the live code uses the per-cell store now. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(sessions): fix editor-cell comments after main merge Main's #9993 added svelte-ignore comments describing the old runtime.savedFlow.val / runtime.rawApp.val singleton bindings. The multi-target refactor binds each tab's own editor cell (cell.store / cell.saved), so update the comment text to match; the ownership_invalid_binding directives themselves remain correct (the targets are still runtime-owned). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sessions): restore data-pipeline preview as a live editor tab The multi-target refactor removed the old single-target editor pane — PipelineEditorView's only mount point — so open_preview(kind="pipeline") opened nothing, even though the chat tool and system prompt still make it the first step of pipeline authoring. Route a /pipeline/<folder> preview tab to the in-process graph editor: - previewRouter: parsePipelineRoute + resolvePreviewTab map the folder to a pipeline editor slot; PreviewSlot.editorKind gains 'pipeline'. - previewTargetForSessionTarget('pipeline') returns the folder route target (was undefined); open() keeps a single pipeline tab and retargets it to the requested folder, since all pipeline tabs share one runtime.pipelineEditorState. - PreviewTabHost mounts PipelineEditorView for the pipeline slot. - PipelineEditorView gains an `active` prop; AI-helper registration and the live-badge poll now gate on isActiveSession && active. Register the pipeline tools on the session's own chat, not the singleton: PreviewTabHost mounts the view outside the SessionWrapper subtree that provides the scoped aiChatManager context, so getAiChatManager() fell back to the app-wide singleton — build_pipeline_node / edit_pipeline_node never reached the session chat and the model fell back to write_script (whose draft never appears on the canvas). Use runtime.manager directly instead. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): scope list-page preview refresh to the page each tool changes The scoped-refresh pass reloaded every open list-page preview tab on any workspace mutation (reloadPages: boolean), so creating a schedule also refreshed the Resources / Variables tabs. Replace the blanket flag with the specific page paths each tool can change: write_schedule → /schedules, write_resource → /resources, write_variable → /variables, create_folder → /folders, write_trigger → the trigger kind's page; delete/deploy/discard/rebase map their `type` to its page (none for script/flow/app). Item-editor writes now reload no pages — their live editor self-syncs. reloadTabs refreshes a list-page tab only when its own path is in the touched set. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(sessions): drop the inert item-reload path; extract a tested previewReload module Post multi-target, every editable item is a live editor whose reload() no-ops, and the one iframe item kind (legacy drag-drop apps) is never emitted as a scope — so the whole `scopes` half of the preview-reload machinery could never fire. Remove it (PreviewKind, PreviewScope, scopeKey, itemTypeToPreviewKind, pendingScopes, and the item-route branch of reloadTabs); the `pages` path already covers every real reload. Lift the surviving pure logic out of the 900-line route component into previewReload.ts — toolReloadEffect(name,args) -> {pages} and a new tabsToReload(tabs,pages) mirroring selectPreviewTabsToClose — and cover it with previewReload.test.ts (per-tool page mapping, item kinds reload nothing, the unknown/local-tool silent-stale guard, loc-over-url matching). Also clear session.target leftovers: delete the unread EDITOR_TARGET_KINDS export and rewrite five comments that still described the removed single-target pane / target-record write. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(sessions): state the preview-reload self-sync invariant once Consolidate the "live editors self-sync, only list pages reload" rationale to previewReload.ts and drop the drafting-history phrasings the review flagged: the update_user_instructions incident and the "(not the runtime)" contrast in sessionDraftCodecs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): follow the editor cell when a live tab retargets Address PR review findings on the multi-target preview. P1 (Codex) — draft sync stayed bound to the old cell after an in-place tab retarget. useUserDraftSync captured `codec` once, but navigate() re-points a live editor tab (script/flow/raw_app) to another item without remounting, so path/workspace/ready followed the new item while the codec still read/wrote the previous cell's store — cross-writing drafts. Make `codec` a reactive getter like the hook's other inputs; SessionEditorTarget rebuilds it per path. P2 (Claude) — navigate() now enforces the single-pipeline-tab invariant that open() does: retargeting to a /pipeline/<folder> route focuses and re-points the existing pipeline tab instead of turning the active tab into a second editor racing the shared pipelineEditorState. P2 (Claude) — the deploy-in-session handler peeked an editor slot via the create-on-miss cell accessors, allocating an empty cell for items with no open tab. Add a non-creating runtime.loadedEditorPath(kind, path) and use it. P2 (Claude) — correct a SessionPicker comment left stale by the session.target removal (the preview no longer seeds from a target). Tests: two navigate() pipeline-invariant cases. npm run check 0 errors; 167 session unit tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
fb12b23e01 |
fix: session preview editors and picker dropdown overflow (#10010)
* fix: constrain script/flow/raw-app editors to container height in session preview Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: clip session preview picker dropdown to popover so it stops overflowing the page Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
a00ee5196b |
feat: shared tab system, universal markdown code blocks, subtle scrollbars (#10003)
* feat: universal styled markdown code blocks with copy button and subtle scrollbar Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sessions): use the shared DraggableTabs for the preview tab strip The session preview tabs were bespoke markup; converge them onto the same DraggableTabs component the raw-app editor uses, gaining drag-reorder and keyboard nav. The active tab keeps its breadcrumb/router picker via a new tabAccessory snippet, and tabs persist their new order. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): keep the new-tab + button right after the last tab Add an afterTabs snippet to DraggableTabs that renders inside the scroll row after the tabs (unlike trailing, which stays pinned outside it), and move the session preview "+" there so it sits next to the last tab. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(tabs): use the subtle ScrollableX scrollbar for Tabs/TabsV2 headers Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * style(sessions): use bg-surface for the preview tab strip Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * style(tabs): add subtle shadow-sm to the selected DraggableTabs tab Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * style(tabs): drop selected-tab shadow; session strip bg-surface-secondary/50 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * style(sessions): drop persistent bg on preview bar buttons, hover-only Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(scrollbar): share a .scrollbar-subtle utility across tabs and chat Extract ScrollableX's hover-revealed scrollbar styling into a global .scrollbar-subtle utility (both axes, size via --wm-scrollbar-size), have ScrollableX consume it, and apply it to the AI chat message list so the chat scrollbar matches the tabs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: address review — scope HighlightCode copy button, plaintext unknown fences, Tailwind ScrollableX - HighlightCode: keep the subtle CopyButton + surface chip behind buttonsOnHover so the ~20 non-markdown callers keep the original light copy Button. - MarkdownCodeBlock: unlabeled/unknown fences render as plaintext instead of being mis-colored as TypeScript; added common language aliases (ts/js/py/...) so real languages still highlight. - ScrollableX: replace the custom <style> block with Tailwind overflow classes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * style: make chat and session-sidebar typing dots slightly smaller Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: address auto-review — powershell fence to plaintext + reorder tests - MarkdownCodeBlock: drop 'powershell' from the sql group so it renders plaintext instead of SQL-colored (no powershell highlighter in the map). - sessionPreviewTabs.test.ts: cover reorder (reorders+persists, ignores unknown ids / keeps omitted at end, no-op when unchanged). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: keep scrollbar-hidden on Tabs row as TroubleshootFlowTutorial selector hook codex-review: removing scrollbar-hidden broke the tutorial's '.border-b.flex .flex-row.whitespace-nowrap.scrollbar-hidden.mx-auto' selector. The class is inert on the non-scrolling row (ScrollableX owns the scroll) but is kept as the tutorial's stable hook. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: preserve raw <pre> content in MarkdownCodeBlock (codex-review) As the universal pre renderer, MarkdownCodeBlock also handles sanitized raw HTML <pre>text</pre> from rehypeRaw, where the text is a direct child of <pre> (no <code>). Fall back to that text child so raw pre content isn't dropped to an empty block. Kitchen-sink sample gains a raw <pre> case. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
286da005ef |
feat: AI chat background jobs tray with detach, approval and preview (#9982)
* feat(ai-chat): background jobs tray with detach, approval and preview Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(ai-chat): route exec_datatable_sql through the jobs tray Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(ai-chat): jobs tray — orange queued badge, 5-recent pagination, drop remove button Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): silence dev-only false-positive binding warnings Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): silence dev-only false-positive binding warning in FlowEditorView Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(ai-chat): auto-expand jobs tray on approval, close modal on resume Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(ai-chat): let the AI set a per-call inline wait before jobs detach Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(ai-chat): auto-resume the chat when a background job finishes while idle Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(ai-chat): merge jobs tray and edits bar into a segmented session bar Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ai-chat): address review — canceled-job handling, cross-chat poll guard, tests Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ai-chat): gray chip dot for canceled-only jobs instead of green Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ai-chat): keep jobs segment right-aligned when there are no edits Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ai-chat): address /review — drain snapshot, live region, a11y, leading-ellipsis, remove dev harness Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ai-chat): announce all same-tick job completions; drop redundant aria-live Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ai-chat): guard poller re-entrancy; datatable error fallback (auto-review P2/nit) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ai-chat): honor tool formatter on detached job completion; coalesce poller Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ai-chat): persist tool result formatter so rehydrated detached jobs keep contract Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
d467161117 |
fix: bump bundled Go CLIs to patched versions to clear image CVEs (#9996)
The runtime image bundles several Go CLIs whose pinned versions were built with an outdated Go toolchain (go1.21.7 for kubectl/helm), which image scanners flag for fixable Go stdlib CVEs. Bump each to the latest release built on the current patched Go 1.26.4: - kubectl 1.28.7 (EOL) -> 1.36.2 (latest stable) - helm 3.14.3 -> 3.21.2 (latest v3; staying on v3 to avoid the Helm 4 breaking changes for a bundled CLI users depend on) - crane v0.20.6 -> v0.21.7 crane is also updated in DockerfileSlim/DockerfileSlimEe (the slim images don't bundle kubectl/helm). The docker client comes from the floating docker:29-dind tag, which already rebuilds to a current Go toolchain. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
1ed979a2de |
refresh picomatch in lockfile to unbreak npm ci (#9994)
The ai-evals CI job's `npm ci` (frontend) failed with:
npm error `npm ci` can only install packages when your package.json
and package-lock.json are in sync.
Missing: picomatch@4.0.5 from lock file
`picomatch` is a floating transitive: svelte-check pulls it as an
`optional peer` at `^4.0.4`, and vite/vitest/tinyglobby at `^4.0.x`. The
lock pinned 4.0.3/4.0.4, but 4.0.5 was published upstream. On a cold-cache
CI runner npm re-resolves those ranges against the registry and picks the
latest (4.0.5), which isn't in the lock — so `npm ci`'s sync check fails.
It passes locally only because a warm npm cache still serves 4.0.4.
Fix: `npm update picomatch --package-lock-only` (npm 10.9.8, matching CI's
node 22) to refresh every picomatch node to 4.0.5 (and the 2.x line to
2.3.2). Lockfile-only, all semver-patch; no package.json change. Verified
`npm ci --dry-run` is back in sync with a cold cache.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
223e1569ce |
chore(main): release 1.752.0 (#9974)
* chore(main): release 1.752.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com>v1.752.0 |
||
|
|
f7efb646bf |
fix(pipelines): live materialize/dataset editing — stale graph, phantom drafts, stale Save-all deploys (#9990)
* fix(pipelines): live materialize/dataset edits reflect on the graph; no phantom draft after deploy Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(pipelines): Save all deploys the open pane's live buffer, not the stale draft snapshot Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(pipelines): pin deployedFromPane to the shipped content so mid-deploy keystrokes still promote to a draft Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(pipelines): draft rename ping-pong loop, stale rename deploys, inactive-draft input lineage Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(pipelines): dedupe inferred-lineage overlay against accumulated edges; first draft teardown still captures reads Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(pipelines): record an authoritative empty read capture on uncaptured draft entries Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(pipelines): teardown skip compares lineage too, so access-only overrides still persist Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * style(pipelines): compress persist-back guard comments to the invariant Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a6276b5900 |
feat: smooth bursty AI chat streaming with a typewriter reveal (#9991)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
6b01caaf26 |
fix(ai): flow writer builds approval steps as scripts, not identity (#9985)
* fix(ai): flow writer builds approval steps as scripts with getResumeUrls, not identity Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(ai-evals): accept rawscript or script for approval step type The flow-writer prompt allows an approval step to be `type: rawscript` or `type: script`, but the topLevelStepTypes check pinned an exact `rawscript` match, so a valid `type: script` approval would fail deterministically. Let the check accept a list of allowed types. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
804178f5e1 |
fix(sessions): auto-rename regression + preview-panel and fork nits (#9993)
* perf(sessions): don't mount preview tabs when side panel is collapsed * fix(sessions): cap metadata max_tokens so Anthropic auto-rename works Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): drop redundant -fork suffix from auto-generated fork names Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): default 'also delete forked workspace' to false Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(copilot): apply metadata max_tokens cap on the OpenAI Responses 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> |
||
|
|
63e3e7735f |
lign copy button on fork-less workspace rows (#9992)
The hover-revealed copy button in the workspace picker sat flush against the menu's right edge on fork-less rows, because only forked rows render an expand chevron that insets the copy button. Reserve the chevron's slot on fork-less rows so copy buttons align across rows and keep right padding. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
4bb82ad6cd |
feat: open runs/schedules pages from AI chat in session preview tabs (#9976)
* feat(copilot): open runs/schedules pages in session preview tabs Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(copilot): drop buggy in-place nav, always chip outside a session Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(copilot): open_page covers variables/resources/assets/audit-logs/settings, perm-gated Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(copilot): open_page adds folders, groups and all trigger kinds (EE-gated) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(copilot): close_page tool to close session preview tabs Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(copilot): fail-closed on unavailable trigger_kind in open_page handler Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(copilot): gate open_page on operator_settings, keep open_preview mention preview-only Gate the open_page page set on the workspace operator_settings for operators (mirrors OperatorMenu) instead of hardcoding runs/assets, with an empty-enum guard. Also move the open_preview cross-reference out of the always-on prompt line into the preview-gated block so it isn't advertised when preview tools are off. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(copilot): gate open_page on the session's operating workspace A session chat targets its own (possibly forked) workspace while $workspaceStore stays on the navigation workspace, so operator_settings must be read for the operating workspace, not the global store. Thread it through GlobalToolHelpers so both setSchema (advertised enum) and the handler guard gate on the same workspace; the global side-panel chat still follows the live store. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
7046dc6dfb |
fix(sessions): scope fork session Edits to session-edited items only (#9989)
* fix(sessions): scope fork session Edits to session-edited items only A session chat with an undefined modified-items mask fell back to showing every draft in its (possibly forked) workspace, so the Edits bar/diff drawer listed all fork drafts instead of just what the session edited. Always track session chats: seed an empty mask for legacy chats in loadPastChat and guard the not-yet-persisted-chat case in initRuntime. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: clarify session chats always persist their modified-items mask Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
88c2d0e8e3 |
feat(cli): clarify fork-branch workspace auto-targeting in output (#9988)
* feat(cli): clarify fork-branch workspace auto-targeting in output * fix(cli): auth comes from saved profile, not wmill.yaml, in fork notes * fix(cli): consolidate workspace resolution logs, fork-target last-used profile * chore: regenerate system prompts Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(cli): fork-target interactively created profiles, dedupe workspace line --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
edfe7b415a |
fix(cli): auto-derive cascade triggers in --local pipeline graph (#9978)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
7efeae26d8 |
feat: add fork_parent_workspace claim to OIDC tokens for fork workspaces (#9987)
* feat: add parent_workspace claim to OIDC job tokens for fork workspaces Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor: rename claim to fork_parent_workspace for clarity Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore: update ee-repo-ref to e2df172596e00877068d4b0a98afaef62fe429d1 This commit updates the EE repository reference after PR #651 was merged in windmill-ee-private. Previous ee-repo-ref: f73001ac6c038694cfc2604233a59be1c0daa40b New ee-repo-ref: e2df172596e00877068d4b0a98afaef62fe429d1 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> |
||
|
|
ffb80d1ae3 | regenerate prompts | ||
|
|
87f8d46aaf | fix(ai-agent): align agent_actions_success with agent_actions for mcp and websearch (#9983) | ||
|
|
95031903eb |
feat(sessions): v2 unified sidebar with family/fork scoping and preview router (#9816)
* feat(sessions): prototype session-mode layout wrapper (design exploration) Do not merge — design exploration of an optional full-page 'session mode' layout for AI sessions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sessions): add full-screen toggle for the session panel Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sessions): workspace-tree rail with browse mode and collapsible sidebar Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sessions): restore sessions page with iframe preview of current view Roll back the session-mode layout wrapper: sessions is a dedicated /sessions page again rather than a layout toggled over the live app. Opening a session from a Windmill page captures that page as the session's preview target; the page shows the chat beside a preview panel that iframes the target, with a breadcrumb and full-screen toggle. - Remove SessionShell wrapper and the sticky sessionLayout flag; +layout.svelte always renders the normal global sidebar. Sidebar components introduced alongside the wrapper are kept for the upcoming sidebar rework. - sessionMode.svelte.ts: per-session preview-URL map (captureSessionView / sessionPreviewUrl) + withMenuHidden to drop the previewed page's own sidebar via the nomenubar flag. - Drop the #content sidebar gutter (pl-12/pl-40) when the menu is hidden, so the nomenubar preview fills the panel edge-to-edge. - SessionPicker: activate() navigates to /sessions; createAndOpen() seeds the new session's preview from the current page. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sessions): add exit (X) button to chat header Add a close button at the top-right of the session chat header that leaves the sessions page and navigates to the session's target (the previewed page), so exiting lands on exactly what was being previewed, full-screen with the sidebar. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sidebar): promote workspace picker and widen the sidebar Replace the Windmill logo header with the workspace picker so the active workspace is the sidebar's anchor: show the workspace name (not the id) in a stronger weight, with a down-chevron and a bottom-aligned dropdown. Add the same dropdown chevron to every other sidebar menu trigger (Favorites, User, Settings, secondary/Help groups) via an opt-in MenuButton option, and widen the expanded sidebar from w-40 to w-48 (content offset kept in sync). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sessions): collapsible preview panel + sidebar session entry polish Add a collapse control to the sessions preview panel (top-left, matching the legacy editor's PanelRightClose), animated with an x-axis slide. The panes carry no explicit size so Splitpanes auto-distributes — the chat fills the width when the preview collapses and splits evenly when both are shown. When collapsed, a floating "Open side panel" Button (top-right) brings it back. Also gather the AI sessions section into the Favorites/Search container via a new embedded mode on SessionPicker, replace the small "+" with a full sidebar "New AI session" entry, and drop the chat header's exit (X) button. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sessions): split family/fork picking with a global breadcrumb Separate workspace-family selection from fork selection. The sidebar workspace picker now lists families (roots) only and shows the active family name even inside a fork. A persistent `family · fork` breadcrumb lives in the global logged layout (WorkspaceBreadcrumb, rendered via a new AiChatLayout topBar snippet): the fork segment opens the fork picker popover, staging a pending fork on a draft session (the old in-chat SessionWorkspaceBar semantics) or switching workspace directly elsewhere. WorkspaceFamilyPicker gains onRequestCreateFork to route create-fork to the global fork modal in non-session contexts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * revert(sessions): drop the global fork breadcrumb top bar Remove WorkspaceBreadcrumb and its AiChatLayout topBar wiring; restore the in-chat SessionWorkspaceBar for draft fork-picking and the original WorkspaceFamilyPicker. The sidebar workspace picker stays family-only (roots, no forks listed). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sessions): family/fork-scoped sidebar with scope header Restructure the sidebar into a family-scoped region (workspace family header → New AI session → session list) and a workspace-scoped region (a Fork scope header → Favorites + Search → workspace items), split by a full-width divider. The new WorkspaceScopeHeader is a full-width root/fork picker: accent-styled on a fork (text + faded border), with a bottom "<workspace> settings" link; picking a different fork from a session navigates home. The family header keeps the root's color when inside a fork, and drops "Fork current workspace" / "Workspace settings" (now surfaced via the scope header and the bottom Settings dropdown). The session preview header shows "family · fork <page path>". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): drop colon from "Workspace root" scope label Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sessions): turn the preview breadcrumb into a page router Every breadcrumb segment now opens a drill picker that lists workspace pages (Home, Runs, Workspace settings, …) alongside scripts/flows/apps. Picking either steers the preview iframe without leaving the sessions page. The non-item case resolves to the page's real name (e.g. "Workspace settings"). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sessions): tabbed preview with mounted tabs + Home quick-access The preview is now a tiny tabbed browser: the first tab is pinned to the session's view, "+" opens the router picker to add more, and every tab stays mounted (stacked + visibility-toggled) so switching preserves each page's state. Per tab, the commanded `url` is decoupled from the observed `loc` so in-iframe navigation never reloads the frame. Home is also pulled up as the first quick-access item in the router picker. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sessions): persist preview tabs with the session in IndexedDB Save the open preview tabs (+ active tab) onto the session record so reopening a session restores its tabs. Write-behind is debounced since a tab's observed location churns as the user browses; transient (unsent) sessions skip it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * perf(sessions): lazy-mount preview tab iframes Only boot a tab's iframe the first time it's activated, then keep it mounted. Restoring a session with N saved tabs now boots just the active tab instead of N full Windmill apps at once. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sessions): fold the breadcrumb picker into the preview tabs Drop the separate family·fork/path breadcrumb bar. The active tab now doubles as its own router picker (click it to re-point the tab); inactive tabs switch on click. Removes the now-unused PreviewRouterSegment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(raw-apps): auto-compact the editor when it opens narrow On the first measured layout, if the editor container is under 800px, drop to the merged single-pane view and retract the file sidebar (e.g. when shown in the narrow session preview pane). Applied once on open; the sidebar is set without persisting so it never overrides the user's saved preference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sessions): auto-refresh preview tabs after mutating chat tools Add a tool-completion hook in the shared chat dispatcher; the sessions page subscribes and debounced-reloads every mounted preview tab when a write/deploy/ delete tool finishes (matched by verb prefix, so read/test/navigate tools skip). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): keep nav bar hidden across in-preview navigation The sessions preview iframes load pages with `nomenubar=true`, but the layout recomputed `menuHidden` from the current URL on every navigation, so a client-side nav inside the preview (an in-page link or redirect) dropped the flag and the global nav popped back in. Make the hidden state sticky for the document's lifetime when running inside an iframe; the top window is unaffected so the oauth-callback toggle still works. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): persist hidden nav across full reloads in preview iframe The in-memory sticky flag was lost on a full document load inside the preview (a navigation that drops the `nomenubar` query param), so the global nav — including the mobile burger — reappeared. Store the sticky state in sessionStorage so it survives full reloads within the iframe's browsing context. The top window is unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): refuse to mount sessions UI inside a preview iframe A preview tab navigating back to /sessions would mount another sessions page with its own preview iframes, nesting endlessly. When the page detects it is running inside an iframe, render a stub that breaks out to the top-level window instead of mounting the full UI. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sessions): Workspace ⇄ AI Sessions mode switch + workspace-decoupled session chat Add a route-derived mode switch that flips the sidebar rail between the classic workspace navigation and a dedicated AI-sessions sidebar, cleanly separating sessions from the workspace nav. - SessionModeSwitch (Workspace | AI Sessions) in the rail; session mode is exactly "on /sessions", so the switch just navigates in/out (sessionSwitch). - Session chats target their own (possibly forked) workspace via AIChatManager.operatingWorkspace/workspaceResolver without mutating the global workspaceStore; "Acting on" header strip shown once a session has started. - Flow editor AI button becomes "Open in AI session": saves the draft, then opens a new session targeting the current flow. - New sessions: no default preview (empty state instead of iframing home, panel collapsed); preview-panel collapse persisted per-session on the record. - Persist nav-rail collapse (manual toggle only) and drop the editor-route auto-collapse that fought it. - Smaller fork picker; add a `preview` proxy so `vite preview` reaches the backend for production-build demos. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ai-chat): replay assistant turns verbatim so thinking blocks validate The global AI chat reconstructs each assistant turn from an OpenAI-shaped message, keeping only the thinking/redacted_thinking blocks and re-injecting them at the front of the content array. When a turn interleaves thinking with the native web_search tool and ends in a tool call, this reorders the thinking blocks and drops the server_tool_use / web_search_tool_result blocks. Anthropic validates each thinking block's signature against the blocks that precede it in the latest assistant message, so the replayed turn is rejected: 400 invalid_request_error "messages.N.content.M: `thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified. These blocks must remain as they were in the original response." Preserve the full `finalMessage.content` verbatim (`_anthropicContent`) and re-emit it unchanged, instead of extracting and reordering thinking blocks. Skip the standalone text message that the streamer emits for the same turn (its text is already inside `_anthropicContent`). The previous thinking-only path is kept as a fallback for sessions persisted before this change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(sessions): give empty-state preview picker its own open state * feat(sessions): render preview editors as components, not iframes Introduce a PreviewTabHost seam that routes each preview tab to either an in-process editor (the session's script/flow/raw_app target, reusing the existing *EditorView wrappers + shared runtime) or an iframe fallback for pages and other items, behind a uniform reload(). resolvePreviewTab classifies a tab from its URL + the session target. Also intercept in-iframe navigation to an editor route (logged layout beforeNavigate): post the target up to the sessions page, which promotes the active tab to the live editor component, so an editor is never booted inside an iframe. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): drive open_preview tool through the multi-tab model Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: plan SessionPreviewTabs deep module for sessions preview tabs Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(sessions): own preview tabs in a SessionPreviewTabs deep module Collapse the three drifting preview-tab copies (page-local state, session record, legacy previewUrls localStorage) into one live owner held on SessionRuntime.previewTabs. Both the sessions page (renderer) and the open_preview/get_preview_status tools cross it, so both sync effects and the localStorage seed disappear; url/target writes become atomic. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): gate the Workspace/Sessions switch behind the global-AI dev flag The SessionModeSwitch is the only entry point into the AI-sessions experience, so gate it on wm_dev_global_ai like the global chat and the sessions page — otherwise the unfinished mode ships to prod. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): pin the settings footer and normalize row text in the fork dropdown Split the family picker menu into a scrollable body + a pinned settings footer so the workspace-settings link stays visible while the fork list scrolls. Give every row a uniform text-primary font-normal style (rows were inheriting a bold 600 weight; the settings link was text-secondary). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sidebar): fold theme switch into the settings dropdown and keep it in session mode Move the Switch-theme toggle into the sidebar Settings dropdown and reorder its entries (bottom-to-top: Instance, Workspace, User). The dropdown now renders in both navigation and session modes; session mode hides only the workspace-settings entry (the rail's global workspace doesn't map to a session's forked workspace). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(fork): validate fork name/id length before creation Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): title open-in-workspace button "Open in workspace" Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): keep AI chat working when the sessions dev flag is off Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): match burger drawer width and keep it open on mode toggle Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sessions): surface the dev-workspace badge across session workspace pickers Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): dedup navigate, sanitize hydration, cap mounted tabs Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(fork): support forks of forks via a base-workspace picker Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sidebar): family expansion, pinned menu actions, animated popovers Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(sessions): persist unsent drafts, gate preview, loading state Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(sidebar): group fork picker on top and unfold the session list Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(sessions): capture splitter pointer so off-window release ends drag Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor(sessions): retire the pinned preview tab (dot and no-close) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(sessions): shared open-in-AI-session button across editors Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(sessions): dedup page tabs, flush on hide, review cleanups Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(sessions): give unsent drafts a side panel, reset tabs on retarget Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(sessions): keep the session fork icon neutral except when detached Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(sessions): scope session-mode restore and transient reuse to family * fix(sessions): preserve session mode across workspace switches Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(sessions): reconcile open session with family on workspace switch Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(sessions): lazy-load runtime in session switch to keep it node-testable Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(sidebar): add bottom brand mark and standalone workers/logs links * feat(sidebar): add name+id copy tooltip to workspace picker * style(sidebar): add spacing between settings and brand mark * feat(forks): id-based fork creation, fork color theming, picker polish * feat(forks): copy-id in session header, inert chip, fork form polish * fix(sidebar): restore logs, help, user and leave-workspace menus * feat(sidebar): carry active tick on collapsed family root * feat(dev): add settings-menu kitchen sink page * fix(sessions): fail closed for unbound persisted sessions in family scope * fix(sidebar): keep workspace URL param in sync across switches * feat(sessions): remove home page from preview tab navigation * refactor(sidebar): dedupe shared helpers and address review findings * feat(sessions): keep preview hosts alive across session switches * feat: workspace settings links in session rail, acting badge and family picker Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: refresh session changes bar after out-of-window deploy The session "Edits" bar re-fetched its draft list and existence checks only on AI turn-end, tab visibilitychange, and drawer open. Deploying an item from a full-page editor in a second browser window left the bar stale: that tab never goes hidden, so visibilitychange never fires, and the badge kept reading "1 draft" while opening the drawer showed no pending change. Add a window `focus` listener alongside visibilitychange so returning to the session window re-syncs the bar, and refresh the dock when a badge is clicked so the drawer always opens on fresh state. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(sessions): show name/id copy tooltip on acting badge, drop inline copy * fix: keep editor header cloud indicator visible at narrow widths Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(sessions): scope preview reload to the mutated item Reloading every mounted preview tab on any mutating chat tool blank- rebooted unrelated raw-app previews: a raw app that isn't the session's live-editor target renders as an /apps_raw/edit iframe, and reloadAllTabs hard-reloaded it (frame.location.reload) on every write/deploy elsewhere. Pass the tool args through the completion listener and scope the reload: an item-route iframe reloads only when its item was actually touched. The changed item is args.path for workspace-path tools; the raw-app file tools (write_app_file, …) pass a leading-'/' frontend file path and edit the active session's target app, so scope to the target; anything else is unresolved and reloads everything (safe fallback). Changed paths accumulate across the 500ms debounce. Non-item pages still always reload; live-editor slots still no-op. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(diff): honor side-by-side/unified toggle and widen draft drawer Monaco forces inline view below its 900px renderSideBySideInlineBreakpoint, which overrode our SIDE_BY_SIDE_MIN_WIDTH gate and made the toggle a no-op in the ~800px draft drawer. Disable useInlineViewWhenSpaceIsLimited so our width logic wins, and widen the drawer default 1200->1500px. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(diff): vertically center the element-header icon with its path The path renders as ExternalEditLink's inline-flex <a> in production, which sat ~2px low on the wrapper's line-box baseline. Make the path wrapper flex+items-center so the icon and path align by box. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(diff): reflect the auto-unified downgrade in the drawer view toggle The side-by-side/unified downgrade lived inside each DiffEditor's width gate, so the drawer toggle still showed side-by-side when the narrow column rendered inline. Measure the diff column, make the drawer authoritative (force inline when narrow), and reflect it in the toggle (unified selected, side-by-side disabled) while preserving the user's preference for when it widens again. Shared SIDE_BY_SIDE_MIN_WIDTH via diffEditorTypes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(sidebar): make the nav rail resizable with rem scaling Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(diff): gate Monaco auto-inline behind a prop to keep narrow diffs unified Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ui): restore instant popover/dropdown default, opt sidebar and sessions in Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sidebar): restore delete-forked-workspace action in the settings menu Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(tooltip): add cursor anchoring option and use it for the name/id tooltip Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(dev): remove settings-menu kitchen sink scaffolding Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(docs): remove session-preview-tabs owner plan doc Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(dev): drop vite preview-server proxy scaffolding Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sidebar): scroll nav as one block with fade hints, pin settings to bottom Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sidebar): guard against concurrent pointer drags leaking resize listeners Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: scope session preview, LLM proxy, and raw-app workspace switch Address PR review findings: session preview iframes, the AI chat LLM proxy client, and the raw-app workspace-switch guard all now resolve the session's effective workspace instead of the global navigation workspace. - withMenuHidden appends the session workspace as ?workspace= so preview iframes render fork-scoped pages against the fork, not the nav workspace. - AIChatManager builds the proxy clients from operatingWorkspace so the LLM request hits the session workspace's /ai/proxy, not the global singleton (init'd only on global workspace changes). - workspaceSwitchUrl adds /apps_raw/edit|get to EDIT_PAGES so switching workspace from a raw-app editor/viewer goes home like other item pages. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: scope session model, preview picker, and open-in-workspace to session Second-layer workspace-scoping fixes from PR review: three more paths resolved the global navigation workspace instead of the session's effective workspace. - SessionWrapper loads copilot config (models/providers) for the session's acting workspace, so getCurrentModel/modelProvider match the workspace the chat writes to, not the nav workspace. - PreviewRouterPicker takes a workspaceId prop; the sessions page passes the session's effective workspace so the breadcrumb/+ picker lists fork items and its drafts, not the nav workspace's. - 'Open in workspace' appends ?workspace= via the new withWorkspaceParam so the full-page link opens the active preview under the session workspace. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): only the active session loads global copilot config Follow-up to the session-workspace copilot fix: SessionWrapper's loadCopilot effect ran in every warm/hidden wrapper, and since copilotInfo/copilotSessionModel are global, a background session in a different workspace could finish loading after the active one and leave the active chat on the wrong provider/model. Gate the load on currentSessionId so only the active session writes the shared config. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): guard copilot load race + scope app handoff to workspace Two more session-vs-navigation workspace fixes from PR review: - loadCopilot now applies only the most recent call's result via a monotonic token, so a stale async load from a just-switched-away session can't clobber the active session's global model/provider config. - navigateEditorTo carries the session workspace on the low-code app handoff (goto /apps/edit) so the app opens in the fork the session acts on, not the navigation workspace. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): scope live-editor breadcrumb picker to session workspace The session preview's live script/flow/raw-app editors mount with a session workspaceId, but their EditorHeader breadcrumb picker (WorkspaceItemDrillPicker) still loaded items and drafts from the global navigation workspace. Thread an optional workspaceId prop from each builder's autosaveWorkspace through EditorHeader -> BreadcrumbSegment -> WorkspaceItemDrillPicker; it falls back to $workspaceStore, so non-session editors are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(sessions): fix stale setSessionTabs transient-persistence comment Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): scope live-editor deploy/save/triggers to session workspace The session preview's live script/flow/raw-app editors load and autosave against the session's acting workspace, but their internal deploy, save-draft, trigger-loading, fork-eligibility, worker-tags and live-editor-draft operations read $workspaceStore directly. Since a session deliberately leaves $workspaceStore on the navigation workspace, a fork-scoped session deployed/saved to the wrong workspace (verified: deploy POSTed to the nav workspace and 400'd). Introduce an opWorkspace derived (autosaveWorkspace ?? $workspaceStore) in each builder and route the operation reads through it. autosaveWorkspace is only set by the session editor views, so opWorkspace equals $workspaceStore for every non-session editor — no behavior change outside sessions. Verified in-browser: a fork-session deploy now POSTs to the fork (201 Created) while a normal editor still targets the navigation workspace. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): staged pending fork chip uses default accent, not parent's color A staged pending fork's effective workspace resolves to its parent (setSessionPendingFork sets pending_workspace_id = parent_workspace_id), so WorkspaceScopeTrigger read the parent workspace's color and painted the 'Acting on' chip in the parent's hue (e.g. yellow) instead of the neutral fork accent. A real fork shows its own color; a not-yet-created one has none, so fall back to the default fork accent unless the creation form passes an explicit color preview. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): scope raw-app deploy/save/version to session workspace The raw-app create/update/version/diff/save operations live in RawAppEditorHeader (not RawAppEditor), and still read $workspaceStore — so a fork-scoped session's raw-app deploy targeted the navigation workspace, the same class of bug already fixed for scripts and flows. Route those operation reads through opWorkspace (autosaveWorkspace ?? $workspaceStore); the inSessionPane-guarded draft-cleanup blocks are intentionally non-session and keep $workspaceStore. Verified in-browser: a fork-session raw-app deploy POSTs update_raw to the session fork (200). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): key live-editor load cache on workspace, not just path The script/flow/raw-app loaders returned early when loadedPath matched the requested path, ignoring the workspace. Retargeting a session to the same item path in a different fork kept the old workspace's loaded content while the editor props switched to the new workspace — so save/deploy/autosave could write stale old-workspace content into the new fork. Add loadedWorkspace to the load slot and include it in the early-return guard so a same-path/different-workspace retarget reloads. Verified in-browser: the script re-fetches from the new fork on an acting-workspace switch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): drop stale content when a live editor retargets to a new workspace Follow-up to keying the load cache on workspace: the loaders reloaded on a workspace retarget but did not clear loadedPath during the fetch, so SessionEditorTarget's loadedPath-keyed ready/notFound/stale gates still treated the editor as ready on the old workspace's content — the outbound draft sync (now wired to the new workspace) could write stale content into the new fork, and a 404 kept rendering the old editor. Clear loadedPath on a workspace change too (like a force reload), so the loading/not-found gates and the draft-sync ready check resolve correctly. Same-workspace path swaps are unaffected (loadedWorkspace still matches, so the old editor stays visible during the swap). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): await committed-workspace copilot config before a session send getCurrentModel() reads the global copilotInfo when the request builds, but SessionWrapper's loadCopilot for the active session is fire-and-forget — so a send right after switching to a session in another workspace could pick the previous workspace's provider/model while the proxy clients and tools target the new workspace. Track the workspace copilotInfo reflects (copilotWorkspace) and, in the session beforeSend hook (awaited before the request builds), load the committed workspace's config when it doesn't already match. Verified in-browser: sending a session committed to a workspace whose copilot config wasn't yet loaded fires get_copilot_info for it just before the LLM proxy call. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): navigate to a fresh session on reset; dedupe preview page tabs Two review findings: - resetToNewSession (deleting/archiving the open session) and the sidebar delete of the active last session created/selected a fresh session but left the URL on the old session_name. The page derives the visible session from that query, not currentSessionId, so it showed the deleted session's not-found state (or stayed on the archived one). Navigate to the fresh session, matching how activate()/enterSessionMode already switch sessions. - Preview page-tab dedupe: the iframe reports its location with the injected nomenubar/workspace params, but tabs dedupe the observed loc against the workspace-less canonical url, so reopening a page spawned a duplicate tab. Canonicalize the observed loc in observeLocation (dropping both params); covered by a new sessionPreviewTabs test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): don't persist preview-iframe workspace; scope fork ducklakes to base Two review findings: - A sessions-preview iframe runs the logged layout, which persisted its ?workspace= (the session's fork) to localStorage — shared with the top-level app, so opening a fork preview clobbered the navigation workspace and reloads restored into the fork. Skip the persist when embedded; $workspaceStore is still set in-memory for the iframe's own API calls. Verified: opening a fork /runs preview leaves localStorage.workspace on the top-level workspace. - ForkDucklakeSection listed ducklakes from $workspaceStore while a fork-of-fork is created from the selected base, so it could show the root's lakes and submit shared_ducklakes the base doesn't have. Add a sourceWorkspace prop (base ?? $workspaceStore) like ForkDatatableSection, and pass baseWorkspaceId at the mount. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): keep preview iframe on session fork across reloads and open-in-workspace Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sessions): scope worker-tag pickers to the session's effective workspace Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
927b8d064f | fix: clear old path asset usage when renaming a script (#9979) |