@tangle-network/agent-runtime 0.167.0 → 0.169.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/dist/graph.d.ts CHANGED
@@ -2,28 +2,6 @@ import { $l as MakeWorkerAgent, Gt as AgentGraph, If as DeliverableSpec, Qt as R
2
2
  import { H as SpawnJournal, K as Spend, V as SpawnEvent, i as Budget, j as ResultBlobStore, t as Agent, z as Scope } from "./types-DjVO-p7R.js";
3
3
  import { o as ExecutorConfig } from "./runtime-B0HZbuEv.js";
4
4
  import { AgentProfile } from "@tangle-network/agent-interface";
5
- //#region src/runtime/graph/condition.d.ts
6
- /** The leaf comparison operators; `exists`/`truthy` are unary, the rest compare against `value`. */
7
- declare const CONDITION_OPS: readonly ["eq", "neq", "gt", "gte", "lt", "lte", "in", "contains", "exists", "truthy"];
8
- type ConditionOp = (typeof CONDITION_OPS)[number];
9
- interface ConditionLeaf {
10
- /** Dotted path with `[N]` indexing into the guard context, e.g. `out.findings[0].severity`. */
11
- readonly path: string;
12
- readonly op: ConditionOp;
13
- readonly value?: unknown;
14
- }
15
- type Condition = ConditionLeaf | {
16
- readonly all: ReadonlyArray<Condition>;
17
- } | {
18
- readonly any: ReadonlyArray<Condition>;
19
- } | {
20
- readonly not: Condition;
21
- };
22
- /** Validate shape, bounds, and per-leaf path/operator rules; returns the input for chaining. */
23
- declare function validateCondition(raw: unknown, context: string): Condition;
24
- /** Walk a validated condition over a context to a boolean. Never throws on data shape. */
25
- declare function evaluateCondition(condition: Condition, context: unknown): boolean;
26
- //#endregion
27
5
  //#region src/runtime/graph/registry.d.ts
28
6
  /**
29
7
  * `Registry<T>` — the ONE name→thing shape for the graph engine.
@@ -163,6 +141,17 @@ interface NodeKind<Config = unknown, Effects extends ReadonlyArray<EffectName> =
163
141
  readonly host?: GraphHost;
164
142
  }) => Agent<unknown, unknown>;
165
143
  }
144
+ /**
145
+ * A kind of ANY config shape — what a registry holds and what every engine signature accepts.
146
+ *
147
+ * `NodeKind<Config>` puts `Config` in a parameter position (`run({ config })`), so it is
148
+ * contravariant: an array of differently-configured kinds is not assignable to
149
+ * `ReadonlyArray<NodeKind<unknown>>`, and every caller composing a heterogeneous kind set would
150
+ * need a cast. That cost belongs here, once, not at each consumer: a registry is heterogeneous by
151
+ * definition, and each kind validates its own config at its own boundary through
152
+ * `validateConfig`, which is where the type is actually enforced.
153
+ */
154
+ type AnyNodeKind = NodeKind<any, ReadonlyArray<EffectName>>;
166
155
  /** Per-node flags a graph author sets; they are node properties, not kinds (agent-runtime#970). */
167
156
  interface NodeFlags {
168
157
  /** An oracle — a judge, grader, auditor, trace analyst — may be bound only by an `analyzes`
@@ -176,7 +165,7 @@ interface NodeFlags {
176
165
  }
177
166
  /** Validate a kind declaration at registration — so a malformed kind is refused by name once,
178
167
  * not at the first node that uses it. */
179
- declare function validateNodeKind(kind: NodeKind, context?: string): NodeKind;
168
+ declare function validateNodeKind(kind: AnyNodeKind, context?: string): AnyNodeKind;
180
169
  /** The handle a graph writes to name this kind. */
181
170
  declare function kindHandle(kind: Pick<NodeKind, 'id' | 'version'>): RegistryHandle;
182
171
  /**
@@ -186,6 +175,97 @@ declare function kindHandle(kind: Pick<NodeKind, 'id' | 'version'>): RegistryHan
186
175
  */
187
176
  declare function narrowEffects<Effects extends ReadonlyArray<EffectName>>(declared: Effects, provided: Readonly<Record<string, unknown>>, context: string): EffectContext<Effects>;
188
177
  //#endregion
178
+ //#region src/runtime/graph/codemode.d.ts
179
+ /** One operation the authored program may call, and the line the model is shown about it. */
180
+ interface CodeOperation {
181
+ /** Identifier the program calls, e.g. `search`. Must be a valid JS identifier. */
182
+ readonly name: string;
183
+ /** The signature and meaning, as the model sees it: `search(query: string): Promise<Hit[]>`. */
184
+ readonly signature: string;
185
+ readonly description: string;
186
+ /** What the call actually does. A spend it reports is added to the node's settlement. */
187
+ readonly call: (...args: ReadonlyArray<unknown>) => Promise<CodeOperationResult> | CodeOperationResult;
188
+ }
189
+ /** An operation's answer. `spend` is optional; an operation that costs nothing omits it. */
190
+ interface CodeOperationResult {
191
+ readonly value: unknown;
192
+ readonly spend?: Spend;
193
+ }
194
+ /** What a host's `codeRunner` effect must do: run authored source with `api` in scope, and answer
195
+ * what it returned. The host decides WHERE that happens — in process, or jailed. */
196
+ interface CodeRunner {
197
+ run(args: {
198
+ readonly code: string;
199
+ readonly api: Readonly<Record<string, (...args: ReadonlyArray<unknown>) => Promise<unknown>>>;
200
+ readonly signal: AbortSignal;
201
+ }): Promise<unknown>;
202
+ }
203
+ /** What a host's `model` effect must do: answer one prompt with text. */
204
+ interface CodeAuthor {
205
+ complete(args: {
206
+ readonly prompt: string;
207
+ readonly profile: AgentProfile;
208
+ readonly signal: AbortSignal;
209
+ }): Promise<{
210
+ readonly text: string;
211
+ readonly spend?: Spend;
212
+ }>;
213
+ }
214
+ interface CodeModeConfig {
215
+ readonly operations: ReadonlyArray<CodeOperation>;
216
+ /** What the program must accomplish, in the author's words. Appended to the generated API doc. */
217
+ readonly task: string;
218
+ /** Import specifiers the authored code may name. Empty (the default) bans every import. */
219
+ readonly allowedImports?: ReadonlyArray<string>;
220
+ }
221
+ /**
222
+ * Refuse the obvious escapes in authored source. A LINT, not a sandbox: it reads text and cannot
223
+ * constrain what running code does. Generalized from `strategy-author.ts`'s contract check, which
224
+ * has guarded agent-authored optimization strategies since 0.60.
225
+ */
226
+ declare function assertAuthoredCode(code: string, options?: {
227
+ readonly allowedImports?: ReadonlyArray<string>;
228
+ readonly context?: string;
229
+ }): void;
230
+ /** The API doc the model is shown — generated from the grant, so the two cannot disagree. */
231
+ declare function renderCodeApi(config: CodeModeConfig): string;
232
+ /** Pull the first fenced block out of a model reply; the whole reply if it carries no fence. */
233
+ declare function extractCodeBlock(reply: string): string;
234
+ /**
235
+ * A node that asks a model for a program and runs it. Declares the two effects it cannot supply
236
+ * itself — `model` (who writes the code) and `codeRunner` (where it runs) — so the host owns both.
237
+ */
238
+ declare function codemodeKind(): NodeKind<CodeModeConfig, readonly ['model', 'codeRunner']>;
239
+ /**
240
+ * An in-process `codeRunner`: builds the authored body as a function with the granted API in
241
+ * scope. **A development convenience, not a security boundary** — `assertAuthoredCode` is a lint,
242
+ * and code running in this process can reach whatever the process can. Supply a jailed runner for
243
+ * code you did not write.
244
+ */
245
+ declare function inlineCodeRunner(): CodeRunner;
246
+ //#endregion
247
+ //#region src/runtime/graph/condition.d.ts
248
+ /** The leaf comparison operators; `exists`/`truthy` are unary, the rest compare against `value`. */
249
+ declare const CONDITION_OPS: readonly ["eq", "neq", "gt", "gte", "lt", "lte", "in", "contains", "exists", "truthy"];
250
+ type ConditionOp = (typeof CONDITION_OPS)[number];
251
+ interface ConditionLeaf {
252
+ /** Dotted path with `[N]` indexing into the guard context, e.g. `out.findings[0].severity`. */
253
+ readonly path: string;
254
+ readonly op: ConditionOp;
255
+ readonly value?: unknown;
256
+ }
257
+ type Condition = ConditionLeaf | {
258
+ readonly all: ReadonlyArray<Condition>;
259
+ } | {
260
+ readonly any: ReadonlyArray<Condition>;
261
+ } | {
262
+ readonly not: Condition;
263
+ };
264
+ /** Validate shape, bounds, and per-leaf path/operator rules; returns the input for chaining. */
265
+ declare function validateCondition(raw: unknown, context: string): Condition;
266
+ /** Walk a validated condition over a context to a boolean. Never throws on data shape. */
267
+ declare function evaluateCondition(condition: Condition, context: unknown): boolean;
268
+ //#endregion
189
269
  //#region src/runtime/graph/projection.d.ts
190
270
  type Projection = {
191
271
  readonly path: string;
@@ -284,15 +364,15 @@ interface EngineGraphSpec {
284
364
  //#region src/runtime/graph/engine.d.ts
285
365
  interface GraphEngineOptions {
286
366
  /** Kinds to register beside the core set. A host adds its own here; nothing is global. */
287
- readonly kinds?: ReadonlyArray<NodeKind>;
367
+ readonly kinds?: ReadonlyArray<AnyNodeKind>;
288
368
  /** The host's effect table, by name. A kind receives only the effects it declared. */
289
369
  readonly effects?: Readonly<Record<EffectName, unknown>>;
290
370
  /** The core set. Injected so a test can substitute, and so the engine never imports a
291
371
  * backend-specific factory at module load. */
292
- readonly coreKinds: ReadonlyArray<NodeKind>;
372
+ readonly coreKinds: ReadonlyArray<AnyNodeKind>;
293
373
  }
294
374
  interface GraphEngine {
295
- readonly kinds: Registry<NodeKind>;
375
+ readonly kinds: Registry<AnyNodeKind>;
296
376
  readonly effects: Readonly<Record<EffectName, unknown>>;
297
377
  /** Every effect name any registered kind declares — what a host must provide for this engine's
298
378
  * whole kind set to be runnable. Listed, never discovered mid-run. */
@@ -363,6 +443,10 @@ type GraphRunReason = 'all-children-down' | 'budget-exhausted' | 'aborted' | 'dr
363
443
  interface GraphNodeSettle {
364
444
  readonly node: string;
365
445
  readonly visit: number;
446
+ /** Run-wide settle ordinal. `GraphRunResult.settles` is sorted by it, so the array reads in the
447
+ * order the run actually settled — not grouped by node, which is what a reader assumes and
448
+ * what the first consumer of this API tripped on. */
449
+ readonly seq: number;
366
450
  readonly status: 'done' | 'down';
367
451
  /** The node's completion check verdict; `undefined` when the node declares no check. */
368
452
  readonly valid?: boolean;
@@ -451,6 +535,10 @@ interface FoldNode {
451
535
  settles: GraphNodeSettle[];
452
536
  }
453
537
  interface GraphFoldState {
538
+ /** Next settle ordinal; the fold is the only writer, so replay reproduces the same order. */
539
+ settleSeq: {
540
+ value: number;
541
+ };
454
542
  readonly nodes: Map<string, FoldNode>;
455
543
  readonly edges: Map<string, FoldEdge>;
456
544
  /** Every node instance the journal knows, keyed by `<node>#<visit>`. */
@@ -710,5 +798,5 @@ declare function runEngineGraph(engine: GraphEngine, spec: EngineGraphSpec | Com
710
798
  */
711
799
  declare function createGraphRun(engine: GraphEngine, spec: EngineGraphSpec | CompiledGraph, task: string, options: GraphRunOptions): GraphRunHandle;
712
800
  //#endregion
713
- export { type AgentKindConfig, type BudgetMode, CONDITION_OPS, type CompiledEdge, type CompiledGraph, type CompiledNode, type Condition, type ConditionLeaf, type ConditionOp, DEFAULT_MAX_NODE_VISITS, ENGINE_WOKEN_SEQ_BASE, type EdgeLedger, type EffectContext, type EffectName, type EngineGraphEdge, type EngineGraphNode, type EngineGraphSpec, type FinalizerChoice, type FoldEdge, type FoldEdgeState, type FoldInstance, type FoldInstanceStatus, type FoldNode, type FoldSuspension, type GatingEdge, type GraphEdgeKind, type GraphEdgeTraversal, type GraphEngine, type GraphEngineOptions, type GraphFoldState, type GraphHost, type GraphNodeSettle, type GraphRunContext, type GraphRunHandle, type GraphRunOptions, type GraphRunReason, type GraphRunResult, JOIN_RULES, type JoinDecision, type JoinRule, type JsonSchema, MAX_MAX_NODE_VISITS, type NodeFlags, type NodeKind, type OnCrash, type PortSpec, type Projection, RUN_GRAPH_ROOT_KIND, type Registered, type Registry, type RegistryHandle, type ScriptBody, type ScriptKindConfig, type SubgraphKindConfig, type SupervisorKindConfig, type SuspensionRequest, admitPayload, agentKind, applyGraphFoldEvent, applyProjection, assembleGraphResult, compileGraph, createEdgeLedger, createGraphEngine, createGraphRun, createRegistry, decideJoin, emptyFoldState, evaluateCondition, foldGraphJournal, formatRegistryHandle, graphFromRunGraph, isEngineFired, isSuspensionRequest, kindHandle, materializeSettles, mintSuspensionToken, narrowEffects, openGraphRun, parseRegistryHandle, runEngineGraph, schemaAccepts, scriptKind, subgraphKind, supervisorKind, suspended, suspensionNodeId, tokenFromSuspensionNodeId, validateCondition, validateNodeKind, validateProjection };
801
+ export { type AgentKindConfig, type AnyNodeKind, type BudgetMode, CONDITION_OPS, type CodeAuthor, type CodeModeConfig, type CodeOperation, type CodeOperationResult, type CodeRunner, type CompiledEdge, type CompiledGraph, type CompiledNode, type Condition, type ConditionLeaf, type ConditionOp, DEFAULT_MAX_NODE_VISITS, ENGINE_WOKEN_SEQ_BASE, type EdgeLedger, type EffectContext, type EffectName, type EngineGraphEdge, type EngineGraphNode, type EngineGraphSpec, type FinalizerChoice, type FoldEdge, type FoldEdgeState, type FoldInstance, type FoldInstanceStatus, type FoldNode, type FoldSuspension, type GatingEdge, type GraphEdgeKind, type GraphEdgeTraversal, type GraphEngine, type GraphEngineOptions, type GraphFoldState, type GraphHost, type GraphNodeSettle, type GraphRunContext, type GraphRunHandle, type GraphRunOptions, type GraphRunReason, type GraphRunResult, JOIN_RULES, type JoinDecision, type JoinRule, type JsonSchema, MAX_MAX_NODE_VISITS, type NodeFlags, type NodeKind, type OnCrash, type PortSpec, type Projection, RUN_GRAPH_ROOT_KIND, type Registered, type Registry, type RegistryHandle, type ScriptBody, type ScriptKindConfig, type SubgraphKindConfig, type SupervisorKindConfig, type SuspensionRequest, admitPayload, agentKind, applyGraphFoldEvent, applyProjection, assembleGraphResult, assertAuthoredCode, codemodeKind, compileGraph, createEdgeLedger, createGraphEngine, createGraphRun, createRegistry, decideJoin, emptyFoldState, evaluateCondition, extractCodeBlock, foldGraphJournal, formatRegistryHandle, graphFromRunGraph, inlineCodeRunner, isEngineFired, isSuspensionRequest, kindHandle, materializeSettles, mintSuspensionToken, narrowEffects, openGraphRun, parseRegistryHandle, renderCodeApi, runEngineGraph, schemaAccepts, scriptKind, subgraphKind, supervisorKind, suspended, suspensionNodeId, tokenFromSuspensionNodeId, validateCondition, validateNodeKind, validateProjection };
714
802
  //# sourceMappingURL=graph.d.ts.map
package/dist/graph.js CHANGED
@@ -4,6 +4,188 @@ import { t as addSpend } from "./util-D6ZEuBMi.js";
4
4
  import { N as createBudgetPool, U as createExecutorRegistry, a as uncertainSpawnBudgets, i as sumMeasuredSpendFromEvents, l as runFinalizer, o as bestDelivered, p as createScope, r as maxSeqOf, s as collectDelivered } from "./supervisor-B-mmmiOU.js";
5
5
  import { i as workerFromBackend, s as supervisorAgent } from "./supervise-rEE46ruH.js";
6
6
  import { t as GraphEdgeCapError } from "./graph-ZDMygFIo.js";
7
+ //#region src/runtime/graph/codemode.ts
8
+ const IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/u;
9
+ /**
10
+ * Refuse the obvious escapes in authored source. A LINT, not a sandbox: it reads text and cannot
11
+ * constrain what running code does. Generalized from `strategy-author.ts`'s contract check, which
12
+ * has guarded agent-authored optimization strategies since 0.60.
13
+ */
14
+ function assertAuthoredCode(code, options = {}) {
15
+ const context = options.context ?? "authored code";
16
+ const allowed = options.allowedImports ?? [];
17
+ for (const line of code.split("\n")) {
18
+ if (!/^\s*import\s/.test(line)) continue;
19
+ if (!allowed.some((specifier) => line.includes(`'${specifier}'`) || line.includes(`"${specifier}"`))) throw new ValidationError(`${context} rejected: foreign import — ${line.trim().slice(0, 120)}${allowed.length === 0 ? " (no import is allowed here)" : ` (allowed: ${allowed.join(", ")})`}`);
20
+ }
21
+ for (const [pattern, what] of [
22
+ [/\brequire\s*\(/, "require()"],
23
+ [/\bimport\s*\(/, "dynamic import()"],
24
+ [/\beval\s*\(/, "eval()"],
25
+ [/new\s+Function\s*\(/, "new Function()"],
26
+ [/\bprocess\s*[.[]/, "process access"],
27
+ [/\bglobalThis\s*[.[]/, "globalThis access"],
28
+ [/\bfetch\s*\(/, "network access"],
29
+ [/child_process|node:fs|node:net|node:http|worker_threads/, "node builtin access"]
30
+ ]) if (pattern.test(code)) throw new ValidationError(`${context} rejected: ${what}`);
31
+ }
32
+ /** The API doc the model is shown — generated from the grant, so the two cannot disagree. */
33
+ function renderCodeApi(config) {
34
+ return [
35
+ "Write ONE async function body. It may call only these operations:",
36
+ "",
37
+ ...config.operations.map((operation) => ` ${operation.signature}\n // ${operation.description}`),
38
+ "",
39
+ "Return the result as the body's return value. No imports, no require, no process, no fetch.",
40
+ "Reply with a single fenced code block and nothing else.",
41
+ "",
42
+ `TASK: ${config.task}`
43
+ ].join("\n");
44
+ }
45
+ /** Pull the first fenced block out of a model reply; the whole reply if it carries no fence. */
46
+ function extractCodeBlock(reply) {
47
+ const code = (/```(?:[a-zA-Z]*)\n([\s\S]*?)```/u.exec(reply)?.[1] ?? reply).trim();
48
+ if (code.length === 0) throw new ValidationError("codemode: the model returned no code");
49
+ return code;
50
+ }
51
+ /**
52
+ * A node that asks a model for a program and runs it. Declares the two effects it cannot supply
53
+ * itself — `model` (who writes the code) and `codeRunner` (where it runs) — so the host owns both.
54
+ */
55
+ function codemodeKind() {
56
+ return {
57
+ id: "codemode",
58
+ version: 1,
59
+ description: "Ask a model for a program over a granted API, then run it as one node.",
60
+ validateConfig: (raw, context) => {
61
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) throw new ValidationError(`${context}: codemode config must be an object`);
62
+ const config = raw;
63
+ if (typeof config.task !== "string" || config.task.trim().length === 0) throw new ValidationError(`${context}: codemode config.task must be a non-empty string`);
64
+ if (!Array.isArray(config.operations) || config.operations.length === 0) throw new ValidationError(`${context}: codemode config.operations must grant at least one operation`);
65
+ const seen = /* @__PURE__ */ new Set();
66
+ for (const operation of config.operations) {
67
+ if (!IDENTIFIER.test(operation?.name ?? "")) throw new ValidationError(`${context}: operation name ${JSON.stringify(operation?.name)} is not a JS identifier`);
68
+ if (seen.has(operation.name)) throw new ValidationError(`${context}: duplicate operation ${operation.name}`);
69
+ seen.add(operation.name);
70
+ if (typeof operation.call !== "function") throw new ValidationError(`${context}: operation ${operation.name} has no call`);
71
+ }
72
+ return {
73
+ operations: config.operations,
74
+ task: config.task,
75
+ ...config.allowedImports === void 0 ? {} : { allowedImports: config.allowedImports }
76
+ };
77
+ },
78
+ configSchema: {
79
+ type: "object",
80
+ properties: {
81
+ task: { type: "string" },
82
+ operations: { type: "array" }
83
+ },
84
+ required: ["task", "operations"]
85
+ },
86
+ inputs: [{
87
+ name: "context",
88
+ schema: {}
89
+ }],
90
+ outputs: [],
91
+ effects: ["model", "codeRunner"],
92
+ onCrash: "restart",
93
+ budget: "metered",
94
+ run: ({ config, profile, inputs, effects }) => {
95
+ const author = effects.model;
96
+ const runner = effects.codeRunner;
97
+ let artifact;
98
+ return {
99
+ name: profile.name ?? "codemode",
100
+ act: () => Promise.reject(new ValidationError("codemode: act() is not the execution path")),
101
+ executorSpec: {
102
+ profile,
103
+ harness: null,
104
+ executor: {
105
+ runtime: "inline",
106
+ async execute(task, signal) {
107
+ const spends = [];
108
+ const prompt = [
109
+ renderCodeApi(config),
110
+ inputs.context === void 0 ? "" : `\nCONTEXT: ${JSON.stringify(inputs.context)}`,
111
+ typeof task === "string" && task.length > 0 ? `\n${task}` : ""
112
+ ].filter((part) => part.length > 0).join("\n");
113
+ const authored = await author.complete({
114
+ prompt,
115
+ profile,
116
+ signal
117
+ });
118
+ if (authored.spend) spends.push(authored.spend);
119
+ const code = extractCodeBlock(authored.text);
120
+ assertAuthoredCode(code, {
121
+ ...config.allowedImports === void 0 ? {} : { allowedImports: config.allowedImports },
122
+ context: `codemode ${JSON.stringify(profile.name ?? "node")}`
123
+ });
124
+ const api = {};
125
+ for (const operation of config.operations) api[operation.name] = async (...args) => {
126
+ const result = await operation.call(...args);
127
+ if (result?.spend) spends.push(result.spend);
128
+ return result?.value;
129
+ };
130
+ const out = await runner.run({
131
+ code,
132
+ api: Object.freeze(api),
133
+ signal
134
+ });
135
+ artifact = {
136
+ outRef: contentAddress({ codemode: out }),
137
+ out,
138
+ spent: totalSpend(spends)
139
+ };
140
+ return artifact;
141
+ },
142
+ teardown: () => Promise.resolve({ destroyed: true }),
143
+ resultArtifact: () => {
144
+ if (!artifact) throw new ValidationError("codemode: resultArtifact() read before execute()");
145
+ return artifact;
146
+ }
147
+ }
148
+ }
149
+ };
150
+ }
151
+ };
152
+ }
153
+ /** The node's spend is the model call plus every operation that reported one. An operation that
154
+ * reports nothing is not assumed free — it contributes an UNKNOWN mark, like the kernel's own. */
155
+ function totalSpend(parts) {
156
+ return parts.reduce((total, part) => ({
157
+ iterations: total.iterations + (part.iterations ?? 0),
158
+ tokens: {
159
+ input: total.tokens.input + (part.tokens?.input ?? 0),
160
+ output: total.tokens.output + (part.tokens?.output ?? 0),
161
+ ...part.tokens?.tokensKnown === false ? { tokensKnown: false } : {}
162
+ },
163
+ usd: total.usd + (part.usd ?? 0),
164
+ ...part.usdKnown === false ? { usdKnown: false } : {},
165
+ ms: total.ms + (part.ms ?? 0)
166
+ }), {
167
+ iterations: 1,
168
+ tokens: {
169
+ input: 0,
170
+ output: 0
171
+ },
172
+ usd: 0,
173
+ ms: 0
174
+ });
175
+ }
176
+ /**
177
+ * An in-process `codeRunner`: builds the authored body as a function with the granted API in
178
+ * scope. **A development convenience, not a security boundary** — `assertAuthoredCode` is a lint,
179
+ * and code running in this process can reach whatever the process can. Supply a jailed runner for
180
+ * code you did not write.
181
+ */
182
+ function inlineCodeRunner() {
183
+ return { async run({ code, api }) {
184
+ const names = Object.keys(api);
185
+ return new Function(...names, `"use strict"; return (async () => { ${code} })()`)(...names.map((name) => api[name]));
186
+ } };
187
+ }
188
+ //#endregion
7
189
  //#region src/runtime/graph/condition.ts
8
190
  /**
9
191
  * The ONE predicate tree: every guard in a graph — an edge `guard`, a filter projection's
@@ -632,6 +814,7 @@ function emptyFoldState(compiled) {
632
814
  capped: false
633
815
  });
634
816
  return {
817
+ settleSeq: { value: 0 },
635
818
  nodes,
636
819
  edges,
637
820
  instances: /* @__PURE__ */ new Map(),
@@ -681,6 +864,7 @@ function applyGraphFoldEvent(state, ev, compiled) {
681
864
  node: instance.node,
682
865
  visit: instance.visit,
683
866
  status: ev.status,
867
+ seq: state.settleSeq.value++,
684
868
  ...ev.outRef !== void 0 ? { outRef: ev.outRef } : {},
685
869
  ...ev.reason !== void 0 ? { reason: ev.reason } : {}
686
870
  };
@@ -776,6 +960,7 @@ function applyGraphFoldEvent(state, ev, compiled) {
776
960
  node: suspension.node,
777
961
  visit: instance.visit,
778
962
  status: "down",
963
+ seq: state.settleSeq.value++,
779
964
  reason: "suspension expired"
780
965
  };
781
966
  instance.settle = settle;
@@ -790,6 +975,7 @@ function applyGraphFoldEvent(state, ev, compiled) {
790
975
  node: suspension.node,
791
976
  visit: instance.visit,
792
977
  status: "done",
978
+ seq: state.settleSeq.value++,
793
979
  ...ev.outRef !== void 0 ? { outRef: ev.outRef } : {}
794
980
  };
795
981
  instance.settle = settle;
@@ -1282,7 +1468,7 @@ async function materializeSettles(compiled, state, blobs, outCache) {
1282
1468
  ...valid !== void 0 ? { valid } : {}
1283
1469
  };
1284
1470
  };
1285
- return Promise.all([...compiled.nodes.keys()].flatMap((id) => state.nodes.get(id)?.settles ?? []).map(rehydrate));
1471
+ return Promise.all([...compiled.nodes.keys()].flatMap((id) => state.nodes.get(id)?.settles ?? []).sort((a, b) => a.seq - b.seq).map(rehydrate));
1286
1472
  }
1287
1473
  /** Turn a finished run into its result: rehydrate, reduce the terminals, classify a no-winner. */
1288
1474
  async function assembleGraphResult(args) {
@@ -2068,6 +2254,6 @@ async function runGraphLoop(engine, compiled, task, options, wakes, onWakeSignal
2068
2254
  });
2069
2255
  }
2070
2256
  //#endregion
2071
- export { CONDITION_OPS, DEFAULT_MAX_NODE_VISITS, ENGINE_WOKEN_SEQ_BASE, JOIN_RULES, MAX_MAX_NODE_VISITS, RUN_GRAPH_ROOT_KIND, admitPayload, agentKind, applyGraphFoldEvent, applyProjection, assembleGraphResult, compileGraph, createEdgeLedger, createGraphEngine, createGraphRun, createRegistry, decideJoin, emptyFoldState, evaluateCondition, foldGraphJournal, formatRegistryHandle, graphFromRunGraph, isEngineFired, isSuspensionRequest, kindHandle, materializeSettles, mintSuspensionToken, narrowEffects, openGraphRun, parseRegistryHandle, runEngineGraph, schemaAccepts, scriptKind, subgraphKind, supervisorKind, suspended, suspensionNodeId, tokenFromSuspensionNodeId, validateCondition, validateNodeKind, validateProjection };
2257
+ export { CONDITION_OPS, DEFAULT_MAX_NODE_VISITS, ENGINE_WOKEN_SEQ_BASE, JOIN_RULES, MAX_MAX_NODE_VISITS, RUN_GRAPH_ROOT_KIND, admitPayload, agentKind, applyGraphFoldEvent, applyProjection, assembleGraphResult, assertAuthoredCode, codemodeKind, compileGraph, createEdgeLedger, createGraphEngine, createGraphRun, createRegistry, decideJoin, emptyFoldState, evaluateCondition, extractCodeBlock, foldGraphJournal, formatRegistryHandle, graphFromRunGraph, inlineCodeRunner, isEngineFired, isSuspensionRequest, kindHandle, materializeSettles, mintSuspensionToken, narrowEffects, openGraphRun, parseRegistryHandle, renderCodeApi, runEngineGraph, schemaAccepts, scriptKind, subgraphKind, supervisorKind, suspended, suspensionNodeId, tokenFromSuspensionNodeId, validateCondition, validateNodeKind, validateProjection };
2072
2258
 
2073
2259
  //# sourceMappingURL=graph.js.map