Folder labels are exposed verbatim as `inherited_labels` (via the
`folder_labels` SQL function) and rendered in keyed `{#each}` blocks that
throw Svelte's `each_key_duplicate` on a repeated key, crashing the list
views. The UI dedups labels on entry, but API / CLI / git-sync writes do
not, so a folder.yaml with `labels: [foo, foo]` persists duplicates.
- Dedup on write in create_folder and update_folder (order-preserving).
- Make folder_labels() dedup on read so it is resilient regardless of how a
row was populated, plus a one-time cleanup of already-persisted duplicates
so direct folder.labels reads (folder list, editor) are safe too.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(frontend): home tree view each_key_duplicate on folder/user name collision
The root keyed each in TreeViewRoot keyed groups by
`folderName ?? 'user__' + username`. A folder named `user__<name>` and a
user `<name>` both produce the key `user__<name>`, and any root-level item
with neither field keys to `user__undefined`, triggering Svelte's
`each_key_duplicate` and crashing the home screen.
Use a discriminated key (`f__`/`u__`/`i__` prefixes) that cannot collide
across folders, users, and items — the same scheme already used in Dev.svelte.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(frontend): remove unused slide import breaking frontend-check
`slide` (added in #9539) is imported but never used in AssistantMessage,
which fails `npm run check` (svelte-check --threshold warning) and reddens
the frontend-check baseline on main for every frontend PR. Remove it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix: actually isolate windows job children from CTRL_BREAK_EVENT + reap on worker death
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* decouple LIMIT_WINDOWS_TO_1CU memory cap from DISABLE_PROCESS_GROUP escape hatch
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* create windows job children suspended, assign job, then resume (close post-spawn race)
Addresses Codex P1: AssignProcessToJobObject post-spawn could miss a grandchild forked before assignment. Creating the child suspended and resuming after assignment guarantees it is in the job before running any code.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(otel): append system CA bundle to tracing proxy cert file
* chore: update ee-repo-ref to a82882f1cb9b1c4cef532f6ad046242903418d29
This commit updates the EE repository reference after PR #611 was merged in windmill-ee-private.
Previous ee-repo-ref: 2bc8ab492b6aa2cdfb81aff8236bd217b2681716
New ee-repo-ref: a82882f1cb9b1c4cef532f6ad046242903418d29
Automated by sync-ee-ref workflow.
---------
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* feat(frontend): improve AI chat cancel and interrupted-turn handling
- Escape stops the in-flight generation when focus is on the chat
(composer, messages, panel) — capture-phase listener so neither the
session Monaco editor nor mounted-but-closed modals swallow the key
- When a turn yields no output (or is cancelled before any), roll it
back and restore the message to the composer
- When a turn is cancelled or fails mid-way, keep the completed
tool-paired steps and the partial answer text as context so a
follow-up like "continue" picks up from there
- Animate the thinking-block collapse like tool boxes (slide 150ms)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(frontend): address review findings on interrupted-turn handling
- Guard the catch in sendRequest so a post-commit throw (e.g. saveChat)
cannot commit the turn a second time or mis-flag the user message
- Delete the persisted chat entry when rolling back a first turn empties
the transcript (saveChat no-ops on empty, leaving a stale entry)
- restoreInstructions skips when the user already typed a new draft
- Use stopImmediatePropagation so one Escape on body focus cannot cancel
several mounted chat panels at once
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore(frontend): tighten comments and dedupe tests in AI chat changes
Keep each invariant comment once at the place it would be broken; drop
narration and repeated rationale. Remove near-duplicate test cases
(chatLoop boundary permutations, cancel-before-output subset).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs: add comment policy to AGENTS.md core principles
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs: comments must describe current code, not PR drafting history
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(frontend): treat completed reasoning-only turns as unsent
A turn that finishes without abort but emits only reasoning produced a
display bubble, so the empty-turn rollback (keyed on display output)
skipped it and the user message was silently swallowed. Key the
decision off usable output instead. Also trim comment blocks to the
AGENTS.md 4-line norm, splitting rationale to its break-site.
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>
* feat: map chat reasoning effort to gemini thinkingConfig in ai proxy
* feat: support claude adaptive thinking through the bedrock ai proxy
* feat: per-model gemini effort levels and thought summary display
* fix: exclude claude opus 4.5 from reasoning effort (rejects adaptive)
* fix: render markdown in thinking blocks and unstick reasoning spinner
* feat: model-aware reasoning effort options across ai chat providers
* fix: scope openrouter reasoning off to the underlying model family
* feat(cli): add --yes, --secret/--no-secret and --description to variable add
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test(cli): cover variable add create/update flag semantics
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(cli): warn on secret downgrade in variable add and pin preserve semantics in test
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix: stop sending temperature for AI chat across all providers
Remove the temperature field from all AI chat completion requests and
drop the model-based send-or-not special-casing. Previously the chat sent
temperature: 0 for determinism and omitted it for reasoning models
(claude-opus-4-7/4-8, gpt-5+, o-series) that reject sampling params, which
required hand-maintaining a growing model list.
The model-detection helper is kept (renamed modelDisallowsSamplingParams ->
requiresMaxCompletionTokens) since it still serves a separate concern:
choosing max_completion_tokens over max_tokens for OpenAI/Azure reasoning
models on the Chat Completions API.
The FIM autocomplete temperature: 0 is intentionally left untouched (it is
the code-autocomplete path, not the chat).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor: drop dead claude-* branches from requiresMaxCompletionTokens
After temperature removal, requiresMaxCompletionTokens only governs the
max_completion_tokens vs max_tokens choice for OpenAI/Azure reasoning
models (its sole call site is gated on provider === openai|azure_openai).
The retained claude-* branches were leftovers from when the function
omitted temperature for Anthropic reasoning models; they are unreachable
for the max_completion_tokens decision and made the kept detection tests
assert a semantically false claim. Claude reasoning behavior is owned by
reasoningRegistry. Drop the dead branches and their tests so name, comment,
code, and tests agree. Behaviorally inert.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix: refetch license key from settings when in-memory key is invalid
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix: only record accepted license keys so rejected keys stay retryable
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* 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>
* feat(cli): improve agent prompts/skills and workspace fork workflow
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(cli): refuse fork --from-branch rename of a base branch
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(cli): auto-detect fork branch workflow, drop rt.d.ts refresh and legacy-name warning
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(skills): reconcile raw-app generate-metadata stance (agent offers+runs)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(skills): agent runs all CLI commands, gated on intent not on user typing them
Extends #9467's safe-vs-destructive model: the agent runs consequential commands (sync push, generate-metadata) itself too, gated on explicit user intent rather than handed to the user to type. The explicit-intent rule is the safeguard; an approval prompt is treated as a possible backstop, not assumed (auto-approve/headless runs have none).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Revert "docs(skills): agent runs all CLI commands, gated on intent not on user typing them"
Reverts 9225e1759b. That commit over-reached: #9467 already established the safe-vs-destructive split, and the targeted item-6 fix already removed the passive "tell the user they can run <safe next step>" phrasing. The blanket "agent runs everything" principle pushed deploys to be more eager and carried a wrong "permission layer prompts for approval" claim (untrue in auto-approve/headless mode). Keep deploys conservative.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(cli): default fork workspace name/id to the current branch when renaming it
When 'wmill workspace fork' converts the current working branch into the fork branch, default the fork's name and id to that branch (sanitized to a slug, since branch names can contain '/'). Interactive: the prompt is pre-filled (enter to accept); non-interactive (--yes): used automatically. Adds a unit test for the slug derivation.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(cli): address fork review — guard fork-branch rename, cap+validate fork id
Two P2s from review:
- --from-branch refused when the current branch is already a fork branch (would detach the existing fork by renaming its branch).
- fork id slug capped to 42 chars (backend max 50 incl. wm-fork- prefix); auto-derived id is slugged; full id validated client-side before existsWorkspace/datatable cloning so an invalid id fails fast instead of leaving cloned Postgres databases behind.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(frontend): stop live activity flickering when user has multiple tabs
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(frontend): use hasOwnProperty instead of Object.hasOwn for ts lib compat
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* 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>
* 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>
* feat(worker): #ssh directive to run a bash script on a remote SSH host
Add a first-class `#ssh <resource_path>` bash directive that reroutes a
normal bash script to run on a remote host reached over SSH (a
jump/utility node) instead of on the worker, with full parity: typed
positional args in, structured result out, live streamed logs,
cancellation, and remote exit-code propagation.
It mirrors the existing `# sandbox <image>` precedent: the directive is
parsed in handle_bash_job and reroutes to a specialized handler that
reuses handle_child for all execution plumbing.
- windmill-common: BashAnnotations::ssh_target() parser (+ unit test)
and the ssh_execution_enabled instance setting (off by default)
- windmill-worker: reroute hook in bash_executor + ssh_executor_oss
shim. OSS returns a clear "enterprise feature" error; the real
handler lives in ssh_executor_ee.rs (private feature) and is gated by
a valid enterprise license + the instance setting.
- examples/usecase/ssh-execution-wrapper: the ssh_target resource type,
a userland wrapper (no-license fallback), and a README documenting
both paths and the trade-offs vs agent workers.
EE companion: windmill-labs/windmill-ee-private (ee-repo-ref.txt bumped).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(worker): ssh host-key opt-in, 0600 key write, instance setting UI
* chore: update ee-repo-ref
* feat(worker): #ssh $arg form to take the ssh target from a job argument
* fix(worker): #ssh token must look like a target; $arg restricted to path strings
* fix(worker): tighten #ssh parser to exact directive; add -- ssh destination guard
* chore: update ee-repo-ref to d45b9a6cbe40f7fe5d322c850c50f64a6980e4f0
This commit updates the EE repository reference after PR #609 was merged in windmill-ee-private.
Previous ee-repo-ref: 2804f1aa8e74b3a7733aeb6f5044d5085193872a
New ee-repo-ref: d45b9a6cbe40f7fe5d322c850c50f64a6980e4f0
Automated by sync-ee-ref workflow.
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* 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>
* feat: clear conflict error + force delete when reusing a fork workspace id
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix: guard fork force-delete against double submit
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* 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>
* fix(frontend): clarify trigger filters evaluate decoded JSON, not base64
The filter description in TriggerFilters didn't explain that filters are
evaluated on the original decoded JSON payload, while a base64-encoding
trigger (Kafka) still delivers the payload to the runnable as a base64
string. Users saw base64 in their scripts and assumed filters couldn't
reference JSON keys.
Adds a `payloadBase64Encoded` prop (set by the Kafka editor) that appends
a sentence clarifying the runnable receives base64 while filter keys
reference the original JSON structure. WebSocket triggers deliver the raw
message string, so the base64 caveat is intentionally not shown there.
Fixes WIN-2029
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(frontend): reword trigger filter help to "parsed as JSON", not "decoded"
Nothing is base64-decoded during filtering: WebSocket parses the text
frame directly, Kafka converts the message bytes to UTF-8 then parses.
The base64 form only exists on the delivery path to the runnable (Kafka,
V2). Reword to "filters match against the message parsed as JSON" and, for
base64 triggers, clarify filters run on the message before encoding.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(frontend): correct filter-key example to match backend semantics
Review follow-up: the "data.status" example implied dot-path filter keys,
but the backend (SupersetVisitor in filter.rs) matches keys literally
against top-level JSON fields — "data.status" would never match a nested
object. Reword to state keys match top-level fields and nested matching
is done via an object value (key data, value {"status": "active"}).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs: investigate pod-deletion-cost for k8s autoscaling scale-in (WIN-2028)
* docs: correct worker_instance aggregation claim per review
* docs: drop investigation doc in favor of implementation
* chore: bump ee-repo-ref for pod-deletion-cost autoscaling scale-in
* chore: update ee-repo-ref to 80c39bf7f3bfeda4cf0974ce32826f53affd9574
This commit updates the EE repository reference after PR #610 was merged in windmill-ee-private.
Previous ee-repo-ref: 51f79d4a49dd6491f4809f3edcb3919571719da7
New ee-repo-ref: 80c39bf7f3bfeda4cf0974ce32826f53affd9574
Automated by sync-ee-ref workflow.
---------
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* docs: replace dead 0x0.st with gh-based PR screenshot recipe
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs: harden PR screenshot recipe (filename, secrets, CI fallback)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: make default chat model optional in AI settings
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: stop auto-seeding default chat model on provider enable
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(flow): support worker tag override on AI agent steps
* refactor: drop ineffective tag passthrough in nested agent tool path
* chore: regenerate openflow-derived system prompt artifacts
The modal's window keydown-capture handler called preventDefault() and
stopPropagation() on every keystroke while open, which swallowed Cmd/Ctrl+C
and Cmd/Ctrl+V (and blocked typing in any child input). Only intercept
Enter/Escape without modifiers and let all other keys through.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Adding or editing environment variables in the worker group config drawer
did not enable the "Apply changes" button. `hasChanges` compares the original
`config` prop against the local `nconfig` copy, but env var edits only mutate
the local `customEnvVars` array — they aren't synced into
`nconfig.env_vars_static`/`env_vars_allowlist` until the Apply handler runs.
This left the button stuck disabled despite real changes.
Add a `hasEnvVarChanges` derived that reconstructs the original env vars from
`config` and compares them to the current `customEnvVars`, and include it in
the Apply button's disabled condition.
Fixes WIN-2023
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>