@agentproto/workflow-runtime 0.1.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jeremy André and agentproto contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,256 @@
1
+ import { DriverHandle, ResolverContext } from '@agentproto/driver';
2
+ import { ToolContext, ToolHandle } from '@agentproto/tool';
3
+ import { WorkflowHandle } from '@agentproto/workflow';
4
+
5
+ /**
6
+ * Typed step algebra for AIP-15 WORKFLOW execution.
7
+ *
8
+ * The AIP-15 manifest leaves the IO-threading (`step.inputs`, `map.over`,
9
+ * `branch.when`, `loop.while`) to a meta-validator — it never pins an
10
+ * expression language. Rather than invent a stringly DSL, this runtime
11
+ * expresses the AIP-16 IO seam as **typed selectors**: each step reads the
12
+ * run-scoped {@link Bindings} (workflow input + every prior step's output, plus
13
+ * the current item inside a `map`) through a plain `(bindings) => value`
14
+ * function. Authoring stays in TypeScript; compiling a declarative manifest's
15
+ * reference strings onto these selectors is a separable follow-up.
16
+ */
17
+
18
+ /** The run-scoped data every selector reads from. */
19
+ interface Bindings {
20
+ /** The workflow's invocation input. */
21
+ readonly input: unknown;
22
+ /** Each completed top-level step's output, keyed by step id. */
23
+ readonly steps: Readonly<Record<string, unknown>>;
24
+ /** Present inside a `map` body — the element being processed. */
25
+ readonly item?: unknown;
26
+ /** Present inside a `map` body — the element's index. */
27
+ readonly index?: number;
28
+ }
29
+ /** The AIP-16 IO seam: read a value out of the run bindings. */
30
+ type Selector<T> = (bindings: Bindings) => T;
31
+ /** Run a TOOL contract through the resolver; its output binds under `id`. */
32
+ interface ToolStep<TInput = unknown, TOutput = unknown, TContext extends ToolContext = ToolContext> {
33
+ kind: "tool";
34
+ id: string;
35
+ tool: ToolHandle<TInput, TOutput, TContext>;
36
+ candidates: readonly DriverHandle[];
37
+ /** Derive the tool input from the run bindings. */
38
+ input: Selector<TInput>;
39
+ /** Derive the injected per-call context (live capabilities) from bindings. */
40
+ context?: Selector<TContext>;
41
+ resolverContext?: ResolverContext;
42
+ secrets?: Record<string, string>;
43
+ }
44
+ /** A pure in-run computation (combine / filter / shape) — no tool dispatch. */
45
+ interface TransformStep {
46
+ kind: "transform";
47
+ id: string;
48
+ compute: Selector<unknown>;
49
+ }
50
+ /**
51
+ * Run a sub-step once per element of an array, optionally with bounded
52
+ * concurrency. The element + index are exposed to the body via `bindings.item`
53
+ * / `bindings.index`; the collected outputs bind under this step's id.
54
+ */
55
+ interface MapStep {
56
+ kind: "map";
57
+ id: string;
58
+ over: Selector<readonly unknown[]>;
59
+ /** Max concurrent bodies (default 1 = sequential). */
60
+ parallelism?: number;
61
+ body: (item: unknown, index: number, bindings: Bindings) => RunStep;
62
+ }
63
+ /** Run one of two branches based on a predicate over the bindings. */
64
+ interface BranchStep {
65
+ kind: "branch";
66
+ id: string;
67
+ cond: Selector<boolean>;
68
+ then: readonly RunStep[];
69
+ otherwise?: readonly RunStep[];
70
+ }
71
+ /** Repeat a body while a predicate holds, up to a hard iteration ceiling. */
72
+ interface LoopStep {
73
+ kind: "loop";
74
+ id: string;
75
+ while: Selector<boolean>;
76
+ maxIterations: number;
77
+ body: readonly RunStep[];
78
+ }
79
+ /** Run several independent branches concurrently; outputs bind by branch id. */
80
+ interface ParallelStep {
81
+ kind: "parallel";
82
+ id: string;
83
+ branches: readonly {
84
+ id: string;
85
+ steps: readonly RunStep[];
86
+ }[];
87
+ }
88
+ /**
89
+ * AIP-7 human-in-the-loop gate. The host's injected `approve` callback decides;
90
+ * the chosen `onApprove` / `onReject` sub-steps then run. Default (no callback)
91
+ * auto-approves. The step's own output is `{ approved }`.
92
+ */
93
+ interface ApprovalStep {
94
+ kind: "approval";
95
+ id: string;
96
+ prompt: Selector<string>;
97
+ approvers?: readonly string[];
98
+ onApprove?: readonly RunStep[];
99
+ onReject?: readonly RunStep[];
100
+ }
101
+ /**
102
+ * Pause until an external event resumes the run. The host's injected `resume`
103
+ * callback supplies the resume payload (bound under this step's id). With no
104
+ * callback the run throws {@link WorkflowSuspendedError} — the durable-suspend
105
+ * path a host persists and re-enters later.
106
+ */
107
+ interface SuspendStep {
108
+ kind: "suspend";
109
+ id: string;
110
+ on: readonly string[];
111
+ timeoutMs?: number;
112
+ }
113
+ /** Run an ordered list of steps as one unit; its output is the last step's. */
114
+ interface GroupStep {
115
+ kind: "group";
116
+ id: string;
117
+ steps: readonly RunStep[];
118
+ }
119
+ /** Run a nested workflow with its own isolated bindings; its output binds here. */
120
+ interface SubworkflowStep {
121
+ kind: "subworkflow";
122
+ id: string;
123
+ workflow: RuntimeWorkflow;
124
+ /** Input for the child (default: the parent's workflow input). */
125
+ input?: Selector<unknown>;
126
+ }
127
+ /**
128
+ * The element generics on `ToolStep` are erased to `any` so heterogeneous
129
+ * steps (different contracts, different input/output/context types) coexist in
130
+ * one `steps[]` array — per-step type safety is enforced where each step is
131
+ * authored, not at the collection level. Same contravariant-function-position
132
+ * constraint `@agentproto/driver`'s `implementations[]` works around (TS
133
+ * issue #21534); tightening the union to `ToolStep<unknown, …>` rejects a
134
+ * concrete `ToolStep<MarketSearchInput, …>` on the zod `ZodType<T>` variance.
135
+ */
136
+ type RunStep = ToolStep<any, any, any> | TransformStep | MapStep | BranchStep | LoopStep | ParallelStep | ApprovalStep | SuspendStep | GroupStep | SubworkflowStep;
137
+ interface RuntimeWorkflow {
138
+ id: string;
139
+ description?: string;
140
+ steps: readonly RunStep[];
141
+ /** Pick the run's final output (default: the last top-level step's output). */
142
+ output?: Selector<unknown>;
143
+ }
144
+ interface ApprovalRequest {
145
+ stepId: string;
146
+ prompt: string;
147
+ approvers: readonly string[];
148
+ }
149
+ interface ResumeRequest {
150
+ stepId: string;
151
+ on: readonly string[];
152
+ }
153
+ interface RunWorkflowArgs {
154
+ workflow: RuntimeWorkflow;
155
+ input?: unknown;
156
+ signal?: AbortSignal;
157
+ /** Decide an {@link ApprovalStep}. Default: auto-approve. */
158
+ approve?: (req: ApprovalRequest) => boolean | Promise<boolean>;
159
+ /** Supply a {@link SuspendStep}'s resume payload. Default: throw + suspend. */
160
+ resume?: (req: ResumeRequest) => unknown | Promise<unknown>;
161
+ }
162
+ interface WorkflowRunResult {
163
+ output: unknown;
164
+ bindings: Bindings;
165
+ }
166
+
167
+ /**
168
+ * The step-walker. Executes a {@link RuntimeWorkflow} top-to-bottom, threading
169
+ * each step's output into a run-scoped binding bag, and dispatching `tool`
170
+ * steps through `@agentproto/driver` `runTool` (resolve DRIVER → validate input
171
+ * + context → execute body → validate output). Composite steps (`map` /
172
+ * `branch` / `loop` / `parallel` / `approval` / `subworkflow`) recurse over the
173
+ * same bindings; `suspend` defers to the host's resume hook.
174
+ */
175
+
176
+ /** Thrown by a `suspend` step when no host `resume` hook is provided. */
177
+ declare class WorkflowSuspendedError extends Error {
178
+ readonly stepId: string;
179
+ readonly on: readonly string[];
180
+ constructor(stepId: string, on: readonly string[]);
181
+ }
182
+ declare function runWorkflow(args: RunWorkflowArgs): Promise<WorkflowRunResult>;
183
+
184
+ /**
185
+ * Compile a declarative AIP-15 `WorkflowHandle` into a runnable
186
+ * {@link RuntimeWorkflow} for {@link runWorkflow}. This is the bridge that makes
187
+ * an authored WORKFLOW.md actually execute.
188
+ *
189
+ * AIP-15 leaves the IO seam (`step.inputs`, `map.over`, `loop.while`) to a
190
+ * meta-validator. This compiler pins a concrete, minimal **reference grammar**
191
+ * for it — the convention a manifest author writes:
192
+ *
193
+ * - data refs: `$input` · `$input.a.b` · `$steps.<id>` · `$steps.<id>.a`
194
+ * · `$item` · `$item.a` · `$index` (`$$` escapes a literal `$`)
195
+ * - `step.inputs`: a JSON object whose leaf strings may be refs (resolved
196
+ * recursively); non-`$` strings are literals
197
+ * - `map.over`: a ref to an array
198
+ * - `loop.while` / approval prompt: `<ref> <op> <literal>` (`== != < <= > >=`)
199
+ * or a bare ref (truthiness)
200
+ *
201
+ * Scope: the **linear / structured subset** of AIP-15 — steps run in document
202
+ * order; `map`/`loop`/`parallel` nest their child step lists. Non-linear `next`
203
+ * gotos and goto-style `branch` routing are rejected with a clear diagnostic
204
+ * (hand-author a structured `BranchStep`, or nest). Compiling the full goto
205
+ * graph is a separable follow-up.
206
+ */
207
+
208
+ interface CompileWorkflowOptions {
209
+ /** TOOL contracts by id — each `tool` step resolves its handle here. */
210
+ tools: ReadonlyMap<string, ToolHandle> | Record<string, ToolHandle>;
211
+ /** DRIVER candidates the resolver dispatches over for every tool step. */
212
+ candidates: readonly DriverHandle[];
213
+ /** Resolve a tool step's injected context (live capabilities) from bindings. */
214
+ contextFor?: (toolId: string, bindings: Bindings) => unknown;
215
+ /** Sub-workflows by id, for `subworkflow` steps. */
216
+ workflows?: ReadonlyMap<string, WorkflowHandle> | Record<string, WorkflowHandle>;
217
+ }
218
+ declare class WorkflowCompileError extends Error {
219
+ constructor(message: string);
220
+ }
221
+ /** Resolve a single `$…` reference string against the run bindings. */
222
+ declare function resolveRef(ref: string, b: Bindings): unknown;
223
+ /** Recursively resolve a value node: refs in strings, into arrays/objects. */
224
+ declare function resolveValue(node: unknown, b: Bindings): unknown;
225
+ /** Evaluate a `while`/`when` predicate string against the bindings. */
226
+ declare function evalPredicate(expr: string, b: Bindings): boolean;
227
+ declare function compileWorkflow(handle: WorkflowHandle, opts: CompileWorkflowOptions): RuntimeWorkflow;
228
+
229
+ /**
230
+ * compileWorkflowManifest — the connective step between an authored
231
+ * `WORKFLOW.md` and a runnable workflow.
232
+ *
233
+ * AIP-15 ships every piece needed to run a declarative manifest except the
234
+ * seam that joins them: `parseWorkflowManifest` (md + frontmatter → manifest)
235
+ * and `workflowFromManifest` (manifest → `WorkflowHandle`) live in
236
+ * `@agentproto/workflow`; `compileWorkflow` (handle → `RuntimeWorkflow`) lives
237
+ * here. Without this chain an authored `WORKFLOW.md` parses and validates but
238
+ * never reaches the executor. This joins the three so a manifest source string
239
+ * compiles straight to a runnable workflow — no hand-built handle.
240
+ *
241
+ * Framework-pure: the caller owns reading the file off disk (this package does
242
+ * no I/O), and passes the source string in. The tool registry + driver
243
+ * candidates are injected via {@link CompileWorkflowOptions}, same as the
244
+ * hand-built path.
245
+ */
246
+
247
+ /**
248
+ * Compile a `WORKFLOW.md` source string into a {@link RuntimeWorkflow} ready
249
+ * for `runWorkflow`. Parses + validates the frontmatter against the AIP-15
250
+ * schema, lifts it to a `WorkflowHandle`, then compiles its step graph against
251
+ * the injected tool registry. Throws on invalid frontmatter (the parser's
252
+ * diagnostic) or an unresolved tool / non-linear step (the compiler's).
253
+ */
254
+ declare function compileWorkflowManifest(source: string, opts: CompileWorkflowOptions): RuntimeWorkflow;
255
+
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 };
package/dist/index.mjs ADDED
@@ -0,0 +1,351 @@
1
+ import { runTool } from '@agentproto/driver';
2
+ import { parseWorkflowManifest, workflowFromManifest } from '@agentproto/workflow/manifest';
3
+
4
+ /**
5
+ * @agentproto/workflow-runtime v0.1.0-alpha
6
+ * AIP-15 step-walker over @agentproto/driver runTool.
7
+ */
8
+
9
+ var WorkflowSuspendedError = class extends Error {
10
+ constructor(stepId, on) {
11
+ super(
12
+ `workflow suspended at step '${stepId}' awaiting [${on.join(", ")}] \u2014 no resume hook supplied`
13
+ );
14
+ this.stepId = stepId;
15
+ this.on = on;
16
+ this.name = "WorkflowSuspendedError";
17
+ }
18
+ stepId;
19
+ on;
20
+ };
21
+ function view(state, item, index) {
22
+ return { input: state.input, steps: state.steps, item, index };
23
+ }
24
+ async function runSequence(steps, ctx, item, index) {
25
+ let last;
26
+ for (const s of steps) {
27
+ const out = await execStep(s, ctx, item, index);
28
+ ctx.state.steps[s.id] = out;
29
+ last = out;
30
+ }
31
+ return last;
32
+ }
33
+ async function execStep(step, ctx, item, index) {
34
+ const { state, signal } = ctx;
35
+ const b = view(state, item, index);
36
+ switch (step.kind) {
37
+ case "tool":
38
+ return runTool({
39
+ tool: step.tool,
40
+ candidates: step.candidates,
41
+ input: step.input(b),
42
+ context: step.context ? step.context(b) : void 0,
43
+ resolverContext: step.resolverContext,
44
+ secrets: step.secrets,
45
+ signal
46
+ });
47
+ case "transform":
48
+ return step.compute(b);
49
+ case "map": {
50
+ const arr = [...step.over(b)];
51
+ const parallelism = Math.max(1, step.parallelism ?? 1);
52
+ const results = new Array(arr.length);
53
+ for (let i = 0; i < arr.length; i += parallelism) {
54
+ const chunk = arr.slice(i, i + parallelism);
55
+ const outs = await Promise.all(
56
+ chunk.map((el, j) => {
57
+ const idx = i + j;
58
+ const inner = step.body(el, idx, view(state, el, idx));
59
+ return execStep(inner, ctx, el, idx);
60
+ })
61
+ );
62
+ for (let j = 0; j < outs.length; j++) results[i + j] = outs[j];
63
+ }
64
+ return results;
65
+ }
66
+ case "branch": {
67
+ const chosen = step.cond(b) ? step.then : step.otherwise ?? [];
68
+ return runSequence(chosen, ctx, item, index);
69
+ }
70
+ case "loop": {
71
+ let iterations = 0;
72
+ let last;
73
+ while (iterations < step.maxIterations && step.while(view(state, item, index))) {
74
+ last = await runSequence(step.body, ctx, item, index);
75
+ iterations++;
76
+ }
77
+ return last;
78
+ }
79
+ case "parallel": {
80
+ const outs = await Promise.all(
81
+ step.branches.map(
82
+ (br) => runSequence(br.steps, ctx, item, index).then((last) => ({
83
+ id: br.id,
84
+ last
85
+ }))
86
+ )
87
+ );
88
+ const record = {};
89
+ for (const { id, last } of outs) record[id] = last;
90
+ return record;
91
+ }
92
+ case "approval": {
93
+ const prompt = step.prompt(b);
94
+ const approvers = step.approvers ?? [];
95
+ const approved = ctx.approve ? await ctx.approve({ stepId: step.id, prompt, approvers }) : true;
96
+ const followups = approved ? step.onApprove ?? [] : step.onReject ?? [];
97
+ await runSequence(followups, ctx, item, index);
98
+ return { approved };
99
+ }
100
+ case "suspend": {
101
+ if (!ctx.resume) throw new WorkflowSuspendedError(step.id, step.on);
102
+ return ctx.resume({ stepId: step.id, on: step.on });
103
+ }
104
+ case "group":
105
+ return runSequence(step.steps, ctx, item, index);
106
+ case "subworkflow": {
107
+ const childInput = step.input ? step.input(b) : state.input;
108
+ const child = await runWorkflowInner(step.workflow, childInput, {
109
+ approve: ctx.approve,
110
+ resume: ctx.resume,
111
+ signal
112
+ });
113
+ return child.output;
114
+ }
115
+ }
116
+ }
117
+ async function runWorkflowInner(workflow, input, hooks) {
118
+ const state = { input, steps: {} };
119
+ const ctx = { state, ...hooks };
120
+ let lastId;
121
+ for (const step of workflow.steps) {
122
+ const out = await execStep(step, ctx, void 0, void 0);
123
+ state.steps[step.id] = out;
124
+ lastId = step.id;
125
+ }
126
+ const bindings = view(state);
127
+ const output = workflow.output ? workflow.output(bindings) : lastId !== void 0 ? state.steps[lastId] : void 0;
128
+ return { output, bindings };
129
+ }
130
+ async function runWorkflow(args) {
131
+ return runWorkflowInner(args.workflow, args.input, {
132
+ approve: args.approve,
133
+ resume: args.resume,
134
+ signal: args.signal
135
+ });
136
+ }
137
+
138
+ // src/compile-workflow.ts
139
+ var WorkflowCompileError = class extends Error {
140
+ constructor(message) {
141
+ super(`compileWorkflow: ${message}`);
142
+ this.name = "WorkflowCompileError";
143
+ }
144
+ };
145
+ var get = (m, key) => m instanceof Map ? m.get(key) : m[key];
146
+ function dig(value, path) {
147
+ let v = value;
148
+ for (const seg of path) {
149
+ if (v == null) return void 0;
150
+ v = v[seg];
151
+ }
152
+ return v;
153
+ }
154
+ function resolveRef(ref, b) {
155
+ if (ref === "$index") return b.index;
156
+ const m = ref.match(/^\$(input|item|steps)((?:\.[^.]+)*)$/);
157
+ if (!m) throw new WorkflowCompileError(`bad reference '${ref}'`);
158
+ const segs = m[2] ? m[2].slice(1).split(".") : [];
159
+ switch (m[1]) {
160
+ case "input":
161
+ return dig(b.input, segs);
162
+ case "item":
163
+ return dig(b.item, segs);
164
+ case "steps": {
165
+ const [stepId, ...rest] = segs;
166
+ if (!stepId) throw new WorkflowCompileError(`'$steps' needs a step id`);
167
+ return dig(b.steps[stepId], rest);
168
+ }
169
+ }
170
+ }
171
+ function resolveValue(node, b) {
172
+ if (typeof node === "string") {
173
+ if (node.startsWith("$$")) return node.slice(1);
174
+ if (node.startsWith("$")) return resolveRef(node, b);
175
+ return node;
176
+ }
177
+ if (Array.isArray(node)) return node.map((n) => resolveValue(n, b));
178
+ if (node && typeof node === "object") {
179
+ const out = {};
180
+ for (const [k, v] of Object.entries(node))
181
+ out[k] = resolveValue(v, b);
182
+ return out;
183
+ }
184
+ return node;
185
+ }
186
+ var COMPARATORS = {
187
+ "<": (a, c) => a < c,
188
+ "<=": (a, c) => a <= c,
189
+ ">": (a, c) => a > c,
190
+ ">=": (a, c) => a >= c
191
+ };
192
+ function literal(token, b) {
193
+ if (token.startsWith("$")) return resolveRef(token, b);
194
+ if (token === "true") return true;
195
+ if (token === "false") return false;
196
+ if (token === "null") return null;
197
+ if (/^-?\d+(\.\d+)?$/.test(token)) return Number(token);
198
+ return token.replace(/^['"]|['"]$/g, "");
199
+ }
200
+ function evalPredicate(expr, b) {
201
+ const m = expr.match(/^(.+?)\s*(==|!=|<=|>=|<|>)\s*(.+)$/);
202
+ if (!m) return Boolean(literal(expr.trim(), b));
203
+ const left = literal(m[1].trim(), b);
204
+ const right = literal(m[3].trim(), b);
205
+ switch (m[2]) {
206
+ case "==":
207
+ return left === right;
208
+ case "!=":
209
+ return left !== right;
210
+ default: {
211
+ const cmp = COMPARATORS[m[2]];
212
+ return cmp(Number(left), Number(right));
213
+ }
214
+ }
215
+ }
216
+ function normalizeToolId(ref) {
217
+ let s = ref.trim();
218
+ if (s.endsWith("/TOOL.md")) s = s.slice(0, -"/TOOL.md".length);
219
+ const slash = s.lastIndexOf("/");
220
+ return slash === -1 ? s : s.slice(slash + 1);
221
+ }
222
+ var f = (step, key) => step[key];
223
+ function assertLinear(steps) {
224
+ steps.forEach((s, i) => {
225
+ const next = s.next;
226
+ const followingId = steps[i + 1]?.id;
227
+ if (next && next !== followingId) {
228
+ throw new WorkflowCompileError(
229
+ `step '${s.id}' has a non-linear next='${next}' \u2014 the structured-subset compiler only runs steps in document order. Hand-author a BranchStep or nest structurally.`
230
+ );
231
+ }
232
+ });
233
+ }
234
+ function compileWorkflow(handle, opts) {
235
+ const steps = handle.steps;
236
+ if (handle.start && handle.start !== steps[0]?.id) {
237
+ throw new WorkflowCompileError(
238
+ `start='${handle.start}' is not the first step \u2014 structured-subset runs in order`
239
+ );
240
+ }
241
+ assertLinear(steps);
242
+ const result = handle.result;
243
+ const output = result !== void 0 ? (b) => resolveValue(result, b) : void 0;
244
+ return {
245
+ id: handle.id,
246
+ description: handle.description,
247
+ steps: steps.map((s) => compileStep(s, opts)),
248
+ ...output ? { output } : {}
249
+ };
250
+ }
251
+ function compileStepList(steps, id, opts) {
252
+ assertLinear(steps);
253
+ if (steps.length === 1) return compileStep(steps[0], opts);
254
+ return { kind: "group", id, steps: steps.map((s) => compileStep(s, opts)) };
255
+ }
256
+ function compileStep(step, opts) {
257
+ const id = step.id;
258
+ switch (step.kind) {
259
+ case "tool": {
260
+ const ref = typeof step.tool === "string" ? step.tool : step.tool.entry;
261
+ const toolId = normalizeToolId(ref);
262
+ const tool = get(opts.tools, toolId);
263
+ if (!tool)
264
+ throw new WorkflowCompileError(`no tool registered for '${toolId}'`);
265
+ const inputs = f(step, "inputs") ?? {};
266
+ return {
267
+ kind: "tool",
268
+ id,
269
+ tool,
270
+ candidates: opts.candidates,
271
+ input: (b) => resolveValue(inputs, b),
272
+ context: opts.contextFor ? (b) => opts.contextFor(toolId, b) : void 0
273
+ };
274
+ }
275
+ case "map": {
276
+ const over = f(step, "over");
277
+ const inner = compileStepList(f(step, "steps"), `${id}__body`, opts);
278
+ return {
279
+ kind: "map",
280
+ id,
281
+ parallelism: f(step, "parallelism"),
282
+ over: (b) => resolveRef(over, b),
283
+ body: () => inner
284
+ };
285
+ }
286
+ case "loop": {
287
+ const whileExpr = f(step, "while");
288
+ return {
289
+ kind: "loop",
290
+ id,
291
+ maxIterations: f(step, "max_iterations"),
292
+ while: (b) => evalPredicate(whileExpr, b),
293
+ body: [compileStepList(f(step, "steps"), `${id}__body`, opts)]
294
+ };
295
+ }
296
+ case "parallel": {
297
+ const branches = f(step, "branches");
298
+ return {
299
+ kind: "parallel",
300
+ id,
301
+ branches: branches.map((br) => ({
302
+ id: br.id,
303
+ steps: [compileStepList(br.steps, `${id}__${br.id}`, opts)]
304
+ }))
305
+ };
306
+ }
307
+ case "approval": {
308
+ const prompt = f(step, "prompt");
309
+ const approvers = (f(step, "approvers") ?? []).map(
310
+ (a) => a.role ?? a.userId ?? String(a)
311
+ );
312
+ return {
313
+ kind: "approval",
314
+ id,
315
+ approvers,
316
+ prompt: (b) => String(resolveValue(prompt, b))
317
+ };
318
+ }
319
+ case "suspend": {
320
+ const resume = f(step, "resume");
321
+ return { kind: "suspend", id, on: resume.on, timeoutMs: resume.timeout_ms };
322
+ }
323
+ case "subworkflow": {
324
+ const wfId = f(step, "workflow");
325
+ const child = opts.workflows ? get(opts.workflows, wfId) : void 0;
326
+ if (!child)
327
+ throw new WorkflowCompileError(
328
+ `subworkflow '${wfId}' not found \u2014 pass it in opts.workflows`
329
+ );
330
+ const compiledChild = compileWorkflow(child, opts);
331
+ return { kind: "subworkflow", id, workflow: compiledChild };
332
+ }
333
+ case "branch":
334
+ throw new WorkflowCompileError(
335
+ `goto-style 'branch' (step '${id}') is unsupported in the structured subset \u2014 hand-author a structured BranchStep, or nest.`
336
+ );
337
+ default:
338
+ throw new WorkflowCompileError(
339
+ `unsupported step kind '${step.kind}' (step '${id}')`
340
+ );
341
+ }
342
+ }
343
+ function compileWorkflowManifest(source, opts) {
344
+ const manifest = parseWorkflowManifest(source);
345
+ const handle = workflowFromManifest(manifest);
346
+ return compileWorkflow(handle, opts);
347
+ }
348
+
349
+ export { WorkflowCompileError, WorkflowSuspendedError, compileWorkflow, compileWorkflowManifest, evalPredicate, resolveRef, resolveValue, runWorkflow };
350
+ //# sourceMappingURL=index.mjs.map
351
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/run-workflow.ts","../src/compile-workflow.ts","../src/load-workflow.ts"],"names":[],"mappings":";;;;;;;;AAmBO,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;AAcA,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,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;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;AACH,MAAA,OAAO,OAAA,CAAQ;AAAA,QACb,MAAM,IAAA,CAAK,IAAA;AAAA,QACX,YAAY,IAAA,CAAK,UAAA;AAAA,QACjB,KAAA,EAAO,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA;AAAA,QACnB,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;AAAA,IAEH,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,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;AAAA,OACD,CAAA;AACD,MAAA,OAAO,KAAA,CAAM,MAAA;AAAA,IACf;AAAA;AAEJ;AAEA,eAAe,gBAAA,CACb,QAAA,EACA,KAAA,EACA,KAAA,EAC4B;AAC5B,EAAA,MAAM,KAAA,GAAkB,EAAE,KAAA,EAAO,KAAA,EAAO,EAAC,EAAE;AAC3C,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;AAAA,GACd,CAAA;AACH;;;AC9JO,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 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"]}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@agentproto/workflow-runtime",
3
+ "version": "0.1.1",
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
+ "keywords": [
6
+ "agentproto",
7
+ "aip-15",
8
+ "workflow",
9
+ "runtime",
10
+ "step-walker",
11
+ "orchestration",
12
+ "open-standard",
13
+ "agentic"
14
+ ],
15
+ "homepage": "https://agentproto.sh/docs/aip-15",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/agentproto/ts"
19
+ },
20
+ "license": "MIT",
21
+ "type": "module",
22
+ "main": "dist/index.mjs",
23
+ "module": "dist/index.mjs",
24
+ "types": "dist/index.d.ts",
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "import": "./dist/index.mjs",
29
+ "default": "./dist/index.mjs"
30
+ },
31
+ "./package.json": "./package.json"
32
+ },
33
+ "files": [
34
+ "dist",
35
+ "README.md",
36
+ "LICENSE"
37
+ ],
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "dependencies": {
42
+ "@agentproto/driver": "0.1.1",
43
+ "@agentproto/tool": "0.1.1",
44
+ "@agentproto/workflow": "0.1.0-alpha.1"
45
+ },
46
+ "devDependencies": {
47
+ "@types/node": "^25.6.2",
48
+ "tsup": "^8.5.1",
49
+ "typescript": "^5.9.3",
50
+ "vitest": "^3.2.4",
51
+ "zod": "^4.4.3",
52
+ "@agentproto/tooling": "0.1.0-alpha.0"
53
+ },
54
+ "scripts": {
55
+ "dev": "tsup --watch",
56
+ "build": "tsup",
57
+ "clean": "rm -rf dist",
58
+ "check-types": "tsc --noEmit",
59
+ "test": "vitest run",
60
+ "test:watch": "vitest"
61
+ }
62
+ }