@agentproto/workflow-runtime 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,217 @@
1
+ # @agentproto/workflow-runtime
2
+
3
+ The execution engine for AIP-15 **WORKFLOW** — a typed step algebra plus the
4
+ interpreter that walks it. A workflow is an ordered list of steps; each step
5
+ reads the run-scoped bindings (the workflow input + every prior step's output)
6
+ through a plain `(bindings) => value` selector, runs, and binds its own output
7
+ back under its `id` for later steps to read.
8
+
9
+ There is **no DSL and no manifest parser here** — you author workflows as
10
+ TypeScript values. Compiling a declarative AIP-15 manifest's reference strings
11
+ onto these selectors is a separable layer on top.
12
+
13
+ ```bash
14
+ npm install @agentproto/workflow-runtime
15
+ ```
16
+
17
+ ## Quick start
18
+
19
+ ```ts
20
+ import { runWorkflow, type RuntimeWorkflow } from "@agentproto/workflow-runtime"
21
+ import { z } from "zod"
22
+ import { defineTool } from "@agentproto/tool"
23
+ import { defineDriver, implementTool } from "@agentproto/driver"
24
+
25
+ const double = defineTool({
26
+ id: "demo.double",
27
+ description: "Double a number.",
28
+ inputSchema: z.object({ n: z.number() }),
29
+ outputSchema: z.object({ n: z.number() }),
30
+ })
31
+ const math = defineDriver({
32
+ id: "math",
33
+ name: "Math",
34
+ description: "arith",
35
+ kind: "builtin",
36
+ implements: [{ tool: "demo.double", version: "0.1.0" }],
37
+ implementations: [implementTool(double, ({ input }) => ({ n: input.n * 2 }))],
38
+ })
39
+
40
+ const wf: RuntimeWorkflow = {
41
+ id: "double-then-add",
42
+ steps: [
43
+ { kind: "tool", id: "d", tool: double, candidates: [math], input: () => ({ n: 21 }) },
44
+ { kind: "transform", id: "plus", compute: (b) => ({ n: (b.steps.d as { n: number }).n + 0 }) },
45
+ ],
46
+ output: (b) => b.steps.plus,
47
+ }
48
+
49
+ const { output, bindings } = await runWorkflow({ workflow: wf })
50
+ // output === { n: 42 }; bindings.steps.d === { n: 42 }
51
+ ```
52
+
53
+ `runWorkflow(args)` returns `{ output, bindings }`. `output` is the workflow's
54
+ `output` selector, or the last top-level step's output if you omit it.
55
+
56
+ ## Step kinds
57
+
58
+ Every step reads `Bindings` (`{ input, steps, item?, index? }`) via selectors
59
+ and binds its output under `id`.
60
+
61
+ | kind | what it does |
62
+ | --- | --- |
63
+ | `tool` | Resolve a TOOL contract against `candidates` and run it. Cacheable. |
64
+ | `agent` | Spawn/reuse an agent session, send a prompt, wait for the turn. Cacheable. |
65
+ | `transform` | Pure in-run compute — combine / filter / shape. No dispatch. |
66
+ | `map` | Run a body once per array element (`bindings.item` / `index`); collect outputs. |
67
+ | `pipeline` | Run N items through K sequential stages with **no cross-item barrier**. |
68
+ | `parallel` | Run several named branches concurrently; outputs bind by branch id. |
69
+ | `branch` | Pick `then` / `otherwise` from a boolean predicate. |
70
+ | `loop` | Repeat a body while a predicate holds, up to `maxIterations`. |
71
+ | `approval` | AIP-7 human gate — host `approve` callback decides. |
72
+ | `suspend` | Pause until an external event; host `resume` supplies the payload. |
73
+ | `group` | Run a list of steps as one unit; output is the last step's. |
74
+ | `subworkflow` | Run a nested workflow with its own isolated bindings. |
75
+
76
+ ## Harness-parity capabilities
77
+
78
+ The engine reaches parity with a code-first agent harness across five axes.
79
+ Each is opt-in and composes with the rest.
80
+
81
+ ### Engine unification
82
+
83
+ Every construct above — including `agent`, `pipeline`, and `subworkflow` — is
84
+ walked by the **one** `execStep` interpreter. There is no second code path for
85
+ agents vs. tools vs. control flow; budget, caching, and IO-threading apply
86
+ uniformly wherever a step runs (top-level, inside a `pipeline` stage, inside a
87
+ `map` body, inside a `subworkflow`).
88
+
89
+ ### Structured output (agent steps)
90
+
91
+ Give an `agent` step an `outputSchema` and the engine validates the session's
92
+ final message against it, **re-prompting on mismatch** up to `maxRetries`
93
+ (default 2). The step's bound output is `{ sessionId, output }` where `output`
94
+ is the parsed, schema-valid value.
95
+
96
+ ```ts
97
+ const Verdict = z.object({
98
+ verdict: z.enum(["real", "false-positive"]),
99
+ reason: z.string(),
100
+ })
101
+
102
+ const wf: RuntimeWorkflow = {
103
+ id: "review-one",
104
+ steps: [
105
+ {
106
+ kind: "agent",
107
+ id: "judge",
108
+ adapter: "claude-code",
109
+ prompt: (b) => `Judge this diff and reply as JSON:\n${b.input}`,
110
+ outputSchema: Verdict,
111
+ maxRetries: 2,
112
+ },
113
+ ],
114
+ output: (b) => b.steps.judge,
115
+ }
116
+ // → { sessionId: "sess_…", output: { verdict: "real", reason: "off-by-one" } }
117
+ ```
118
+
119
+ Requires a host that implements `readFinalMessage` (see **AgentSessionHost**).
120
+
121
+ ### Aggregate budget ceiling
122
+
123
+ `maxTotalCostUsd` caps the summed cost of every spawned session across the whole
124
+ run. Before each `agent` spawn the engine sums `readCostUsd` over live sessions;
125
+ once the total would reach the cap, the spawn fails with `budget_exceeded` —
126
+ so a runaway fan-out stops instead of draining the account.
127
+
128
+ ```ts
129
+ await runWorkflow({ workflow: wf, agents: host, maxTotalCostUsd: 5.0 })
130
+ // throws: step 's2': budget_exceeded — run spend $5.40 >= cap $5
131
+ ```
132
+
133
+ ### Pipeline mode (no cross-item barrier)
134
+
135
+ `kind: "pipeline"` runs each item through the stages as its **own** chain —
136
+ item A can be in stage 3 while item B is still in stage 0. Wall-clock is the
137
+ slowest single-item chain, not the sum of per-stage barriers. `concurrency`
138
+ caps how many item-chains are in flight; outputs bind ordered by item index.
139
+
140
+ ```ts
141
+ {
142
+ kind: "pipeline",
143
+ id: "review",
144
+ over: (b) => b.input as string[], // the files to review
145
+ concurrency: 4,
146
+ stages: [
147
+ (file) => ({ kind: "agent", id: "find", adapter: "claude-code",
148
+ prompt: () => `Review ${file}`, outputSchema: Findings }),
149
+ (file, _i, prev) => ({ kind: "agent", id: "verify", adapter: "claude-code",
150
+ prompt: () => `Adversarially verify: ${JSON.stringify(prev)}`,
151
+ outputSchema: Verdict }),
152
+ ],
153
+ }
154
+ ```
155
+
156
+ Each stage body is `(item, index, prevOutput, bindings) => RunStep`; `prevOutput`
157
+ is the previous stage's output **for that item** (undefined at stage 0). Use a
158
+ `parallel` step instead only when a later stage genuinely needs *all* prior
159
+ results at once (a barrier).
160
+
161
+ ### Resume cache (journaled replay)
162
+
163
+ Mark an idempotent `tool` or `agent` step `cacheable: true`, pass a `cache` and
164
+ a `cacheKey`, and the engine journals its output. On a re-run with the same
165
+ `cacheKey`, a cacheable step whose **resolved inputs are unchanged** replays
166
+ from the journal instead of re-dispatching — no tool call, no session spawn, no
167
+ budget spend. The cache key hashes `(step.kind, resolved inputs)`; a `tool`
168
+ hashes its `input`, an `agent` hashes its resolved `prompt` + `adapter` +
169
+ `sessionRef`.
170
+
171
+ ```ts
172
+ import { createFileStepCache } from "@agentproto/runtime" // file-backed, ~/.agentproto/workflow-cache/
173
+
174
+ const cache = createFileStepCache("nightly-review")
175
+ await runWorkflow({ workflow: wf, cache, cacheKey: "nightly-review" }) // run 1: executes
176
+ await runWorkflow({ workflow: wf, cache, cacheKey: "nightly-review" }) // run 2: unchanged steps replay
177
+ ```
178
+
179
+ Both `cache` and `cacheKey` must be set for any caching to happen. Supply your
180
+ own `StepCache` (`{ get, set }`) for an in-memory or custom-backed journal.
181
+
182
+ ## AgentSessionHost — the host seam
183
+
184
+ The runtime has **no** knowledge of concrete session registries or event buses.
185
+ `agent` steps drive an injected `AgentSessionHost`:
186
+
187
+ ```ts
188
+ interface AgentSessionHost {
189
+ spawn(adapter: string, opts: { cwd?; workspaceSlug?; stepId? }): Promise<string>
190
+ sendPromptAndWait(sessionId: string, prompt: string): Promise<void>
191
+ resolveByLabel(stepId: string): string | undefined // for sessionRef reuse
192
+ onAwaitingInput?(sessionId, policy): Promise<void>
193
+ readFinalMessage?(sessionId): Promise<string> // required for outputSchema
194
+ readCostUsd?(sessionId): Promise<number> // required for maxTotalCostUsd
195
+ }
196
+ ```
197
+
198
+ With no host, `agent` steps throw. `@agentproto/runtime` ships a production host
199
+ (`SessionsRegistryAgentHost`) backed by the real sessions registry + event bus,
200
+ and `createFileStepCache` for the journal — both wired end-to-end behind the
201
+ daemon's `workflow_start` MCP tool.
202
+
203
+ ## Where this runs
204
+
205
+ - **Embed it** — import `runWorkflow` and inject your own host for the full step
206
+ algebra and all five capabilities above.
207
+ - **Through the daemon** — `@agentproto/runtime`'s `WorkflowRunner` translates
208
+ the MCP `workflow_start` stage/barrier shape onto this engine. That surface
209
+ exposes agent-session stages + resume-cache today; `pipeline`, `outputSchema`,
210
+ and `maxTotalCostUsd` are available on the embedding path. See the CLI docs'
211
+ **Workflows** concept page.
212
+
213
+ ## Spec
214
+
215
+ AIP-15 (WORKFLOW) — `agentproto/specs`. The manifest pins the abstract shape
216
+ (named steps, branching, parallelism, approval gates, suspend/resume, budget);
217
+ this package is the execution seam beneath it.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { DriverHandle, ResolverContext } from '@agentproto/driver';
2
2
  import { ToolContext, ToolHandle } from '@agentproto/tool';
3
+ import { ZodType } from 'zod';
3
4
  import { WorkflowHandle } from '@agentproto/workflow';
4
5
 
5
6
  /**
@@ -40,6 +41,9 @@ interface ToolStep<TInput = unknown, TOutput = unknown, TContext extends ToolCon
40
41
  context?: Selector<TContext>;
41
42
  resolverContext?: ResolverContext;
42
43
  secrets?: Record<string, string>;
44
+ /** Cache this step's output under the run's cacheKey; only its `input` is hashed
45
+ * (not `context`/secrets). Default false. */
46
+ cacheable?: boolean;
43
47
  }
44
48
  /** A pure in-run computation (combine / filter / shape) — no tool dispatch. */
45
49
  interface TransformStep {
@@ -60,6 +64,22 @@ interface MapStep {
60
64
  parallelism?: number;
61
65
  body: (item: unknown, index: number, bindings: Bindings) => RunStep;
62
66
  }
67
+ /**
68
+ * Run N items through K sequential stage bodies with NO cross-item barrier:
69
+ * each item flows through the stages as its own chain, independent of siblings.
70
+ * Only `concurrency` (max item-chains in flight) is shared. The per-item final
71
+ * output binds under this step's id, ordered by the item's index.
72
+ */
73
+ interface PipelineStep {
74
+ kind: "pipeline";
75
+ id: string;
76
+ over: Selector<readonly unknown[]>;
77
+ /** Max concurrent item-chains (default: all items at once). */
78
+ concurrency?: number;
79
+ /** Ordered stage bodies; each item flows through them in order. `prevOutput`
80
+ * is the previous stage's output for THIS item (undefined for stage 0). */
81
+ stages: readonly ((item: unknown, index: number, prevOutput: unknown, bindings: Bindings) => RunStep)[];
82
+ }
63
83
  /** Run one of two branches based on a predicate over the bindings. */
64
84
  interface BranchStep {
65
85
  kind: "branch";
@@ -124,6 +144,39 @@ interface SubworkflowStep {
124
144
  /** Input for the child (default: the parent's workflow input). */
125
145
  input?: Selector<unknown>;
126
146
  }
147
+ /**
148
+ * Spawn or reuse an agent session and send it a prompt, waiting for the
149
+ * turn to complete. The host injects an {@link AgentSessionHost} — this
150
+ * runtime has no knowledge of concrete session registries or event buses.
151
+ */
152
+ interface AgentStep {
153
+ kind: "agent";
154
+ id: string;
155
+ /** Adapter slug to spawn a NEW session. Omit to reuse via sessionRef. */
156
+ adapter?: Selector<string> | string;
157
+ /** Reuse an earlier AgentStep's spawned session, by that step's id. */
158
+ sessionRef?: string;
159
+ /** Prompt to send. */
160
+ prompt: Selector<string>;
161
+ policy?: {
162
+ awaiting: "auto-allow";
163
+ prompt: string;
164
+ } | {
165
+ awaiting: "escalate";
166
+ webhookUrl?: string;
167
+ timeoutMs?: number;
168
+ } | {
169
+ awaiting: "fail";
170
+ };
171
+ /** Validate the session's final message against this schema; re-prompt on mismatch. */
172
+ outputSchema?: ZodType<unknown>;
173
+ /** Re-prompt-and-retry attempts on schema mismatch before failing. Default 2. */
174
+ maxRetries?: number;
175
+ /** Cache this step's output under the run's cacheKey; the resolved prompt +
176
+ * adapter + sessionRef are hashed. Default false — most agent steps have
177
+ * side effects. */
178
+ cacheable?: boolean;
179
+ }
127
180
  /**
128
181
  * The element generics on `ToolStep` are erased to `any` so heterogeneous
129
182
  * steps (different contracts, different input/output/context types) coexist in
@@ -133,7 +186,7 @@ interface SubworkflowStep {
133
186
  * issue #21534); tightening the union to `ToolStep<unknown, …>` rejects a
134
187
  * concrete `ToolStep<MarketSearchInput, …>` on the zod `ZodType<T>` variance.
135
188
  */
136
- type RunStep = ToolStep<any, any, any> | TransformStep | MapStep | BranchStep | LoopStep | ParallelStep | ApprovalStep | SuspendStep | GroupStep | SubworkflowStep;
189
+ type RunStep = ToolStep<any, any, any> | TransformStep | MapStep | PipelineStep | BranchStep | LoopStep | ParallelStep | ApprovalStep | SuspendStep | GroupStep | SubworkflowStep | AgentStep;
137
190
  interface RuntimeWorkflow {
138
191
  id: string;
139
192
  description?: string;
@@ -150,6 +203,36 @@ interface ResumeRequest {
150
203
  stepId: string;
151
204
  on: readonly string[];
152
205
  }
206
+ interface AgentSessionHost {
207
+ /** Spawn a new agent session and return its id. */
208
+ spawn(adapter: string, opts: {
209
+ cwd?: string;
210
+ workspaceSlug?: string;
211
+ stepId?: string;
212
+ }): Promise<string>;
213
+ /** Send a prompt to an existing session and wait for its turn to end. */
214
+ sendPromptAndWait(sessionId: string, prompt: string): Promise<void>;
215
+ /** Look up a session by the step id that spawned it (for sessionRef reuse). */
216
+ resolveByLabel(stepId: string): string | undefined;
217
+ /** Handle an awaiting-input policy for a session. */
218
+ onAwaitingInput?(sessionId: string, policy: AgentStep["policy"]): Promise<void>;
219
+ /** Return the session's final assistant message text (for outputSchema validation). */
220
+ readFinalMessage?(sessionId: string): Promise<string>;
221
+ /** Current cumulative cost (USD) of a session, for run-level budgeting. */
222
+ readCostUsd?(sessionId: string): Promise<number>;
223
+ }
224
+ /** One journal entry: a cached step output plus the hash of the inputs that produced it. */
225
+ interface StepCacheEntry {
226
+ output: unknown;
227
+ resolvedInputHash: string;
228
+ }
229
+ /** Opt-in journal for cacheable steps. Host-injected; file-backed in the runtime. */
230
+ interface StepCache {
231
+ /** Look up a step's journal entry by its namespaced key. */
232
+ get(stepCacheKey: string): Promise<StepCacheEntry | undefined>;
233
+ /** Write/overwrite a step's journal entry. */
234
+ set(stepCacheKey: string, entry: StepCacheEntry): Promise<void>;
235
+ }
153
236
  interface RunWorkflowArgs {
154
237
  workflow: RuntimeWorkflow;
155
238
  input?: unknown;
@@ -158,6 +241,20 @@ interface RunWorkflowArgs {
158
241
  approve?: (req: ApprovalRequest) => boolean | Promise<boolean>;
159
242
  /** Supply a {@link SuspendStep}'s resume payload. Default: throw + suspend. */
160
243
  resume?: (req: ResumeRequest) => unknown | Promise<unknown>;
244
+ /** Host-injected agent session runtime. Undefined ⇒ {@link AgentStep} throws. */
245
+ agents?: AgentSessionHost;
246
+ /** Working directory for spawned agent sessions. */
247
+ cwd?: string;
248
+ /** Workspace slug for spawned agent sessions. */
249
+ workspaceSlug?: string;
250
+ /** Run-level cost ceiling (USD). Once the summed cost of spawned sessions
251
+ * reaches this, the next AgentStep spawn fails with `budget_exceeded`. */
252
+ maxTotalCostUsd?: number;
253
+ /** Opt-in journal cache for cacheable steps. Undefined ⇒ caching disabled. */
254
+ cache?: StepCache;
255
+ /** Namespacing label for this run's cache lookups (the workflow_start cacheKey).
256
+ * Both `cache` and `cacheKey` must be set for any caching to happen. */
257
+ cacheKey?: string;
161
258
  }
162
259
  interface WorkflowRunResult {
163
260
  output: unknown;
@@ -253,4 +350,4 @@ declare function compileWorkflow(handle: WorkflowHandle, opts: CompileWorkflowOp
253
350
  */
254
351
  declare function compileWorkflowManifest(source: string, opts: CompileWorkflowOptions): RuntimeWorkflow;
255
352
 
256
- export { type ApprovalRequest, type ApprovalStep, type Bindings, type BranchStep, type CompileWorkflowOptions, type GroupStep, type LoopStep, type MapStep, type ParallelStep, type ResumeRequest, type RunStep, type RunWorkflowArgs, type RuntimeWorkflow, type Selector, type SubworkflowStep, type SuspendStep, type ToolStep, type TransformStep, WorkflowCompileError, type WorkflowRunResult, WorkflowSuspendedError, compileWorkflow, compileWorkflowManifest, evalPredicate, resolveRef, resolveValue, runWorkflow };
353
+ export { type AgentSessionHost, type AgentStep, type ApprovalRequest, type ApprovalStep, type Bindings, type BranchStep, type CompileWorkflowOptions, type GroupStep, type LoopStep, type MapStep, type ParallelStep, type PipelineStep, type ResumeRequest, type RunStep, type RunWorkflowArgs, type RuntimeWorkflow, type Selector, type StepCache, type StepCacheEntry, type SubworkflowStep, type SuspendStep, type ToolStep, type TransformStep, WorkflowCompileError, type WorkflowRunResult, WorkflowSuspendedError, compileWorkflow, compileWorkflowManifest, evalPredicate, resolveRef, resolveValue, runWorkflow };
package/dist/index.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  import { runTool } from '@agentproto/driver';
2
+ import { createHash } from 'crypto';
2
3
  import { parseWorkflowManifest, workflowFromManifest } from '@agentproto/workflow/manifest';
3
4
 
4
5
  /**
@@ -21,6 +22,50 @@ var WorkflowSuspendedError = class extends Error {
21
22
  function view(state, item, index) {
22
23
  return { input: state.input, steps: state.steps, item, index };
23
24
  }
25
+ function resolveSel(sel, b) {
26
+ return typeof sel === "function" ? sel(b) : sel;
27
+ }
28
+ function extractJsonCandidate(raw) {
29
+ const jsonFence = /```json\s*([\s\S]*?)```/g;
30
+ const lastJson = lastMatch(jsonFence, raw);
31
+ if (lastJson !== void 0) return lastJson;
32
+ const anyFence = /```\s*([\s\S]*?)```/g;
33
+ const lastAny = lastMatch(anyFence, raw);
34
+ if (lastAny !== void 0) return lastAny;
35
+ return raw.trim();
36
+ }
37
+ function lastMatch(re, s) {
38
+ let m;
39
+ let last = null;
40
+ while ((m = re.exec(s)) !== null) last = m;
41
+ return last ? last[1]?.trim() : void 0;
42
+ }
43
+ function spentUsd(state) {
44
+ let total = 0;
45
+ for (const c of state.costBySession.values()) total += c;
46
+ return total;
47
+ }
48
+ function hashResolvedInputs(kind, resolved) {
49
+ return createHash("sha256").update(`${kind}\0${JSON.stringify(resolved) ?? "undefined"}`).digest("hex");
50
+ }
51
+ function stepJournalKey(cacheKey, step) {
52
+ return `${cacheKey}\0${step.id}\0${step.kind}`;
53
+ }
54
+ function isCacheEnabled(ctx, step) {
55
+ return step.cacheable === true && ctx.cache !== void 0 && ctx.cacheKey !== void 0;
56
+ }
57
+ async function readStepCache(ctx, step, resolvedInputs) {
58
+ const key = stepJournalKey(ctx.cacheKey, step);
59
+ const hash = hashResolvedInputs(step.kind, resolvedInputs);
60
+ const entry = await ctx.cache.get(key);
61
+ if (entry !== void 0 && entry.resolvedInputHash === hash) {
62
+ return { hit: true, output: entry.output };
63
+ }
64
+ return { hit: false, key, hash };
65
+ }
66
+ function formatZodError(err) {
67
+ return err.issues.map((i) => `${i.path.length > 0 ? i.path.join(".") + ": " : ""}${i.message}`).join(", ");
68
+ }
24
69
  async function runSequence(steps, ctx, item, index) {
25
70
  let last;
26
71
  for (const s of steps) {
@@ -30,20 +75,77 @@ async function runSequence(steps, ctx, item, index) {
30
75
  }
31
76
  return last;
32
77
  }
78
+ async function execAgentStep(step, ctx, b) {
79
+ if (step.adapter && ctx.state.maxTotalCostUsd !== void 0 && spentUsd(ctx.state) >= ctx.state.maxTotalCostUsd) {
80
+ throw new Error(
81
+ `step '${step.id}': budget_exceeded \u2014 run spend $${spentUsd(ctx.state).toFixed(4)} >= cap $${ctx.state.maxTotalCostUsd}`
82
+ );
83
+ }
84
+ const sessionId = step.adapter ? await ctx.agents.spawn(resolveSel(step.adapter, b), { cwd: ctx.cwd, workspaceSlug: ctx.workspaceSlug, stepId: step.id }) : ctx.agents.resolveByLabel(step.sessionRef);
85
+ if (!sessionId) throw new Error(`step '${step.id}': no session (adapter and sessionRef both unresolved)`);
86
+ await ctx.agents.sendPromptAndWait(sessionId, step.prompt(b));
87
+ if (step.policy && ctx.agents.onAwaitingInput) {
88
+ await ctx.agents.onAwaitingInput(sessionId, step.policy);
89
+ }
90
+ if (ctx.agents.readCostUsd) {
91
+ ctx.state.costBySession.set(sessionId, await ctx.agents.readCostUsd(sessionId));
92
+ }
93
+ if (!step.outputSchema) return { sessionId };
94
+ if (!ctx.agents.readFinalMessage) {
95
+ throw new Error(`step '${step.id}': outputSchema requires a host with readFinalMessage`);
96
+ }
97
+ const maxRetries = step.maxRetries ?? 2;
98
+ let lastErr = "";
99
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
100
+ const raw = await ctx.agents.readFinalMessage(sessionId);
101
+ const candidate = extractJsonCandidate(raw);
102
+ let value;
103
+ try {
104
+ value = JSON.parse(candidate);
105
+ } catch {
106
+ lastErr = "not valid JSON";
107
+ if (attempt < maxRetries) {
108
+ await ctx.agents.sendPromptAndWait(
109
+ sessionId,
110
+ `Your previous reply did not match the required schema: ${lastErr}. Reply again with ONLY a JSON object that matches. No prose, no code fence needed.`
111
+ );
112
+ }
113
+ continue;
114
+ }
115
+ const res = step.outputSchema.safeParse(value);
116
+ if (res.success) return { sessionId, output: res.data };
117
+ lastErr = formatZodError(res.error);
118
+ if (attempt < maxRetries) {
119
+ await ctx.agents.sendPromptAndWait(
120
+ sessionId,
121
+ `Your previous reply did not match the required schema: ${lastErr}. Reply again with ONLY a JSON object that matches. No prose, no code fence needed.`
122
+ );
123
+ }
124
+ }
125
+ throw new Error(`step '${step.id}': output_invalid \u2014 final message never matched outputSchema (${lastErr})`);
126
+ }
33
127
  async function execStep(step, ctx, item, index) {
34
128
  const { state, signal } = ctx;
35
129
  const b = view(state, item, index);
36
130
  switch (step.kind) {
37
- case "tool":
38
- return runTool({
131
+ case "tool": {
132
+ const input = step.input(b);
133
+ const runIt = () => runTool({
39
134
  tool: step.tool,
40
135
  candidates: step.candidates,
41
- input: step.input(b),
136
+ input,
42
137
  context: step.context ? step.context(b) : void 0,
43
138
  resolverContext: step.resolverContext,
44
139
  secrets: step.secrets,
45
140
  signal
46
141
  });
142
+ if (!isCacheEnabled(ctx, step)) return runIt();
143
+ const c = await readStepCache(ctx, step, input);
144
+ if (c.hit) return c.output;
145
+ const out = await runIt();
146
+ await ctx.cache.set(c.key, { output: out, resolvedInputHash: c.hash });
147
+ return out;
148
+ }
47
149
  case "transform":
48
150
  return step.compute(b);
49
151
  case "map": {
@@ -63,6 +165,28 @@ async function execStep(step, ctx, item, index) {
63
165
  }
64
166
  return results;
65
167
  }
168
+ case "pipeline": {
169
+ const items = [...step.over(b)];
170
+ if (items.length === 0) return [];
171
+ const cap = Math.max(1, step.concurrency ?? items.length);
172
+ const results = new Array(items.length);
173
+ let next = 0;
174
+ const runItem = async (idx) => {
175
+ let prev = void 0;
176
+ for (const stage of step.stages) {
177
+ prev = await execStep(stage(items[idx], idx, prev, view(state, items[idx], idx)), ctx, items[idx], idx);
178
+ }
179
+ results[idx] = prev;
180
+ };
181
+ const worker = async () => {
182
+ while (next < items.length) {
183
+ const idx = next++;
184
+ await runItem(idx);
185
+ }
186
+ };
187
+ await Promise.all(Array.from({ length: Math.min(cap, items.length) }, () => worker()));
188
+ return results;
189
+ }
66
190
  case "branch": {
67
191
  const chosen = step.cond(b) ? step.then : step.otherwise ?? [];
68
192
  return runSequence(chosen, ctx, item, index);
@@ -108,14 +232,33 @@ async function execStep(step, ctx, item, index) {
108
232
  const child = await runWorkflowInner(step.workflow, childInput, {
109
233
  approve: ctx.approve,
110
234
  resume: ctx.resume,
111
- signal
235
+ signal,
236
+ agents: ctx.agents,
237
+ cwd: ctx.cwd,
238
+ workspaceSlug: ctx.workspaceSlug,
239
+ cache: ctx.cache,
240
+ cacheKey: ctx.cacheKey
112
241
  });
113
242
  return child.output;
114
243
  }
244
+ case "agent": {
245
+ if (!ctx.agents) throw new Error(`step '${step.id}': AgentStep requires a host agents implementation`);
246
+ if (!isCacheEnabled(ctx, step)) return execAgentStep(step, ctx, b);
247
+ const resolved = {
248
+ prompt: step.prompt(b),
249
+ adapter: step.adapter ? resolveSel(step.adapter, b) : void 0,
250
+ sessionRef: step.sessionRef
251
+ };
252
+ const c = await readStepCache(ctx, step, resolved);
253
+ if (c.hit) return c.output;
254
+ const out = await execAgentStep(step, ctx, b);
255
+ await ctx.cache.set(c.key, { output: out, resolvedInputHash: c.hash });
256
+ return out;
257
+ }
115
258
  }
116
259
  }
117
- async function runWorkflowInner(workflow, input, hooks) {
118
- const state = { input, steps: {} };
260
+ async function runWorkflowInner(workflow, input, hooks, maxTotalCostUsd) {
261
+ const state = { input, steps: {}, costBySession: /* @__PURE__ */ new Map(), maxTotalCostUsd };
119
262
  const ctx = { state, ...hooks };
120
263
  let lastId;
121
264
  for (const step of workflow.steps) {
@@ -131,8 +274,13 @@ async function runWorkflow(args) {
131
274
  return runWorkflowInner(args.workflow, args.input, {
132
275
  approve: args.approve,
133
276
  resume: args.resume,
134
- signal: args.signal
135
- });
277
+ signal: args.signal,
278
+ agents: args.agents,
279
+ cwd: args.cwd,
280
+ workspaceSlug: args.workspaceSlug,
281
+ cache: args.cache,
282
+ cacheKey: args.cacheKey
283
+ }, args.maxTotalCostUsd);
136
284
  }
137
285
 
138
286
  // src/compile-workflow.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/run-workflow.ts","../src/compile-workflow.ts","../src/load-workflow.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * The step-walker. Executes a {@link RuntimeWorkflow} top-to-bottom, threading\n * each step's output into a run-scoped binding bag, and dispatching `tool`\n * steps through `@agentproto/driver` `runTool` (resolve DRIVER → validate input\n * + context → execute body → validate output). Composite steps (`map` /\n * `branch` / `loop` / `parallel` / `approval` / `subworkflow`) recurse over the\n * same bindings; `suspend` defers to the host's resume hook.\n */\n\nimport { runTool } from \"@agentproto/driver\"\nimport type {\n Bindings,\n RunStep,\n RunWorkflowArgs,\n RuntimeWorkflow,\n WorkflowRunResult,\n} from \"./types.js\"\n\n/** Thrown by a `suspend` step when no host `resume` hook is provided. */\nexport class WorkflowSuspendedError extends Error {\n constructor(\n readonly stepId: string,\n readonly on: readonly string[],\n ) {\n super(\n `workflow suspended at step '${stepId}' awaiting [${on.join(\", \")}] — ` +\n `no resume hook supplied`,\n )\n this.name = \"WorkflowSuspendedError\"\n }\n}\n\ninterface RunState {\n readonly input: unknown\n readonly steps: Record<string, unknown>\n}\n\ninterface RunCtx {\n readonly state: RunState\n readonly approve?: RunWorkflowArgs[\"approve\"]\n readonly resume?: RunWorkflowArgs[\"resume\"]\n readonly signal?: AbortSignal\n}\n\nfunction view(state: RunState, item?: unknown, index?: number): Bindings {\n return { input: state.input, steps: state.steps, item, index }\n}\n\n/** Run an ordered list of steps, binding each output under its id; return last. */\nasync function runSequence(\n steps: readonly RunStep[],\n ctx: RunCtx,\n item: unknown,\n index: number | undefined,\n): Promise<unknown> {\n let last: unknown\n for (const s of steps) {\n const out = await execStep(s, ctx, item, index)\n ctx.state.steps[s.id] = out\n last = out\n }\n return last\n}\n\nasync function execStep(\n step: RunStep,\n ctx: RunCtx,\n item: unknown,\n index: number | undefined,\n): Promise<unknown> {\n const { state, signal } = ctx\n const b = view(state, item, index)\n switch (step.kind) {\n case \"tool\":\n return runTool({\n tool: step.tool,\n candidates: step.candidates,\n input: step.input(b),\n context: step.context ? step.context(b) : undefined,\n resolverContext: step.resolverContext,\n secrets: step.secrets,\n signal,\n })\n\n case \"transform\":\n return step.compute(b)\n\n case \"map\": {\n const arr = [...step.over(b)]\n const parallelism = Math.max(1, step.parallelism ?? 1)\n const results: unknown[] = new Array(arr.length)\n for (let i = 0; i < arr.length; i += parallelism) {\n const chunk = arr.slice(i, i + parallelism)\n const outs = await Promise.all(\n chunk.map((el, j) => {\n const idx = i + j\n const inner = step.body(el, idx, view(state, el, idx))\n return execStep(inner, ctx, el, idx)\n }),\n )\n for (let j = 0; j < outs.length; j++) results[i + j] = outs[j]\n }\n return results\n }\n\n case \"branch\": {\n const chosen = step.cond(b) ? step.then : (step.otherwise ?? [])\n return runSequence(chosen, ctx, item, index)\n }\n\n case \"loop\": {\n let iterations = 0\n let last: unknown\n while (\n iterations < step.maxIterations &&\n step.while(view(state, item, index))\n ) {\n last = await runSequence(step.body, ctx, item, index)\n iterations++\n }\n return last\n }\n\n case \"parallel\": {\n const outs = await Promise.all(\n step.branches.map((br) =>\n runSequence(br.steps, ctx, item, index).then((last) => ({\n id: br.id,\n last,\n })),\n ),\n )\n const record: Record<string, unknown> = {}\n for (const { id, last } of outs) record[id] = last\n return record\n }\n\n case \"approval\": {\n const prompt = step.prompt(b)\n const approvers = step.approvers ?? []\n const approved = ctx.approve\n ? await ctx.approve({ stepId: step.id, prompt, approvers })\n : true\n const followups = approved\n ? (step.onApprove ?? [])\n : (step.onReject ?? [])\n await runSequence(followups, ctx, item, index)\n return { approved }\n }\n\n case \"suspend\": {\n if (!ctx.resume) throw new WorkflowSuspendedError(step.id, step.on)\n return ctx.resume({ stepId: step.id, on: step.on })\n }\n\n case \"group\":\n return runSequence(step.steps, ctx, item, index)\n\n case \"subworkflow\": {\n const childInput = step.input ? step.input(b) : state.input\n const child = await runWorkflowInner(step.workflow, childInput, {\n approve: ctx.approve,\n resume: ctx.resume,\n signal,\n })\n return child.output\n }\n }\n}\n\nasync function runWorkflowInner(\n workflow: RuntimeWorkflow,\n input: unknown,\n hooks: Pick<RunCtx, \"approve\" | \"resume\" | \"signal\">,\n): Promise<WorkflowRunResult> {\n const state: RunState = { input, steps: {} }\n const ctx: RunCtx = { state, ...hooks }\n let lastId: string | undefined\n for (const step of workflow.steps) {\n const out = await execStep(step, ctx, undefined, undefined)\n state.steps[step.id] = out\n lastId = step.id\n }\n const bindings = view(state)\n const output = workflow.output\n ? workflow.output(bindings)\n : lastId !== undefined\n ? state.steps[lastId]\n : undefined\n return { output, bindings }\n}\n\nexport async function runWorkflow(\n args: RunWorkflowArgs,\n): Promise<WorkflowRunResult> {\n return runWorkflowInner(args.workflow, args.input, {\n approve: args.approve,\n resume: args.resume,\n signal: args.signal,\n })\n}\n","/**\n * Compile a declarative AIP-15 `WorkflowHandle` into a runnable\n * {@link RuntimeWorkflow} for {@link runWorkflow}. This is the bridge that makes\n * an authored WORKFLOW.md actually execute.\n *\n * AIP-15 leaves the IO seam (`step.inputs`, `map.over`, `loop.while`) to a\n * meta-validator. This compiler pins a concrete, minimal **reference grammar**\n * for it — the convention a manifest author writes:\n *\n * - data refs: `$input` · `$input.a.b` · `$steps.<id>` · `$steps.<id>.a`\n * · `$item` · `$item.a` · `$index` (`$$` escapes a literal `$`)\n * - `step.inputs`: a JSON object whose leaf strings may be refs (resolved\n * recursively); non-`$` strings are literals\n * - `map.over`: a ref to an array\n * - `loop.while` / approval prompt: `<ref> <op> <literal>` (`== != < <= > >=`)\n * or a bare ref (truthiness)\n *\n * Scope: the **linear / structured subset** of AIP-15 — steps run in document\n * order; `map`/`loop`/`parallel` nest their child step lists. Non-linear `next`\n * gotos and goto-style `branch` routing are rejected with a clear diagnostic\n * (hand-author a structured `BranchStep`, or nest). Compiling the full goto\n * graph is a separable follow-up.\n */\n\nimport type { WorkflowHandle } from \"@agentproto/workflow\"\nimport type { DriverHandle } from \"@agentproto/driver\"\nimport type { ToolHandle } from \"@agentproto/tool\"\nimport type { Bindings, RunStep, RuntimeWorkflow } from \"./types.js\"\n\nexport interface CompileWorkflowOptions {\n /** TOOL contracts by id — each `tool` step resolves its handle here. */\n tools: ReadonlyMap<string, ToolHandle> | Record<string, ToolHandle>\n /** DRIVER candidates the resolver dispatches over for every tool step. */\n candidates: readonly DriverHandle[]\n /** Resolve a tool step's injected context (live capabilities) from bindings. */\n contextFor?: (toolId: string, bindings: Bindings) => unknown\n /** Sub-workflows by id, for `subworkflow` steps. */\n workflows?:\n | ReadonlyMap<string, WorkflowHandle>\n | Record<string, WorkflowHandle>\n}\n\nexport class WorkflowCompileError extends Error {\n constructor(message: string) {\n super(`compileWorkflow: ${message}`)\n this.name = \"WorkflowCompileError\"\n }\n}\n\n// ── reference + predicate resolution (the AIP-16 IO seam) ────────────\n\nconst get = <T>(\n m: ReadonlyMap<string, T> | Record<string, T>,\n key: string,\n): T | undefined =>\n m instanceof Map ? m.get(key) : (m as Record<string, T>)[key]\n\nfunction dig(value: unknown, path: readonly string[]): unknown {\n let v = value\n for (const seg of path) {\n if (v == null) return undefined\n v = (v as Record<string, unknown>)[seg]\n }\n return v\n}\n\n/** Resolve a single `$…` reference string against the run bindings. */\nexport function resolveRef(ref: string, b: Bindings): unknown {\n if (ref === \"$index\") return b.index\n const m = ref.match(/^\\$(input|item|steps)((?:\\.[^.]+)*)$/)\n if (!m) throw new WorkflowCompileError(`bad reference '${ref}'`)\n const segs = m[2] ? m[2].slice(1).split(\".\") : []\n switch (m[1]) {\n case \"input\":\n return dig(b.input, segs)\n case \"item\":\n return dig(b.item, segs)\n case \"steps\": {\n const [stepId, ...rest] = segs\n if (!stepId) throw new WorkflowCompileError(`'$steps' needs a step id`)\n return dig(b.steps[stepId], rest)\n }\n }\n}\n\n/** Recursively resolve a value node: refs in strings, into arrays/objects. */\nexport function resolveValue(node: unknown, b: Bindings): unknown {\n if (typeof node === \"string\") {\n if (node.startsWith(\"$$\")) return node.slice(1) // $$ → literal $\n if (node.startsWith(\"$\")) return resolveRef(node, b)\n return node\n }\n if (Array.isArray(node)) return node.map((n) => resolveValue(n, b))\n if (node && typeof node === \"object\") {\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(node as Record<string, unknown>))\n out[k] = resolveValue(v, b)\n return out\n }\n return node\n}\n\nconst COMPARATORS: Record<string, (a: number, b: number) => boolean> = {\n \"<\": (a, c) => a < c,\n \"<=\": (a, c) => a <= c,\n \">\": (a, c) => a > c,\n \">=\": (a, c) => a >= c,\n}\n\nfunction literal(token: string, b: Bindings): unknown {\n if (token.startsWith(\"$\")) return resolveRef(token, b)\n if (token === \"true\") return true\n if (token === \"false\") return false\n if (token === \"null\") return null\n if (/^-?\\d+(\\.\\d+)?$/.test(token)) return Number(token)\n return token.replace(/^['\"]|['\"]$/g, \"\")\n}\n\n/** Evaluate a `while`/`when` predicate string against the bindings. */\nexport function evalPredicate(expr: string, b: Bindings): boolean {\n const m = expr.match(/^(.+?)\\s*(==|!=|<=|>=|<|>)\\s*(.+)$/)\n if (!m) return Boolean(literal(expr.trim(), b)) // bare ref → truthiness\n const left = literal(m[1]!.trim(), b)\n const right = literal(m[3]!.trim(), b)\n switch (m[2]) {\n case \"==\":\n return left === right\n case \"!=\":\n return left !== right\n default: {\n const cmp = COMPARATORS[m[2]!]!\n return cmp(Number(left), Number(right))\n }\n }\n}\n\n// ── step compilation ─────────────────────────────────────────────────\n\n/** AIP step ids may be paths/refs; the runtime key is the last segment. */\nfunction normalizeToolId(ref: string): string {\n let s = ref.trim()\n if (s.endsWith(\"/TOOL.md\")) s = s.slice(0, -\"/TOOL.md\".length)\n const slash = s.lastIndexOf(\"/\")\n return slash === -1 ? s : s.slice(slash + 1)\n}\n\n// AIP step frontmatter leaves IO fields as opaque `{}`; read them dynamically.\nconst f = <T>(step: object, key: string): T =>\n (step as Record<string, unknown>)[key] as T\n\nfunction assertLinear(steps: readonly { id: string; kind: string; next?: string }[]): void {\n steps.forEach((s, i) => {\n const next = (s as { next?: string }).next\n const followingId = steps[i + 1]?.id\n if (next && next !== followingId) {\n throw new WorkflowCompileError(\n `step '${s.id}' has a non-linear next='${next}' — the structured-subset ` +\n `compiler only runs steps in document order. Hand-author a BranchStep ` +\n `or nest structurally.`,\n )\n }\n })\n}\n\nexport function compileWorkflow(\n handle: WorkflowHandle,\n opts: CompileWorkflowOptions,\n): RuntimeWorkflow {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const steps = handle.steps as unknown as any[]\n if (handle.start && handle.start !== steps[0]?.id) {\n throw new WorkflowCompileError(\n `start='${handle.start}' is not the first step — structured-subset runs in order`,\n )\n }\n assertLinear(steps)\n // `result` is the optional output value-expression (AIP-15): map it through\n // the same ref grammar as a step's inputs. Absent ⇒ no output selector, so\n // runWorkflow falls back to the final step's result.\n const result = (handle as { result?: unknown }).result\n const output =\n result !== undefined ? (b: Bindings) => resolveValue(result, b) : undefined\n return {\n id: handle.id,\n description: handle.description,\n steps: steps.map((s) => compileStep(s, opts)),\n ...(output ? { output } : {}),\n }\n}\n\nfunction compileStepList(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n steps: any[],\n id: string,\n opts: CompileWorkflowOptions,\n): RunStep {\n assertLinear(steps)\n if (steps.length === 1) return compileStep(steps[0], opts)\n return { kind: \"group\", id, steps: steps.map((s) => compileStep(s, opts)) }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction compileStep(step: any, opts: CompileWorkflowOptions): RunStep {\n const id: string = step.id\n switch (step.kind) {\n case \"tool\": {\n const ref = typeof step.tool === \"string\" ? step.tool : step.tool.entry\n const toolId = normalizeToolId(ref)\n const tool = get(opts.tools, toolId)\n if (!tool)\n throw new WorkflowCompileError(`no tool registered for '${toolId}'`)\n const inputs = f<unknown>(step, \"inputs\") ?? {}\n return {\n kind: \"tool\",\n id,\n tool,\n candidates: opts.candidates,\n input: (b) => resolveValue(inputs, b),\n context: opts.contextFor\n ? (b) => opts.contextFor!(toolId, b)\n : undefined,\n }\n }\n\n case \"map\": {\n const over = f<string>(step, \"over\")\n const inner = compileStepList(f(step, \"steps\"), `${id}__body`, opts)\n return {\n kind: \"map\",\n id,\n parallelism: f<number | undefined>(step, \"parallelism\"),\n over: (b) => resolveRef(over, b) as readonly unknown[],\n body: () => inner,\n }\n }\n\n case \"loop\": {\n const whileExpr = f<string>(step, \"while\")\n return {\n kind: \"loop\",\n id,\n maxIterations: f<number>(step, \"max_iterations\"),\n while: (b) => evalPredicate(whileExpr, b),\n body: [compileStepList(f(step, \"steps\"), `${id}__body`, opts)],\n }\n }\n\n case \"parallel\": {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const branches = f<any[]>(step, \"branches\")\n return {\n kind: \"parallel\",\n id,\n branches: branches.map((br) => ({\n id: br.id,\n steps: [compileStepList(br.steps, `${id}__${br.id}`, opts)],\n })),\n }\n }\n\n case \"approval\": {\n const prompt = f<string>(step, \"prompt\")\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const approvers = (f<any[]>(step, \"approvers\") ?? []).map(\n (a) => a.role ?? a.userId ?? String(a),\n )\n return {\n kind: \"approval\",\n id,\n approvers,\n prompt: (b) => String(resolveValue(prompt, b)),\n }\n }\n\n case \"suspend\": {\n const resume = f<{ on: string[]; timeout_ms?: number }>(step, \"resume\")\n return { kind: \"suspend\", id, on: resume.on, timeoutMs: resume.timeout_ms }\n }\n\n case \"subworkflow\": {\n const wfId = f<string>(step, \"workflow\")\n const child = opts.workflows ? get(opts.workflows, wfId) : undefined\n if (!child)\n throw new WorkflowCompileError(\n `subworkflow '${wfId}' not found — pass it in opts.workflows`,\n )\n const compiledChild = compileWorkflow(child, opts)\n return { kind: \"subworkflow\", id, workflow: compiledChild }\n }\n\n case \"branch\":\n throw new WorkflowCompileError(\n `goto-style 'branch' (step '${id}') is unsupported in the structured ` +\n `subset — hand-author a structured BranchStep, or nest.`,\n )\n\n default:\n throw new WorkflowCompileError(\n `unsupported step kind '${step.kind}' (step '${id}')`,\n )\n }\n}\n","/**\n * compileWorkflowManifest — the connective step between an authored\n * `WORKFLOW.md` and a runnable workflow.\n *\n * AIP-15 ships every piece needed to run a declarative manifest except the\n * seam that joins them: `parseWorkflowManifest` (md + frontmatter → manifest)\n * and `workflowFromManifest` (manifest → `WorkflowHandle`) live in\n * `@agentproto/workflow`; `compileWorkflow` (handle → `RuntimeWorkflow`) lives\n * here. Without this chain an authored `WORKFLOW.md` parses and validates but\n * never reaches the executor. This joins the three so a manifest source string\n * compiles straight to a runnable workflow — no hand-built handle.\n *\n * Framework-pure: the caller owns reading the file off disk (this package does\n * no I/O), and passes the source string in. The tool registry + driver\n * candidates are injected via {@link CompileWorkflowOptions}, same as the\n * hand-built path.\n */\n\nimport {\n parseWorkflowManifest,\n workflowFromManifest,\n} from \"@agentproto/workflow/manifest\"\n\nimport { compileWorkflow } from \"./compile-workflow.js\"\nimport type { CompileWorkflowOptions } from \"./compile-workflow.js\"\nimport type { RuntimeWorkflow } from \"./types.js\"\n\n/**\n * Compile a `WORKFLOW.md` source string into a {@link RuntimeWorkflow} ready\n * for `runWorkflow`. Parses + validates the frontmatter against the AIP-15\n * schema, lifts it to a `WorkflowHandle`, then compiles its step graph against\n * the injected tool registry. Throws on invalid frontmatter (the parser's\n * diagnostic) or an unresolved tool / non-linear step (the compiler's).\n */\nexport function compileWorkflowManifest(\n source: string,\n opts: CompileWorkflowOptions,\n): RuntimeWorkflow {\n const manifest = parseWorkflowManifest(source)\n const handle = workflowFromManifest(manifest)\n return compileWorkflow(handle, opts)\n}\n"]}
1
+ {"version":3,"sources":["../src/run-workflow.ts","../src/compile-workflow.ts","../src/load-workflow.ts"],"names":[],"mappings":";;;;;;;;;AAsBO,IAAM,sBAAA,GAAN,cAAqC,KAAA,CAAM;AAAA,EAChD,WAAA,CACW,QACA,EAAA,EACT;AACA,IAAA,KAAA;AAAA,MACE,+BAA+B,MAAM,CAAA,YAAA,EAAe,EAAA,CAAG,IAAA,CAAK,IAAI,CAAC,CAAA,gCAAA;AAAA,KAEnE;AANS,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,EAAA,GAAA,EAAA;AAMT,IAAA,IAAA,CAAK,IAAA,GAAO,wBAAA;AAAA,EACd;AAAA,EARW,MAAA;AAAA,EACA,EAAA;AAQb;AAwBA,SAAS,IAAA,CAAK,KAAA,EAAiB,IAAA,EAAgB,KAAA,EAA0B;AACvE,EAAA,OAAO,EAAE,OAAO,KAAA,CAAM,KAAA,EAAO,OAAO,KAAA,CAAM,KAAA,EAAO,MAAM,KAAA,EAAM;AAC/D;AAGA,SAAS,UAAA,CAAW,KAAgD,CAAA,EAAqB;AACvF,EAAA,OAAO,OAAO,GAAA,KAAQ,UAAA,GAAa,GAAA,CAAI,CAAC,CAAA,GAAI,GAAA;AAC9C;AAMA,SAAS,qBAAqB,GAAA,EAAqB;AACjD,EAAA,MAAM,SAAA,GAAY,0BAAA;AAClB,EAAA,MAAM,QAAA,GAAW,SAAA,CAAU,SAAA,EAAW,GAAG,CAAA;AACzC,EAAA,IAAI,QAAA,KAAa,QAAW,OAAO,QAAA;AAEnC,EAAA,MAAM,QAAA,GAAW,sBAAA;AACjB,EAAA,MAAM,OAAA,GAAU,SAAA,CAAU,QAAA,EAAU,GAAG,CAAA;AACvC,EAAA,IAAI,OAAA,KAAY,QAAW,OAAO,OAAA;AAElC,EAAA,OAAO,IAAI,IAAA,EAAK;AAClB;AAEA,SAAS,SAAA,CAAU,IAAY,CAAA,EAA+B;AAC5D,EAAA,IAAI,CAAA;AACJ,EAAA,IAAI,IAAA,GAA+B,IAAA;AACnC,EAAA,OAAA,CAAQ,IAAI,EAAA,CAAG,IAAA,CAAK,CAAC,CAAA,MAAO,MAAM,IAAA,GAAO,CAAA;AACzC,EAAA,OAAO,IAAA,GAAO,IAAA,CAAK,CAAC,CAAA,EAAG,MAAK,GAAI,MAAA;AAClC;AAEA,SAAS,SAAS,KAAA,EAAyB;AACzC,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,KAAA,MAAW,CAAA,IAAK,KAAA,CAAM,aAAA,CAAc,MAAA,IAAU,KAAA,IAAS,CAAA;AACvD,EAAA,OAAO,KAAA;AACT;AAGA,SAAS,kBAAA,CAAmB,MAAc,QAAA,EAA2B;AACnE,EAAA,OAAO,UAAA,CAAW,QAAQ,CAAA,CACvB,MAAA,CAAO,GAAG,IAAI,CAAA,EAAA,EAAS,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAA,IAAK,WAAW,CAAA,CAAE,CAAA,CAChE,OAAO,KAAK,CAAA;AACjB;AAGA,SAAS,cAAA,CAAe,UAAkB,IAAA,EAAuB;AAC/D,EAAA,OAAO,GAAG,QAAQ,CAAA,EAAA,EAAS,KAAK,EAAE,CAAA,EAAA,EAAS,KAAK,IAAI,CAAA,CAAA;AACtD;AAGA,SAAS,cAAA,CAAe,KAAa,IAAA,EAAwC;AAC3E,EAAA,OAAO,KAAK,SAAA,KAAc,IAAA,IAAQ,IAAI,KAAA,KAAU,MAAA,IAAa,IAAI,QAAA,KAAa,MAAA;AAChF;AAGA,eAAe,aAAA,CACb,GAAA,EACA,IAAA,EACA,cAAA,EACqF;AACrF,EAAA,MAAM,GAAA,GAAM,cAAA,CAAe,GAAA,CAAI,QAAA,EAAW,IAAI,CAAA;AAC9C,EAAA,MAAM,IAAA,GAAO,kBAAA,CAAmB,IAAA,CAAK,IAAA,EAAM,cAAc,CAAA;AACzD,EAAA,MAAM,KAAA,GAAQ,MAAM,GAAA,CAAI,KAAA,CAAO,IAAI,GAAG,CAAA;AACtC,EAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,CAAM,iBAAA,KAAsB,IAAA,EAAM;AAC3D,IAAA,OAAO,EAAE,GAAA,EAAK,IAAA,EAAM,MAAA,EAAQ,MAAM,MAAA,EAAO;AAAA,EAC3C;AACA,EAAA,OAAO,EAAE,GAAA,EAAK,KAAA,EAAO,GAAA,EAAK,IAAA,EAAK;AACjC;AAEA,SAAS,eAAe,GAAA,EAAuB;AAC7C,EAAA,OAAO,GAAA,CAAI,OACR,GAAA,CAAI,CAAC,MAAM,CAAA,EAAG,CAAA,CAAE,IAAA,CAAK,MAAA,GAAS,CAAA,GAAI,CAAA,CAAE,KAAK,IAAA,CAAK,GAAG,CAAA,GAAI,IAAA,GAAO,EAAE,CAAA,EAAG,EAAE,OAAO,CAAA,CAAE,CAAA,CAC5E,IAAA,CAAK,IAAI,CAAA;AACd;AAGA,eAAe,WAAA,CACb,KAAA,EACA,GAAA,EACA,IAAA,EACA,KAAA,EACkB;AAClB,EAAA,IAAI,IAAA;AACJ,EAAA,KAAA,MAAW,KAAK,KAAA,EAAO;AACrB,IAAA,MAAM,MAAM,MAAM,QAAA,CAAS,CAAA,EAAG,GAAA,EAAK,MAAM,KAAK,CAAA;AAC9C,IAAA,GAAA,CAAI,KAAA,CAAM,KAAA,CAAM,CAAA,CAAE,EAAE,CAAA,GAAI,GAAA;AACxB,IAAA,IAAA,GAAO,GAAA;AAAA,EACT;AACA,EAAA,OAAO,IAAA;AACT;AAGA,eAAe,aAAA,CAAc,IAAA,EAAiB,GAAA,EAAa,CAAA,EAA+B;AACxF,EAAA,IACE,IAAA,CAAK,OAAA,IACL,GAAA,CAAI,KAAA,CAAM,eAAA,KAAoB,MAAA,IAC9B,QAAA,CAAS,GAAA,CAAI,KAAK,CAAA,IAAK,GAAA,CAAI,KAAA,CAAM,eAAA,EACjC;AACA,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,MAAA,EAAS,IAAA,CAAK,EAAE,CAAA,qCAAA,EAAmC,SAAS,GAAA,CAAI,KAAK,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAC,CAAA,SAAA,EAAY,GAAA,CAAI,MAAM,eAAe,CAAA;AAAA,KACxH;AAAA,EACF;AACA,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,OAAA,GACnB,MAAM,GAAA,CAAI,MAAA,CAAQ,KAAA,CAAM,UAAA,CAAW,IAAA,CAAK,OAAA,EAAS,CAAC,CAAA,EAAG,EAAE,GAAA,EAAK,GAAA,CAAI,GAAA,EAAK,aAAA,EAAe,GAAA,CAAI,aAAA,EAAe,MAAA,EAAQ,IAAA,CAAK,EAAA,EAAI,CAAA,GACxH,GAAA,CAAI,MAAA,CAAQ,cAAA,CAAe,IAAA,CAAK,UAAW,CAAA;AAC/C,EAAA,IAAI,CAAC,WAAW,MAAM,IAAI,MAAM,CAAA,MAAA,EAAS,IAAA,CAAK,EAAE,CAAA,sDAAA,CAAwD,CAAA;AACxG,EAAA,MAAM,IAAI,MAAA,CAAQ,iBAAA,CAAkB,WAAW,IAAA,CAAK,MAAA,CAAO,CAAC,CAAC,CAAA;AAC7D,EAAA,IAAI,IAAA,CAAK,MAAA,IAAU,GAAA,CAAI,MAAA,CAAQ,eAAA,EAAiB;AAC9C,IAAA,MAAM,GAAA,CAAI,MAAA,CAAQ,eAAA,CAAgB,SAAA,EAAW,KAAK,MAAM,CAAA;AAAA,EAC1D;AAEA,EAAA,IAAI,GAAA,CAAI,OAAQ,WAAA,EAAa;AAC3B,IAAA,GAAA,CAAI,KAAA,CAAM,cAAc,GAAA,CAAI,SAAA,EAAW,MAAM,GAAA,CAAI,MAAA,CAAQ,WAAA,CAAY,SAAS,CAAC,CAAA;AAAA,EACjF;AAEA,EAAA,IAAI,CAAC,IAAA,CAAK,YAAA,EAAc,OAAO,EAAE,SAAA,EAAU;AAG3C,EAAA,IAAI,CAAC,GAAA,CAAI,MAAA,CAAQ,gBAAA,EAAkB;AACjC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,MAAA,EAAS,IAAA,CAAK,EAAE,CAAA,qDAAA,CAAuD,CAAA;AAAA,EACzF;AACA,EAAA,MAAM,UAAA,GAAa,KAAK,UAAA,IAAc,CAAA;AACtC,EAAA,IAAI,OAAA,GAAU,EAAA;AACd,EAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,IAAW,UAAA,EAAY,OAAA,EAAA,EAAW;AACtD,IAAA,MAAM,GAAA,GAAM,MAAM,GAAA,CAAI,MAAA,CAAQ,iBAAiB,SAAS,CAAA;AACxD,IAAA,MAAM,SAAA,GAAY,qBAAqB,GAAG,CAAA;AAC1C,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI;AACF,MAAA,KAAA,GAAQ,IAAA,CAAK,MAAM,SAAS,CAAA;AAAA,IAC9B,CAAA,CAAA,MAAQ;AACN,MAAA,OAAA,GAAU,gBAAA;AACV,MAAA,IAAI,UAAU,UAAA,EAAY;AACxB,QAAA,MAAM,IAAI,MAAA,CAAQ,iBAAA;AAAA,UAChB,SAAA;AAAA,UACA,0DAA0D,OAAO,CAAA,mFAAA;AAAA,SAEnE;AAAA,MACF;AACA,MAAA;AAAA,IACF;AACA,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,YAAA,CAAa,SAAA,CAAU,KAAK,CAAA;AAC7C,IAAA,IAAI,IAAI,OAAA,EAAS,OAAO,EAAE,SAAA,EAAW,MAAA,EAAQ,IAAI,IAAA,EAAK;AACtD,IAAA,OAAA,GAAU,cAAA,CAAe,IAAI,KAAK,CAAA;AAClC,IAAA,IAAI,UAAU,UAAA,EAAY;AACxB,MAAA,MAAM,IAAI,MAAA,CAAQ,iBAAA;AAAA,QAChB,SAAA;AAAA,QACA,0DAA0D,OAAO,CAAA,mFAAA;AAAA,OAEnE;AAAA,IACF;AAAA,EACF;AACA,EAAA,MAAM,IAAI,KAAA,CAAM,CAAA,MAAA,EAAS,KAAK,EAAE,CAAA,mEAAA,EAAiE,OAAO,CAAA,CAAA,CAAG,CAAA;AAC7G;AAEA,eAAe,QAAA,CACb,IAAA,EACA,GAAA,EACA,IAAA,EACA,KAAA,EACkB;AAClB,EAAA,MAAM,EAAE,KAAA,EAAO,MAAA,EAAO,GAAI,GAAA;AAC1B,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,EAAO,IAAA,EAAM,KAAK,CAAA;AACjC,EAAA,QAAQ,KAAK,IAAA;AAAM,IACjB,KAAK,MAAA,EAAQ;AACX,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA;AAC1B,MAAA,MAAM,KAAA,GAAQ,MACZ,OAAA,CAAQ;AAAA,QACN,MAAM,IAAA,CAAK,IAAA;AAAA,QACX,YAAY,IAAA,CAAK,UAAA;AAAA,QACjB,KAAA;AAAA,QACA,SAAS,IAAA,CAAK,OAAA,GAAU,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA,GAAI,MAAA;AAAA,QAC1C,iBAAiB,IAAA,CAAK,eAAA;AAAA,QACtB,SAAS,IAAA,CAAK,OAAA;AAAA,QACd;AAAA,OACD,CAAA;AACH,MAAA,IAAI,CAAC,cAAA,CAAe,GAAA,EAAK,IAAI,CAAA,SAAU,KAAA,EAAM;AAC7C,MAAA,MAAM,CAAA,GAAI,MAAM,aAAA,CAAc,GAAA,EAAK,MAAM,KAAK,CAAA;AAC9C,MAAA,IAAI,CAAA,CAAE,GAAA,EAAK,OAAO,CAAA,CAAE,MAAA;AACpB,MAAA,MAAM,GAAA,GAAM,MAAM,KAAA,EAAM;AACxB,MAAA,MAAM,GAAA,CAAI,KAAA,CAAO,GAAA,CAAI,CAAA,CAAE,GAAA,EAAK,EAAE,MAAA,EAAQ,GAAA,EAAK,iBAAA,EAAmB,CAAA,CAAE,IAAA,EAAM,CAAA;AACtE,MAAA,OAAO,GAAA;AAAA,IACT;AAAA,IAEA,KAAK,WAAA;AACH,MAAA,OAAO,IAAA,CAAK,QAAQ,CAAC,CAAA;AAAA,IAEvB,KAAK,KAAA,EAAO;AACV,MAAA,MAAM,MAAM,CAAC,GAAG,IAAA,CAAK,IAAA,CAAK,CAAC,CAAC,CAAA;AAC5B,MAAA,MAAM,cAAc,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,eAAe,CAAC,CAAA;AACrD,MAAA,MAAM,OAAA,GAAqB,IAAI,KAAA,CAAM,GAAA,CAAI,MAAM,CAAA;AAC/C,MAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,MAAA,EAAQ,KAAK,WAAA,EAAa;AAChD,QAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,CAAA,EAAG,IAAI,WAAW,CAAA;AAC1C,QAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,GAAA;AAAA,UACzB,KAAA,CAAM,GAAA,CAAI,CAAC,EAAA,EAAI,CAAA,KAAM;AACnB,YAAA,MAAM,MAAM,CAAA,GAAI,CAAA;AAChB,YAAA,MAAM,KAAA,GAAQ,KAAK,IAAA,CAAK,EAAA,EAAI,KAAK,IAAA,CAAK,KAAA,EAAO,EAAA,EAAI,GAAG,CAAC,CAAA;AACrD,YAAA,OAAO,QAAA,CAAS,KAAA,EAAO,GAAA,EAAK,EAAA,EAAI,GAAG,CAAA;AAAA,UACrC,CAAC;AAAA,SACH;AACA,QAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,MAAA,EAAQ,CAAA,EAAA,EAAK,OAAA,CAAQ,CAAA,GAAI,CAAC,CAAA,GAAI,IAAA,CAAK,CAAC,CAAA;AAAA,MAC/D;AACA,MAAA,OAAO,OAAA;AAAA,IACT;AAAA,IAEA,KAAK,UAAA,EAAY;AACf,MAAA,MAAM,QAAQ,CAAC,GAAG,IAAA,CAAK,IAAA,CAAK,CAAC,CAAC,CAAA;AAC9B,MAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AAChC,MAAA,MAAM,MAAM,IAAA,CAAK,GAAA,CAAI,GAAG,IAAA,CAAK,WAAA,IAAe,MAAM,MAAM,CAAA;AACxD,MAAA,MAAM,OAAA,GAAqB,IAAI,KAAA,CAAM,KAAA,CAAM,MAAM,CAAA;AACjD,MAAA,IAAI,IAAA,GAAO,CAAA;AACX,MAAA,MAAM,OAAA,GAAU,OAAO,GAAA,KAA+B;AACpD,QAAA,IAAI,IAAA,GAAgB,MAAA;AACpB,QAAA,KAAA,MAAW,KAAA,IAAS,KAAK,MAAA,EAAQ;AAC/B,UAAA,IAAA,GAAO,MAAM,SAAS,KAAA,CAAM,KAAA,CAAM,GAAG,CAAA,EAAG,GAAA,EAAK,MAAM,IAAA,CAAK,KAAA,EAAO,MAAM,GAAG,CAAA,EAAG,GAAG,CAAC,CAAA,EAAG,KAAK,KAAA,CAAM,GAAG,GAAG,GAAG,CAAA;AAAA,QACxG;AACA,QAAA,OAAA,CAAQ,GAAG,CAAA,GAAI,IAAA;AAAA,MACjB,CAAA;AACA,MAAA,MAAM,SAAS,YAA2B;AACxC,QAAA,OAAO,IAAA,GAAO,MAAM,MAAA,EAAQ;AAC1B,UAAA,MAAM,GAAA,GAAM,IAAA,EAAA;AACZ,UAAA,MAAM,QAAQ,GAAG,CAAA;AAAA,QACnB;AAAA,MACF,CAAA;AACA,MAAA,MAAM,QAAQ,GAAA,CAAI,KAAA,CAAM,IAAA,CAAK,EAAE,QAAQ,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,KAAA,CAAM,MAAM,CAAA,EAAE,EAAG,MAAM,MAAA,EAAQ,CAAC,CAAA;AACrF,MAAA,OAAO,OAAA;AAAA,IACT;AAAA,IAEA,KAAK,QAAA,EAAU;AACb,MAAA,MAAM,MAAA,GAAS,KAAK,IAAA,CAAK,CAAC,IAAI,IAAA,CAAK,IAAA,GAAQ,IAAA,CAAK,SAAA,IAAa,EAAC;AAC9D,MAAA,OAAO,WAAA,CAAY,MAAA,EAAQ,GAAA,EAAK,IAAA,EAAM,KAAK,CAAA;AAAA,IAC7C;AAAA,IAEA,KAAK,MAAA,EAAQ;AACX,MAAA,IAAI,UAAA,GAAa,CAAA;AACjB,MAAA,IAAI,IAAA;AACJ,MAAA,OACE,UAAA,GAAa,IAAA,CAAK,aAAA,IAClB,IAAA,CAAK,KAAA,CAAM,KAAK,KAAA,EAAO,IAAA,EAAM,KAAK,CAAC,CAAA,EACnC;AACA,QAAA,IAAA,GAAO,MAAM,WAAA,CAAY,IAAA,CAAK,IAAA,EAAM,GAAA,EAAK,MAAM,KAAK,CAAA;AACpD,QAAA,UAAA,EAAA;AAAA,MACF;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,IAEA,KAAK,UAAA,EAAY;AACf,MAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,GAAA;AAAA,QACzB,KAAK,QAAA,CAAS,GAAA;AAAA,UAAI,CAAC,EAAA,KACjB,WAAA,CAAY,EAAA,CAAG,KAAA,EAAO,GAAA,EAAK,IAAA,EAAM,KAAK,CAAA,CAAE,IAAA,CAAK,CAAC,IAAA,MAAU;AAAA,YACtD,IAAI,EAAA,CAAG,EAAA;AAAA,YACP;AAAA,WACF,CAAE;AAAA;AACJ,OACF;AACA,MAAA,MAAM,SAAkC,EAAC;AACzC,MAAA,KAAA,MAAW,EAAE,EAAA,EAAI,IAAA,MAAU,IAAA,EAAM,MAAA,CAAO,EAAE,CAAA,GAAI,IAAA;AAC9C,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,IAEA,KAAK,UAAA,EAAY;AACf,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA;AAC5B,MAAA,MAAM,SAAA,GAAY,IAAA,CAAK,SAAA,IAAa,EAAC;AACrC,MAAA,MAAM,QAAA,GAAW,GAAA,CAAI,OAAA,GACjB,MAAM,GAAA,CAAI,OAAA,CAAQ,EAAE,MAAA,EAAQ,IAAA,CAAK,EAAA,EAAI,MAAA,EAAQ,SAAA,EAAW,CAAA,GACxD,IAAA;AACJ,MAAA,MAAM,SAAA,GAAY,WACb,IAAA,CAAK,SAAA,IAAa,EAAC,GACnB,IAAA,CAAK,YAAY,EAAC;AACvB,MAAA,MAAM,WAAA,CAAY,SAAA,EAAW,GAAA,EAAK,IAAA,EAAM,KAAK,CAAA;AAC7C,MAAA,OAAO,EAAE,QAAA,EAAS;AAAA,IACpB;AAAA,IAEA,KAAK,SAAA,EAAW;AACd,MAAA,IAAI,CAAC,IAAI,MAAA,EAAQ,MAAM,IAAI,sBAAA,CAAuB,IAAA,CAAK,EAAA,EAAI,IAAA,CAAK,EAAE,CAAA;AAClE,MAAA,OAAO,GAAA,CAAI,OAAO,EAAE,MAAA,EAAQ,KAAK,EAAA,EAAI,EAAA,EAAI,IAAA,CAAK,EAAA,EAAI,CAAA;AAAA,IACpD;AAAA,IAEA,KAAK,OAAA;AACH,MAAA,OAAO,WAAA,CAAY,IAAA,CAAK,KAAA,EAAO,GAAA,EAAK,MAAM,KAAK,CAAA;AAAA,IAEjD,KAAK,aAAA,EAAe;AAClB,MAAA,MAAM,aAAa,IAAA,CAAK,KAAA,GAAQ,KAAK,KAAA,CAAM,CAAC,IAAI,KAAA,CAAM,KAAA;AACtD,MAAA,MAAM,KAAA,GAAQ,MAAM,gBAAA,CAAiB,IAAA,CAAK,UAAU,UAAA,EAAY;AAAA,QAC9D,SAAS,GAAA,CAAI,OAAA;AAAA,QACb,QAAQ,GAAA,CAAI,MAAA;AAAA,QACZ,MAAA;AAAA,QACA,QAAQ,GAAA,CAAI,MAAA;AAAA,QACZ,KAAK,GAAA,CAAI,GAAA;AAAA,QACT,eAAe,GAAA,CAAI,aAAA;AAAA,QACnB,OAAO,GAAA,CAAI,KAAA;AAAA,QACX,UAAU,GAAA,CAAI;AAAA,OACf,CAAA;AACD,MAAA,OAAO,KAAA,CAAM,MAAA;AAAA,IACf;AAAA,IAEA,KAAK,OAAA,EAAS;AACZ,MAAA,IAAI,CAAC,IAAI,MAAA,EAAQ,MAAM,IAAI,KAAA,CAAM,CAAA,MAAA,EAAS,IAAA,CAAK,EAAE,CAAA,kDAAA,CAAoD,CAAA;AACrG,MAAA,IAAI,CAAC,eAAe,GAAA,EAAK,IAAI,GAAG,OAAO,aAAA,CAAc,IAAA,EAAM,GAAA,EAAK,CAAC,CAAA;AACjE,MAAA,MAAM,QAAA,GAAW;AAAA,QACf,MAAA,EAAQ,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA;AAAA,QACrB,SAAS,IAAA,CAAK,OAAA,GAAU,WAAW,IAAA,CAAK,OAAA,EAAS,CAAC,CAAA,GAAI,MAAA;AAAA,QACtD,YAAY,IAAA,CAAK;AAAA,OACnB;AACA,MAAA,MAAM,CAAA,GAAI,MAAM,aAAA,CAAc,GAAA,EAAK,MAAM,QAAQ,CAAA;AACjD,MAAA,IAAI,CAAA,CAAE,GAAA,EAAK,OAAO,CAAA,CAAE,MAAA;AACpB,MAAA,MAAM,GAAA,GAAM,MAAM,aAAA,CAAc,IAAA,EAAM,KAAK,CAAC,CAAA;AAC5C,MAAA,MAAM,GAAA,CAAI,KAAA,CAAO,GAAA,CAAI,CAAA,CAAE,GAAA,EAAK,EAAE,MAAA,EAAQ,GAAA,EAAK,iBAAA,EAAmB,CAAA,CAAE,IAAA,EAAM,CAAA;AACtE,MAAA,OAAO,GAAA;AAAA,IACT;AAAA;AAEJ;AAEA,eAAe,gBAAA,CACb,QAAA,EACA,KAAA,EACA,KAAA,EACA,eAAA,EAC4B;AAC5B,EAAA,MAAM,KAAA,GAAkB,EAAE,KAAA,EAAO,KAAA,EAAO,IAAI,aAAA,kBAAe,IAAI,GAAA,EAAI,EAAG,eAAA,EAAgB;AACtF,EAAA,MAAM,GAAA,GAAc,EAAE,KAAA,EAAO,GAAG,KAAA,EAAM;AACtC,EAAA,IAAI,MAAA;AACJ,EAAA,KAAA,MAAW,IAAA,IAAQ,SAAS,KAAA,EAAO;AACjC,IAAA,MAAM,MAAM,MAAM,QAAA,CAAS,IAAA,EAAM,GAAA,EAAK,QAAW,MAAS,CAAA;AAC1D,IAAA,KAAA,CAAM,KAAA,CAAM,IAAA,CAAK,EAAE,CAAA,GAAI,GAAA;AACvB,IAAA,MAAA,GAAS,IAAA,CAAK,EAAA;AAAA,EAChB;AACA,EAAA,MAAM,QAAA,GAAW,KAAK,KAAK,CAAA;AAC3B,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,MAAA,GACpB,QAAA,CAAS,MAAA,CAAO,QAAQ,CAAA,GACxB,MAAA,KAAW,MAAA,GACT,KAAA,CAAM,KAAA,CAAM,MAAM,CAAA,GAClB,MAAA;AACN,EAAA,OAAO,EAAE,QAAQ,QAAA,EAAS;AAC5B;AAEA,eAAsB,YACpB,IAAA,EAC4B;AAC5B,EAAA,OAAO,gBAAA,CAAiB,IAAA,CAAK,QAAA,EAAU,IAAA,CAAK,KAAA,EAAO;AAAA,IACjD,SAAS,IAAA,CAAK,OAAA;AAAA,IACd,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,KAAK,IAAA,CAAK,GAAA;AAAA,IACV,eAAe,IAAA,CAAK,aAAA;AAAA,IACpB,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,UAAU,IAAA,CAAK;AAAA,GACjB,EAAG,KAAK,eAAe,CAAA;AACzB;;;AC5WO,IAAM,oBAAA,GAAN,cAAmC,KAAA,CAAM;AAAA,EAC9C,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,CAAA,iBAAA,EAAoB,OAAO,CAAA,CAAE,CAAA;AACnC,IAAA,IAAA,CAAK,IAAA,GAAO,sBAAA;AAAA,EACd;AACF;AAIA,IAAM,GAAA,GAAM,CACV,CAAA,EACA,GAAA,KAEA,CAAA,YAAa,GAAA,GAAM,CAAA,CAAE,GAAA,CAAI,GAAG,CAAA,GAAK,CAAA,CAAwB,GAAG,CAAA;AAE9D,SAAS,GAAA,CAAI,OAAgB,IAAA,EAAkC;AAC7D,EAAA,IAAI,CAAA,GAAI,KAAA;AACR,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,IAAI,CAAA,IAAK,MAAM,OAAO,MAAA;AACtB,IAAA,CAAA,GAAK,EAA8B,GAAG,CAAA;AAAA,EACxC;AACA,EAAA,OAAO,CAAA;AACT;AAGO,SAAS,UAAA,CAAW,KAAa,CAAA,EAAsB;AAC5D,EAAA,IAAI,GAAA,KAAQ,QAAA,EAAU,OAAO,CAAA,CAAE,KAAA;AAC/B,EAAA,MAAM,CAAA,GAAI,GAAA,CAAI,KAAA,CAAM,sCAAsC,CAAA;AAC1D,EAAA,IAAI,CAAC,CAAA,EAAG,MAAM,IAAI,oBAAA,CAAqB,CAAA,eAAA,EAAkB,GAAG,CAAA,CAAA,CAAG,CAAA;AAC/D,EAAA,MAAM,IAAA,GAAO,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA,CAAE,KAAA,CAAM,CAAC,CAAA,CAAE,KAAA,CAAM,GAAG,IAAI,EAAC;AAChD,EAAA,QAAQ,CAAA,CAAE,CAAC,CAAA;AAAG,IACZ,KAAK,OAAA;AACH,MAAA,OAAO,GAAA,CAAI,CAAA,CAAE,KAAA,EAAO,IAAI,CAAA;AAAA,IAC1B,KAAK,MAAA;AACH,MAAA,OAAO,GAAA,CAAI,CAAA,CAAE,IAAA,EAAM,IAAI,CAAA;AAAA,IACzB,KAAK,OAAA,EAAS;AACZ,MAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,IAAI,CAAA,GAAI,IAAA;AAC1B,MAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAI,qBAAqB,CAAA,wBAAA,CAA0B,CAAA;AACtE,MAAA,OAAO,GAAA,CAAI,CAAA,CAAE,KAAA,CAAM,MAAM,GAAG,IAAI,CAAA;AAAA,IAClC;AAAA;AAEJ;AAGO,SAAS,YAAA,CAAa,MAAe,CAAA,EAAsB;AAChE,EAAA,IAAI,OAAO,SAAS,QAAA,EAAU;AAC5B,IAAA,IAAI,KAAK,UAAA,CAAW,IAAI,GAAG,OAAO,IAAA,CAAK,MAAM,CAAC,CAAA;AAC9C,IAAA,IAAI,KAAK,UAAA,CAAW,GAAG,GAAG,OAAO,UAAA,CAAW,MAAM,CAAC,CAAA;AACnD,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,EAAG,OAAO,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM,YAAA,CAAa,CAAA,EAAG,CAAC,CAAC,CAAA;AAClE,EAAA,IAAI,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACpC,IAAA,MAAM,MAA+B,EAAC;AACtC,IAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,CAAA,IAAK,MAAA,CAAO,QAAQ,IAA+B,CAAA;AACjE,MAAA,GAAA,CAAI,CAAC,CAAA,GAAI,YAAA,CAAa,CAAA,EAAG,CAAC,CAAA;AAC5B,IAAA,OAAO,GAAA;AAAA,EACT;AACA,EAAA,OAAO,IAAA;AACT;AAEA,IAAM,WAAA,GAAiE;AAAA,EACrE,GAAA,EAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAA;AAAA,EACnB,IAAA,EAAM,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,IAAK,CAAA;AAAA,EACrB,GAAA,EAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAA;AAAA,EACnB,IAAA,EAAM,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,IAAK;AACvB,CAAA;AAEA,SAAS,OAAA,CAAQ,OAAe,CAAA,EAAsB;AACpD,EAAA,IAAI,MAAM,UAAA,CAAW,GAAG,GAAG,OAAO,UAAA,CAAW,OAAO,CAAC,CAAA;AACrD,EAAA,IAAI,KAAA,KAAU,QAAQ,OAAO,IAAA;AAC7B,EAAA,IAAI,KAAA,KAAU,SAAS,OAAO,KAAA;AAC9B,EAAA,IAAI,KAAA,KAAU,QAAQ,OAAO,IAAA;AAC7B,EAAA,IAAI,kBAAkB,IAAA,CAAK,KAAK,CAAA,EAAG,OAAO,OAAO,KAAK,CAAA;AACtD,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,cAAA,EAAgB,EAAE,CAAA;AACzC;AAGO,SAAS,aAAA,CAAc,MAAc,CAAA,EAAsB;AAChE,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,oCAAoC,CAAA;AACzD,EAAA,IAAI,CAAC,GAAG,OAAO,OAAA,CAAQ,QAAQ,IAAA,CAAK,IAAA,EAAK,EAAG,CAAC,CAAC,CAAA;AAC9C,EAAA,MAAM,OAAO,OAAA,CAAQ,CAAA,CAAE,CAAC,CAAA,CAAG,IAAA,IAAQ,CAAC,CAAA;AACpC,EAAA,MAAM,QAAQ,OAAA,CAAQ,CAAA,CAAE,CAAC,CAAA,CAAG,IAAA,IAAQ,CAAC,CAAA;AACrC,EAAA,QAAQ,CAAA,CAAE,CAAC,CAAA;AAAG,IACZ,KAAK,IAAA;AACH,MAAA,OAAO,IAAA,KAAS,KAAA;AAAA,IAClB,KAAK,IAAA;AACH,MAAA,OAAO,IAAA,KAAS,KAAA;AAAA,IAClB,SAAS;AACP,MAAA,MAAM,GAAA,GAAM,WAAA,CAAY,CAAA,CAAE,CAAC,CAAE,CAAA;AAC7B,MAAA,OAAO,IAAI,MAAA,CAAO,IAAI,CAAA,EAAG,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,IACxC;AAAA;AAEJ;AAKA,SAAS,gBAAgB,GAAA,EAAqB;AAC5C,EAAA,IAAI,CAAA,GAAI,IAAI,IAAA,EAAK;AACjB,EAAA,IAAI,CAAA,CAAE,QAAA,CAAS,UAAU,CAAA,EAAG,CAAA,GAAI,EAAE,KAAA,CAAM,CAAA,EAAG,CAAC,UAAA,CAAW,MAAM,CAAA;AAC7D,EAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,WAAA,CAAY,GAAG,CAAA;AAC/B,EAAA,OAAO,UAAU,EAAA,GAAK,CAAA,GAAI,CAAA,CAAE,KAAA,CAAM,QAAQ,CAAC,CAAA;AAC7C;AAGA,IAAM,CAAA,GAAI,CAAI,IAAA,EAAc,GAAA,KACzB,KAAiC,GAAG,CAAA;AAEvC,SAAS,aAAa,KAAA,EAAqE;AACzF,EAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA,EAAG,CAAA,KAAM;AACtB,IAAA,MAAM,OAAQ,CAAA,CAAwB,IAAA;AACtC,IAAA,MAAM,WAAA,GAAc,KAAA,CAAM,CAAA,GAAI,CAAC,CAAA,EAAG,EAAA;AAClC,IAAA,IAAI,IAAA,IAAQ,SAAS,WAAA,EAAa;AAChC,MAAA,MAAM,IAAI,oBAAA;AAAA,QACR,CAAA,MAAA,EAAS,CAAA,CAAE,EAAE,CAAA,yBAAA,EAA4B,IAAI,CAAA,yHAAA;AAAA,OAG/C;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AACH;AAEO,SAAS,eAAA,CACd,QACA,IAAA,EACiB;AAEjB,EAAA,MAAM,QAAQ,MAAA,CAAO,KAAA;AACrB,EAAA,IAAI,OAAO,KAAA,IAAS,MAAA,CAAO,UAAU,KAAA,CAAM,CAAC,GAAG,EAAA,EAAI;AACjD,IAAA,MAAM,IAAI,oBAAA;AAAA,MACR,CAAA,OAAA,EAAU,OAAO,KAAK,CAAA,8DAAA;AAAA,KACxB;AAAA,EACF;AACA,EAAA,YAAA,CAAa,KAAK,CAAA;AAIlB,EAAA,MAAM,SAAU,MAAA,CAAgC,MAAA;AAChD,EAAA,MAAM,MAAA,GACJ,WAAW,MAAA,GAAY,CAAC,MAAgB,YAAA,CAAa,MAAA,EAAQ,CAAC,CAAA,GAAI,MAAA;AACpE,EAAA,OAAO;AAAA,IACL,IAAI,MAAA,CAAO,EAAA;AAAA,IACX,aAAa,MAAA,CAAO,WAAA;AAAA,IACpB,KAAA,EAAO,MAAM,GAAA,CAAI,CAAC,MAAM,WAAA,CAAY,CAAA,EAAG,IAAI,CAAC,CAAA;AAAA,IAC5C,GAAI,MAAA,GAAS,EAAE,MAAA,KAAW;AAAC,GAC7B;AACF;AAEA,SAAS,eAAA,CAEP,KAAA,EACA,EAAA,EACA,IAAA,EACS;AACT,EAAA,YAAA,CAAa,KAAK,CAAA;AAClB,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG,OAAO,YAAY,KAAA,CAAM,CAAC,GAAG,IAAI,CAAA;AACzD,EAAA,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,EAAA,EAAI,KAAA,EAAO,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,WAAA,CAAY,CAAA,EAAG,IAAI,CAAC,CAAA,EAAE;AAC5E;AAGA,SAAS,WAAA,CAAY,MAAW,IAAA,EAAuC;AACrE,EAAA,MAAM,KAAa,IAAA,CAAK,EAAA;AACxB,EAAA,QAAQ,KAAK,IAAA;AAAM,IACjB,KAAK,MAAA,EAAQ;AACX,MAAA,MAAM,GAAA,GAAM,OAAO,IAAA,CAAK,IAAA,KAAS,WAAW,IAAA,CAAK,IAAA,GAAO,KAAK,IAAA,CAAK,KAAA;AAClE,MAAA,MAAM,MAAA,GAAS,gBAAgB,GAAG,CAAA;AAClC,MAAA,MAAM,IAAA,GAAO,GAAA,CAAI,IAAA,CAAK,KAAA,EAAO,MAAM,CAAA;AACnC,MAAA,IAAI,CAAC,IAAA;AACH,QAAA,MAAM,IAAI,oBAAA,CAAqB,CAAA,wBAAA,EAA2B,MAAM,CAAA,CAAA,CAAG,CAAA;AACrE,MAAA,MAAM,MAAA,GAAS,CAAA,CAAW,IAAA,EAAM,QAAQ,KAAK,EAAC;AAC9C,MAAA,OAAO;AAAA,QACL,IAAA,EAAM,MAAA;AAAA,QACN,EAAA;AAAA,QACA,IAAA;AAAA,QACA,YAAY,IAAA,CAAK,UAAA;AAAA,QACjB,KAAA,EAAO,CAAC,CAAA,KAAM,YAAA,CAAa,QAAQ,CAAC,CAAA;AAAA,QACpC,OAAA,EAAS,KAAK,UAAA,GACV,CAAC,MAAM,IAAA,CAAK,UAAA,CAAY,MAAA,EAAQ,CAAC,CAAA,GACjC;AAAA,OACN;AAAA,IACF;AAAA,IAEA,KAAK,KAAA,EAAO;AACV,MAAA,MAAM,IAAA,GAAO,CAAA,CAAU,IAAA,EAAM,MAAM,CAAA;AACnC,MAAA,MAAM,KAAA,GAAQ,gBAAgB,CAAA,CAAE,IAAA,EAAM,OAAO,CAAA,EAAG,CAAA,EAAG,EAAE,CAAA,MAAA,CAAA,EAAU,IAAI,CAAA;AACnE,MAAA,OAAO;AAAA,QACL,IAAA,EAAM,KAAA;AAAA,QACN,EAAA;AAAA,QACA,WAAA,EAAa,CAAA,CAAsB,IAAA,EAAM,aAAa,CAAA;AAAA,QACtD,IAAA,EAAM,CAAC,CAAA,KAAM,UAAA,CAAW,MAAM,CAAC,CAAA;AAAA,QAC/B,MAAM,MAAM;AAAA,OACd;AAAA,IACF;AAAA,IAEA,KAAK,MAAA,EAAQ;AACX,MAAA,MAAM,SAAA,GAAY,CAAA,CAAU,IAAA,EAAM,OAAO,CAAA;AACzC,MAAA,OAAO;AAAA,QACL,IAAA,EAAM,MAAA;AAAA,QACN,EAAA;AAAA,QACA,aAAA,EAAe,CAAA,CAAU,IAAA,EAAM,gBAAgB,CAAA;AAAA,QAC/C,KAAA,EAAO,CAAC,CAAA,KAAM,aAAA,CAAc,WAAW,CAAC,CAAA;AAAA,QACxC,IAAA,EAAM,CAAC,eAAA,CAAgB,CAAA,CAAE,IAAA,EAAM,OAAO,CAAA,EAAG,CAAA,EAAG,EAAE,CAAA,MAAA,CAAA,EAAU,IAAI,CAAC;AAAA,OAC/D;AAAA,IACF;AAAA,IAEA,KAAK,UAAA,EAAY;AAEf,MAAA,MAAM,QAAA,GAAW,CAAA,CAAS,IAAA,EAAM,UAAU,CAAA;AAC1C,MAAA,OAAO;AAAA,QACL,IAAA,EAAM,UAAA;AAAA,QACN,EAAA;AAAA,QACA,QAAA,EAAU,QAAA,CAAS,GAAA,CAAI,CAAC,EAAA,MAAQ;AAAA,UAC9B,IAAI,EAAA,CAAG,EAAA;AAAA,UACP,KAAA,EAAO,CAAC,eAAA,CAAgB,EAAA,CAAG,KAAA,EAAO,CAAA,EAAG,EAAE,CAAA,EAAA,EAAK,EAAA,CAAG,EAAE,CAAA,CAAA,EAAI,IAAI,CAAC;AAAA,SAC5D,CAAE;AAAA,OACJ;AAAA,IACF;AAAA,IAEA,KAAK,UAAA,EAAY;AACf,MAAA,MAAM,MAAA,GAAS,CAAA,CAAU,IAAA,EAAM,QAAQ,CAAA;AAEvC,MAAA,MAAM,aAAa,CAAA,CAAS,IAAA,EAAM,WAAW,CAAA,IAAK,EAAC,EAAG,GAAA;AAAA,QACpD,CAAC,CAAA,KAAM,CAAA,CAAE,QAAQ,CAAA,CAAE,MAAA,IAAU,OAAO,CAAC;AAAA,OACvC;AACA,MAAA,OAAO;AAAA,QACL,IAAA,EAAM,UAAA;AAAA,QACN,EAAA;AAAA,QACA,SAAA;AAAA,QACA,QAAQ,CAAC,CAAA,KAAM,OAAO,YAAA,CAAa,MAAA,EAAQ,CAAC,CAAC;AAAA,OAC/C;AAAA,IACF;AAAA,IAEA,KAAK,SAAA,EAAW;AACd,MAAA,MAAM,MAAA,GAAS,CAAA,CAAyC,IAAA,EAAM,QAAQ,CAAA;AACtE,MAAA,OAAO,EAAE,MAAM,SAAA,EAAW,EAAA,EAAI,IAAI,MAAA,CAAO,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,UAAA,EAAW;AAAA,IAC5E;AAAA,IAEA,KAAK,aAAA,EAAe;AAClB,MAAA,MAAM,IAAA,GAAO,CAAA,CAAU,IAAA,EAAM,UAAU,CAAA;AACvC,MAAA,MAAM,QAAQ,IAAA,CAAK,SAAA,GAAY,IAAI,IAAA,CAAK,SAAA,EAAW,IAAI,CAAA,GAAI,MAAA;AAC3D,MAAA,IAAI,CAAC,KAAA;AACH,QAAA,MAAM,IAAI,oBAAA;AAAA,UACR,gBAAgB,IAAI,CAAA,4CAAA;AAAA,SACtB;AACF,MAAA,MAAM,aAAA,GAAgB,eAAA,CAAgB,KAAA,EAAO,IAAI,CAAA;AACjD,MAAA,OAAO,EAAE,IAAA,EAAM,aAAA,EAAe,EAAA,EAAI,UAAU,aAAA,EAAc;AAAA,IAC5D;AAAA,IAEA,KAAK,QAAA;AACH,MAAA,MAAM,IAAI,oBAAA;AAAA,QACR,8BAA8B,EAAE,CAAA,+FAAA;AAAA,OAElC;AAAA,IAEF;AACE,MAAA,MAAM,IAAI,oBAAA;AAAA,QACR,CAAA,uBAAA,EAA0B,IAAA,CAAK,IAAI,CAAA,SAAA,EAAY,EAAE,CAAA,EAAA;AAAA,OACnD;AAAA;AAEN;AC3QO,SAAS,uBAAA,CACd,QACA,IAAA,EACiB;AACjB,EAAA,MAAM,QAAA,GAAW,sBAAsB,MAAM,CAAA;AAC7C,EAAA,MAAM,MAAA,GAAS,qBAAqB,QAAQ,CAAA;AAC5C,EAAA,OAAO,eAAA,CAAgB,QAAQ,IAAI,CAAA;AACrC","file":"index.mjs","sourcesContent":["/**\n * The step-walker. Executes a {@link RuntimeWorkflow} top-to-bottom, threading\n * each step's output into a run-scoped binding bag, and dispatching `tool`\n * steps through `@agentproto/driver` `runTool` (resolve DRIVER → validate input\n * + context → execute body → validate output). Composite steps (`map` /\n * `branch` / `loop` / `parallel` / `approval` / `subworkflow`) recurse over the\n * same bindings; `suspend` defers to the host's resume hook.\n */\n\nimport { runTool } from \"@agentproto/driver\"\nimport { createHash } from \"node:crypto\"\nimport type { ZodError } from \"zod\"\nimport type {\n AgentStep,\n Bindings,\n RunStep,\n RunWorkflowArgs,\n RuntimeWorkflow,\n WorkflowRunResult,\n} from \"./types.js\"\n\n/** Thrown by a `suspend` step when no host `resume` hook is provided. */\nexport class WorkflowSuspendedError extends Error {\n constructor(\n readonly stepId: string,\n readonly on: readonly string[],\n ) {\n super(\n `workflow suspended at step '${stepId}' awaiting [${on.join(\", \")}] — ` +\n `no resume hook supplied`,\n )\n this.name = \"WorkflowSuspendedError\"\n }\n}\n\ninterface RunState {\n readonly input: unknown\n readonly steps: Record<string, unknown>\n readonly maxTotalCostUsd?: number\n /** Last-known cost per session id; summed to get the run's total spend.\n * A Map (not a running delta) so a session reused across steps via\n * sessionRef is counted once, not double-counted. */\n readonly costBySession: Map<string, number>\n}\n\ninterface RunCtx {\n readonly state: RunState\n readonly approve?: RunWorkflowArgs[\"approve\"]\n readonly resume?: RunWorkflowArgs[\"resume\"]\n readonly signal?: AbortSignal\n readonly agents?: RunWorkflowArgs[\"agents\"]\n readonly cwd?: string\n readonly workspaceSlug?: string\n readonly cache?: RunWorkflowArgs[\"cache\"]\n readonly cacheKey?: RunWorkflowArgs[\"cacheKey\"]\n}\n\nfunction view(state: RunState, item?: unknown, index?: number): Bindings {\n return { input: state.input, steps: state.steps, item, index }\n}\n\n/** Resolve a value that is either a static string or a binding selector. */\nfunction resolveSel(sel: string | ((bindings: Bindings) => string), b: Bindings): string {\n return typeof sel === \"function\" ? sel(b) : sel\n}\n\n/** Extract a JSON candidate from raw assistant text:\n * 1. last ```json fenced block if present, else\n * 2. last generic ``` fenced block if present, else\n * 3. the whole trimmed string. */\nfunction extractJsonCandidate(raw: string): string {\n const jsonFence = /```json\\s*([\\s\\S]*?)```/g\n const lastJson = lastMatch(jsonFence, raw)\n if (lastJson !== undefined) return lastJson\n\n const anyFence = /```\\s*([\\s\\S]*?)```/g\n const lastAny = lastMatch(anyFence, raw)\n if (lastAny !== undefined) return lastAny\n\n return raw.trim()\n}\n\nfunction lastMatch(re: RegExp, s: string): string | undefined {\n let m: RegExpExecArray | null\n let last: RegExpExecArray | null = null\n while ((m = re.exec(s)) !== null) last = m\n return last ? last[1]?.trim() : undefined\n}\n\nfunction spentUsd(state: RunState): number {\n let total = 0\n for (const c of state.costBySession.values()) total += c\n return total\n}\n\n/** Deterministic content hash of a step's resolved inputs. */\nfunction hashResolvedInputs(kind: string, resolved: unknown): string {\n return createHash(\"sha256\")\n .update(`${kind}\\u0000${JSON.stringify(resolved) ?? \"undefined\"}`)\n .digest(\"hex\")\n}\n\n/** Namespaced journal key for a step under a run's cacheKey. */\nfunction stepJournalKey(cacheKey: string, step: RunStep): string {\n return `${cacheKey}\\u0000${step.id}\\u0000${step.kind}`\n}\n\n/** True when this step should consult/populate the journal. */\nfunction isCacheEnabled(ctx: RunCtx, step: { cacheable?: boolean }): boolean {\n return step.cacheable === true && ctx.cache !== undefined && ctx.cacheKey !== undefined\n}\n\n/** Read the journal; on a hit return the output, else the key+hash to write on miss. */\nasync function readStepCache(\n ctx: RunCtx,\n step: RunStep,\n resolvedInputs: unknown,\n): Promise<{ hit: true; output: unknown } | { hit: false; key: string; hash: string }> {\n const key = stepJournalKey(ctx.cacheKey!, step)\n const hash = hashResolvedInputs(step.kind, resolvedInputs)\n const entry = await ctx.cache!.get(key)\n if (entry !== undefined && entry.resolvedInputHash === hash) {\n return { hit: true, output: entry.output }\n }\n return { hit: false, key, hash }\n}\n\nfunction formatZodError(err: ZodError): string {\n return err.issues\n .map((i) => `${i.path.length > 0 ? i.path.join(\".\") + \": \" : \"\"}${i.message}`)\n .join(\", \")\n}\n\n/** Run an ordered list of steps, binding each output under its id; return last. */\nasync function runSequence(\n steps: readonly RunStep[],\n ctx: RunCtx,\n item: unknown,\n index: number | undefined,\n): Promise<unknown> {\n let last: unknown\n for (const s of steps) {\n const out = await execStep(s, ctx, item, index)\n ctx.state.steps[s.id] = out\n last = out\n }\n return last\n}\n\n/** Execute the full AgentStep body — spawn, prompt, policy, budget, outputSchema retry loop. */\nasync function execAgentStep(step: AgentStep, ctx: RunCtx, b: Bindings): Promise<unknown> {\n if (\n step.adapter &&\n ctx.state.maxTotalCostUsd !== undefined &&\n spentUsd(ctx.state) >= ctx.state.maxTotalCostUsd\n ) {\n throw new Error(\n `step '${step.id}': budget_exceeded — run spend $${spentUsd(ctx.state).toFixed(4)} >= cap $${ctx.state.maxTotalCostUsd}`,\n )\n }\n const sessionId = step.adapter\n ? await ctx.agents!.spawn(resolveSel(step.adapter, b), { cwd: ctx.cwd, workspaceSlug: ctx.workspaceSlug, stepId: step.id })\n : ctx.agents!.resolveByLabel(step.sessionRef!)\n if (!sessionId) throw new Error(`step '${step.id}': no session (adapter and sessionRef both unresolved)`)\n await ctx.agents!.sendPromptAndWait(sessionId, step.prompt(b))\n if (step.policy && ctx.agents!.onAwaitingInput) {\n await ctx.agents!.onAwaitingInput(sessionId, step.policy)\n }\n\n if (ctx.agents!.readCostUsd) {\n ctx.state.costBySession.set(sessionId, await ctx.agents!.readCostUsd(sessionId))\n }\n\n if (!step.outputSchema) return { sessionId }\n\n // Validate-and-retry loop\n if (!ctx.agents!.readFinalMessage) {\n throw new Error(`step '${step.id}': outputSchema requires a host with readFinalMessage`)\n }\n const maxRetries = step.maxRetries ?? 2\n let lastErr = \"\"\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const raw = await ctx.agents!.readFinalMessage(sessionId)\n const candidate = extractJsonCandidate(raw)\n let value: unknown\n try {\n value = JSON.parse(candidate)\n } catch {\n lastErr = \"not valid JSON\"\n if (attempt < maxRetries) {\n await ctx.agents!.sendPromptAndWait(\n sessionId,\n `Your previous reply did not match the required schema: ${lastErr}. ` +\n `Reply again with ONLY a JSON object that matches. No prose, no code fence needed.`,\n )\n }\n continue\n }\n const res = step.outputSchema.safeParse(value)\n if (res.success) return { sessionId, output: res.data }\n lastErr = formatZodError(res.error)\n if (attempt < maxRetries) {\n await ctx.agents!.sendPromptAndWait(\n sessionId,\n `Your previous reply did not match the required schema: ${lastErr}. ` +\n `Reply again with ONLY a JSON object that matches. No prose, no code fence needed.`,\n )\n }\n }\n throw new Error(`step '${step.id}': output_invalid — final message never matched outputSchema (${lastErr})`)\n}\n\nasync function execStep(\n step: RunStep,\n ctx: RunCtx,\n item: unknown,\n index: number | undefined,\n): Promise<unknown> {\n const { state, signal } = ctx\n const b = view(state, item, index)\n switch (step.kind) {\n case \"tool\": {\n const input = step.input(b)\n const runIt = (): Promise<unknown> =>\n runTool({\n tool: step.tool,\n candidates: step.candidates,\n input,\n context: step.context ? step.context(b) : undefined,\n resolverContext: step.resolverContext,\n secrets: step.secrets,\n signal,\n })\n if (!isCacheEnabled(ctx, step)) return runIt()\n const c = await readStepCache(ctx, step, input)\n if (c.hit) return c.output\n const out = await runIt()\n await ctx.cache!.set(c.key, { output: out, resolvedInputHash: c.hash })\n return out\n }\n\n case \"transform\":\n return step.compute(b)\n\n case \"map\": {\n const arr = [...step.over(b)]\n const parallelism = Math.max(1, step.parallelism ?? 1)\n const results: unknown[] = new Array(arr.length)\n for (let i = 0; i < arr.length; i += parallelism) {\n const chunk = arr.slice(i, i + parallelism)\n const outs = await Promise.all(\n chunk.map((el, j) => {\n const idx = i + j\n const inner = step.body(el, idx, view(state, el, idx))\n return execStep(inner, ctx, el, idx)\n }),\n )\n for (let j = 0; j < outs.length; j++) results[i + j] = outs[j]\n }\n return results\n }\n\n case \"pipeline\": {\n const items = [...step.over(b)]\n if (items.length === 0) return []\n const cap = Math.max(1, step.concurrency ?? items.length)\n const results: unknown[] = new Array(items.length)\n let next = 0\n const runItem = async (idx: number): Promise<void> => {\n let prev: unknown = undefined\n for (const stage of step.stages) {\n prev = await execStep(stage(items[idx], idx, prev, view(state, items[idx], idx)), ctx, items[idx], idx)\n }\n results[idx] = prev\n }\n const worker = async (): Promise<void> => {\n while (next < items.length) {\n const idx = next++\n await runItem(idx)\n }\n }\n await Promise.all(Array.from({ length: Math.min(cap, items.length) }, () => worker()))\n return results\n }\n\n case \"branch\": {\n const chosen = step.cond(b) ? step.then : (step.otherwise ?? [])\n return runSequence(chosen, ctx, item, index)\n }\n\n case \"loop\": {\n let iterations = 0\n let last: unknown\n while (\n iterations < step.maxIterations &&\n step.while(view(state, item, index))\n ) {\n last = await runSequence(step.body, ctx, item, index)\n iterations++\n }\n return last\n }\n\n case \"parallel\": {\n const outs = await Promise.all(\n step.branches.map((br) =>\n runSequence(br.steps, ctx, item, index).then((last) => ({\n id: br.id,\n last,\n })),\n ),\n )\n const record: Record<string, unknown> = {}\n for (const { id, last } of outs) record[id] = last\n return record\n }\n\n case \"approval\": {\n const prompt = step.prompt(b)\n const approvers = step.approvers ?? []\n const approved = ctx.approve\n ? await ctx.approve({ stepId: step.id, prompt, approvers })\n : true\n const followups = approved\n ? (step.onApprove ?? [])\n : (step.onReject ?? [])\n await runSequence(followups, ctx, item, index)\n return { approved }\n }\n\n case \"suspend\": {\n if (!ctx.resume) throw new WorkflowSuspendedError(step.id, step.on)\n return ctx.resume({ stepId: step.id, on: step.on })\n }\n\n case \"group\":\n return runSequence(step.steps, ctx, item, index)\n\n case \"subworkflow\": {\n const childInput = step.input ? step.input(b) : state.input\n const child = await runWorkflowInner(step.workflow, childInput, {\n approve: ctx.approve,\n resume: ctx.resume,\n signal,\n agents: ctx.agents,\n cwd: ctx.cwd,\n workspaceSlug: ctx.workspaceSlug,\n cache: ctx.cache,\n cacheKey: ctx.cacheKey,\n })\n return child.output\n }\n\n case \"agent\": {\n if (!ctx.agents) throw new Error(`step '${step.id}': AgentStep requires a host agents implementation`)\n if (!isCacheEnabled(ctx, step)) return execAgentStep(step, ctx, b)\n const resolved = {\n prompt: step.prompt(b),\n adapter: step.adapter ? resolveSel(step.adapter, b) : undefined,\n sessionRef: step.sessionRef,\n }\n const c = await readStepCache(ctx, step, resolved)\n if (c.hit) return c.output // cache hit ⇒ NO spawn, NO budget spend\n const out = await execAgentStep(step, ctx, b)\n await ctx.cache!.set(c.key, { output: out, resolvedInputHash: c.hash })\n return out\n }\n }\n}\n\nasync function runWorkflowInner(\n workflow: RuntimeWorkflow,\n input: unknown,\n hooks: Pick<RunCtx, \"approve\" | \"resume\" | \"signal\" | \"agents\" | \"cwd\" | \"workspaceSlug\" | \"cache\" | \"cacheKey\">,\n maxTotalCostUsd?: number,\n): Promise<WorkflowRunResult> {\n const state: RunState = { input, steps: {}, costBySession: new Map(), maxTotalCostUsd }\n const ctx: RunCtx = { state, ...hooks }\n let lastId: string | undefined\n for (const step of workflow.steps) {\n const out = await execStep(step, ctx, undefined, undefined)\n state.steps[step.id] = out\n lastId = step.id\n }\n const bindings = view(state)\n const output = workflow.output\n ? workflow.output(bindings)\n : lastId !== undefined\n ? state.steps[lastId]\n : undefined\n return { output, bindings }\n}\n\nexport async function runWorkflow(\n args: RunWorkflowArgs,\n): Promise<WorkflowRunResult> {\n return runWorkflowInner(args.workflow, args.input, {\n approve: args.approve,\n resume: args.resume,\n signal: args.signal,\n agents: args.agents,\n cwd: args.cwd,\n workspaceSlug: args.workspaceSlug,\n cache: args.cache,\n cacheKey: args.cacheKey,\n }, args.maxTotalCostUsd)\n}\n","/**\n * Compile a declarative AIP-15 `WorkflowHandle` into a runnable\n * {@link RuntimeWorkflow} for {@link runWorkflow}. This is the bridge that makes\n * an authored WORKFLOW.md actually execute.\n *\n * AIP-15 leaves the IO seam (`step.inputs`, `map.over`, `loop.while`) to a\n * meta-validator. This compiler pins a concrete, minimal **reference grammar**\n * for it — the convention a manifest author writes:\n *\n * - data refs: `$input` · `$input.a.b` · `$steps.<id>` · `$steps.<id>.a`\n * · `$item` · `$item.a` · `$index` (`$$` escapes a literal `$`)\n * - `step.inputs`: a JSON object whose leaf strings may be refs (resolved\n * recursively); non-`$` strings are literals\n * - `map.over`: a ref to an array\n * - `loop.while` / approval prompt: `<ref> <op> <literal>` (`== != < <= > >=`)\n * or a bare ref (truthiness)\n *\n * Scope: the **linear / structured subset** of AIP-15 — steps run in document\n * order; `map`/`loop`/`parallel` nest their child step lists. Non-linear `next`\n * gotos and goto-style `branch` routing are rejected with a clear diagnostic\n * (hand-author a structured `BranchStep`, or nest). Compiling the full goto\n * graph is a separable follow-up.\n */\n\nimport type { WorkflowHandle } from \"@agentproto/workflow\"\nimport type { DriverHandle } from \"@agentproto/driver\"\nimport type { ToolHandle } from \"@agentproto/tool\"\nimport type { Bindings, RunStep, RuntimeWorkflow } from \"./types.js\"\n\nexport interface CompileWorkflowOptions {\n /** TOOL contracts by id — each `tool` step resolves its handle here. */\n tools: ReadonlyMap<string, ToolHandle> | Record<string, ToolHandle>\n /** DRIVER candidates the resolver dispatches over for every tool step. */\n candidates: readonly DriverHandle[]\n /** Resolve a tool step's injected context (live capabilities) from bindings. */\n contextFor?: (toolId: string, bindings: Bindings) => unknown\n /** Sub-workflows by id, for `subworkflow` steps. */\n workflows?:\n | ReadonlyMap<string, WorkflowHandle>\n | Record<string, WorkflowHandle>\n}\n\nexport class WorkflowCompileError extends Error {\n constructor(message: string) {\n super(`compileWorkflow: ${message}`)\n this.name = \"WorkflowCompileError\"\n }\n}\n\n// ── reference + predicate resolution (the AIP-16 IO seam) ────────────\n\nconst get = <T>(\n m: ReadonlyMap<string, T> | Record<string, T>,\n key: string,\n): T | undefined =>\n m instanceof Map ? m.get(key) : (m as Record<string, T>)[key]\n\nfunction dig(value: unknown, path: readonly string[]): unknown {\n let v = value\n for (const seg of path) {\n if (v == null) return undefined\n v = (v as Record<string, unknown>)[seg]\n }\n return v\n}\n\n/** Resolve a single `$…` reference string against the run bindings. */\nexport function resolveRef(ref: string, b: Bindings): unknown {\n if (ref === \"$index\") return b.index\n const m = ref.match(/^\\$(input|item|steps)((?:\\.[^.]+)*)$/)\n if (!m) throw new WorkflowCompileError(`bad reference '${ref}'`)\n const segs = m[2] ? m[2].slice(1).split(\".\") : []\n switch (m[1]) {\n case \"input\":\n return dig(b.input, segs)\n case \"item\":\n return dig(b.item, segs)\n case \"steps\": {\n const [stepId, ...rest] = segs\n if (!stepId) throw new WorkflowCompileError(`'$steps' needs a step id`)\n return dig(b.steps[stepId], rest)\n }\n }\n}\n\n/** Recursively resolve a value node: refs in strings, into arrays/objects. */\nexport function resolveValue(node: unknown, b: Bindings): unknown {\n if (typeof node === \"string\") {\n if (node.startsWith(\"$$\")) return node.slice(1) // $$ → literal $\n if (node.startsWith(\"$\")) return resolveRef(node, b)\n return node\n }\n if (Array.isArray(node)) return node.map((n) => resolveValue(n, b))\n if (node && typeof node === \"object\") {\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(node as Record<string, unknown>))\n out[k] = resolveValue(v, b)\n return out\n }\n return node\n}\n\nconst COMPARATORS: Record<string, (a: number, b: number) => boolean> = {\n \"<\": (a, c) => a < c,\n \"<=\": (a, c) => a <= c,\n \">\": (a, c) => a > c,\n \">=\": (a, c) => a >= c,\n}\n\nfunction literal(token: string, b: Bindings): unknown {\n if (token.startsWith(\"$\")) return resolveRef(token, b)\n if (token === \"true\") return true\n if (token === \"false\") return false\n if (token === \"null\") return null\n if (/^-?\\d+(\\.\\d+)?$/.test(token)) return Number(token)\n return token.replace(/^['\"]|['\"]$/g, \"\")\n}\n\n/** Evaluate a `while`/`when` predicate string against the bindings. */\nexport function evalPredicate(expr: string, b: Bindings): boolean {\n const m = expr.match(/^(.+?)\\s*(==|!=|<=|>=|<|>)\\s*(.+)$/)\n if (!m) return Boolean(literal(expr.trim(), b)) // bare ref → truthiness\n const left = literal(m[1]!.trim(), b)\n const right = literal(m[3]!.trim(), b)\n switch (m[2]) {\n case \"==\":\n return left === right\n case \"!=\":\n return left !== right\n default: {\n const cmp = COMPARATORS[m[2]!]!\n return cmp(Number(left), Number(right))\n }\n }\n}\n\n// ── step compilation ─────────────────────────────────────────────────\n\n/** AIP step ids may be paths/refs; the runtime key is the last segment. */\nfunction normalizeToolId(ref: string): string {\n let s = ref.trim()\n if (s.endsWith(\"/TOOL.md\")) s = s.slice(0, -\"/TOOL.md\".length)\n const slash = s.lastIndexOf(\"/\")\n return slash === -1 ? s : s.slice(slash + 1)\n}\n\n// AIP step frontmatter leaves IO fields as opaque `{}`; read them dynamically.\nconst f = <T>(step: object, key: string): T =>\n (step as Record<string, unknown>)[key] as T\n\nfunction assertLinear(steps: readonly { id: string; kind: string; next?: string }[]): void {\n steps.forEach((s, i) => {\n const next = (s as { next?: string }).next\n const followingId = steps[i + 1]?.id\n if (next && next !== followingId) {\n throw new WorkflowCompileError(\n `step '${s.id}' has a non-linear next='${next}' — the structured-subset ` +\n `compiler only runs steps in document order. Hand-author a BranchStep ` +\n `or nest structurally.`,\n )\n }\n })\n}\n\nexport function compileWorkflow(\n handle: WorkflowHandle,\n opts: CompileWorkflowOptions,\n): RuntimeWorkflow {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const steps = handle.steps as unknown as any[]\n if (handle.start && handle.start !== steps[0]?.id) {\n throw new WorkflowCompileError(\n `start='${handle.start}' is not the first step — structured-subset runs in order`,\n )\n }\n assertLinear(steps)\n // `result` is the optional output value-expression (AIP-15): map it through\n // the same ref grammar as a step's inputs. Absent ⇒ no output selector, so\n // runWorkflow falls back to the final step's result.\n const result = (handle as { result?: unknown }).result\n const output =\n result !== undefined ? (b: Bindings) => resolveValue(result, b) : undefined\n return {\n id: handle.id,\n description: handle.description,\n steps: steps.map((s) => compileStep(s, opts)),\n ...(output ? { output } : {}),\n }\n}\n\nfunction compileStepList(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n steps: any[],\n id: string,\n opts: CompileWorkflowOptions,\n): RunStep {\n assertLinear(steps)\n if (steps.length === 1) return compileStep(steps[0], opts)\n return { kind: \"group\", id, steps: steps.map((s) => compileStep(s, opts)) }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction compileStep(step: any, opts: CompileWorkflowOptions): RunStep {\n const id: string = step.id\n switch (step.kind) {\n case \"tool\": {\n const ref = typeof step.tool === \"string\" ? step.tool : step.tool.entry\n const toolId = normalizeToolId(ref)\n const tool = get(opts.tools, toolId)\n if (!tool)\n throw new WorkflowCompileError(`no tool registered for '${toolId}'`)\n const inputs = f<unknown>(step, \"inputs\") ?? {}\n return {\n kind: \"tool\",\n id,\n tool,\n candidates: opts.candidates,\n input: (b) => resolveValue(inputs, b),\n context: opts.contextFor\n ? (b) => opts.contextFor!(toolId, b)\n : undefined,\n }\n }\n\n case \"map\": {\n const over = f<string>(step, \"over\")\n const inner = compileStepList(f(step, \"steps\"), `${id}__body`, opts)\n return {\n kind: \"map\",\n id,\n parallelism: f<number | undefined>(step, \"parallelism\"),\n over: (b) => resolveRef(over, b) as readonly unknown[],\n body: () => inner,\n }\n }\n\n case \"loop\": {\n const whileExpr = f<string>(step, \"while\")\n return {\n kind: \"loop\",\n id,\n maxIterations: f<number>(step, \"max_iterations\"),\n while: (b) => evalPredicate(whileExpr, b),\n body: [compileStepList(f(step, \"steps\"), `${id}__body`, opts)],\n }\n }\n\n case \"parallel\": {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const branches = f<any[]>(step, \"branches\")\n return {\n kind: \"parallel\",\n id,\n branches: branches.map((br) => ({\n id: br.id,\n steps: [compileStepList(br.steps, `${id}__${br.id}`, opts)],\n })),\n }\n }\n\n case \"approval\": {\n const prompt = f<string>(step, \"prompt\")\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const approvers = (f<any[]>(step, \"approvers\") ?? []).map(\n (a) => a.role ?? a.userId ?? String(a),\n )\n return {\n kind: \"approval\",\n id,\n approvers,\n prompt: (b) => String(resolveValue(prompt, b)),\n }\n }\n\n case \"suspend\": {\n const resume = f<{ on: string[]; timeout_ms?: number }>(step, \"resume\")\n return { kind: \"suspend\", id, on: resume.on, timeoutMs: resume.timeout_ms }\n }\n\n case \"subworkflow\": {\n const wfId = f<string>(step, \"workflow\")\n const child = opts.workflows ? get(opts.workflows, wfId) : undefined\n if (!child)\n throw new WorkflowCompileError(\n `subworkflow '${wfId}' not found — pass it in opts.workflows`,\n )\n const compiledChild = compileWorkflow(child, opts)\n return { kind: \"subworkflow\", id, workflow: compiledChild }\n }\n\n case \"branch\":\n throw new WorkflowCompileError(\n `goto-style 'branch' (step '${id}') is unsupported in the structured ` +\n `subset — hand-author a structured BranchStep, or nest.`,\n )\n\n default:\n throw new WorkflowCompileError(\n `unsupported step kind '${step.kind}' (step '${id}')`,\n )\n }\n}\n","/**\n * compileWorkflowManifest — the connective step between an authored\n * `WORKFLOW.md` and a runnable workflow.\n *\n * AIP-15 ships every piece needed to run a declarative manifest except the\n * seam that joins them: `parseWorkflowManifest` (md + frontmatter → manifest)\n * and `workflowFromManifest` (manifest → `WorkflowHandle`) live in\n * `@agentproto/workflow`; `compileWorkflow` (handle → `RuntimeWorkflow`) lives\n * here. Without this chain an authored `WORKFLOW.md` parses and validates but\n * never reaches the executor. This joins the three so a manifest source string\n * compiles straight to a runnable workflow — no hand-built handle.\n *\n * Framework-pure: the caller owns reading the file off disk (this package does\n * no I/O), and passes the source string in. The tool registry + driver\n * candidates are injected via {@link CompileWorkflowOptions}, same as the\n * hand-built path.\n */\n\nimport {\n parseWorkflowManifest,\n workflowFromManifest,\n} from \"@agentproto/workflow/manifest\"\n\nimport { compileWorkflow } from \"./compile-workflow.js\"\nimport type { CompileWorkflowOptions } from \"./compile-workflow.js\"\nimport type { RuntimeWorkflow } from \"./types.js\"\n\n/**\n * Compile a `WORKFLOW.md` source string into a {@link RuntimeWorkflow} ready\n * for `runWorkflow`. Parses + validates the frontmatter against the AIP-15\n * schema, lifts it to a `WorkflowHandle`, then compiles its step graph against\n * the injected tool registry. Throws on invalid frontmatter (the parser's\n * diagnostic) or an unresolved tool / non-linear step (the compiler's).\n */\nexport function compileWorkflowManifest(\n source: string,\n opts: CompileWorkflowOptions,\n): RuntimeWorkflow {\n const manifest = parseWorkflowManifest(source)\n const handle = workflowFromManifest(manifest)\n return compileWorkflow(handle, opts)\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentproto/workflow-runtime",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Reference step-walker for AIP-15 WORKFLOW composition: executes a typed step graph (tool / map / branch / loop / transform) over @agentproto/driver runTool, threading each step's output into a run-scoped binding bag (the AIP-16 IO seam, expressed as typed selectors). The missing executor that makes 'composition = config' runnable.",
5
5
  "keywords": [
6
6
  "agentproto",
@@ -39,9 +39,9 @@
39
39
  "access": "public"
40
40
  },
41
41
  "dependencies": {
42
+ "@agentproto/driver": "0.1.2",
42
43
  "@agentproto/tool": "0.2.0",
43
- "@agentproto/workflow": "0.1.0-alpha.1",
44
- "@agentproto/driver": "0.1.2"
44
+ "@agentproto/workflow": "0.1.0-alpha.1"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@types/node": "^25.6.2",