Expand description
Dynamic Workflow runtime for CodeWhale.
This crate is the imperative half of Workflow: a sandboxed QuickJS
(rquickjs) runtime that executes a model-authored JS program which
dispatches fleet-routed subagents via task(), fans out with
parallel()/pipeline(), reports progress with log()/phase(), and
scales itself to a token pool via the budget global. The static,
declarative IR (record/replay, model policy) stays in codewhale-workflow;
this crate only speaks to the outside world through the
WorkflowDriver seam, so it is fully testable without spawning a real
subagent (see testing::FakeDriver).
§Script surface
Every script runs inside an async function with these globals:
args— the invocation input, verbatim.await task(opts)— dispatch one subagent; resolves to the full result text, or to a parsed + schema-validated object whenopts.responseSchemais set. Throws on rejection, failure, cancellation, budget exhaustion, or onceWORKFLOW_LIFETIME_CAPspawn attempts have been made.parallel(thunks)— all-settled fan-out; an ordinary failed slot becomesnull; schema-contract failures and run cancellation still fail the run; at mostPARALLEL_MAX_ITEMSitems.pipeline(items, ...stages)— per-item stage chains with no barrier between stages; an ordinary stage error drops that item tonull, while schema-contract failures and cancellation still fail the run; same cap.log(msg)/phase(title)— progress events forwarded to the driver.budget.total/budget.spent()/budget.remaining()— live driver snapshots (totalisnullandremaining()isInfinitywhen no ceiling is configured).
Date.now(), new Date(), Date.parse/UTC, and Math.random() throw:
runs must be deterministic so recorded traces can be replayed.
§Ownership boundaries
Token accounting and admission belong to the driver; the VM only reads
snapshots and fast-fails a spawn when the shared pool is already exhausted.
Already-running parallel children can reconcile above the hint because
provider usage arrives at response boundaries, not token-by-token. Fleet
roster resolution for profile also happens driver-side; this crate
normalizes and token-validates the profile string, nothing more.
Modules§
- testing
- Test support: a scriptable in-memory
WorkflowDriver.
Structs§
- Budget
Snapshot - Live view of the run’s shared token pool, owned by the driver.
- Spawned
Task - A successfully admitted spawn: the driver-assigned task id (the engine’s
agent_id) plus the oneshot the driver resolves on completion. - Task
Request - One
task()invocation, fully resolved and validated on the VM side. - VmLimits
- Resource limits applied to the QuickJS runtime before any script runs.
- Workflow
RunCancel - Cooperative cancel signal shared by the run future (guard side) and the VM thread. The atomic flag feeds the QuickJS interrupt handler (sync, called mid-bytecode); the watch channel wakes host futures parked on driver completions.
- Workflow
Vm - Executes Workflow scripts, one isolated QuickJS runtime per run.
Enums§
- Driver
Error - Errors a
crate::WorkflowDrivercan return fromspawn_task. - Progress
Event - Progress events emitted by the script (
log(..)/phase(..)), delivered to the driver synchronously and in script order. - Task
Completion - Terminal outcome of one spawned task, delivered over the completion
oneshot. Everything except
Completedbecomes a JS throw on the awaitingtask()call. - Workflow
JsError - Errors surfaced by
crate::WorkflowVm::run_script.
Constants§
- PARALLEL_
MAX_ ITEMS - Maximum items per
parallel()orpipeline()call (design §4.2). Kept at the per-run agent ceiling so a single fan-out cannot declare more work than the lifetime cap can ever complete. - WORKFLOW_
LIFETIME_ CAP - Maximum
task()spawn attempts per run (design §4.3). Counted in the VM before the driver is consulted, so a runawayloop-until-dryterminates even if the driver would keep admitting work. - WORKFLOW_
MAX_ CONCURRENT - Maximum concurrently executing agents within one Workflow run.
Traits§
- Workflow
Driver - Host-side executor for a Workflow run.
Functions§
- normalize_
profile - Normalize and validate a Fleet profile token: trim, lowercase, then apply
the same token rule as
crates/workflow’svalidate_leaf_profile— non-empty, no whitespace, and none of",',`,=.