* Show effective isolation level on workers page, not configured
The workers page displayed the configured isolation level (nsjail/unshare)
even when the binary wasn't actually available, which was misleading.
Now shows "none (nsjail unavailable)" or "none (unshare unavailable)"
when the setting is enabled but the binary failed its startup test,
so admins can immediately see the mismatch from the UI.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Simplify: use standard 'none' value when isolation binary unavailable
Keep the string as one of the 3 known values (nsjail/unshare/none)
since the frontend checks === 'none' for the warning badge. Now if
nsjail/unshare is configured but the binary is unavailable, it
correctly reports 'none' so the warning badge shows up.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Debounce node works
* sqlx prepare
* sqlx prepare
* fix: address PR review issues for flow node debouncing
- Add sibling check in parent-walking loop to avoid killing branchall siblings
- Remove stale .sqlx cache files from earlier iterations
- Remove single-variant FlowNodeDebounceResult enum, use Result<()>
- Parse flow value once in version guard, recurse into nested modules
- Fix Svelte reactivity when switching selected flow modules
- Fix Tab indentation in FlowModuleComponent
- Use integer types in OpenAPI spec for debounce fields
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ee repo ref
* nit sqlx
* add Debouncing: None
* ee repo ref
* ee repo
* sqlx update
* fix: reject node-level debouncing inside branches (branchall/branchone)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Revert "fix: reject node-level debouncing inside branches (branchall/branchone)"
This reverts commit fa4820dde2.
* ee repo
* sqlx prepare
* sqlx prepare
* feat: add MIN_VERSION_SUPPORTS_NODE_DEBOUNCING (1.658.0) version guard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: mark node-level debouncing as EE only in openflow schema
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: guard node debouncing against parallel steps (len > 1)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* generate system prompts
* system prompts
* chore: update ee-repo-ref to c04f3851c03758662e4936ff4b6e71bc56dbae7e
This commit updates the EE repository reference after PR #451 was merged in windmill-ee-private.
Previous ee-repo-ref: d140bb8944dfe3efb23cf8c12f556eacf30e2f87
New ee-repo-ref: c04f3851c03758662e4936ff4b6e71bc56dbae7e
Automated by sync-ee-ref workflow.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* SQL Query builders in Rust
* Remove frontend sql scripts and substitute at execution
* fix null value bug
* Handle WM_INTERNAL_DB marker for apps deployed prior
* Revert policy handling
* Fix database studio empty string as where clause
* check policy
* Revert "check policy"
This reverts commit 3ea7899979.
* Revert "Fix database studio empty string as where clause"
This reverts commit 432fc87915.
* Revert
* legacy comments
* Move DDL queries to backend
* tests
* move bigquery bun scripts to backend
* expand markers + other nits
* fix: escape sql literals in query builders and async preview sql
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: quote all user-supplied identifiers in query builders to prevent SQL injection
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: suppress dead_code warnings for deserialization-only fields and test-only helpers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: correct DDL test assertions and drop_table schema handling for non-schema DBs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* MySQL fix
* Fix 0/1 bool
* MySQL fix Yes/No casing
* Better error toasts
* Fix ms sql ntext cast
* fix: quote table name in Snowflake SHOW PRIMARY KEYS query
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: quote schema and table in Snowflake SHOW IMPORTED KEYS query
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: quote BigQuery dataset name in metadata query
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: remove invalid + separator in MSSQL CONCAT for count query
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Fix worker panic when job_isolation changed to unshare at runtime
When an admin changes the Instance Setting "job_isolation" to "unshare"
while UNSHARE_PATH was never initialized (binary not available at startup),
the worker panics in build_command_with_isolation().
This happens because reload_job_isolation_setting() in monitor.rs validates
nsjail availability but not unshare availability before applying the setting.
Fix:
- Add unshare availability check in reload_job_isolation_setting(), matching
the existing nsjail check
- Replace panic! in build_command_with_isolation() with an error log and
graceful fallback to running without isolation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Improve error logging for unshare/nsjail unavailability at startup
- Upgrade unshare init logs from warn/debug to error level with detailed
diagnostics (exit code, stderr, common causes, impact on job isolation)
- Upgrade nsjail init logs from info/warn to error level with clear
messaging about unavailability consequences
- Force both UNSHARE_PATH and NSJAIL_AVAILABLE initialization at worker
startup (not just when isolation is currently enabled) so availability
is always logged regardless of current config
- Add explicit startup warnings when worker is configured for isolation
but the binary is unavailable, referencing the init errors above
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix
Signed-off-by: pyranota <pyra@duck.com>
* reduce tests
Signed-off-by: pyranota <pyra@duck.com>
* update
Signed-off-by: pyranota <pyra@duck.com>
* fix
Signed-off-by: pyranota <pyra@duck.com>
* update
Signed-off-by: pyranota <pyra@duck.com>
* WIP: stash changes after merge with origin/main
* Delete backend/parsers/windmill-parser-wasm/Cargo.lock
* reset cargo.toml
* feat(cli): integrate dependency tree into generate-metadata command
- Add isDirectlyStale field to DependencyNode for staleness tracking
- Update addScript to accept itemType, folder, isRawApp, isDirectlyStale
- Update propagateStaleness to use isDirectlyStale field instead of parameter
- Handlers now determine staleness and pass it to tree.addScript
- generate-metadata calls propagateStaleness() and populates staleItems from tree
- Pass legacyBehaviour=false and tree to handlers during generation phase
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(cli): store originalPath in tree for correct handler invocation
Scripts need the path with extension to be passed to the handler.
Added originalPath field to DependencyNode to track this.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix parsers
Signed-off-by: pyranota <pyra@duck.com>
* rever sqlx removal
* update sqlx
* feat: make py-imports parser WASM-compatible and add as separate WASM package
Gate heavy deps (sqlx, windmill-common, async-recursion, toml, pep440_rs,
tracing) behind cfg(not(wasm32)). Make parse_code_for_imports,
parse_relative_imports, NImport, and ImportPin public. Remove duplicate
import_parser from parser-py (reset to origin/main). Add py-imports-parser
feature to windmill-parser-wasm and py-imports target to build.nu.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* safer return
* update
* fix: CLI metadata fixes - folder filter, staleness detection, WASM py-imports setup
- Fix lazy_static cfg gating for WASM compatibility (split into separate blocks)
- Fix folder argument filter to match specific file paths (not just directories)
- Fix staleness detection to use checkHash with conf (includes module hashes)
- Convert relative_imports_skip tests from Deno to bun APIs
- Add windmill-parser-wasm-py-imports to CLI and build-npm dependencies
- Relax module stale test to not require per-module change detail in output
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: restore temp_script_refs parameter in parse_python_imports
Re-adds the temp_script_refs parameter that was lost when resetting
py-imports crate to origin/main. This enables resolving relative imports
from not-yet-deployed scripts during CLI lock generation.
* fixes
* extend testsuit
* update ee repo ref
* fix: diff endpoint bytea cast, upload only mismatched scripts
- Add POST /scripts/raw_temp/diff endpoint to batch-compare local content
hashes against deployed versions using Postgres sha256()
- Use convert_to(content, 'UTF8') instead of content::bytea to avoid
failure on scripts containing backslash sequences (e.g. \n)
- CLI now diffs all scripts against deployed, uploads only mismatched ones
- propagateStaleness no longer deletes non-stale nodes (needed for diff)
- Suppress verbose log.info messages during metadata generation
- Add E2E tests for locally modified and unpushed helper scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* rework
* sqlx
* fixes
* add index
* expand tests
* fix flows
* archive script before executing
* disable tests for ci
* skip Python-dependent E2E tests on CI
Tests requiring the python backend feature are skipped when
CI_MINIMAL_FEATURES=true since CI builds with zip-only features.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: make flow fixture lock optional and reset nonDottedPaths after tests
Flow fixtures no longer emit an empty lock file by default. The lockContent
parameter controls whether a lock: "!inline ..." line appears in flow.yaml.
This prevents flows from appearing "up-to-date" when they should be processed
by generate-metadata.
Also adds afterAll to reset setNonDottedPaths(false) so global state doesn't
leak between test files when run together.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* debug: add error logging in withTestBackend to diagnose CI failures
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* debug: add --bail 1 to CI test runner to show full error on first failure
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* debug: include CLI stdout/stderr in assertion message for workspace deps test
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: set WMDEBUG_FORCE_V0_WORKSPACE_DEPENDENCIES in test backend
The workspace deps feature requires workers to report their version, but
in test/CI there are no separate workers (standalone mode). The version
check fails because workers haven't had time to ping yet. Setting this
env var bypasses the version check.
Also reverts --bail 1 from CI workflow now that the root cause is fixed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* debug: add --bail 1 to Windows CI and assertion messages for Windows failure diagnosis
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: replace TEMP_SCRIPT_REFS_PLACEHOLDER in bun builder tests
The loader.bun.js now includes a TEMP_SCRIPT_REFS_PLACEHOLDER that must
be replaced before execution. The builder tests were missing this
replacement, causing all 6 bun_builder_tests to fail.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use cdirFwd in Windows loader filterLoad regex
Raw cdir (with backslashes) interpolated into RegExp causes \r to
become carriage return and \w to become word-char, so filterLoad
never matches main.ts. This prevents replaceRelativeImports from
running, leaving bare relative imports like "./script_b" in the
bundled output, which scanImports then misparses as package ".".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: Windows filterLoad regex + graceful fallback for old backends
- Fix filterLoad in loader.bun.windows.js to match both native backslash
and forward-slash paths from Bun's resolver by escaping cdir for regex
- Wrap uploadScripts in try/catch so generate-metadata degrades gracefully
when the backend lacks /raw_temp endpoints (locks use deployed versions)
- Add TODO for missing TEMP_SCRIPT_REFS support in Windows loader
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* debug: add loader/builder debug logging for Windows CI diagnosis
Temporary console.log statements to understand:
- What path Bun passes to onLoad for main.ts
- Whether filterLoad regex matches
- Whether replaceRelativeImports fires
- What the bundled output contains
- What imports scanImports extracts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: trigger CI for cli path
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: trigger CI via workflow file change
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Add TEMP_SCRIPT_REFS to Windows loader, use .ts extensions in test imports
- Add TEMP_SCRIPT_REFS_PLACEHOLDER support to loader.bun.windows.js
(mirrors loader.bun.js) so CLI lock generation can resolve imports
from locally-modified scripts on Windows
- Use .ts extensions in all test relative imports to work around the
Windows filterLoad regex bug (replaceRelativeImports doesn't fire
on Windows, so extensionless imports fail)
- Remove unused uploadSucceeded variable
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Remove debug logging from loader_builder.bun.js
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Remove windmill-parser-wasm-py-imports from frontend package.json
This dependency is only needed by the CLI, not the frontend.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* debug: add temp_script_refs logging for Windows CI investigation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ci: remove --bail 1 from Windows CLI tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: normalize backslashes in folder filter treePath lookup (Windows)
On Windows, item.path (originalPath) uses backslashes but tree keys
use forward slashes. The isRelevant filter's touchesFolder call
passed the unnormalized path to traverseTransitive, which couldn't
find the node. This caused cross-folder importers to be excluded
from generate-metadata when a folder argument was specified.
Also removes debug logging from previous commit.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Update cli-tests.yml
* fix: normalize backslashes in strict-folder-boundaries warning message (Windows)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update ee-repo-ref to fe8f0d1d7448464c98474d994e6492c0a45e8e38
This commit updates the EE repository reference after PR #467 was merged in windmill-ee-private.
Previous ee-repo-ref: 03e6eaf950776c96b9581848a583af9ad735be60
New ee-repo-ref: fe8f0d1d7448464c98474d994e6492c0a45e8e38
Automated by sync-ee-ref workflow.
* revert cli-tests.yml
---------
Signed-off-by: pyranota <pyra@duck.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* feat: add AZ_ACCOUNT_NAME_WORKSPACE_RESTRICTIONS env var
Add workspace restrictions by Azure account name, similar to the existing
S3_BUCKETS_WORKSPACE_RESTRICTIONS for bucket names. Refactored parsing
into a shared parse_restrictions_from_str function.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: update ee-repo-ref.txt
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: update ee-repo-ref to a997285e976d0642b72584e1966a70a79d84e7dc
This commit updates the EE repository reference after PR #472 was merged in windmill-ee-private.
Previous ee-repo-ref: 5718dc7deca18ad52ffb413813e97b8ca75805b8
New ee-repo-ref: a997285e976d0642b72584e1966a70a79d84e7dc
Automated by sync-ee-ref workflow.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* fix: stop_after_if with empty error_message no longer prevents flow from stopping
When skip_if_stopped=true and error_message="" were both set, the flow
would continue executing instead of stopping because the empty string
was converted to a default error message, which triggered the error
handler path. Now skip_if_stopped takes precedence and the two options
are treated as mutually exclusive in both backend and frontend.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: regenerate system prompts after openflow schema change
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* [ee] feat: add OTel metrics support
Add OpenTelemetry metrics export for Windmill operational metrics.
When the OTel metrics toggle is enabled in instance settings (EE),
Windmill exports 16 metrics to any OTLP-compatible collector, letting
users observe queue depths, worker execution, DB pool state, and health
without a separate Prometheus setup.
Changes:
- otel_oss.rs: no-op stubs for OSS builds
- monitor.rs: queue count/running count gauges, zombie counters, DB pool
monitoring (shared single DB query and loop with Prometheus)
- worker.rs: execution count/duration, worker busy, pull duration
- jobs.rs: queue push/delete/pull counters
- health.rs: DB latency gauge
- main.rs: call monitor_pool_otel unconditionally
- InstanceSetting.svelte: enable metrics toggle for EE licenses
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: update ee-repo-ref.txt for OTel metrics
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add worker_started, worker_uptime, health_status, health_db_unresponsive OTel metrics
Wire up 5 additional metrics to reach parity with Prometheus:
- worker_execution_failed: wired in add_completed_job_error (was defined but unused)
- worker.started: incremented on worker startup
- worker.uptime: recorded each loop iteration
- health.status: phase gauge (healthy/degraded/unhealthy)
- health.db_unresponsive: flag (0/1)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: update ee-repo-ref.txt
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: update ee-repo-ref to fbe68e4aa621e30378995cfd328a6ccf74176614
This commit updates the EE repository reference after PR #469 was merged in windmill-ee-private.
Previous ee-repo-ref: 6fa1881aafdfb60f4abf11a37f01f6fedaecb3ec
New ee-repo-ref: fbe68e4aa621e30378995cfd328a6ccf74176614
Automated by sync-ee-ref workflow.
* fix: remove duplicate cfg attr and duplicate OTel pool reporting
- Remove duplicate #[cfg(feature = "prometheus")] on monitor_pool
- Remove OTel block from monitor_pool; monitor_pool_otel is the sole
OTel reporter, eliminating duplicate windmill.db.pool.* metrics in
EE builds
- Simplify monitor_pool back to its original Prometheus-only structure
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* fix: prevent AI agent tool jobs from becoming zombies on cancellation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* kill tool tasks on cancel timeout
* fix: address review feedback and update sqlx cache
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* perf: cache composer vendor dir to skip reinstall on repeated php executions
* feat: add COMPOSER_VENDOR_CACHE_DISABLED env var to opt out of vendor caching
---------
Co-authored-by: hugocasa <hugo@casademont.ch>
* feat: add workspace-specific registry overrides
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: move workspace registries to end of registries tab
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: workspace overrides use field selector instead of showing all fields
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* style: polish workspace registries UI to match design guidelines
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: show field selector directly and fix addField initialization logic
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: namespace pip_resolution_cache by workspace when registry overrides exist
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: namespace binary/bundle caches by workspace when registry overrides exist
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* perf: zero-cost cache suffix when no workspace overrides exist
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: reload workspace_registries via notify events on setting change
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address PR review findings
- Fix discardCategory not reverting workspace_registries changes
- Fix get_no_default: convert to async fn with owned Uuid param
- Fix append_logs: use windmill_queue import already available
- Fix ruby URL parsing: support both comma and whitespace delimiters
- Add WorkspaceRegistryMap type alias to reduce inline type noise
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* all
---------
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>
* fix: improve OOM killer observability for debugging pod-level kills
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: lower worker oom_score_adj to protect it from OOM killer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address PR review feedback on OOM observability
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: return structured error object on AI agent max iterations
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: avoid double serialization in max iterations error
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: replace unwrap with ? for to_raw_value in max iterations error
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add step_id to max iterations error for consistency with SerializedError
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add workspace dependencies support for powershell
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: improve workspace deps editor UX for powershell
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add powershell workspace deps support to CLI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: soft error when AI agent reaches max iterations instead of hard error
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: set output to error message when AI agent reaches max iterations
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add error field to AI agent result for max iterations soft error
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: restore default max iterations to 10
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: include partial result in max iterations error message
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: rename retries tab to error handling and reorganize sections
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Native mode (from DB config) was not accounted for when sizing the
connection pool or setting SLEEP_QUEUE, because both read NUM_WORKERS
from env which is never set when native mode is configured via the
worker group config in the database.
- Resolve native mode early (before connect_db) by querying the config
table with the initial DB connection
- Pass num_workers directly to connect_db instead of re-reading env
- Replace SLEEP_QUEUE lazy_static with sleep_queue() function that
checks NATIVE_MODE_RESOLVED at runtime (returns 300ms for native)
- Set NATIVE_MODE_RESOLVED immediately when is_native_mode_from_env()
- Allow native_mode in CE worker group config (was silently stripped)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add preprocessor support for dedicated workers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update ee-repo-ref.txt
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: extract transform_and_run helper in python dedicated wrapper
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add preprocessor support for bunnative scripts
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: resolve unused postprocessor variable in python wrapper
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* chore: add workflow_dispatch trigger to backend integration tests
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: bunnative fixture lock format and PrewarmedIsolate::spawn callers
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: update generate_dedicated_worker_wrapper callers in bun_jobs test
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: use non-dedicated workers in preprocessor integration tests
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: prewarm preprocessor isolate for bunnative dedicated workers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: flatten bunnative dedicated worker preprocessing into single result path
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use labeled block instead of async block for EE compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Update commit reference in ee-repo-ref.txt
* chore: update ee-repo-ref to e36945b987f7904fa984181baf3124e7b2722bd1
This commit updates the EE repository reference after PR #445 was merged in windmill-ee-private.
Previous ee-repo-ref: 8a2625833452aadb8907242bf502b24ca2dffd73
New ee-repo-ref: e36945b987f7904fa984181baf3124e7b2722bd1
Automated by sync-ee-ref workflow.
* Fix merge conflict in ee-repo-ref.txt
Resolve merge conflict in ee-repo-ref.txt
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* refactor: rename AnthropicPlatform to AIPlatform for generic vertex support
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add Vertex AI support for Google Gemini models
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update platform doc comments to be provider-generic
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update googleai default models to latest gemini 2.5 and 3
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: move AIPlatform to windmill_common to avoid duplication
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: hugocasa <hugo@casademont.ch>
* fix: correct debounce max_total_debounces_amount semantics and complete previous job on limit exceeded
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: enable debounce arg accumulation for post-preprocessing flows
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: add debounce accumulation tests for max_count and max_time limits
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: add push-time max_count and max_time accumulation tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* sqlx
* sqlx
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* perf: optimize job_stats storage for timestamps and zero-memory jobs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update sqlx offline cache nullable metadata
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: use centisecond offsets for job_stats timestamps (~248 day range)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: update SELECT to use offsets_cs column name
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: workflow-as-code v2 with @task decorator API
Replace ctx.step("name", "script") API with @task decorators where
functions are called directly. Users no longer need to pass WorkflowCtx
or use string-based step names/script paths.
Python: @task decorator with contextvars-based implicit context
TypeScript: task() wrapper with module-level context variable
Parsers: detect @task function calls instead of ctx.step() calls
Worker: updated wrappers to set implicit context
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: WAC v2 checkpoint/replay with _executing_key child dispatch
- Rust-side orchestration: parent dispatches child jobs, suspends, resumes on completion
- _executing_key in checkpoint tells child which step to execute directly
- task() throws StepSuspend(mode="step_complete") after executing target step
- result_processor handles child completion and updates parent checkpoint
- WacGraph.svelte for runtime execution visualization
- Sequential and parallel workflows tested end-to-end
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: WAC v2 bundle cache, globalThis ctx sharing, description optional
- Disable bun bundle caching for WAC v2 scripts (wrapper needs
windmill-client from node_modules, not available in bundle mode)
- Use Reflect.set/get(globalThis, "__wmill_wf_ctx") to share workflow
context across dual module instances (wrapper vs user script)
- Never-resolving thenable for non-matching steps in child job mode
prevents Promise.all race conditions
- Make description field optional in NewScript API (defaults to "")
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add step() primitive for inline checkpointed steps
step() executes a function inline (no child job) and persists the result
to the checkpoint. On replay, the cached value is returned — ensuring
deterministic behavior for non-deterministic operations like Date.now()
or Math.random().
- TypeScript: step(name, fn) — executes inline, throws StepSuspend with
mode "inline_checkpoint" to persist before continuing
- Rust: InlineCheckpoint variant in WacOutput, saves to checkpoint and
resets running=false for immediate re-pickup (no zombie wait)
- Shared step counter between task() and step() via _allocKey()
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add Python WAC v2 support with task(), step(), workflow()
- Python SDK: WorkflowCtx with _executing_key child mode, _alloc_key
shared counter, _run_inline_step for step(), _execute_directly and
_never_resolve for child mode, step() async function
- Python executor: WAC v2 detection, checkpoint.json writing, WAC
wrapper.py generation calling _run_workflow(), post-execution hook
into shared handle_wac_v2_output()
- Make handle_wac_v2_output pub so both bun and python executors share
the same dispatch/suspend/inline-checkpoint logic
- 17 Python tests covering dispatch, replay, parallel, conditional,
inline checkpoint, and child mode
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update sqlx prepared queries
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: WacGraph Tooltip→Popover, simplify wacToFlow parsers
- Fix type error: Tooltip doesn't accept text snippet, use Popover
- Extract shared helpers for task matching and block collection
- Replace linear tasks.find() with Map lookups
- Remove mutable module-level counter
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: Box::pin WAC v2 output handler to prevent stack overflow
handle_python_job's async state machine was too large when combined
with handle_wac_v2_output. Box::pin heap-allocates the future.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: merge WAC v1 and v2 task decorators to preserve backward compat
The v2 @task decorator was shadowing the v1 one, breaking WAC v1
scripts that rely on HTTP-based dispatch via /workflow_as_code/ API.
The merged decorator handles three modes:
- v2: inside @workflow context → checkpoint/replay dispatch
- v1: WM_JOB_ID set, no @workflow → HTTP API dispatch + wait_job
- standalone: no Windmill env → execute function body directly
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: skip no_main_func detection for WAC v2 scripts in TS and Python parsers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: prevent empty/noop dispatch causing infinite requeue loop
- Validate steps.len() > 0 in WAC dispatch handler (issue 3)
- Replace noop StepSuspend throw with never-resolving promise so it
can't reach the backend as an empty dispatch (issue 4)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: Python task wrapper now converts positional args to kwargs in v2 mode
Previously only **kwargs were passed to _next_step(), silently dropping
positional arguments. Extract shared _merge_args() helper used by both
v1 and v2 paths.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: replace unwrap() with proper error propagation in WAC arg serialization
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add workspace_id filter to v2_job queries in WAC dispatch
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: prevent race condition in WAC child dispatch
Restructure dispatch to save checkpoint + suspend parent + seed child
checkpoints in a single transaction BEFORE pushing child jobs. This
ensures a fast child can't complete before the parent is suspended.
Also wrap InlineCheckpoint save + running reset in a transaction to
prevent corrupted state on crash.
Use ULID for pre-generated child job IDs (consistent with rest of API).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: include step key and child job ID in WAC error propagation
Move step_key lookup before the success check so failed child errors
include which task failed, the child job ID, and the original error.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: document WAC determinism contract and step dispatch semantics
- Document that workflow functions must be deterministic across replays
- Document that WacStepDispatch.script/args are metadata, not dispatch targets
- Add comments on counter-based key allocation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: tighten WAC v2 detection to reduce false positives
Replace naive substring matching with line-aware checks that skip
comments and look for specific patterns:
- TS: import from "windmill-client" containing workflow/task
- Python: @workflow and @task decorators with wmill import
Extracted shared helpers in wac_executor.rs used by both executors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: show failed steps in WacGraph when workflow completes with errors
When flowDone is true and a pending step isn't in completedSteps,
mark it as 'failed' instead of 'running'. The failed state CSS and
XCircle icon were already defined but never triggered.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: unsuspend and fail parent when WAC child push fails
Previously if a child push failed mid-batch, the parent remained
suspended with suspend = num_steps but fewer children, hanging until
the 14-day timeout. Now the push loop catches errors and unsuspends
the parent before returning the error.
Also adds source hash validation: if the script content changes between
replays, the job fails with a clear error instead of silently feeding
stale checkpoint data into wrong steps.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: clear suspend_until when unsuspending WAC parent
Set suspend_until = NULL alongside suspend = 0 in both the child
failure and all-children-complete paths, so the parent doesn't rely
on subtle pull query invariants to be re-picked-up.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: add exhaustive edge case tests for WAC v2 SDK
fix: make TS task wrapper non-async to fix unawaited task flush
The async wrapper caused microtask-based thenable auto-resolution that
fired .then() and threw StepSuspend before _flushPending() could capture
unawaited steps — making the flush mechanism completely broken. Now the
thenable is returned directly without async wrapping. Backward compatible
with v1 (all code paths still return awaitables).
Tests added (59 TS + 66 Python) covering: full sequential lifecycle,
step after parallel, parallel after parallel, conditional on step result,
empty/single-task workflows, 10+ steps, falsy value preservation, inline
steps, mixed step/task, unawaited flush, child mode with parallel,
key determinism, large parallel groups, and complex mixed patterns.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: atomic checkpoint updates to prevent parallel child race condition
Replace read-modify-write pattern in handle_wac_child_completion with
atomic SQL operations:
- completed_steps merged via jsonb_set(... || jsonb_build_object(...))
so concurrent children on different workers don't overwrite each other
- suspend counter decremented atomically with RETURNING to determine
"all done" condition (instead of checking completed_steps in memory)
- suspend_until cleared in the same atomic decrement statement
Before this fix, two parallel children completing simultaneously could
both load the same checkpoint, each add their step, and save — the
second write would overwrite the first, silently losing a child result
and leaving the parent suspended forever.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: cancel already-pushed children on partial WAC dispatch failure
When pushing child jobs sequentially, if pushing child N fails, children
1..N-1 are already running. Previously the error handler only unsuspended
the parent, leaving orphaned children that would complete and corrupt the
checkpoint state (decrementing suspend on an already-unsuspended parent,
potentially causing duplicate step execution on re-run).
Now on partial failure:
1. Cancel all already-pushed children (prevents them from completing
and corrupting checkpoint state)
2. Clear pending_steps from checkpoint (so parent doesn't think
children are outstanding on re-run)
3. Then unsuspend parent (so the error propagates)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: skip WAC duration write and child check for non-WAC parents
The duration write to workflow_as_code_status was running for every
non-flow child with a parent (error handlers, success handlers,
run_script children), even though it was only intended for WAC jobs.
Add WHERE workflow_as_code_status IS NOT NULL to skip non-WAC parents
entirely. Piggyback RETURNING pending_steps.job_ids on the same query
so WAC v2 child completion needs zero extra DB round-trips on the
success path.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: seed child checkpoint in same transaction as push
The child checkpoint insert was happening before the child job was
pushed, violating the FK constraint on v2_job_status. Move it into
the push transaction so the job row exists and the child can't be
picked up before its checkpoint is ready.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: set running=false when WAC parent suspends for child dispatch
The parent job kept running=true after suspending, so workers wouldn't
pick it up when children completed and suspend reached 0. The parent
only advanced when the zombie job detector reset it (~90s). Now the
dispatch suspend sets running=false so the parent is immediately
eligible for pickup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: WAC parent suspend/unsuspend lifecycle
Keep running=true when suspending the parent so the normal pull query
(WHERE running=false) never picks it up. Keep suspend_until non-null
when decrementing suspend to 0 so the suspended pull query
(WHERE suspend_until IS NOT NULL AND suspend<=0) picks it up.
Previously: setting running=false caused infinite restart loops because
the normal pull query has no suspend check and would immediately re-pick
the parent. Clearing suspend_until on the last child prevented the
suspended pull from ever seeing it, requiring the 90s zombie detector.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add approval primitive, flow child completion, timeline fixes for WAC v2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add error propagation, task options, sleep, and parallel for WAC v2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: fix python SDK tests to use name-based keys and add new test coverage
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address WAC v2 review findings (sleep timing, error marker, atomicity)
- Fix sleep using suspend=1 instead of 0 to enforce actual delay
- Add approval/sleep resume injection to Python executor
- Fix TS SDK concurrency_limit mapping (was reading wrong property)
- Namespace error marker as __wmill_error to avoid user data collision
- Wrap child completion SQL in transaction for atomicity
- Decrement suspend even when step key is missing (prevents hang)
- Expand TASK_RE to handle export const, let, var, generics
- Validate step key uniqueness before dispatch
- Log warning on checkpoint deserialization failure
- Remove unimplemented delete_after_use from SDKs
- Add TaskError exception class to Python SDK with diagnostic context
- Fix extra positional args handling and add functools.wraps
- Improve getParamNames to handle typed/destructured params
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* sqlx
* sqlx
* test: add WAC v1 e2e integration tests for TS and Python
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: revert fake test versions in typescript-client
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: remove unused WacGraph component and strip wacToFlow to isWorkflowAsCode
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: extract shared approval/sleep resume logic into wac_executor
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: extract google ai logic to windmill-common and use native gemini api in chat proxy
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: use x-goog-api-key header for google ai non-chat requests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: transform gemini models response to openai format and use correct auth header
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: skip thought parts from gemini thinking models in sse stream
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Revert "fix: skip thought parts from gemini thinking models in sse stream"
This reverts commit dfa01d282c.
* fix: handle tool calls and sanitize schemas in gemini chat proxy
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: move Gemini→OpenAI response conversion to windmill-common
Extract streaming and non-streaming Gemini response conversion into
shared functions in ai_google so the API proxy and worker use the same
logic instead of duplicating format translation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: review fixes for google ai refactor
- Remove duplicate parse_data_url from worker utils, use shared version
from windmill_common::ai_google in both google_ai and anthropic providers
- Improve error diagnostics in google.rs by including HTTP status code
in error messages from Gemini API responses
- Change GeminiToolCallEvent::into_extra_content to instance method
to_extra_content using &self
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: deduplicate worker Gemini message conversion using pre-flight pattern
Replace the worker's `convert_messages_to_gemini` and
`convert_content_to_parts_with_s3` (~130 lines) with the existing
pre-flight pattern: `prepare_messages_for_api` converts S3 objects to
data URLs, then the shared `openai_messages_to_gemini` handles the rest.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: hugocasa <hugo@casademont.ch>
* feat: add secretKeyRef support for package registry and storage credentials
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update ee-repo-ref for test coverage commit
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update ee-repo-ref to 716b350bce1730b302c66ea69df618fa40f2f16b
This commit updates the EE repository reference after PR #443 was merged in windmill-ee-private.
Previous ee-repo-ref: d8498f003af407853eb1e98673d86d1816dbfeae
New ee-repo-ref: 716b350bce1730b302c66ea69df618fa40f2f16b
Automated by sync-ee-ref workflow.
* fix: box::pin database executor futures to prevent stack overflow
The if-else chain for database languages (postgresql, mysql, bigquery,
snowflake, mssql, oracledb, duckdb, graphql, nativets) was awaiting
futures directly on the stack. With all features enabled, the combined
async state machine became too large for the default thread stack size,
causing stack overflow in test_workflow_as_code.
The match block for main languages already used Box::pin; this applies
the same pattern to the database language branches.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
Two fixes:
1. When a parallel branchall/forloop has a `stop_after_all_iters_if` expression
that fails (e.g. bad JS syntax), the error was propagated with `?`, causing
the transaction to roll back the parallel index increment. Since all parallel
jobs were already completed, nothing could ever increment the index again and
the flow hung forever. Now the error is caught and converted to a stop-early
failure so the transaction commits and the flow fails gracefully.
2. Expressions like `results.a.length` in step input transforms resolved to null
because the `handle_full_regex` fast path intercepted them and used
PostgreSQL's `#>` JSON path operator, which can't resolve JS runtime
properties like `.length` on arrays. Now the fast path skips expressions
ending with JS-only properties (like `length`), falling through to full
QuickJS evaluation where they work correctly.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: gracefully handle uninitialized OTEL tracing proxy port
When OTEL tracing proxy is enabled but the MITM proxy port hasn't been
assigned yet (race condition at startup, or NUM_WORKERS > 1), fall back
to standard proxy envs instead of failing the job with
"OTEL tracing proxy port not initialized".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: log to job logs when OTEL tracing proxy is unavailable
When the OTEL tracing proxy is enabled but the port isn't initialized
(race at startup or NUM_WORKERS > 1), append a warning to the job logs
explaining why HTTP request tracing is unavailable for that job.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: suppress unused variable warnings on windows builds
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update ee-repo-ref.txt to merged commit
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: write fallback package.json for codebase mode to fix nsjail ERR_INVALID_PACKAGE_CONFIG
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* test: add e2e tests for codebase mode with and without nsjail
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* ci: add Windows backend integration test workflow
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* ci: temporarily add push trigger for testing
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* ci: add --no-fail-fast to run all test binaries
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: Windows path handling for backend integration tests
- WINDMILL_DIR: use std::env::temp_dir() on Windows instead of /tmp/windmill
- HOME_ENV: fall back to USERPROFILE on Windows when HOME is not set
- loader.bun.js: normalize paths to forward slashes for consistent
comparison with Bun's resolver output on Windows
- bun_executor.rs: convert job_dir to forward slashes in JS template
strings to avoid backslash escape issues (\t -> tab, etc.)
- go_executor.rs: fix windows_gopath() double backslash bug (r"\\" -> "\\")
- bash_executor.rs: default to "bash" (in PATH) on Windows instead of /bin/bash
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: improve Windows diagnostics and fix onLoad handler
- Include path in create_directory_async/sync panic messages
- Add WINDMILL_DIR initialization debug output
- Fix loader.bun.js onLoad: use properly escaped regex instead of
returning undefined (Bun requires onLoad to return an object)
- Add env var debug output to CI workflow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: sanitize Windows-invalid characters in test worker names and fix cargo path
- Replace :: with __ in worker names (colons illegal in Windows dir names)
- Fix HOME_DIR to fall back to USERPROFILE on Windows
- Add PATH fallback for cargo discovery on Windows
- Add debug logging to bun loader for fetch errors
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: handle single colons in worker names, pass MSVC linker env vars, revert bun debug
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: use .exe binary name on Windows and normalize bun import URL paths
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: use absolute path for rust binary, normalize bun resolve paths
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: use .wurl extension instead of .url for bun import resolution on Windows
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: use custom namespace for bun plugin to bypass default file resolution
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: use virtual namespace for bun import resolution to avoid Windows path issues
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: handle Windows 8.3 paths and namespace-prefixed importers in bun loader
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: strip namespace prefix from args.path and handle absolute imports without leading slash in bun loader
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: simplify bun loader and remove redundant cargo path lookups
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: use platform-specific cargo binary path with .exe on Windows
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: replace HOME_DIR with HOME_ENV in rust_executor to remove duplication
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: keep original bun loader on linux, use virtual namespace loader only on windows
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add variable and resource types to flow env variables
Flow env variables can now reference workspace variables ($var:path)
and resources ($res:path) that are resolved at runtime. Adds Variable
and Resource type options to the flow env editor with ItemPicker and
ResourcePicker components, and resolves references in both the flow
worker (via transform_json) and the API fallback endpoint.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(frontend): use inline DollarSign icon for variable picker
Replace the separate "Pick" button with the standard inline DollarSign
icon overlay that appears on hover, matching the existing ArgInput
pattern. Also add the icon to the string type input for quick variable
linking from any string field.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: simplify flow env var resolution and json_path handling in API
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(frontend): always show flow env variables in property picker
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: update flow_env openapi type to allow any JSON value
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor(frontend): remove redundant variable type from env var dropdown
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(frontend): use Label component and fix alert text in flow env vars editor
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(frontend): avoid redundant stringify/parse roundtrip in env type switch
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: address PR review comments for flow env vars
- Deduplicate db_authed in jobs.rs $var/$res resolution
- Add warn logging on variable/resource resolution failures
- Consolidate $effect blocks and remove auto-type-correction effect
- Make linked variable text a clickable link to variable editor
- Add hash-based variable editor opening on variables page
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* perf: avoid cloning entire FlowValue to resolve flow_env references
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: auto-heal corrupted python runtime cache on remote workers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Revert "fix: auto-heal corrupted python runtime cache on remote workers"
This reverts commit 0ea013a554.
* feat: make WINDMILL_DIR configurable via environment variable
Allow users to configure the base directory for Windmill's tmp/cache files
via the WINDMILL_DIR env var (default: /tmp/windmill). This fixes Python
runtime cache corruption on RHEL systems where systemd-tmpfiles-clean
removes files from /tmp.
Converts TMP_DIR (renamed to WINDMILL_DIR) and all derived cache directory
constants from compile-time const &str (concatcp!) to runtime lazy_static
String values.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update ee ref
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update ee ref
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: deref ERROR_DIR lazy_static for AsRef<Path> and Display traits
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update ee ref to branch name for CI compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: deref lazy_static constants in all executor files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update ee ref
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update ee ref
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update ee ref
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: panic if WINDMILL_DIR has trailing slash
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: also reject trailing backslash in WINDMILL_DIR for Windows
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: deref GO_BIN_CACHE_DIR in test utils
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: replace remaining hardcoded /tmp/windmill paths and validate empty WINDMILL_DIR
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: nsjail powershell mount dst, Windows path assumptions, pwsh deref consistency
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: restore Windows /tmp path translation in go and bun executors
The Windows path translation replaces /tmp with the Windows temp dir
(e.g. C:\tmp) before normalizing slashes. Without this, the default
WINDMILL_DIR=/tmp/windmill produces paths without a drive letter on
Windows.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update ee-repo-ref to 6fd5a2ce908235a17975ad4dbdf0051cd89334f3
This commit updates the EE repository reference after PR #436 was merged in windmill-ee-private.
Previous ee-repo-ref: e8c03e16720833230ebd1878b4c63642ecc6c80f
New ee-repo-ref: 6fd5a2ce908235a17975ad4dbdf0051cd89334f3
Automated by sync-ee-ref workflow.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* fix: skip stop_after_if evaluation for skipped (identity) flow steps
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: relax is_identity_job guard to only require skip_if
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: preserve debouncing settings for post-preprocessing arg accumulation
After preprocessing completes, store the flow's debouncing settings in
runnable_settings_handle on v2_job_queue so that maybe_apply_debouncing
can find them when the surviving job is pulled. Without this, the handle
is NULL and arg accumulation silently does nothing for flows with
preprocessors.
Also adds a debouncing badge in flow settings and 4 focused accumulation
tests covering scripts, flows without preprocessor, flows with
preprocessor (with and without the fix).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: update sqlx prepared query for worker_flow.rs change
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Support arg type decl in postgres
* Python datatable client no longer requires explicit arg typing
* compilation fix
* Set correct type in statement exec
* reset to main
* Explicit pg arg types
* remove code duplication
* update parser js
* FLOAT8 doesn't have space
---------
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
When a flow has a flow-level `skip_expr` (or `no_flow_overlap`) and the first
module has `skip_if` defined, the flow-level condition returns `UpdateFlow`
before any identity job is created. The `UpdateFlow` path passes `Uuid::nil()`
as `job_id_for_status`, causing `fetch_one` to fail with "no rows returned".
- Change `fetch_one` to `fetch_optional` so a missing row returns false
- Short-circuit the DB query with `stop_early && skip_if_stop_early` so both
skip mechanisms (identity job check and early-stop skip flag) are considered
- Also fixes the logical gap where a module with both `skip_if` and
`stop_after_if` would only check the identity job, ignoring the early-stop
skip signal
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* worker: support AIAgent tools in AI executor
* worker: complete nested AIAgent tool execution path
* worker: inline AIAgent tool schema usage
* fix agent action
* frontend: add AI Agent as tool type in flow builder
Add the ability to insert a nested AI Agent as a tool within another
AI Agent step. Includes type definitions, factory function, graph icon,
insert/event wiring, and a dedicated editor component.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: remove AiAgentToolEditor, reuse FlowModuleComponent for AI agent tools
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: populate all input transforms for nested AI agent tools
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: avoid missing v2_job_status error for nested AI agent tools
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* sqlx
* nit
* refactor: cleanup nested AI agent tool implementation
- Add max nesting depth guard (5) on parent chain traversal
- Reject 3+ level nesting explicitly with clear error message
- Remove unnecessary flow_step_id tuple scaffolding in tool dispatch
- Consolidate get_value() calls using borrow in first match
- Replace unsafe `as unknown as FlowModule` casts with agentToolToFlowModule()
- Simplify toolKind ternary chain with .includes() lookup
- Fix leftover over-indentation from tuple removal
- Remove duplicate doc comment on is_completed_input_transform
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: pass flow_step_id and flow_job_id overrides to run_agent for nested AI agents
For nested AI agent tools, job.flow_step_id is None and job.parent_job
points to the parent agent instead of the flow. This caused memory
read/write and flow context resolution to silently fail.
handle_ai_agent_job already computes the correct flow_step_id (via
runnable_path fallback) and flow_job_id (via parent chain traversal).
This change threads those values through run_agent and
ToolExecutionContext so all downstream consumers use the correct IDs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* cleaning
* cleaning
* move const
* fix
* refactor: replace defaultToAi boolean with allowedAiTransforms whitelist
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: propagate root_job at push time, remove flow_job_id_override
Instead of threading flow_job_id_override through run_agent and
get_flow_context, propagate root_job and flow_innermost_root_job
when pushing tool jobs so nested AI agents can find the flow
job naturally via the existing job fields.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: simplify nested AI agent parent chain walk-up
Replace the generic depth-limited loop with a single-level check since
only flow → agent → nested agent tool is supported. Remove
MAX_AGENT_NESTING_DEPTH constant and flatten the module lookup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: reject 3+ level nested AI agent tools before job creation
Check at the parent agent level whether a nested AIAgent tool contains
AIAgent sub-tools. If so, return a fatal error immediately, preventing
the sub-job from being created and avoiding retry loops.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve deadlock in nested AI agent tool execution
Replace channel forwarding with inline DB writes for tool job
completions. Nested agents used bounded(1) channels where a sub-tool's
forwarded result would fill the parent channel, leaving no room for the
agent's own completion — causing a deadlock. Writing directly via
add_completed_job/add_completed_job_error bypasses the channel entirely.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>