mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-28 16:02:47 +00:00
d286f22faaf0cd9ad2da0ceaafbff10897a600fa
8113
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d286f22faa |
chore(main): release 1.706.0 (#9270)
* chore(main): release 1.706.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com> |
||
|
|
b2d74fb7ce |
feat(nsjail): optional disk-backed /tmp via instance setting (#9272)
* feat(nsjail): optional disk-backed /tmp via instance setting * test(nsjail): unit-test tmp mount resolver and narrow visibility * refactor(nsjail): switch tmp backing to select + conditional UI * ui(nsjail): make tmpfs the visible default in /tmp backing select * fix(nsjail): refuse preexisting jail_tmp to block symlink escape * fix(nsjail): allow jail_tmp reuse on sequential nsjail calls Codex flagged that python/ruby/rust executors invoke nsjail twice per job_dir (install then run). The previous resolver treated any preexisting jail_tmp as hostile and silently fell back to tmpfs on the second call, so disk-backed mode never reached the main script run for those langs. Use symlink_metadata().is_dir() to distinguish a real directory left by an earlier call in the same job_dir (safe to reuse) from a symlink or other entity (still refused, as the codebase-tar escape requires). Also loosen the frontend visibility predicate: only hide nsjail settings when job_isolation is explicitly 'none' or 'unshare', so deployments that enable nsjail via DISABLE_NSJAIL=false with no DB setting can still see the controls. |
||
|
|
9d2dfacb3e |
feat: add userdraft listing primitives (#9268)
* feat: add userdraft listing primitives * fix: cancel stale userdraft discard writes * docs: remove global ai userdraft plan |
||
|
|
e2587cff48 |
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 |
||
|
|
66bb08940c |
perf(deploy-to-hub): parallelize public-app URL resolution
resolvePublicUrl now runs once per anonymous app via Promise.all instead of serially inside the items loop, removing N round-trips from initial tab load. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
2dec554abf |
fix(deploy-to-hub): paginate workspace list and cancel stale record polls
- loadWorkspace fetches all pages instead of capping at 100 items per kind - pollJobUntilComplete now bails when recordRunSeq advances (new record target, re-run, or drawer close), preventing late completion of a previous run from overwriting current state Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
6c3132c512 | Nits | ||
|
|
c346318ffe | Small fix | ||
|
|
7cc5267763 | Add diff button once approved by admins | ||
|
|
486d6406f6 |
Allow per-item selection inside the bundle scope
- Items in predeploy now have checkboxes (all selected by default) - Select all / Deselect all act on the current folder filter - manualDeselected resets when the folder filter changes - Bundle button uses the selected count, disabled when zero - Draft snapshot keeps only the selected items - Checkboxes hidden in draft / under_review / live phases Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
cc43faabdd |
Make recordings optional, encourage them for discoverability
- Submit for review no longer gated on full recordings - Footer hint now frames recordings as boosting approval speed and public Hub featuring, not as a hard requirement - Progress card label switched from 'Recordings needed' to 'Recordings recommended' - Items without a recording display a yellow 'No recording' badge in every phase so the gap stays visible after submission Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
e9e25e6554 |
Add draft/review state machine and submission gating
- Phases: predeploy → draft → under_review → live, with workflow step indicator and contextual footer actions per phase - Bundle drawer collects name + readme before pushing the draft - draftItems snapshot frozen at deploy time; workspaceItems keep refreshing without affecting the draft - Folder MultiSelect lets users scope the bundle to one or more folders; empty = whole workspace - Submit-for-review disabled until every script and flow in the draft has a recording (progress bar + counter) - Recordings now run the real job and poll for success/failure; only successful runs can be saved - under_review phase locks editing, sharing, and recording - Dark mode variants on every coloured banner - Steps card shows the full 3-step process always, highlighting the current step Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
577868ef2a |
Wire recordings to real jobs with run-preview UX
- Recording flow now fetches the real schema, runs the job, and polls getCompletedJobResultMaybe to surface success/failure before saving. - Drawer shows a sticky status box (loader / success / failure) with a result preview, a job link, and an in-context Save CTA. - Only successful runs can be saved as a recording. Failures show the error and offer re-run. - Filter cache/state/app_theme internal resource types (mirrors workspaces_export.rs filter). - Added "What is a recording?" explainer banner above the items list. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
be8a42224f |
Wire DeployToHub to real workspace data
- Fetch apps, raw_apps, flows, scripts, resources via their services - Fetch workspace rate limit via WorkspaceService.getSettings - Share-as-iframe flips app policy.execution_mode to 'anonymous' via AppService.updateApp and resolves the real public URL via getPublicSecretOfApp + computeSecretUrl - Detect already-public apps from listApps execution_mode field - Filter out app_theme resources (noise, present in every workspace) - Hub bundle/version push and recording remain mocked (no backend yet) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
16e61e00d8 |
Rename publish-app drawer wording to 'Share as iframe'
'Publish publicly' was ambiguous (publish to Hub vs make public URL). Use 'Share as iframe' for the button and drawer title, and 'Generate iframe' for the confirm action. Intro text now explicitly mentions iframe embedding use cases (Hub, docs page, own site). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
19ab7e2e41 |
Simplify publish drawer to show workspace-wide rate limit only
Drop per-app rate limit fields (req/min, burst, per-IP) — none of these are supported by the backend. The drawer now shows the existing workspace-level rate limit read-only with a link to edit it in Workspace settings → Apps. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
dd416cf519 |
Add publish-app drawer with per-app rate limit mock
- Publish drawer on raw_apps/apps exposes public URL, copy-iframe, unpublish - Inline per-app rate limit config (req/min, burst, per-IP toggle) - Rename workspace settings "Default app" tab header to "Apps" to cover both default app and public rate limiting Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
31d94e8d3a | Fix wordings | ||
|
|
bc06337cce | Init record logic | ||
|
|
3843376913 | feat: add Deploy to Hub workspace settings tab | ||
|
|
1169371d48 |
feat: add UV_PYTHON_INSTALL_MIRROR env and instance setting (#9271)
* feat: add UV_PYTHON_INSTALL_MIRROR env and instance setting Allows operators to point `uv python install` at a private mirror of the python-build-standalone releases. Configurable via the `UV_PYTHON_INSTALL_MIRROR` env var or the `uv_python_install_mirror` instance setting, with the env var as the boot fallback and the instance setting taking precedence at reload. Fixes WIN-1966 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: hoist uv_python_install_mirror binding above sandboxing branch The non-sandboxed uv pip install branch referenced a binding that was only declared inside the sandboxed branch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: neutral placeholder for uv_python_install_mirror The previous placeholder was the default public URL the setting is meant to redirect away from. A neutral example mirror URL is clearer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
9cb34397eb |
chore(main): release 1.705.0 (#9229)
* chore(main): release 1.705.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com> |
||
|
|
740a35bf7b |
fix(flows): flag noLogs jobs and lazily resolve them in log panel (#9099)
* fix(flows): flag noLogs jobs and lazily resolve them in log panel * fix appending to flag * fix: preserve WM_LOGS_SKIPPED sentinel on SSE/replay completion pickMoreCompleteLogs resolved both sentinel and undefined to '', so the SSE completion event (whose job field is fetched .without_logs()) would clobber the sentinel placed by flagSkippedLogs. The module log panel then saw '' instead of the sentinel, defeating the lazy-resolve path. Also wire onLogsResolved on the OutputPickerInner inline LogViewer so a lazy resolve writes back to flowStateStore.previewLogs, matching ModulePreviewResultViewer and avoiding repeated fetches on remount. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
0f7dd86e5c |
feat: persistent in-editor drafts via UserDraft (#9121)
* refactor(frontend): remove localStorage-backed autosave drafts
Strip the per-editor localStorage autosave for flows, apps and raw apps,
along with the associated restore toasts and diff actions, so we can
replace them with a unified UserDraft service in a follow-up. The
backend DraftService (DB-backed drafts) is untouched.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(frontend): add UserDraft service for per-workspace local drafts
Introduces UserDraft, a key-value store keyed by
`{workspace}/{itemKind}/{path}` and backed by localStorage. Supports
save/get/remove plus a reactive use() handle so multiple component
instances observing the same draft stay in sync via a shared $state
loaded through useLocalStorageValue. Designed to host drafts for
scripts, flows, apps, raw apps, resources, variables, and all trigger
kinds.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* tests
* nit schedule_ prefix
* feat(frontend): persist deep mutations in useLocalStorageValue
Track the serialized value alongside the $state and add an $effect that
deep-reads it (via readFieldsRecursively). When a deep mutation produces
a serialization that differs from the last persisted blob, write it to
localStorage. The setter keeps writing synchronously so callers reading
localStorage right after assignment still see the new value; the effect
no-ops on those because lastSerialized was already updated by the setter.
Undefined values are persisted as a removal.
UserDraft no longer needs its own removeItem workarounds for undefined
values — useLocalStorageValue handles that uniformly now.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(frontend): add defaultValue + empty-path handling to UserDraft
UserDraft.use() accepts an opts.defaultValue used when no localStorage
entry exists yet. It is not persisted on first read — only an actual
mutation writes through.
Empty paths (new items) bypass localStorage entirely. The entry still
lives in the in-memory Map so multiple components on the same /add page
share state, but save/get/remove/use never read or write localStorage
with an empty path. Once the item is saved and the route navigates to
its new URL, a fresh use() on the non-empty path takes over.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(frontend): wire script editor to UserDraft
The script editor's top-level state now lives in UserDraft.use(), keyed
on the route's path (page.params.path on /scripts/edit, '' on /scripts/add).
Deep edits inside ScriptBuilder persist automatically; deploy and draft
restore now call UserDraft.remove to clear the local autosave alongside
the backend draft.
Replaces the URL-hash autosave that ScriptBuilder used to write via
replaceStateFn — that prop is now gone, the encodeScriptState debounce
is gone, and Triggers no longer takes a saveSessionDraft callback.
Viewing a specific historical hash (?hash=...) is kept draft-free by
passing '' as the path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(frontend): wire flow editor to UserDraft
flows/add and flows/edit drive the flow value through a StateStore
adapter backed by UserDraft.use, so every edit auto-persists at
userdraft/w/{ws}/flow/{path} without touching FlowBuilder's internal
.val convention. On returning visits the local autosave wins and a
toast offers a diff against the latest backend draft/deployed version;
on a fresh visit the backend value is written into the handle. Deploy,
save-as-draft rename, restore-draft and restore-deployed each call
UserDraft.remove on the route path so the local autosave doesn't
outlive the action.
Adds UserDraft.has() for "is there already a local draft?" detection
in the load path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(frontend): wire app editor to UserDraft
AppEditor registers a UserDraft.use<App> handle for its current path
(empty path for /apps/add stays in-memory) and a single $effect
deep-tracks the internal stateApp and forwards every mutation to the
handle. useLocalStorageValue's lastSerialized check then dedupes the
actual localStorage writes per tick, so even fast drag/resize loops
only persist when the JSON output really changes.
/apps/edit overlays a local autosave from UserDraft.get on top of the
backend value when one exists, with the existing "Discard / Show diff"
toast wired to UserDraft.remove. Deploy, save-as-draft, restore-draft
and restore-deployed all call UserDraft.remove on the relevant path,
including the JSON editor save paths.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(frontend): wire raw app editor to UserDraft
/apps_raw/edit owns the canonical raw-app state (files, runnables,
data, summary) in four $state vars; a single $effect deep-tracks them
and forwards the bundle to a UserDraft.use<RawAppDraft> handle so each
mutation tick persists at userdraft/w/{ws}/raw_app/{path} (deduped by
useLocalStorageValue's serialized check). On load the route overlays
the local autosave on top of backend.draft/deployed and offers a
"Discard / Show diff" toast when they diverge; matching local entries
are silently dropped. Deploy, save-as-draft rename, restore-draft and
restore-deployed each call UserDraft.remove on the route path.
/apps_raw/add keeps the same shape (UserDraft.use with empty path)
so the draft is in-memory only and we drop it explicitly when the
initial save creates the real path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(frontend): wire resource editor to UserDraft
ResourceEditor registers a UserDraft.use<ResourceState> handle keyed
on the initialPath (empty for new resources, in-memory only). A
$effect deep-tracks the current workspace's edit state and forwards
mutations to the handle; on bootstrap and lazy backend-fetch the
local autosave wins over the backend value when they diverge. After
a successful save() we call UserDraft.remove so the local autosave
doesn't outlive the deploy. Cross-workspace deploys always start from
the live backend value rather than the local draft.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(frontend): wire variable editor to UserDraft
VariableEditor persists the current workspace's edit state via
UserDraft.save on every mutation, keyed on editPath ('' for new
variables → in-memory only). Backend fetches now overlay a matching
local autosave when one exists, and initNew() rehydrates from the
in-memory empty-path entry so opening a fresh "Add variable" drawer
keeps any unsaved work from the previous open. After a successful
save we drop the corresponding entry.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* editor external changes sync
* fix(frontend): don't UserDraft.remove flows while route is still mounted
The /flows/add and /flows/edit routes drive FlowBuilder from a flowStore
whose getter reads flowHandle.draft directly. Calling UserDraft.remove
synchronously before goto() therefore wiped the in-memory entry, made
flowStore.val collapse to emptyFlow(), and tripped
UnsavedConfirmationModal against the just-saved value — even though the
deploy/save-draft itself succeeded.
Drop those explicit removes in onSaveInitial, /add onDeploy, and
/edit onDeploy. The empty-path entry self-cleans on unmount via
onDestroy ref counting; for the non-empty edit path the next visit's
load-time diff will silently overwrite localStorage when the local
autosave matches the deployed value. Restore-draft/restore-deployed
keep their explicit remove because they navigate to the same route
(no modal) and loadFlow immediately rehydrates the handle.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Revert "fix(frontend): don't UserDraft.remove flows while route is still mounted"
This reverts commit
|
||
|
|
413404a788 | fix: collapse successful ai tool details (#9265) | ||
|
|
c4a86838fb |
set explicit cursor color in light editor theme (#9134)
The light Monaco theme ('myTheme') did not define editorCursor.foreground,
causing the cursor to be invisible on white backgrounds. The dark theme
('nord') already sets this explicitly.
Fixes #8876
|
||
|
|
9c28bbfd69 |
feat(frontend): new path component (#9017)
* stash
* ui nits
* Fix contenteditable feedback look (duplicate typing)
* fix right icon wrong position with placeholder
* user editor in Path editor takes correct width
* nits
* nit
* chore: remove assets-operator changes (moved to separate PR)
These files were mistakenly included in this PR and belong in a dedicated PR
("Allow assets page to operators").
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore: remove sidebar assets-operator change (moved to separate PR)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix disabled
* border nit
* Fix disabled styling
* Apply suggestion from @cubic-dev-ai[bot]
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* nit
* Update frontend/src/lib/components/text_input/TextInput.svelte
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* Fix disabled tabindex and aria-disabled on contenteditable Select
The useContentEditable branch had an unconditional tabindex="0", keeping
a disabled Select in the tab order, and was missing aria-disabled.
Mirror the TextInput div branch.
Co-authored-by: Diego Imbert <diegoimbert@users.noreply.github.com>
* fix: drop obsolete hideFullPath prop from EditorHeader Path usage
* invalidate autocomplete paths on deploy
* nit pixel
* use Badge in auto complete
* nit prevent default
* fix(autocomplete): don't let stale fetch clobber forced refresh
A non-forced fetchWorkspacePaths() that started before invalidateWorkspacePaths()
could still resolve afterward, overwrite the cache, and clear forceNextFetch —
making the post-deploy refresh a no-op. Only write back from the promise that
is still the current pending one, and only clear the force flag when the
completing fetch was itself forced.
* refactor(path): drop unreachable 'group' branch in owner-kind setter
The Select only offers user/folder, so the 'group' branch was dead. Leave a
short note pointing at validateName which still accepts 'group' for
forward-compat.
* fix(path): respect disableEditing on owner-kind selector
Other path-editor controls disable on (disabled || disableEditing); the
owner-kind Select only checked `disabled`, so read-only users (trigger
editors with !can_write) could still toggle User/Folder and mutate the
bound path. Reuse the existing nameDisabled flag.
* Revert "fix(autocomplete): don't let stale fetch clobber forced refresh"
This reverts commit
|
||
|
|
9111f8908d |
feat(nsjail): make tmpfs size configurable via instance setting (#9261)
* feat(nsjail): make tmpfs size configurable via instance setting Adds a new `nsjail_tmpfs_size_mb` instance setting that overrides the size of the `/tmp` tmpfs mount inside the nsjail sandbox across all languages. When unset, the existing per-language defaults (500MB or 800MB) continue to apply, so no behavior change for existing deployments. The setting is exposed under Settings → Jobs and is read at job execution time, so changes take effect on the next job without a restart. Fixes WIN-1963 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(nsjail): unify default tmpfs size to 800MB Previously each executor passed its own per-language default (500MB or 800MB) to resolve_nsjail_tmpfs_size. Unify on a single DEFAULT_NSJAIL_TMPFS_SIZE_BYTES constant (800MB) so the placeholder behavior is consistent across languages. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(nsjail): resolve tmpfs size outside ruby download closure The download.ruby config render runs inside a sync closure passed to par_install_language_dependencies_seq, so `.await` on resolve_nsjail_tmpfs_size() was a compile error under the `ruby` feature. Resolve the size once before the closure and capture the string instead. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(nsjail): rename resolver to *_bytes and clarify fallback Addresses CI review feedback: - Rename `resolve_nsjail_tmpfs_size` to `resolve_nsjail_tmpfs_size_bytes` so the returned unit is unambiguous at the call site (cubic P2). - Fix the `NSJAIL_TMPFS_SIZE_MB` doc comment that still said "per-language default" — there is no per-language fallback anymore, all unset values resolve to the unified 800MB `DEFAULT_NSJAIL_TMPFS_SIZE_BYTES` (codex/pi P2). - Expand the resolver doc to call out that `Some(0)` and negative values also fall back, since the match arm is `Some(mb) if mb > 0`. No behavior change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
271f0cbd08 |
feat(debug): show ghost breakpoint and tooltip on gutter hover (#9150)
* feat(debug): show ghost breakpoint and tooltip on gutter hover * fix(debug): show ghost breakpoint only on glyph margin to match click handler * revert(debug): show ghost across entire gutter, not only glyph margin * refactor(debug): use MouseTargetType enum, short-circuit hover decoration |
||
|
|
b0ed27096d |
feat(editors): responsive top-bars + collapsible raw-app sidebar (#9237)
* feat(editors): responsive top-bars + script test-pane pixel-min + flow graph overlay
Editor top bars now collapse on narrow widths (measured via container
clientWidth, not viewport — they live inside drawers / session panes
where the viewport stays wide):
- FlowBuilder: Diff + Save draft fold into the ellipsis menu when
the top bar narrows below 720px (Save draft keeps its ⌘S / Ctrl+S
shortcut indicator). Test-flow button moves out of the top bar
and into a graph-pane overlay matching the dev page; the overlay
position flips from top-2 right-2 to top-14 left-1/2 when the
graph pane itself is narrower than 800px. FlowEditor exposes a
graphOverlay snippet prop for that.
- ScriptBuilder: Settings + Draft labels collapse to icon-only;
a new DropdownV2 ellipsis surfaces Tag / Settings / Save draft
when even icons don't fit. The ellipsis itself uses variant=subtle.
- AppEditorHeader / RawAppEditorHeader: fullscreen / dark-mode /
breakpoint toggle group + Debug-runs / Jobs buttons hide; Save
draft moves into the Deploy dropdown.
- EditorBar: a "Helpers" DropdownV2 collapse for Context var /
Variable / S3 / Resource / Git repo / Resource type / Database /
Ducklake / Data table / Reset when the bar narrows below 800px
(EDITOR_BAR_HELPERS_COMPACT_THRESHOLD). Above that, the existing
icon-only mode (1420px threshold) still applies.
- ScriptEditor's test pane gets a pixel-based minimum width (400px)
derived from the splitpane's clientWidth. The Pane uses Svelte 5
function-binding so the splitter writes to a raw $state while the
splitpane reads the clamped derived value — no $effect, no
release-time bounce, drag stops at the boundary. Cap raised to
80% so the test pane can take most of the editor on very narrow
layouts while leaving a sliver of code visible.
- VS Code button on ScriptEditor: collapses to icon-only below the
EDITOR_BAR_WIDTH_THRESHOLD (1420px) instead of being hidden
entirely by viewport `lg:` breakpoint; hidden completely when the
editor is rendered inside a session pane.
- AI wand button on ScriptEditor + RawAppEditorHeader: hidden inside
a session pane (detected via `getContext('aiChatManager')`) — the
session owns its own AI chat.
- DeployButton: drops the unused `newFlow` gate (callers updated).
- FlowDiffViewer / FlowGraphDiffViewer: inlineDiff prop forwarding
+ onHeight callback on FlowGraphV2 so diff viewers can equalize
side-by-side graph heights.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ui: unify Debug / wand / test-toggle button sizes + HideButton defaults
Two small consistency passes on shared button components:
- ScriptEditor's Debug, AI wand and Test-panel-toggle buttons all
use unifiedSize="sm" so they line up in the toolbar; Test toggle
switches from custom marine btnClasses to variant="accent-secondary".
HideButton gains a passthrough unifiedSize prop so the wand and
test toggle can match Debug without overriding btnClasses.
- HideButton's own defaults shift to variant="subtle" + sm
unifiedSize, dropping the legacy color="light" / variant="contained"
+ tailwind-merge background overlay; the selected (hidden) state
is now a tinted wrapper div instead of overriding btnClasses.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ui(script): editor toolbar polish
Small consistency tweaks on the script editor's top-right overlay:
- Lowercase "test" / "Exit debug" panel labels.
- `bg-surface` on the overlay container so the absolute-positioned
buttons read as a single panel over the graph rather than disjoint
pills.
- Debug button picks up `destructive={debugMode}` so the active
state reads as "you're in debug mode" instead of accent.
- Console and "Delegating to git repo" buttons drop the custom
`btnClasses` border-on-surface treatment and switch from
`size="xs"` to `unifiedSize="sm"` so they match the other buttons
in the cluster.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(raw-app): collapsible file sidebar, default-collapsed in session preview
The raw-app editor's left sidebar (file tree, runnables, history) ate a
lot of horizontal space — fine in the standalone editor, painful in the
session preview pane where the chat is already taking half the screen.
Add a small collapse / expand toggle. Persist the user's preference in
localStorage so it sticks across opens.
Two independent localStorage keys via the new `sidebarStorageKey` prop:
- standalone editor: `raw-app-sidebar-collapsed` (default expanded)
- session preview: `raw-app-sidebar-collapsed-preview` (default collapsed)
Otherwise the two contexts would race for the same key — whichever
opens first would dictate the other's default. Splitting the keys lets
each have its own remembered preference.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fixup(editors): use untyped getContext for AI-chat-manager session detection
The cherry-picks landed `getContext<AIChatManager>('aiChatManager')` to
hide per-editor AI/VSCode buttons when rendered inside a session pane.
The `AIChatManager` class is exported only on the sessions branch (used
for typing session-provided manager overrides). On `main` the manager
file exports only the singleton instance, so importing the class fails
the type-check.
The session-pane detection just needs a truthy/falsy probe — drop the
type parameter and the class import. `inSessionPane` ends up as
`getContext('aiChatManager')` (returns `unknown`, coerced to boolean
via `!!`). Same runtime behaviour, no class-export dependency.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* ui(editors): flow test in top bar; ellipsis folds draft/jobs/tutorials
* refactor(app-editor): drop dead AppEditorTutorial button path
* ui(editors): wire compactHelpers in flow-step + raw-app inline editors
* ui(raw-app): sidebar Cmd/Ctrl+B toggle + uppercase section titles
* ui(editors): keep Diff/Settings inline as icon-only when narrow
* fix(editors): address review nits on test-pane/Helpers/thresholds
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
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
|
||
|
|
31b781000e |
feat(frontend): sync home search bar state to URL (#9256)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
78cf6c7f81 |
fix(saml): preserve deep links from /a/[...path] across SAML round-trip (#9259)
* [ee] fix(saml): preserve deep links from /a/[...path] across SAML round-trip Fixes WIN-1962. PR #9225 only covered users who pass through /user/login on their way to the IdP — that's where `redirectSaml()` runs and where the deep link gets stuffed into `RelayState`. The reported flow doesn't go through that page: it hits `/a/[...path]` (the public-app custom-path route, outside the `(logged)` layout) where `PublicApp.svelte` renders its own `<Login>` and was passing `page.url.toString()` as `rd` — the full URL. Three problems compounded: 1. `redirectSaml()` only set `RelayState` when `rd.startsWith('/')`, so a full URL silently fell through and the deep link was lost. The IdP echoed back the SP-library default (BASE_URL), which the ACS validator correctly rejected as a potential open-redirect. 2. `persistRd()` stored the full URL in `localStorage.rd`. On the fallback landing at `/user/login`, the post-login redirect saw an `http://...` value, hit the cross-origin branch, and bounced to `/` — which from a logged-in but workspace-less state shows the "Loading user…" modal forever (bug 2). 3. The EE `safe_relay_state_redirect` validator rejected any full URL, including same-origin ones, so even IdPs that prepend the origin or that pass a configured absolute deep link via IdP-initiated SSO got dropped on the floor. The fix is a single concept applied at every layer: reduce a redirect target to a safe same-origin relative path, or refuse it. Frontend: - `logoutRedirect.ts`: new `toSameOriginRelativePath(rd)` helper that accepts both `/foo` and `https://current-origin/foo`, with the same open-redirect guards as the backend (length cap, control chars, no protocol-relative or back-slash tricks). Returns `null` for cross-origin or malformed input. - `PublicApp.svelte`: pass `pathname + search + hash` to `<Login>` instead of the full URL — this alone fixes the happy path. - `Login.svelte`: `redirectSaml()`, `persistRd()`, and `redirectUser()` all route through the helper, so full URLs from `/a/[...path]` are reduced before being put in `RelayState`/`localStorage`/`goto()`. - `/user/login/+page.svelte`: the same reduction is applied to the resolved `rd` so any stale full-URL value in `localStorage.rd` still navigates to the intended page instead of falling into the cross-origin branch. Backend (EE companion: windmill-ee-private#TBD): - `safe_relay_state_redirect` now reduces a `RelayState` whose origin matches `BASE_URL` to its path before applying the same-origin path safety rules. Bare BASE_URL with no path still falls back to `/user/login` (no useful deep link to honor). - New `same_origin_relative_path` helper + expanded unit tests. Test plan: - [x] Frontend: `vitest run src/lib/logoutRedirect.test.ts` — 9 passed - [x] Backend: `cargo test -p windmill-api ... saml_ee::tests` — 3 passed (`honors_same_origin_relative_path`, `reduces_same_origin_full_url_to_path`, `falls_back_on_open_redirect_attempts`) - [ ] Manual e2e (needs configured SAML IdP — not on local CE): - Unauthenticated visit to `/a/<path>` → click SSO → SAML → land on `/a/<path>` (RelayState now carries the relative path). - IdP that echoes BASE_URL as default → ACS still falls back to `/user/login` (no useful path to honor), but the page no longer hangs: the stale full-URL `localStorage.rd` is reduced to its path and the post-login redirect navigates to it. - Tampered `RelayState` (`//evil.com`, `https://evil.com/x`) → ACS rejects, lands on `/user/login`. * chore: update ee-repo-ref to 3489c243b0e5a8eb0dbc86e90917fbe72843573b This commit updates the EE repository reference after PR #584 was merged in windmill-ee-private. Previous ee-repo-ref: 635ff3eeb8e47bb84d5686942605f67f8f6224b4 New ee-repo-ref: 3489c243b0e5a8eb0dbc86e90917fbe72843573b Automated by sync-ee-ref workflow. --------- Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
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> |
||
|
|
cc141effa3 |
fix(frontend): flow progress bar for early-stop completion and error handler (WIN-1961) (#9254)
Two FlowProgressBar bugs: 1. stop_after_if (without 'label as skipped') ends the flow with step < modules.length, leaving the bar at <100% with a spinner. 2. failure_module execution drives step past modules.length, so the bar overflows past 100% and never reflects the error. The fix clamps progress to the failed module when the error handler runs, and forces 100% Done when the flow completed successfully but stopped early. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
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>
|
||
|
|
d08f72b3e1 |
feat(vault): optional KV secret path prefix setting (WIN-1960) (#9249)
* feat(vault): add optional KV secret path prefix setting (WIN-1960) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to 0189ba6504fd70eb4929e4881d624d48efd14aee This commit updates the EE repository reference after PR #581 was merged in windmill-ee-private. Previous ee-repo-ref: e32e8d6483550c67897e09b6f900dff1034bdae8 New ee-repo-ref: 0189ba6504fd70eb4929e4881d624d48efd14aee Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
285a78752a |
feat(indexer): observability for unavailable search index (WIN-1956) (#9239)
* [ee] feat(indexer): observability for unavailable search index A user hit `Not found: There is no index reader to search from` when searching service logs and could not tell whether it was a config error or a bug, and asked for visibility into the indexer status (WIN-1956). Backend (EE companion PR): - Replace the opaque error with an actionable message explaining the likely causes (indexer disabled, still starting, or blocked acquiring the indexer lock) and pointing to the status panel. - Add a coarse `state` (running | stale | never_started) to `/indexer/status`, derived from the lock row, distinguishing a never-configured indexer from a stale/blocked one. Frontend: - Instance Settings > Indexer now shows Running / Stale / Not started with a tooltip explaining what to check for each. - Service logs search now catches failures and shows an inline, actionable Alert instead of an unhandled rejection. Fixes WIN-1956 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to 017d36418a65ce5c840c502e3174df0c393612ba This commit updates the EE repository reference after PR #580 was merged in windmill-ee-private. Previous ee-repo-ref: 18b7e1b30a1ff582c4a072580bbb8aec34e22cdc New ee-repo-ref: 017d36418a65ce5c840c502e3174df0c393612ba Automated by sync-ee-ref workflow. * fix(indexer): address review nits - IndexerMemorySettings: older backends without `state` reporting `is_alive: false` now show "Stopped" (red) again instead of falling through to "Unknown" (codex/cubic P2). - ServiceLogsInner: clear stale logs/counts on a failed search so the error isn't shown alongside results from a previous query (codex P2). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
f51b51a9a1 |
fix(frontend): open customer portal in popup synchronously to bypass Safari blocker (#9242)
* fix(frontend): open customer portal in popup synchronously to bypass Safari blocker Safari blocks window.open() called after an await because it loses the user-gesture context. Open a blank tab synchronously on click, then assign location.href once the portal URL resolves. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(backend): wire dev_override feature flag in backend crate Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
ba6fb7021b |
feat: export audit logs to a dedicated object store folder (#9207)
* feat: export audit logs to dedicated object store folder * fix: gap-free audit export via snapshot-xmin gate and stable object keys * test: add integration test for audit log object store exporter * fix: cursor audit export on snapshot xmin to prevent id-leapfrog loss * fix: protect audit s3 checkpoint from config sync and bound export interval * fix: anchor audit s3 checkpoint at enable time to not skip first-window rows * fix: anchor first audit export at the enable transaction's xid * fix: use epoch timestamp floor on first audit export run to not drop old backlog * fix: anchor audit export at startup for env-var enable path * fix: anchor audit export via enabling-txn snapshot xmin trigger * fix: bound the bootstrap audit export to MAX_XID_INTERVAL per tick * refactor: store audit export cursor in background_task_state, add status endpoint * docs: align store_audit_logs_s3 setting text with the actual enable-boundary contract * [ee] refactor: move audit s3 export core logic to EE, gate on Enterprise license * chore: update ee-repo-ref to ec3cd353245e1cdf6a290528dbd7f2ac2498386c This commit updates the EE repository reference after PR #579 was merged in windmill-ee-private. Previous ee-repo-ref: 4ffc6d5f874e64d7dc4a147b4e73baa6c44867a5 New ee-repo-ref: ec3cd353245e1cdf6a290528dbd7f2ac2498386c Automated by sync-ee-ref workflow. --------- Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
bd062825a2 |
fix: scope VSCode webview clipboard paste to focused editor (#9221)
* fix: scope SimpleEditor webview paste to focused editor instance * fix: scope webview clipboard paste to focused editor instance Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: bail on missing selection instead of pasting at document start Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: hide SimpleEditor paste sink input from a11y tree and tab order Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
8c1f6ccc5d | fix: prevent undefined user flickering in multiplayer presence list (#9231) | ||
|
|
c8ab030aa4 |
chore(main): release 1.704.1 (#9226)
* chore(main): release 1.704.1 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.com> |
||
|
|
9c6deec8ff |
avoid stale localStorage rd when SAML RelayState carries the deep link (#9228)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
89306d7dbc |
fix: honor SAML RelayState to redirect to deep link after SSO login (#9225)
* fix: honor SAML RelayState to redirect to deep link after SSO login Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: bump ee-repo-ref for SAML RelayState validator test Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to a3fefe85f5f2f52bb473fa47acc9efa8fd0b2206 This commit updates the EE repository reference after PR #577 was merged in windmill-ee-private. Previous ee-repo-ref: 445a22536b1a6c342cde0baa6fbca9e25092f94b New ee-repo-ref: a3fefe85f5f2f52bb473fa47acc9efa8fd0b2206 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
11c03ca14e |
chore(main): release 1.704.0 (#9210)
* chore(main): release 1.704.0 * Apply automatic changes --------- Co-authored-by: rubenfiszel <275584+rubenfiszel@users.noreply.github.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 |
||
|
|
2e05bdd73a |
feat: show job status in favicon on the run page (#9206)
* feat: show job status in favicon on the run page * test: cover getJobStatusKind favicon status mapping * chore: remove favicon unit tests Co-authored-by: Diego Imbert <diegoimbert@users.noreply.github.com> Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Diego Imbert <diegoimbert@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
156eb0b045 |
fix: resolve absolute-path imports in monaco ts editor (#9213)
* fix: resolve absolute-path imports in monaco ts editor * fix: dispose absolute-path extra libs on editor teardown and reset * fix: skip late ata local-file callbacks after editor teardown |