mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-11 00:06:06 +00:00
bd00beeac54dbcfa9ab86fd336fca1a8fa289341
360
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
bd00beeac5 | fix: omit temperature for claude fable 5 (#9540) | ||
|
|
f86d0d79fc |
feat: add get_app_runtime_logs tool to global chat (#9502)
* feat: add get_app_runtime_logs tool to global chat Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: only handle raw app backend messages from the runner's own iframe Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: add list_app_runs tool to global chat for raw app backend runs Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor: simplify raw app chat tool results * nits * nits * chore: bump ui builder artifact * fix: resolve pending runtime log requests on cleanup * fix: harden raw app runtime log requests * nits * fix: show raw app tool results in status * fix: cap raw app runtime log results --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
d3f5fe1c8c |
feat: enable native web search in copilot (#9522)
* feat: enable native web search in copilot * fix: add web search fallback and settings * test: use frontend uuid helper * fix: tighten web search fallback * fix: add web search error hint * fix: classify web search fallback errors * fix: avoid web search fallback tool error * fix: handle anthropic web search enablement errors |
||
|
|
a8f1062f37 |
feat(frontend): show AI sessions in narrow-screen burger menu (#9523)
* feat(frontend): show AI sessions in narrow-screen burger menu Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(frontend): show burger menu on sessions page in narrow setup Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
ce6e2f7ade | fix(frontend): stop echoing draft values in global chat write tool results (#9530) | ||
|
|
4e868062d4 |
fix(frontend): improve AI chat markdown and typing dots in dark mode (#9497)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
ab015dd44b |
style: lean tool-call rendering and tighter ai chat spacing (#9517)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
7f987e8c98 |
feat: add reasoning effort control and thinking display to AI chat (#9511)
* feat: add reasoning effort control and thinking display to AI chat Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: strip legacy /thinking suffix from configured model slots Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: refine reasoning effort UX and drop dynamic-capability scaffolding Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: show textless reasoning on the typing indicator Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
61a4dd6e91 | refactor: extract frontend uuid helper (#9521) | ||
|
|
365e20410e |
feat(ai-chat): collapse big pastes, cap input height, escape HTML (#9487)
* feat(ai-chat): collapse big pastes, cap input height, escape HTML Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(ai-chat): concentrate paste expand/render in a ChatDraft module Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(ai-chat): step caret over paste chips as one unit Arrow-Left/Right now jump edge-to-edge across a collapsed-paste chip instead of crawling through the invisible token characters, and snap the caret out if it lands inside a token. Shift extends the selection across the whole chip; word/line jumps (alt/cmd/ctrl) are left to the browser. Mirrors the existing atomic-deletion behavior so traversal and deletion both treat the chip as a single object. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(ai-chat): atomic chip deletion on overlapping selections + plural label A selection that partially overlapped a paste token previously hit the collapsed-caret early-return, so the browser deleted a partial token and left an orphaned zero-width run plus a dangling pastes registry entry. handlePasteDeletion now widens the deletion range to cover each overlapped token whole and drops all affected pastes entries (shared removePasteRange helper). Strict overlap, so abutting a chip edge doesn't pull it in. Also route line-count pluralization through a shared lineCount() helper so a 1-line paste reads "1 line" in the conversation bubble too, not "1 lines". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(ai-chat): full chip atomicity via beforeinput + expand on copy/cut Addresses review nits on PR #9487: - Chip atomicity is no longer limited to Backspace/Delete keydown. A new beforeinput handler takes over any selection-spanning edit that overlaps a paste chip — typing over a selection, paste, drag-and-drop, and Backspace/Delete over a selection — and applies it to the whole token(s) via a shared replacePasteRange, so a partial edit can no longer leave an orphaned zero-width run or a dangling pastes registry entry. handlePaste is likewise widened so a large paste onto a chip replaces it whole. The keydown handler now only covers the collapsed-caret-at-boundary case beforeinput can't see. - Copy/cut of a selection containing a chip now puts the expanded content on the clipboard instead of the chip label + its zero-width run; cut also removes the chip whole. This also removes the duplicate-token re-paste vector (the clipboard never carries a raw token anymore). - Rename lineCount -> lineCountLabel: it returns a formatted string, not a count, so the name shouldn't read like an accessor. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(ai-chat): address cubic + claude review findings on the paste feature cubic-dev-ai findings: - autosize: clear inline overflow-y on the uncapped path so a capped-> uncapped toggle can't leave a stale `auto`/`hidden`. - pasteTokens: new countLines() ignores a single trailing newline, so a 10-line paste with a trailing \n no longer counts as 11 (off-by-one in shouldCollapsePaste and the chip's reported line count). - ContextTextarea: the @-mention picker anchor now subtracts the textarea's own scrollTop/Left and is recomputed on internal scroll, so it stays pinned once the input is capped at 40vh and scrolls. claude re-review findings: - ContextTextarea: drag-and-drop of a selection containing a chip now puts the expanded content on the drag payload via ondragstart (mirroring copy/cut), so a dragged chip no longer orphans its token and loses the pasted content (or leaks the label to an external target). - ContextTextarea: handlePasteBeforeInput now guards on e.cancelable and a HANDLED_INPUT_TYPES whitelist, so historyUndo/Redo (Ctrl+Z) and non-cancelable insertCompositionText (IME) are left to the browser instead of being reinterpreted as a delete / rewritten mid-composition. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
b894f783f1 |
feat(ai-chat): quick access to AI prompt settings from chat (#9508)
* feat(ai-chat): quick access to AI prompt settings from chat Add a cog next to the AI model selector in the chat that opens a dropdown to edit the current chat mode's user (localStorage) and workspace (DB ai_config) AI prompts, reusing the shared AIPromptsModal. Workspace prompt editing is admin-only; non-admins get a read-only view with an info Alert. The dropdown and modal footer include an admin-only deep-link to the full AI settings page, opening in a new tab. Workspace save re-applies the saved custom_prompts onto the store after the ai_config round-trip, since effective_ai_config falls back to the instance config (and would drop them) when the workspace has no providers of its own. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(ai-chat): snapshot mode when opening prompt settings modal Prompt edits were keyed off the live chat mode (a $derived of aiChatManager.mode). If the chat mode changed while the modal was open, save/reset/hasChanges and the modal's target mode would follow the new mode and write to the wrong key. Capture the mode into an activeMode snapshot at open time and use it throughout the modal lifecycle. Identified by cubic. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(ai-chat): base-prefix AI settings links and reset hasChanges after save - Prefix the AI-settings deep-links (dropdown item + modal footer) with {base} so they resolve under a deployment base path instead of 404ing. - After a successful save, sync customPrompts to the trimmed value so hasChanges flips back to false (Save/Reset disable, Reset no longer snaps the textarea). Identified by Claude review. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(ai-chat): gate workspace prompt editing on workspace having own providers When a workspace has no AI providers of its own (it uses instance defaults), the backend never makes workspace custom_prompts effective — get_copilot_info returns the instance config verbatim. A workspace prompt saved in that state would be dead config that silently disappears on reload, and the earlier re-apply hack also transiently replaced instance prompts in copilotInfo. Mirror the settings page (AISettings.svelte): detect the workspace's own providers in the same getSettings fetch used to seed the prompt, and when there are none, surface the workspace prompt read-only with an explanatory Alert (new readOnlyReason prop on AIPromptsModal) instead of an editable field. Since editing is now gated to workspaces with their own providers, effective_ai_config equals the saved config, so the re-apply is reverted to a plain setCopilotInfo(effective). Identified by Claude review. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(ai-chat): await async save before closing prompts modal AIPromptsModal.handleSave called onSave() without awaiting, then closed the modal immediately — so the workspace save round-trip was still in flight when the modal dismissed, with no loading state and any error toast landing after the modal was gone. Make handleSave await onSave (now typed to allow a Promise), show a loading state on Save while in flight, and keep the modal open if the save throws. AIChatSettingsMenu.save() re-throws on failure so the modal stays open. The synchronous user-prompt path and existing callers are unaffected. Identified by Pi review. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
cfe5119035 |
feat(ai): add list_runs and get_job_logs tools to global chat mode (#9488)
* feat(ai): add list_runs and get_job_logs tools to global chat mode Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(ai): always suppress ansi hint in get_job_logs, drop misnamed param Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(ai_evals): add global list_runs and get_job_logs eval cases Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * style(ai): trim get_job_logs description and format global core Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ai): surface list_runs/get_job_logs output as tool result The tools set showDetails but never set message.result, so the details panel rendered "No result yet" even on success. Set result in setToolStatus (logs go in result for get_job_logs). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
64b089cd23 |
feat(frontend): use unified drill picker for AI chat @-mention dropdown (#9159)
* feat(frontend): use unified drill picker for AI chat @-mention dropdown * fix(frontend): chat picker review followups + overlay alignment - AIChatDisplay: migrate @-badge popover to ChatContextPicker (was still importing the deleted AvailableContextList after the rebase onto #9034, causing a build break). - DrillPicker: handle Tab as Enter so the inline @<word> mention completes without losing focus. Tweak leaf-row weight to font-normal; secondary text uses text-hint. - ContextTextarea: drop px-0.5 from the highlight span — extra horizontal padding made every glyph typed after a mention drift right of the invisible textarea below. box-decoration-clone keeps the rounded corners. - ContextElementBadge: explicit font-normal label, hoist label into a {@const} and pass to title= so the truncated badge shows the full title on hover. - workspaceTree: drop orphaned doc-comment left dangling by the rebase. - Add unit tests for drillPicker.ts and workspaceTree.ts (51 tests cover resolveScope/scopeChain/collectLeavesGrouped/leafHaystack, buildWorkspaceTree shape + loading + dir forest + leaf shape, withCurrent rename suppression, extraItemsByKind dedup, legacyScopeToPath, relativizeWorkspacePath). * fix(flow-editor): ignore keyboard shortcuts when focus is outside the flow root Menus, modals, drawers etc. live outside the flow root and capture focus explicitly. Flow nodes aren't focusable, so the unfocused default (activeElement === body) means "flow is the canvas" and we should react; anything else means another surface has the user's attention and our shortcuts would steal it. * fix(frontend): inline @ mention picker + chat layout polish - ContextTextarea: swap manual Portal+caret-math positioning for svelte-floating-ui anchored at the `@` character (virtual reference, middleware [offset, flip(crossAxis:false), shift]). Picker stays pinned to `@` while the user types the query, slides leftward when hitting the right edge instead of flipping alignment, and floating-ui handles above-vs-below + edge clamping automatically. Drops the 60vh-worst-case reservation that left a big gap above the caret in sessions, and the now-unused isFirstMessage prop is marked deprecated. - AIChatDisplay: the `@`-button Popover now opens with placement bottom-start (was the default `bottom`), aligning its left edge with the button instead of centering under it. - ChatContextPicker: when no Diffs/Modules/Databases branches are present (e.g. global chat), return the Workspace tree's children at the root instead of wrapping them under a redundant "Workspace" row. handleScopeChange handles both the wrapped and unwrapped layouts and the single-kind `dir:` top segment. * chore(frontend): address review suggestions on chat picker PR - DrillPicker: clamp width to viewport on narrow screens — w-[420px] → w-[min(420px,calc(100vw-20px))]. - workspaceTree.buildWorkspaceTree: make loadingKind optional (defaults to {}). Chat picker still passes it; callers that don't track loading no longer need to thread an empty object. - ChatContextPicker.handleScopeChange: name the WRAPPED vs UNWRAPPED layouts in a comment block so the dir:/kind: branches are obvious. - ContextTextarea: drop deprecated isFirstMessage prop (floating-ui handles direction); drop defensive Math.max on the @ index now that the invariant is documented; comment the floatingRef(anchorRef) call as the supported virtual-reference path in svelte-floating-ui. - AIChatInput: stop forwarding isFirstMessage to ContextTextarea. * feat(frontend): sync selectedContext with @-mentions in textarea Both picker entry points now insert a visible `@title` token in the textarea, and deleting that token drops the matching entry from selectedContext. - AIChatInput: new insertMention(title) export. Appends `@title ` to instructions, prefixing a space only if the existing text doesn't already end in whitespace. - AIChatDisplay: the `@`-button popover calls insertMention after addContextToSelection so its picks match the inline-mention path's textarea state. - ContextTextarea: new onRemoveContext callback. A $effect compares the set of `@title` tokens in `value` (derived) against the previous snapshot; titles that disappeared trigger onRemoveContext for any selectedContext entry with `deletable !== false`. The diff lives in an effect (not handleInput) so it catches both keystroke deletions AND programmatic value updates from updateInstructionsWithContext. - AIChatInput: passes onRemoveContext that filters selectedContext by type+title — mirrors the existing badge X-button handler. * chore(frontend): narrow ChatContextPicker `inner` from `any` to `DrillPicker | undefined` The previous `let inner: any` worked around svelte-check rejecting `DrillPicker<ChatLeafData>` (the imported component is seen as the non-generic `Comp`). Dropping the type parameter keeps the workaround without `any`, so handleKeydown / pickHighlighted are at least typed at the call site. Addresses May-14 PR review. * fix(frontend): address PR #9159 bot-review findings (eager preload, focus, dedup, icon types) - [P1] ChatContextPicker.handleScopeChange: stop preloading workspace kinds at the wrapped picker root. New `isWorkspaceOnly` $derived (true when no Diffs/Modules/Databases branches are present) gates the at- root preload, so the chat root no longer fires two list requests before the user enters Workspace. Reported by Codex. - [P2] AIChatDisplay @-button popover: call aiChatInput.focusInput() after close() so the textarea is focused for immediate typing — mirrors the inline-mention path's setTimeout(textarea.focus, 0). Reported by Claude. - [P2] AIChatInput.insertMention: no-op when the `@title` token is already present in instructions, so re-picking a workspace item doesn't leave duplicate visible tokens for a single selectedContext entry. Reported by Codex. - [P2] drillPicker.ts: introduce `DrillIcon = ComponentType | Component<any, {}, ''>` and replace `icon: any` on DrillLeaf, DrillBranch, and ChatContextPicker.buildContextBranch. Mirrors the ComponentType | Component pattern used in TriggersBadge.svelte for the same Svelte 4/5 compatibility window. Reported by Pi. * fix(frontend): preserve workspace context on refresh + load all kinds for internal search - [P1, Codex] ContextManager.updateAvailableContextForScript/Flow: preserve workspace_script and workspace_flow entries through the selectedContext filter on editor refresh. They're user-picked refs that don't appear in availableContext, so the previous filter was silently dropping them whenever the script/flow editor refreshed options (e.g. on any code change). - [P2, cubic-dev-ai] WorkspaceItemDrillPicker: in internal-search mode (externalFilter === undefined, DrillPicker renders its own search box), preload all kinds on mount. Without this, typing in the picker's search before clicking a kind branch produced incomplete results since DrillPicker can't reach back through the adapter to trigger fetches on internalFilter change. Cached items keep the effective cost near-zero on warm sessions. * fix(frontend): preserve workspace refs through script-mode context refresh The script-mode updateAvailableContext overwrites newSelectedContext with a fresh [code] entry, defeating the workspace_script / workspace_flow preservation in the later filter — the entries are already gone by the time the filter runs. Seed newSelectedContext with the refreshed code block AND the user- picked workspace_script / workspace_flow / code_piece entries from currentlySelectedContext, so editor refreshes don't wipe @-mention badges in script chat. The existing line-271 filter still validates each entry against newAvailableContext + the per-type allowlist. Reported by Codex on PR #9159 — completes the prior workspace-context- on-refresh fix (b02d1f2d35) which only patched the filter, not the rebuild step that runs before it. * fix(frontend): preserve all previously-selected contexts on script refresh The prior c2775fe0c5 fix only carried over workspace_script / workspace_flow / code_piece entries from currentlySelectedContext. That preserved the workspace P1 path but still dropped previously- selected diff / error / db / runtime-context badges, which cubic flagged in its 16:55 review. Spread the full currentlySelectedContext (minus `code`, which we just rebuilt). The downstream filter validates each entry against newAvailableContext + the per-type allowlist, so auto-derived types like diff / error / db survive when still applicable, and unrelated items are dropped automatically. Reported by cubic-dev-ai on PR #9159. * fix(frontend): rehydrate auto-derived context + sync badge X with textarea - [P2, cubic] ContextManager.updateAvailableContext: when the rebuild carries over previously-selected diff/error/db entries, swap each one for the matching freshly-built entry from newAvailableContext in the final .map() step. Preserves the user's `deletable` override on top of the fresh content/diff/schema, so refreshes don't keep stale payloads while still surviving the badge across edits. - [P2, Pi/Codex] AIChatInput: new `removeMention(title)` export that strips `@title` tokens from `instructions` (whitespace-bounded so substring matches don't bleed). The badge X-button now calls it after filtering selectedContext, mirroring the inverse textarea-to- badge sync. No double-remove: ContextTextarea's $effect-driven onRemoveContext is a no-op once selectedContext no longer holds the entry. * fix(frontend): retype ChatContextPicker.inner to DrillPicker<ChatLeafData> `npm run check:fast` (TypeScript-only) and `npm run check` (svelte-check) disagree on whether the imported DrillPicker is generic — `check:fast` sees it as `Comp` and rejects the type parameter, while `svelte-check` sees the real generic component and requires it. CI runs `check`, so follow that: `DrillPicker<ChatLeafData> | undefined`. This also fully replaces the prior `inner: any` workaround called out in multiple bot reviews — handleKeydown / pickHighlighted now type-check at the call site against the correct component instance. * fix(frontend): scope removeMention's whitespace collapse to the mention site The trailing `.replace(/ +/g, ' ')` in `removeMention` was global, collapsing any pre-existing double-spaces in the prompt — e.g. a user typing `"hello world @foo bar"` lost their intentional formatting when they deleted the `@foo` badge. Rework the regex to match `(^|\s)@title(\s|$)` and decide per-match: - Mention at a boundary (no lead or no trail): drop entirely. - Mention in the middle: keep ONE bordering whitespace char (the leading one verbatim, so newlines/tabs aren't downgraded to spaces). No global pass over `instructions`. Unrelated whitespace stays intact. Reported by cubic-dev-ai on PR #9159 (07:27 review of 9e07eac4). * fix(frontend): expose DrillPicker.onFilterChange + lazy-load workspace kinds Both Codex P1s came from over-eager preload heuristics on my prior fixes: the workspace picker cold-loaded every configured kind on mount in internal-filter mode, and the chat badge popover never observed its own internal filter so workspace results were missing from search until the user drilled into Workspace. Replace both ad-hoc effects with a single `onFilterChange` callback on DrillPicker that fires whenever the EFFECTIVE filter (external or internal) changes: - [P1] WorkspaceItemDrillPicker: drop the "cold-load on mount when externalFilter === undefined" effect. Workspace kinds now load only once the user actually types something — closer to the pre-refactor behavior where the breadcrumb / "Open editor" pickers only fetched the drilled-into kind plus all kinds on search. - [P1] ChatContextPicker: handleFilterChange replaces the prior externalFilter-only effect. Badge-popover search (internal filter) now triggers the same preload as inline-mention search (external filter), so workspace results appear without needing to drill first. Both fixes reported by Codex on PR #9159. * fix(frontend): skip mention-removal sync when textarea is programmatically cleared sendRequest() sets `instructions = ''` immediately after dispatching to AIChatManager. The mention-removal effect treated this as user-initiated deletion and cleared selectedContext BEFORE AIChatManager.beforeSend snapshotted it — selected `@` contexts disappeared from the outgoing request. Skip the sync when value is empty; user-initiated mention deletes happen in-place against non-empty content. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(frontend): scope post-send wipe protection to the send path only Replace the blanket `if (value !== '')` guard on the mention-removal effect with an explicit `clearForSend()` export. `sendRequest()` now calls it instead of `instructions = ''`, so a user manually clearing the whole textarea still drops the corresponding context badges while the post-dispatch programmatic wipe is silent. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(frontend): extract useWorkspaceItemsLoader composable shared by both drill picker adapters WorkspaceItemDrillPicker and ChatContextPicker each duplicated the same machinery: loaded/loadingKind state seeded from the module cache, a stale-while-revalidate ensureLoaded coroutine with an untrack guard, a kind:/dir: scope-segment decoder, and the "load every kind once the user starts searching" filter callback. Move that to a single useWorkspaceItemsLoader() returning {loaded, loadingKind, ensureLoaded, ensureAll, ensureForScopeSegment, onFilterChange}. Adapters keep their own scope-walking policy (chat collapses an optional 'workspace' wrapper, workspace handles single-kind mode) but delegate kind decoding and lazy fetch to the composable. Net: -135 +28 LOC in the two adapters; +109 LOC in the new composable. The cache-version race, untrack discipline, and stale-while-revalidate semantics now live in one place. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(frontend): address Codex P1+P2s — non-context clear, same-title cross-removal, single-kind cold load P1: sendRequest() now clears `instructions` unconditionally after the optional `clearForSend()` so APP/NAVIGATOR/ASK/API modes (which don't mount ContextTextarea) still reset the input after send. P2: removeMention() now calls a new `unsyncMention(title)` on the textarea before stripping `@title` from `value`, so the mention-removal effect doesn't fire a second onRemoveContext on a same-title sibling (e.g. workspace_script + workspace_flow sharing a path). P2: single-kind WorkspaceItemDrillPicker loads its kind at mount even when scope is empty — buildWorkspaceTree collapses to the kind's children, so there's no kind row to drill into to trigger the load. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
f2f0812a04 |
feat(flows): opt-in to include the stopping step's result in early-stop errors (#9446)
* feat(flows): early stop can include the stopping step's result in the raised error
When a step uses Early Stop with "Raise an error message if stopped", the
flow result was entirely replaced with a static error object
({"error": {"name": "EarlyStopError", "message": "..."}}), discarding the
stopping step's own output. This made it impossible to stop+fail a flow
while preserving the data the step produced (e.g. an API that returns
HTTP 200 with a userErrors payload).
Add an opt-in `error_include_result` flag on StopAfterIf. When enabled on
the raise-error path, the raised payload becomes
{"error": {...}, "result": <step result>} instead of dropping the result.
Default is false, so existing behavior is unchanged. The option is threaded
through the worker's stop-after-if handling (including stop_after_all_iters_if
for loops/branchall) and exposed in the flow editor's Early Stop panel.
Fixes WIN-2012
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(flows): cover early-stop error_include_result payload shaping
Add a regression test asserting that a step using Early Stop with a raised
error message and error_include_result=true fails the flow while preserving
the step output as {"error": {..}, "result": <step result>}, and that with
the flag off the result is the bare {"error": {..}} object.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(flows): nest early-stop step result inside the error object
Embed the stopping step's result under `error.result` rather than as a
top-level sibling of `error`. This keeps the flow result shape as
`{ "error": { .. } }` — identical to a normal error — so consumers that
key off the top-level shape (single `error` key) keep working, while the
data is still preserved for those that look inside the error object.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(flows): always include the stopping step's result in early-stop errors
Drop the opt-in `error_include_result` gate. Since the step result is nested
inside the error object (`error.result`), the top-level result shape stays
`{ "error": .. }` — identical to a normal error — so consumers that detect or
parse failures by the top-level shape are unaffected. Gating it added schema
surface, plumbing, and a UI toggle for no real compatibility benefit.
Now, whenever a step early-stops with a raised error message, the flow fails
and the raised error embeds the stopping step's own result under
`error.result` (aggregated iteration results for loops/branchall). This
reverts the `StopAfterIf.error_include_result` field, its threading, the
OpenAPI/generated-client surface, and the editor toggle; the "Raise an error
message" tooltip now notes that the step result is included.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(flows): gate early-stop result inclusion behind opt-in flag
Re-introduce the per-step `error_include_result` flag (default off) instead
of always embedding the step result. Although nesting the result under
`error.result` keeps the result *shape* backward-compatible, it does not
address data exposure: a failed flow's result is propagated to synchronous
webhook callers, the flow's failure module, and the workspace/global error
handler (commonly a Slack/email/outbound-webhook notifier). Always including
the step output would surface previously-redacted intermediate data to all of
those sinks for every existing error-stop flow.
Gating keeps the existing behavior (bare `{ "error": .. }`) as the default and
only embeds `error.result` when the flow author explicitly opts in, matching
the original issue's intent.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(flows): omit error_include_result when false; refresh generated prompts
- Add `skip_serializing_if = "is_false"` to `StopAfterIf.error_include_result`
so serialized flows are byte-identical when the flag is off. Fixes the
`flowmodule_serde` round-trip test (cargo_test) and avoids churn on existing
flows.
- Regenerate `system_prompts/auto-generated/` and `cli/src/guidance/skills.gen.ts`
for the new OpenFlow `error_include_result` property. Fixes check-freshness.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(flows): cover error_include_result for the loop "stop after all iters" path
Add a regression test for the stop_after_all_iters_if branch, where `nresult`
already holds the aggregated iteration results — confirming `error.result`
carries each iteration's output (distinct from the per-step fallback path).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
819ba5e150 |
fix: read latest db draft for scripts/flows in global mode read tool (#9441)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
e4e0984e55 |
feat: let flow AI chat create and edit sticky notes (#9412)
* feat: let flow AI chat create and edit sticky notes Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: strengthen flow AI guidance to prefer groups for organizing flows Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: harden flow note validation (validate position/size, document color default and group acceptance) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: make AI-created free notes draggable by seeding default position and size Free notes need explicit geometry to be draggable/resizable in the editor; UI-created notes always set position+size but agent-created notes omitted both, so they couldn't be moved until resized. Seed defaults in validateFlowNotes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
79178f6f5a | feat: use metadata model for small AI tasks (#9431) | ||
|
|
26b7270418 | feat: auto-generate AI session names (#9399) | ||
|
|
cf5fefb521 | feat: add metadata generation model setting (#9418) | ||
|
|
11d1ad9a87 |
fix: omit temperature for gpt-5+ and o-series models on all providers (#9422)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
1275487f02 |
feat: refine ask-user-question chat display and keyboard nav (#9392)
* feat: refine ask-user-question chat display and keyboard nav Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * style: use text-accent for ask-user-question icon Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: focus active choice when clicking ask-user-question card Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: disable chat input while an ask-user-question is pending Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor: focus active choice on card click instead of pointerdown Preserves text selection on the question card; wired as a use: action so the non-interactive card needs no keyboard handler. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor: extract isActiveUserQuestion shared predicate Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: cover isActiveUserQuestion predicate Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
943ef6eb20 |
feat: add workspace datatable tools to global AI chat mode (#9395)
* feat: add workspace datatable tools to global AI chat mode Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: cover global-mode datatable tools pure logic Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: expose datatable SQL SDK reference via get_instructions in global mode Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: make datatable get_instructions language-aware, default TypeScript Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor: drop datatable/whitelist args from global init_app tool Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: flag missing datatable config as an explicit blocking error in global mode Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor: drop dead branch in exec_datatable_sql result handling Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
5c20d6b4f7 |
feat: add global ai chat test tools (#9391)
* feat: add global ai chat test tools
* fix: avoid session id in flow test preview
* test: cover global flow preview ids
* test: require script and flow test tools
* fix: harden global flow test fallback
* Revert "fix: harden global flow test fallback"
This reverts commit
|
||
|
|
e4213c1ab8 |
feat(flow-ai): constrain flow-group colors to the NoteColor palette (#9343)
The flow AI chat's set_flow_json tool lets the model set a `color` on each semantic flow group, but nothing told it which colors are valid, so it would sometimes emit hex codes / arbitrary CSS color names. Those render with default styling at best and break the group color picker at worst. - core.ts: the set_flow_json schema `.describe()` and the `groups` system-prompt bullet now spell out that `color` MUST be one of the palette names (yellow, blue, green, purple, pink, orange, red, cyan, lime, gray) — no hex, no CSS colors — and that omitting it lets the editor auto-assign one. - helperUtils.ts: validateFlowGroups now rejects any color outside that palette, sourced from the NoteColor enum so the two can't drift. - helperUtils.test.ts: tests for reject-unknown / accept-known / accept-omitted. Split out of the sessions branch (gl/layout-ai), where it had been bundled into the large feature commit; it's an independent flow-AI improvement. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
eadeac248b |
feat: sessions page with isolated AI chat + flow editor (#9034)
* feat(sessions): chat + editor side-by-side with multi-session state
Introduces the Sessions feature: a workspace where the AI chat and an
editor (flow / script / app / raw-app) sit side-by-side, with each session
having its own AIChatManager instance, history, and target item. Sessions
are persisted across reloads and can be staged into forks for review.
Key pieces:
- sessions/ — SessionWrapper (the split-pane shell), SessionPicker
(sidebar list), SessionForkBar, SessionWorkspaceBar, FlowEditorView /
ScriptEditorView / AppEditorView / RawAppEditorView, ForkDiffDrawer,
sessionRuntime (per-session AIChatManager + draft state),
sessionState (in-memory + persisted index), sessionUnread, sessionScope,
appDraftCodec / flowDraftCodec, forkEditUrl, /sessions route.
- WorkspaceItemDrillPicker refactor — extracts WorkspaceItemRow + adds
surfaceAI drafts, stale-while-revalidate. workspacePicker.ts drops
explicit invalidate() in favor of always re-fetching in the background.
- ForkDiffDrawer + WorkspaceItemDiffViewer — per-kind diff bodies
reusable from the compare page. FlowGraphDiffViewer / FlowGraphV2 gain
inlineDiff forwarding + onHeight callback for equal-height layout.
- Global AI chat sessions plumbing — AIChatManager exports the class +
adds disabledModes, beforeSend hook, scoped instance context. AIChat /
AIChatDisplay accept session-only props (wideLayout, emptyHint,
inputPreface, hideHeader, hideModeSelector, forceDisabled). Chat
preserved across /flows/add → /flows/edit, /scripts/add → /scripts/edit.
- Draft-first loaders — sessions open drafts when present, otherwise
seed a draft from the last deployed value via globalDraftStore.
RawAppEditor / AppEditor / AppEditorHeaderDeploy get newApp prop +
fixes so draft-only apps can deploy.
- Compare page (/forks/compare) — bigger overhaul to plug into the new
drawer.
- Sidebar — Sessions entry + unread badge + status dot in
SidebarContent / MenuButton / SideBarNotification.
- Misc fixes — chat group color palette constraint, deploy_workspace_item
confirmation dropped, open_preview tool, picker drafts surfacing,
fork archive/delete buttons on compare page.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sessions): bypass UserDraft inside session panes + sessionUnread crash
After merging main's UserDraft PR (#9121) into the sessions branch, two
integration issues surfaced:
1. AppEditor.svelte calls `UserDraft.use<App>('app', path)` at the
component level — keyed by ($workspaceStore, 'app', path). Sessions
that haven't materialized a fork yet stay at the user's main
workspace, so a session targeting an app at the same path as a
regular /apps/edit tab shared the same LS key. The session would
read the regular tab's autosave and write its fork-edits back over
it.
Gate UserDraft.use on `!getContext('aiChatManager')` — sessions
inject the manager via setContext, so inside a session pane the
handle is `undefined`, stateApp falls through to the `app` prop
the session loaded, and the auto-save $effect bails. Same gate on
the four UserDraft.remove call sites in AppEditorHeader and
RawAppEditorHeader so save/deploy from a session pane doesn't wipe
the LS draft of a non-session tab at the same path.
2. sessionUnread.svelte.ts called useLocalStorageValue at module
scope. Main's PR added a deep-mutation $effect inside that helper,
which now requires component-initialization context — every page
crashed at import time with `Svelte error: effect_orphan`.
Replaced with a plain module-level $state + manual localStorage
persist; same reactivity contract for callers.
3. ScriptEditorView.svelte was passing a `replaceStateFn` prop that
ScriptBuilder dropped on main. Removed.
Verified end-to-end with Playwright:
- /flows/edit/{path} regression: UserDraft handle still created, no
console errors
- /sessions loads, sessionUnread doesn't crash
- Session targeting non-raw app `u/admin/userdraft_collision_test`
displays the fork content (FORK_ONLY_MARKER) even with an LS
poison at `userdraft/w/local/app/{path}` containing a
POISONED_BY_REGULAR_TAB_AUTOSAVE marker; poison remains untouched
after the session loads and renders
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sessions): stop fork-create retry loop on first user message
Removed the SessionWrapper $effect that retroactively committed the
session's workspace from the in-memory chat history. When opening a
session whose previous commit attempt had failed (or whose response was
lost) the effect ran in a tight retry loop, flooding the user with
`workspace_pkey` violations from `create_workspace_fork`.
The send path already commits through `AIChatManager.beforeSend` →
`commitSessionWorkspace`, which is the deterministic moment-of-action.
The $effect was a redundant reactive bridge that turned every backend
failure into an infinite retry.
Also hardens `materializeFork`/`commitSessionWorkspace` so the most
common cause of the duplicate-key error self-heals:
- `materializeFork` short-circuits when `fork.id` is already in
`$userWorkspaces` (the previous create actually succeeded, we just
lost the response). On a `workspace_pkey` catch, refresh the workspace
list and adopt the existing row instead of toasting an error.
- On a real `materializeFork` failure, `commitSessionWorkspace` now
drops `pending_fork` so the session falls through to the
workspace-pick fallback instead of looping on the same broken intent.
* feat(sessions): show EditorHeader breadcrumb in the not-found state
When a session's target item has been deleted or moved, the editor pane
used to render a bare "Script not found at path X" line — leaving the
user with no way to navigate to a different target without backing out
of the session.
Each editor view now renders a `SessionItemNotFound` shell instead: a
real `EditorHeader` (read-only summary, no pen popover) with a
breadcrumb keyed to the missing kind+path, plus the "not found" copy
below. Clicking any breadcrumb segment opens the workspace picker
scoped to that level — pick a replacement and the session swaps target
via the existing `onNavigate` callback.
`SessionItemNotFound` maps `raw_app` to `EditorHeader`'s `kind: 'app'
+ raw_app: true` so the picker routes through `/apps_raw/...`; the
local label still says "Raw app not found" (not "App not found") so
the user knows which surface is missing.
* fix(picker): stop self-feeding fetch effect that OOM'd the tab
The drill picker's $effect watched `scope` and called `ensureLoaded`
on every change. `ensureLoaded` reads `loaded[kind]` synchronously
(to decide whether to show a spinner), so the effect ended up
subscribed to the very signal it fills. Each fetch result wrote
`loaded[kind] = items`; Svelte 5's $state proxy notifies on every
property set even when the reference is unchanged from cache, which
refired the effect, which called `ensureLoaded` again, which awaited
the cached fetch, which wrote `loaded[kind]` again... runaway loop.
In `/scripts/edit/...` the picker's lifecycle stabilised quickly
enough to mask the loop, but in a session pane (multiple warm
sessions, picker kept alive by the surrounding state) the cycle
spun freely — 29.8 million iterations in <100 ms during testing,
enough to OOM Firefox / kill the Chromium tab.
Two changes:
- Replace the scope-watching $effect with an explicit `setScope()`
helper called from `drill()`, `goUp()`, and `onMount`. Fetch is
now a callback reaction to user navigation, never a reactive
consequence of one. No closed feedback cycle is possible.
- Untrack the `loaded[kind]` read inside `ensureLoaded`. The search
$effect (which loads every kind on first keystroke) is still a
reactive caller; the untrack stops it from subscribing to the
signal `ensureLoaded` fills, so the same loop can't form there.
* feat(script-editor): wire initialTestPanelCollapsed through ScriptBuilder
The `initialTestPanelCollapsed` prop was already declared on
`ScriptBuilderProps` (used by the session preview to start the editor
with the run/test pane closed) but never destructured in
`ScriptBuilder.svelte`, so the value silently dropped on the floor
and the test pane always opened.
- `ScriptBuilder.svelte` — destructure the prop and forward it to
`<ScriptEditor>`.
- `ScriptEditor.svelte` — accept the prop and seed `rawTestPanelSize`
to 0 when true, while keeping `storedTestPanelSize` at the default
30 so the user's first toggle expands the pane to a sensible width
rather than 0.
Regular `/scripts/edit/...` doesn't pass the prop → default `false`
→ panel still opens by default.
* fix(sessions): resolve aiChatManager via context in AskUserQuestionDisplay
Inside a session the chat uses a per-pane AIChatManager injected via context. AskUserQuestionDisplay imported the global singleton, so answers clicked in a session dispatched to the singleton's callback map and the AI loop stalled. Resolve via getContext with singleton fallback, matching ChatMode / ToolExecutionDisplay.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(raw_apps): let preview start in single-view on the preview tab
Add a defaultSplitWithPreview prop (default true). When false (session preview), the editor boots in single view with the preview tab selected: gate the onMount default-file activation, the setActiveDocument auto-activation, and iframeShouldMount so the UI Builder bundler iframe still mounts when preview is the active tab. RawAppEditorView passes defaultSplitWithPreview={false}.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* feat(copilot): add get_preview_status tool and make open_preview idempotent
So the assistant can tell whether the session preview already shows the item it just edited, instead of re-opening or re-offering it. Mirrors the open_preview handler plumbing (setGetPreviewStatusHandler) and the session runtime registers it alongside open_preview. open_preview now returns 'already open' when the requested target matches the active session's current target. The system prompt steers the AI to check status before offering. Unit tests cover the no-arg schema, the session-only error, and handler dispatch.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sessions): make script preview reactive to AI draft writes
ScriptEditorView read the draft via static UserDraft.get inside an effect, which only subscribes to UserDraft's reactive cell when a live entry exists. None did for the preview path, so the chat's writes (UserDraft.save) only touched localStorage and the open preview never updated. Hold a live handle via UserDraft.useMany (reactive getter so it re-acquires when open_preview swaps the path without remounting) and read inbound through handle.draft, materializing the shared $state cell that bridges the chat's writes to the editor.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sessions): make raw-app preview reactive to AI draft writes
Mirror of the script-preview fix. RawAppEditorView read the draft via static UserDraft.get inside an effect, which only subscribes to UserDraft's reactive cell when a live entry exists. None did for the preview path, so the chat's raw-app writes (UserDraft.save / setDraftAndMeta, from write_app_file / patch_app_file / write_app_runnable) only touched localStorage and the open preview never updated. Hold a live handle via UserDraft.useMany (reactive getter so it re-acquires when open_preview swaps the path without remounting) and read inbound through handle.draft. Verified in-browser: an external UserDraft.save live-updates the bound summary in the open preview.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sessions): make flow preview reactive to AI draft writes
Mirror of the script/raw-app preview fixes, completing two-way binding for all three session editor kinds. FlowEditorView read the draft via static UserDraft.get inside an effect, which only subscribes to UserDraft's reactive cell when a live entry exists — none did, so the chat's writes (write_flow / patch_flow_json / set_flow_module_code) only touched localStorage and the open preview never updated. Hold a live handle via UserDraft.useMany (reactive getter so it re-acquires when open_preview swaps the path without remounting) and read inbound through handle.draft. Verified in-browser both directions: an external UserDraft.save live-updates the flow header summary and rebuilds the module graph; a preview edit propagates through the debounced save to both UserDraft.get and the chat's getGlobalDraft adapter.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* feat(sessions): surface local-storage drafts in fork diff & compare page
Augments the backend fork-vs-parent comparison with browser-local (UserDraft) drafts so a session's uncommitted AI/user changes are visible in the Fork Diff Viewer and the /forks/compare page. Adds forkDraftDiff.ts (augmentForkComparisonWithLocalDrafts + getForkItemValue), a 'local changes detected' / new-draft warning surface (checkbox-slot warning icon, no-op-baseline filtering, dedup), a 'Local draft <> fork' tab in DiffDrawer, and selectTooltip/nonSelectableTooltip plumbing in Row/WorkspaceDeployLayout.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Revert "feat(sessions): surface local-storage drafts in fork diff & compare page"
This reverts commit
|
||
|
|
2553fbfe31 | feat: add deepseek fim support (#9365) | ||
|
|
9e7eaf3684 | feat: inject active editor into global chat (#9361) | ||
|
|
4efc37212a |
fix: infer script arg schema when deploying via AI chat (#9356)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
dec58e6c4f |
feat: deploy raw apps from global chat (#9349)
* feat: deploy raw apps from global chat * fix: require raw app bundle protocol * chore: bump ui builder artifact * docs: explain app custom path deploy handling |
||
|
|
2f50e8bab0 |
feat(ai-chat): align footer bar + DropdownV2 mode/autonomy selectors (#9308)
* feat(ai-chat): align footer bar, use DropdownV2 for mode/autonomy selectors Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(dropdown): add `selected` item prop rendering a trailing check Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * style(ai-chat): add small spacing between chat input and footer bar Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(ai-chat): always offer the 3 autonomy options in the auto-accept picker Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(ai-chat): default autonomy mode to auto-accept on Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(ai-chat): use Button component for footer dropdown triggers Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * style(ai-chat): use a hand icon for the auto-accept-off autonomy state Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * style(ai-chat): use subtle Button variant for mode and model selectors Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * style(ai-chat): tighten spacing between input and footer bar Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(ai-chat): reword autonomy levels as ask/auto-accept/bypass permissions Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(button): add 2xs unified size with tighter padding Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(ai-chat): compact footer bar — 2xs buttons, AtSign context icon, short Yolo label, discreet model Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * style(ai-chat): widen the permission selector dropdown Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(dropdown): group shortcut + selected check to avoid ml-auto collision Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(ai-chat): cover getPersistedAutonomyMode default; clarify default comment Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
3f219aed98 | feat(ai-chat): expand chat question answers (#9310) | ||
|
|
1eef53170b |
feat: plug global chat drafts into userdraft (#9291)
* refactor: move global chat drafts to userdraft * feat: share script and flow drafts with editors * feat: share trigger drafts with editors * feat: share raw app drafts with editor * feat: share resource drafts with editors * docs: rename global chat drafts copy * feat: add global chat draft discard tool * fix: resolve global chat editor draft paths * fix: remove editor draft path resolver * feat: track live editor drafts in userdraft * fix: snapshot live userdraft reads * chore: checkpoint pending global draft changes * fix: address global draft review issues * fix: defer raw app draft persistence * docs: remove pr investigation docs * fix: persist live global draft writes |
||
|
|
ac26aa4e4c |
feat: add yolo mode for ai chat tools (#9258)
* feat: add yolo mode for ai chat tools * nit * fix: align chat footer controls * feat: add ai chat autonomy modes * feat: add autonomy mode dropdown * fix: highlight yolo autonomy icon * fix: auto accept flow edits * fix: hide unsupported autonomy modes * fix: handle auto-accept flow editor races |
||
|
|
413404a788 | fix: collapse successful ai tool details (#9265) | ||
|
|
7909878313 |
feat(chat): waiting-for-user indicator + scroll-to-latest polish (#9252)
* feat(chat): waiting-for-user indicator and arrow polish
- Show "Waiting for your input" (text-accent + flipping Hourglass) instead
of the typing dots when the latest tool is staged for confirmation
(Run/Cancel) or has an active askUserQuestion. The dots imply the AI
is working, which is misleading when the loop is paused on the user.
- Scroll-to-latest arrow:
- Move up to bottom-12 when the flow Accept/Reject row is visible so
they no longer overlap.
- Wrap in a solid bg-surface + shadow + border badge so the icon
doesn't bleed into messages behind it.
- Bump unifiedSize xs → sm for a slightly larger target.
- Hourglass uses a custom CSS keyframe (:global so the rule reaches the
Lucide SVG root) with 4 s period and cubic-bezier(0.65, 0, 0.35, 1)
easing — feels like flipping the hourglass rather than spinning.
* fix(chat): raise waiting indicator above accept/reject row
* fix(chat): solid background behind reject all button
* feat(chat): @ picker in controls row, badges above input, polish
|
||
|
|
f6fcdb5599 |
feat: open ai chat path links in drawers (#9220)
* feat(ai-chat): link workspace paths and show tool item references Detect Windmill paths (u/..., f/...) in assistant messages and render them as clickable pills with the right icon, resolved against a per- workspace cache. Tool execution headers now list the script/flow/app paths referenced in tool parameters as external links. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(ai-chat): linkify inline-code paths, refine pill styling - Inline-code spans whose value is exactly a Windmill path now render as a link pill (paths inside larger inline code or fenced blocks stay as code). - Tool-header chips moved to their own row to avoid overflow clipping when the title wraps. - Borderless pills, no default background (hover only), kind icons use the home-page palette (script blue, flow teal, app orange), and the external-link indicator only appears on hover. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(ai-chat): linkify variables/resources/triggers + inline drawer - Workspace item registry now also lists variables, resources, schedules, and all 10 trigger kinds; resource wins over variable on path collisions (Windmill auto-creates a companion variable for every resource). - Pill icons delegated to the canonical RowIcon component so each kind matches the home-page styling (script blue, flow teal, app orange, resource boxes, schedule calendar, etc.). - Pill href includes the hash fragment each list page already consumes (#/resource/<path>, #<path> for variables/schedules/triggers), so opening the link puts the user on the list page with the matching editor drawer already open. - For variable and resource pills, a hover-revealed side-panel button opens (or toggles closed) the editor drawer inline next to the chat, without navigating away. VariableEditor and ResourceEditorDrawer gain a closeDrawer() export and forward their close event so the host can drive toggling. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor: simplify ai chat workspace item links * refactor: keep ai chat path linkification only * perf: avoid eager ai chat path cache loads * refactor: simplify ai chat path linking * feat: open ai chat path links in drawers * refactor: homogenize workspace item kinds * fix: toggle ai chat item drawer * refactor: trim ai chat path cache * fix: cancel ai chat drawer reopen --------- Co-authored-by: Guilhem Lemouel <guilhemlemouel@gmail.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev> |
||
|
|
31a046973a |
feat(chat): visual redesign — input, streaming indicator, scroll polish (#9232)
* feat(chat): visual redesign — input, streaming indicator, scroll polish
Visual refresh of the AI chat surface used in both the global right-side
panel (Cmd+L) and inline editor panels. No new features, no system-prompt
or tool changes, no sessions code.
Input redesign
- Default textarea to `rows={1}` and autosize as the user types.
- Drop the separate Send button row in favour of a single
`<Button variant="subtle" iconOnly>` overlaid bottom-right of the
textarea — `ArrowUp` when idle (disabled until text is typed),
`Square` when loading (cancels via `aiChatManager.cancel()`).
- Padding `!pl-3 !pr-10 !py-2` keeps text clear of the floating button.
- Top spacing `mt-1` on the outer wrapper restores breathing room
above the input (lost when the old @-button row was removed).
- Context chip row renders only when something is selected.
- `ContextTextarea` `min-height: 2.25rem` so the empty textarea
collapses to a tight single line.
Streaming indicator
- Replace the old floating "Stop" button with a sticky-bottom badge
showing three animated typing dots and a formatted wall-clock
(`Xs`, `Xm Ys`, `Xh Ym`) — driven by `aiChatManager.loading`.
- CSS keyframes `chat-typing` with staggered animation-delay for the
wave effect.
Scroll behaviour
- Replace `onwheel`-based stick-to-bottom detection with `onscroll`
position check (8px threshold). Auto-scroll re-engages when the
user scrolls back near the tail.
- Smooth scroll → `behavior: 'auto'` so token-append doesn't race
the animation.
- New `enableAutomaticScroll` method on `AIChatManager`, complement to
the existing `disableAutomaticScroll`.
- Floating "scroll to latest" arrow (`ArrowDown` design-system Button,
`transition:fade`, `unifiedSize="xs"`, `iconOnly`) appears once the
user scrolls >200px above the tail; click re-enables auto-scroll
and jumps to bottom. Centered horizontally over the scroll viewport.
Message rendering
- Assistant markdown tuned: `prose-headings:font-medium`, h1 `text-sm`,
h2+ `text-xs`, plus `prose-p:text-xs prose-li:text-xs
prose-code:text-xs prose-pre:text-xs`. Stops AI replies blasting
oversized titles.
- Fenced code blocks shrink to `!text-xs` on the `not-prose` wrapper
so fenced code matches inline code at 12px.
- User-message wrapper switches to symmetric spacing (`mt-4 mb-6`)
with a new `isLast` prop that adds `!mb-12` to the latest message
— breathing room between the last bubble and the input without
affecting siblings.
Layout / padding
- Wide-layout messages tightened to `px-7` (was `px-8`); input outer
to `px-6`. The input box sits a touch left of the message text;
textarea's own `!pl-3` brings the typed text back into alignment
with the messages above.
Other
- `AIChatManager` class is now exported (was private). Allows callers
to type a `getContext<AIChatManager>('aiChatManager')` provider
override. No behaviour change for the global singleton.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* refactor(chat): restore @ picker, extract typing indicator and shared helpers
* feat(chat): cap non-wide chat at max-w-2xl, add side padding, drop input top border
* feat(chat): esc cancels active generation, tone down snapshot row
* fix(chat): only draw tool-content fade when content actually overflows
* style(chat): tighten non-wide side padding (px-4/px-3 -> px-3/px-2)
* fix(chat): inline ⌘K shows dots + stop button, swallow programmatic scroll events
* fix(chat): keep scroll-to-latest fresh during cooldown; ResizeObserver for tool-content fade
* fix(chat): contain wide content - propagate showFade, table scroll, bubble + inline code wrapping
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
49ebf6f8ba |
feat: add global chat selected context (#9216)
* feat: add global chat selected context * refactor: store workspace context as references * fix: refresh db context after global mode |
||
|
|
f965512c7a |
feat: add global ask user question tool (#9217)
* feat: add global ask user question tool * feat: add keyboard navigation to user questions * feat: simplify ask user question answers * fix: disable strict mode for optional tool schemas * fix: scope ask question keyboard events * fix: clean up ask question display state |
||
|
|
fec4008696 |
fix: preserve ai reasoning content (#9208)
* fix: preserve ai reasoning content * fix: avoid text-only reasoning replay * feat: add deepseek ai eval models |
||
|
|
25172bdc28 |
sidebar rendering expanded-but-empty at sub-pixel widths near 768px (#9191)
* fix: sidebar menu rendering expanded-but-empty near 768px width The desktop sidebar branch is gated by JS (`innerWidth < 768`), but its width was set only via Tailwind `md:` classes (`@media (min-width:768px)`). `window.innerWidth` rounds fractional viewport widths, so at e.g. 767.8px JS rounds to 768 and renders the desktop sidebar, while the CSS media query does not match and no width class applies — leaving the sidebar shell expanded with no width/content. Drop the now-redundant `md:` prefix so width tracks the JS branch decision. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: align content offset breakpoint with sidebar JS gate The sidebar width now follows the JS innerWidth gate, but the main content left-offset in AiChatLayout still used the `md:` CSS media query, leaving the two breakpoints out of sync in the same sub-pixel band. Pass an `isMobile` flag from the layout (mirroring the sidebar's `innerWidth < 768` condition) and gate the content padding on it with unprefixed classes so sidebar width and content offset always flip together. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
d243e0cde8 | align global flow tool arguments (#9146) | ||
|
|
110384580e |
refactor: add global ai chat mode with workspace-item draft tools (#9056)
* docs: add global ai mode plan
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add global ai draft mode
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: scope global ai mode to scripts and flows
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: simplify global ai workspace item shape
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: split global ai write tool into per-type tools
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add global ai schedule and trigger workspace item tools
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add dev-only /global_drafts route to inspect ai draft store
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add edit_script and patch_flow_json global ai tools
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add deploy_workspace_item global ai tool with confirmation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: emit open-resource action card after deploy_workspace_item
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add delete_workspace_item global ai tool with confirmation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* chore(system_prompts): emit RESOURCES_BASE and resource/variable zod schemas
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add global ai resource and variable workspace item tools
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: search_resource_types uses listResourceType to avoid embedding feature dep
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Revert "fix: search_resource_types uses listResourceType to avoid embedding feature dep"
This reverts commit
|
||
|
|
502a029986 |
feat: add ai chat resource action buttons (#9016)
* feat: add ai chat resource action buttons Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: avoid proxied drawer state equality Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: show tool action cards Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
0d0557fc9d |
feat: add wac ai context for frontend chat (#9021)
* feat: add wac ai context * fix: limit wac context languages * fix: pass wac auto kind in flow script drawer |
||
|
|
b883f9a9d2 |
feat: add ai chat schedule and trigger tools (#8961)
* feat: add ai chat schedule and trigger tools * refactor: use zod for ai chat workspace tools * refactor: let ai provide runnable target fields * refactor: generate ai chat workspace tool schemas * fix: add object type to composed tool schemas * fix: avoid top-level trigger schema unions Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: block undeployed workspace ai tools Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: inject ai workspace tool target Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: add ai evals for workspace tools Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: make workspace tool eval prompts realistic Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: surface workspace tool errors * fix: show workspace tool success details * fix: describe workspace tool path format * fix: clarify workspace path examples * fix: tighten workspace tool validation * fix: align workspace tool prompts * chore: mark generated chat schemas * chore: mark generated cli skills --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
34b549cfe2 |
perf: optimize datatable app chat schemas (#8960)
* perf: optimize datatable app chat schemas Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * perf: optimize datatable catalog queries Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: narrow datatable chat optimization Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: restrict datatable schema lookups Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: block system datatable schema lookups Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: handle datatable context edge cases Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: handle datatable schema edge cases Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
483fb1fb9a |
perf: reduce app ai chat token usage (#8928)
* test: add app chat token usage evals Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * perf: make app file listing metadata only Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * perf: reduce app datatable prompt context Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: add app datatable persistence eval Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: fix file manager rename app eval Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: remove selected app context eval cases Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: address app eval review feedback Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
132d8a61f9 |
fix: slim app ai chat context (#8922)
* fix: slim app ai chat context Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: remove stale app chat selection UI Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: trim app chat selected context Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: trim app chat context coverage Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: remove app tool assertion Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
932d183311 |
fix: persist flow groups from AI chat tool calls (#8906)
* fix: persist flow groups from AI chat tool calls Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: validate group ids and coerce empty groups to undefined Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |