* Update clients to check for agent workers
* fixes
* typescript uses 127.0.0.1
* Refresh system prompts
* fix: check both localhost and 127.0.0.1 in workerHasInternalServer detection
Both Python and TypeScript clients now check for both hostnames to avoid
silent breakage if BASE_INTERNAL_URL uses one or the other. Also adds
return type annotation to the Python method.
Co-authored-by: Diego Imbert <diegoimbert@users.noreply.github.com>
* refresh system prompts
* nit localhost regex boundary
* fix: use provider.language instead of undefined bare language in sqlUtils
The language variable was referenced as a bare identifier in the fetch
calls, resolving to undefined at runtime instead of reading from
provider.language.
Co-Authored-By: Claude Opus 4.6 (1M context) <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: Ruben Fiszel <ruben@windmill.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: set 300s timeout on python client httpx to prevent ducklake query timeouts
The httpx.Client was using the default 5s timeout, causing ducklake SQL
queries (which run synchronously via run_inline_preview_script) to timeout
for any query taking longer than 5 seconds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: disable timeout on python client httpx
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Update client.py
* Update client.py
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add selfApproval option to WAC waitForApproval + inline approval buttons
Add self-approval configuration to WAC workflows and inline
approve/reject buttons in WorkflowTimeline.
- TS SDK: add selfApproval option to waitForApproval()
- Python SDK: add self_approval param to wait_for_approval()
- Backend: store approval_conditions in flow_status for WAC,
enforce self-approval checks on resume endpoints
- Frontend: show Approve/Reject buttons in timeline with form
support (EE), gated by user permissions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: revert sqlx query change + regenerate system prompts
- Revert get_suspended_flow_info to use original sqlx::query_as!
with COALESCE to avoid sqlx offline cache mismatch in CI
- Detect WAC by checking if FlowStatus parsing fails + suspend > 0
- Re-fetch flow_status column separately for WAC approval conditions
- Regenerate auto-generated system prompt files for SDK changes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: use resume URLs for WAC inline approval buttons
- Backend generates HMAC-signed resume/cancel URLs when creating
WAC approval, stores them in timeline entry and approval meta
- Frontend uses anonymous resume endpoint (like classic flows)
with fallback to resumeSuspendedFlowAsOwner for admins
- Buttons show for everyone when URLs are present; server-side
self_approval_disabled check enforces restrictions
- Show warning for admins/owners when self-approval is disabled
- selfApproval: false requires EE (errors at dispatch on CE)
- self_approval_disabled check moved outside user_auth_required
gate so it works independently
- WAC detection no longer requires task import
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add resume_suspended and approval_info endpoints
- New approval_token DB table for token-based approval access
- New POST /jobs_u/flow/resume_suspended/{job_id} endpoint:
- OptAuthed: works with login or approval_token
- Checks approval_conditions (self_approval, groups, auth)
- Admins/owners bypass rules
- New GET /jobs_u/flow/approval_info/{job_id} endpoint:
- Returns form, rules, can_approve status
- HMAC anonymous endpoint now bypasses all approval_conditions
(secret = full capability)
- getResumeUrls approvalPage URL now uses token format
- WAC approval dispatch generates and stores approval tokens
- Mark resumeSuspendedFlowAsOwner as legacy
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: simplify frontend to use resume_suspended endpoint
- OpenAPI spec updated with resume_suspended and approval_info endpoints
- WorkflowTimeline: removed URL parsing, now calls single
resumeSuspended endpoint for both approve and reject
- Buttons show for any logged-in user viewing the job (backend
enforces authorization rules)
- Kept self-approval warning for admins
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: stateless approval tokens, new approval page, FlowStatusWaitingForEvents update
- Replace DB-stored approval tokens with stateless HMAC derivation:
token = HMAC(workspace_key, job_id + "approval_token")
Verifiable without DB lookup, not reversible to resume secret
- Drop approval_token migration (no DB table needed)
- FlowStatusWaitingForEvents: use resumeSuspended endpoint instead
of URL parsing + resumeSuspendedFlowAsOwner
- New approval page route /approve/{ws}/{job}?token= that uses
approval_info and resume_suspended endpoints
- Old approval page route kept for back-compat
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: match old approval page content in new approval page
- Add FlowMetadata, JobArgs, FlowGraphV2, DisplayResult
- Add approvers with tooltips, flow arguments section
- Add admin self-approval bypass warning
- Add "Open run details" link
- Fetch full job alongside approval_info for all UI data
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: filter _MODULES from args, show 'workflow' for WAC approvals
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: remove deno template from approval/prompt SuspendDrawer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: approval page form display + hide deno from approval script picker
- Fix form schema rendering on new approval page by wrapping flat
WAC form schemas in { properties, order } for SchemaForm
- Hide deno from the approval step language picker in flow editor
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove deno from canHaveApproval in script_helpers.ts
The insert menu uses canHaveApproval() from script_helpers.ts via
FlowInputsQuick, not the displayLang function in FlowInputs.svelte.
Revert the unnecessary FlowInputs.svelte change.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: return form schema and description in approval_info for classic flows
The approval_info endpoint was returning None for form_schema on
classic flows. Now fetches raw_flow to get suspend.resume_form
schema, hide_cancel, and the step's completed result for description.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: inline Login component on approval page instead of redirect
Show the Login component directly on the approval page when
authentication is required. On successful login, reloads user
and approval info without navigating away.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: show resume buttons for all users, not just owners
The resume_suspended endpoint handles authorization server-side,
so the frontend should always show the buttons. Remove isOwner
gate and the "cannot resume" message.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: prevent layout shift on resume by removing spinner from cancel button
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: prevent resume button expansion by using disabled instead of loading
The loading prop adds a Loader2 spinner that expands the button width.
Use disabled={loading} instead to prevent layout shift.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: approval page login redirects back with full page reload
Set rd to the full URL (starts with http) so Login.redirectUser()
uses window.location.href instead of goto(), triggering a full page
reload after login. This ensures the approval page re-fetches data
as an authenticated user.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: fetch flow definition from flow_version when raw_flow is null
Deployed flows don't store raw_flow on the job. Fall back to
flow_version table using runnable_id to get suspend settings
(form schema, hide_cancel) for the approval_info endpoint.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: show specific reasons when user cannot approve
Display whether denial is due to self-approval being disabled,
required group membership, or both.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: support both nested and flat form schema in waitForApproval
Users can now pass either:
waitForApproval({ form: { schema: { name: { type: "string" } } } })
or:
waitForApproval({ form: { name: { type: "string" } } })
Both WorkflowTimeline and approval page handle both formats.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: convert sqlx query macros to non-macro for CI offline cache
Replace sqlx::query! and sqlx::query_scalar! with sqlx::query and
sqlx::query_as to avoid SQLX_OFFLINE cache misses in CI.
Also remove unused LogIn import from approval page.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: suppress dead code warning + unused isOwner variable
- Add #[allow(dead_code)] to without_flow method (CI -D warnings)
- Rename isOwner to _isOwner in FlowStatusWaitingForEvents (unused)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: security and robustness fixes from PR review
- Add workspace_id verification in resume_suspended to prevent
cross-workspace approval (#3)
- Fix token leakage: use relative path for login redirect instead
of full URL with token (#4)
- Handle getJob failure independently from approval_info so the
page works for unauthenticated users (#7)
- Clear error state on successful data load (#13)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address review feedback — shared token gen, rand resume_id, UX
- Move generate_approval_token to windmill-common::variables (shared
between windmill-api and windmill-worker, eliminates duplicate HMAC)
- Use rand::random::<u32>() for resume_id instead of DefaultHasher
- Stop polling after approve/reject on approval page
- Add cancelLoading state to WorkflowTimeline Reject button
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add script module mode with folder model for Bun and Python
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add missing modules field to RawCode in bun_executor
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* sqlx
* feat: enrich WAC templates with checkpoint and replay semantics
Add prominent comments explaining that all computation must happen
inside task/step/taskScript or it will be replayed on resume/retry.
Clarify that waitForApproval does not hold a worker and that
approve/reject URLs are available in the timeline step details.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(cli): script module sync idempotency, per-module hash tracking, and preview support
- Fix pull→push idempotency: use `??` instead of `||` for module lock
field so empty strings are preserved (matches API's `lock: ""`)
- Add per-module hash tracking in wmill-lock.yaml following the flow
inline script pattern (SCRIPT_TOP_HASH + per-module subpath hashes)
- Selective module lock regeneration: only regenerate locks for modules
whose content actually changed, not all modules
- Use unfiltered rawWorkspaceDependencies for module hashes to match
what updateModuleLocks passes to fetchScriptLock
- Show changed module names in stale script output for clarity
- Add module support to `script preview` command: read modules from
__mod/ folder and pass them in the preview API request
- Add preview tests for taskScript pattern (flat and folder layout)
- Update test assertion for module stale detection output
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(frontend): WAC UI improvements — reorder templates, module tab rename, import consolidation
- Reorder WAC template buttons: TypeScript before Python in
ScriptBuilder, CreateActionsScript, and CreateActionsFlow
- Remove dropdown items from +Script button (simplify to direct link)
- Move "Import Workflow-as-Code" to +Flow dropdown with dedicated drawer
- Add module tab rename: pencil icon on hover opens popover with
validation, fixed-width icon container prevents layout shift
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: remaining module-mode changes from working branch
- Backend parser updates for WAC detection
- CLI sync/types updates for raw app path and module support
- Frontend UI polish (Dev.svelte, ScriptRow, script hash page)
- Test fixture updates
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test(cli): add test for module modification detection in generate-metadata
Verifies that modifying a single module file re-triggers stale
detection and only the changed module is listed, not all modules.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(backend): critical fixes from PR review
- Fix hardcoded dev path in bun_executor.rs WAC v2 wrapper — use
"windmill-client" import instead of absolute filesystem path
- Fix missed no_main_func → auto_kind rename in parser TS test
- Add modules column to clone_script SQL (windmill-common and
windmill-api-workspaces) so cloned scripts retain their modules
- Add modules: None to RawCode structs in worker tests
- Restore complete sqlx cache (merge main's cache + our new queries)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(backend): fix clone warning treated as error in CI
Change `.clone()` on double reference to `*k` dereference in
scripts.rs hash implementation. Update sqlx cache with new query
hashes from modified clone_script SQL.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(frontend): use published parser wasm versions for CI build
The local file:// paths for windmill-parser-wasm-py and
windmill-parser-wasm-ts don't exist in the Cloudflare Pages build
environment. Revert to published npm versions (1.655.0).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(frontend): update parser wasm packages to 1.657.2
Use newly published windmill-parser-wasm-ts and windmill-parser-wasm-py
v1.657.2 which include auto_kind/WAC detection changes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(frontend): regenerate package-lock.json for npm ci compatibility
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(frontend): use main's lockfile as base, update only parser wasm packages
Regenerating package-lock.json from scratch pulled different dependency
versions causing svelte-check type errors. Instead, start from main's
lockfile and only update the two changed packages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(backend): add modules column to fetch_script_for_update query
The Script<SR> struct has a modules field (FromRow), but
fetch_script_for_update didn't SELECT modules, causing a runtime
error "no column found for name: modules" when the worker processed
dependency jobs. This was the root cause of the relock_skip test
timeout.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(backend): fix script module execution for Python and Bun
- Fix modules not passed through job queue: inject _MODULES into
PushArgs.extra when pushing Code jobs so worker can extract them
- Fix Python module imports: use relative imports (from .helper)
and add sys.path.insert for module directory in wrapper
- Fix Python tests: use relative imports and empty lock to prevent
pip from resolving module names as packages
- Add local file check in Bun loader for module resolution
- Ignore Bun module test (bundle mode loader integration tracked
separately)
- Add missing modules column to fetch_script_for_update query
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(backend): remove unnecessary empty lock in Python module tests
Relative imports (from .helper) are not parsed as pip packages,
so the empty lock workaround is not needed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(backend): fix module execution for Python and Bun — all tests pass
Python modules:
- Use relative imports (from .helper import greet) since scripts run
as packages
- Add sys.path.insert for module directory in wrapper to ensure local
modules take precedence over pip packages with same name
Bun modules:
- Use bundled output (./out/main.js) as wrapper import when modules
are present — the bundled output has module content inlined by
Bun.build, avoiding runtime loader resolution issues
- Add local file check in loader.bun.js onResolve to short-circuit
API URL resolution for module files on disk
Job queue:
- Inject _MODULES into PushArgs.extra when pushing Code jobs so
the worker can extract them at execution time
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: address PR review — simplify, fix correctness, remove dead code
Critical fixes:
- Replace all CLI `no_main_func` references with `auto_kind` (string)
to match the backend migration and API changes
- Remove duplicated `compute_python_module_dir` in worker.rs, use
the canonical version from python_executor.rs
High priority:
- Auto-create `__init__.py` in intermediate directories for nested
Python modules so imports like `from .utils.math import add` work
without users manually creating __init__.py files
- Remove redundant `sys_path_insert` — relative imports use Python's
package system, not sys.path
Medium:
- Fix lock file base name extraction: use regex to strip only the
final extension (`.replace(/\.[^.]+$/, '')`) instead of `indexOf(".")`
which breaks for files like `helper.test.ts`
Simplification:
- Remove dead `{#if false}` Popover block in ScriptEditor.svelte
- Guard loader.bun.js local file check to only run for relative paths
(matching the Windows loader pattern)
- Add clarifying comment on Bun dual mechanism (build + run phases)
- Add maintenance comment on manual Hash impl for NewScript
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: final review fixes — stale cleanup, baseName, auto_kind export
- Fix sync.ts baseName extraction using indexOf(".") → regex
(same fix as script.ts/metadata.ts, missed this instance)
- Add stale module file cleanup in writeModulesToDisk: removes files
from __mod/ that are no longer in the modules map before writing,
fixing the pull→push cycle that couldn't delete modules
- Log warning when _MODULES serialization fails in job push instead
of silently dropping modules
- Use strict equality (===) for auto_kind comparison
- Exclude auto_kind from workspace export — it is auto-detected by
the parser at deploy time from script content
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(cli): remove auto_kind from push, comparison, and metadata
auto_kind is auto-detected by the parser at deploy time, so the CLI
should not send it, compare it, or write it to script.yaml.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove erroneously added backend/backend/.sqlx directory
Duplicate .sqlx cache was committed at the wrong nested path.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address PR review feedback + fix CI dead_code warning
Frontend (ScriptEditor.svelte):
- Fix switchToMain() missing lastSyncedCode update — prevents stale
code sync on external changes while editing a module tab
- Fix formatAction saving module code to main script's localStorage
draft — now saves main code when on a module tab
- Fix non-null assertion on inferModuleLang in renameModule — fall
back to original language instead of force unwrap
- Remove redundant activeModuleTab truthy check in runTest
CLI (script.ts):
- Clean up empty directories after removing stale module files in
writeModulesToDisk
Backend:
- Add path traversal guard in write_module_files — reject module
paths containing ".."
- Fix dead_code warning on auto_kind field in workspace export struct
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(frontend): improve auto_kind UX + address review findings
- Rename "Include without main function" toggle to "Include library
scripts" in script list (ItemsList.svelte)
- Update NoMainFuncBadge: "No main" → "Library" with clearer tooltip
- Filter module file extensions by main script language — Python
scripts only allow .py modules, TypeScript only .ts, etc.
- Split flushModuleState into flushModuleContent (no UI side-effect)
and flushModuleState (flush + reset tab), reducing duplication
- Dynamic placeholder and hint text in add module popover based on
main script language
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>