@noetic-tools/types 3.1.0 → 3.2.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/README.md CHANGED
@@ -8,14 +8,14 @@ on: the conversation `Item` data model, LLM configuration (`LlmProviderConfig`,
8
8
  platform adapter interfaces (`FsAdapter`, `ShellAdapter`, `SubprocessAdapter`),
9
9
  the error model, and the `Item` schema.
10
10
 
11
- It is consumed by [`@noetic-tools/memory`](https://www.npmjs.com/package/@noetic-tools/memory)
11
+ It is consumed by [`@noetic-tools/context`](https://www.npmjs.com/package/@noetic-tools/context)
12
12
  and [`@noetic-tools/core`](https://www.npmjs.com/package/@noetic-tools/core),
13
13
  both of which re-export the parts relevant to their public surface. Application
14
14
  code normally imports these types from `@noetic-tools/core` rather than from
15
15
  this package directly.
16
16
 
17
- The `MemoryLayer` contract is additionally exported at the
18
- `@noetic-tools/types/contract` subpath for memory-layer authors who want the
17
+ The `ContextLayer` contract is additionally exported at the
18
+ `@noetic-tools/types/contract` subpath for context-layer authors who want the
19
19
  contract without the rest of the vocabulary.
20
20
 
21
21
  ## License
@@ -43,12 +43,12 @@ function formatMessage(error) {
43
43
  switch (error.kind) {
44
44
  case 'step_failed':
45
45
  return `Step '${error.stepId}' failed: ${error.cause.message}`;
46
- case 'llm_refused':
47
- return `LLM refused at step '${error.stepId}': ${error.refusal}`;
48
- case 'llm_parse_error':
49
- return `LLM parse error at step '${error.stepId}': failed to parse output`;
50
- case 'llm_rate_limit':
51
- return `LLM rate limited at step '${error.stepId}'${error.retryAfter ? ` (retry after ${error.retryAfter}ms)` : ''}`;
46
+ case 'model_refused':
47
+ return `Model refused at step '${error.stepId}': ${error.refusal}`;
48
+ case 'model_parse_error':
49
+ return `Model parse error at step '${error.stepId}': failed to parse output`;
50
+ case 'model_rate_limit':
51
+ return `Model rate limited at step '${error.stepId}'${error.retryAfter ? ` (retry after ${error.retryAfter}ms)` : ''}`;
52
52
  case 'fork_partial':
53
53
  return `Fork '${error.stepId}' partial failure: ${error.succeeded.length} succeeded, ${error.failed.length} failed`;
54
54
  case 'channel_timeout':
@@ -66,7 +66,7 @@ function formatMessage(error) {
66
66
  ? `Item type '${error.itemType}' did not match any registered item extension schema.`
67
67
  : `Item did not match any registered ${error.category} extension schema.`;
68
68
  case 'handle_evicted':
69
- return `Subprocess handle '${error.handleId}' evicted (step '${error.stepId}'): adapter returned null for ${error.gracePeriodMs}ms`;
69
+ return `Subprocess handle '${error.handleId}' evicted (step '${error.stepId}'): adapter returned null for ${error.gracePeriod}ms`;
70
70
  default: {
71
71
  const _exhaustive = error;
72
72
  void _exhaustive;
package/dist/index.d.ts CHANGED
@@ -2,7 +2,6 @@
2
2
  * @noetic-tools/types — foundational type contracts and primitives shared
3
3
  * across the Noetic framework.
4
4
  */
5
- export * from './deprecated.js';
6
5
  export * from './errors/noetic-config-error.js';
7
6
  export * from './errors/noetic-error.js';
8
7
  export * from './schemas/item.js';
@@ -11,6 +10,7 @@ export * from './types/channel.js';
11
10
  export * from './types/common.js';
12
11
  export * from './types/context.js';
13
12
  export * from './types/context-cache.js';
13
+ export * from './types/context-harness.js';
14
14
  export * from './types/context-layer.js';
15
15
  export * from './types/context-parts/item-log.js';
16
16
  export * from './types/context-parts/layer-usage.js';
@@ -23,6 +23,7 @@ export * from './types/items.js';
23
23
  export * from './types/observability.js';
24
24
  export * from './types/output-codec.js';
25
25
  export * from './types/runtime.js';
26
+ export * from './types/schema.js';
26
27
  export * from './types/shell-adapter.js';
27
28
  export * from './types/steering.js';
28
29
  export * from './types/step.js';
package/dist/index.js CHANGED
@@ -2,7 +2,6 @@
2
2
  * @noetic-tools/types — foundational type contracts and primitives shared
3
3
  * across the Noetic framework.
4
4
  */
5
- export * from './deprecated.js';
6
5
  export * from './errors/noetic-config-error.js';
7
6
  export * from './errors/noetic-error.js';
8
7
  export * from './schemas/item.js';
@@ -11,6 +10,7 @@ export * from './types/channel.js';
11
10
  export * from './types/common.js';
12
11
  export * from './types/context.js';
13
12
  export * from './types/context-cache.js';
13
+ export * from './types/context-harness.js';
14
14
  export * from './types/context-layer.js';
15
15
  export * from './types/context-parts/item-log.js';
16
16
  export * from './types/context-parts/layer-usage.js';
@@ -23,6 +23,7 @@ export * from './types/items.js';
23
23
  export * from './types/observability.js';
24
24
  export * from './types/output-codec.js';
25
25
  export * from './types/runtime.js';
26
+ export * from './types/schema.js';
26
27
  export * from './types/shell-adapter.js';
27
28
  export * from './types/steering.js';
28
29
  export * from './types/step.js';
@@ -2,8 +2,8 @@
2
2
  * Zod schemas for JSON-serialisable workflow definitions.
3
3
  *
4
4
  * A `WorkflowDocument` is a portable, JSON-safe representation of a noetic
5
- * step tree. It covers every step kind. The `run` node carries its body as a
6
- * code STRING (not an in-process closure) dispatched through a subprocess
5
+ * step tree. It covers every step kind. The `runCode` node carries its body as
6
+ * a code STRING (not an in-process closure) dispatched through a subprocess
7
7
  * adapter, keeping the document JSON-safe. The hydrator in
8
8
  * `@noetic-tools/core` (`builders/workflow-hydrator.ts`) converts a validated
9
9
  * document back into live `Step` objects via the existing builders.
@@ -27,9 +27,11 @@ export type UntilPredicate = {
27
27
  usd: number;
28
28
  } | {
29
29
  kind: 'maxDuration';
30
- ms: number;
30
+ duration: number;
31
31
  } | {
32
32
  kind: 'noToolCalls';
33
+ } | {
34
+ kind: 'never';
33
35
  } | {
34
36
  kind: 'outputContains';
35
37
  marker: string;
@@ -48,9 +50,9 @@ export declare const MergeStrategy: {
48
50
  readonly First: 'first';
49
51
  readonly Concat: 'concat';
50
52
  };
51
- /** @public Named merge strategy for fork nodes. */
53
+ /** @public Named merge strategy for inParallel nodes. */
52
54
  export type MergeStrategy = (typeof MergeStrategy)[keyof typeof MergeStrategy];
53
- /** @public Zod schema for the named merge strategy used by `fork` nodes. */
55
+ /** @public Zod schema for the named merge strategy used by `inParallel` nodes. */
54
56
  export declare const MergeStrategySchema: z.ZodEnum<{
55
57
  concat: "concat";
56
58
  first: "first";
@@ -63,7 +65,7 @@ declare const ModelParamsSchema: z.ZodObject<{
63
65
  stopSequences: z.ZodOptional<z.ZodArray<z.ZodString>>;
64
66
  }, z.core.$strip>;
65
67
  /**
66
- * A uniform tool entry on an `llm` node. Every entry is an object keyed by
68
+ * A uniform tool entry on a `callModel` node. Every entry is an object keyed by
67
69
  * `type`:
68
70
  * - A CLIENT tool is `{ type: "<registered-tool-name>" }`. The hydrator
69
71
  * resolves `type` against the tool registry; `parameters` (if present) is
@@ -76,11 +78,11 @@ declare const ModelParamsSchema: z.ZodObject<{
76
78
  * Server vs client is decided by the `type` value (a reserved `openrouter:*`
77
79
  * server-tool literal vs an arbitrary tool name), not by the entry's shape.
78
80
  */
79
- declare const LlmToolEntrySchema: z.ZodObject<{
81
+ declare const CallModelToolEntrySchema: z.ZodObject<{
80
82
  type: z.ZodString;
81
83
  parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
82
84
  }, z.core.$strip>;
83
- /** Retry policy for a `run` node, mirroring `RetryPolicy` in `@noetic-tools/types`. */
85
+ /** Retry policy for a `runCode` node, mirroring `RetryPolicy` in `@noetic-tools/types`. */
84
86
  declare const RetryPolicySchema: z.ZodObject<{
85
87
  maxAttempts: z.ZodNumber;
86
88
  backoff: z.ZodEnum<{
@@ -115,7 +117,7 @@ interface WorkflowNodeBase {
115
117
  id: string;
116
118
  }
117
119
  /**
118
- * A reference to a streaming `OutputCodec` for an `llm` node's structured
120
+ * A reference to a streaming `OutputCodec` for a `callModel` node's structured
119
121
  * output. The hydrator resolves `library` from `HydrationContext.uiLibraries`
120
122
  * to a live codec (e.g. `openUi(myLibrary)` from `@noetic-tools/openui`), the
121
123
  * same registry-resolution pattern sub-harness nodes use for adapters. Kept a
@@ -127,8 +129,8 @@ export interface OutputCodecRef {
127
129
  /** Registry key resolved from `HydrationContext.uiLibraries`. */
128
130
  library: string;
129
131
  }
130
- export interface LlmWorkflowNode extends WorkflowNodeBase {
131
- kind: 'llm';
132
+ export interface CallModelWorkflowNode extends WorkflowNodeBase {
133
+ kind: 'callModel';
132
134
  model?: string;
133
135
  instructions: string;
134
136
  /**
@@ -138,26 +140,27 @@ export interface LlmWorkflowNode extends WorkflowNodeBase {
138
140
  * parameters?: {...} }` (executed by the provider). Client vs server is
139
141
  * decided by the `type` value.
140
142
  */
141
- tools?: z.infer<typeof LlmToolEntrySchema>[];
143
+ tools?: z.infer<typeof CallModelToolEntrySchema>[];
142
144
  params?: z.infer<typeof ModelParamsSchema>;
143
145
  /** Streaming output-codec reference, resolved from `HydrationContext.uiLibraries`. */
144
146
  output?: OutputCodecRef;
145
147
  }
146
- export interface ToolWorkflowNode extends WorkflowNodeBase {
147
- kind: 'tool';
148
+ export interface InvokeToolWorkflowNode extends WorkflowNodeBase {
149
+ kind: 'invokeTool';
148
150
  toolName: string;
149
151
  args?: Record<string, unknown>;
150
152
  }
151
153
  /**
152
- * A node that runs a serialised code body. Unlike the programmatic `step.run`
153
- * (which carries a closure), the JSON form carries `execute` as a code STRING.
154
+ * A node that runs a serialised code body. Unlike the programmatic
155
+ * `step.runCode` (which carries a closure), the JSON form carries `execute` as
156
+ * a code STRING.
154
157
  * The code is never eval'd in-process (Cloudflare Workers forbid eval); it is
155
158
  * dispatched through a subprocess adapter (`ctx.subprocess`, or a named adapter
156
159
  * resolved by ref). Execution therefore requires a subprocess adapter capable
157
160
  * of running the code and returning its stdout.
158
161
  */
159
- export interface RunWorkflowNode extends WorkflowNodeBase {
160
- kind: 'run';
162
+ export interface RunCodeWorkflowNode extends WorkflowNodeBase {
163
+ kind: 'runCode';
161
164
  /** Source code executed in the subprocess. Receives the step input on stdin. */
162
165
  execute: string;
163
166
  /** Optional retry policy applied to the step. */
@@ -165,17 +168,17 @@ export interface RunWorkflowNode extends WorkflowNodeBase {
165
168
  /** Named subprocess adapter ref; defaults to `ctx.subprocess` when omitted. */
166
169
  subprocess?: string;
167
170
  }
168
- export interface BranchRoute {
171
+ export interface ConditionalRoute {
169
172
  match: string;
170
173
  target: WorkflowNode;
171
174
  }
172
- export interface BranchWorkflowNode extends WorkflowNodeBase {
173
- kind: 'branch';
174
- routes: BranchRoute[];
175
+ export interface ConditionalWorkflowNode extends WorkflowNodeBase {
176
+ kind: 'conditional';
177
+ routes: ConditionalRoute[];
175
178
  default?: WorkflowNode;
176
179
  }
177
- export interface ForkWorkflowNode extends WorkflowNodeBase {
178
- kind: 'fork';
180
+ export interface InParallelWorkflowNode extends WorkflowNodeBase {
181
+ kind: 'inParallel';
179
182
  mode: 'race' | 'all' | 'settle';
180
183
  /**
181
184
  * Static fan-out: one child per entry. Mutually exclusive with `each` —
@@ -188,8 +191,8 @@ export interface ForkWorkflowNode extends WorkflowNodeBase {
188
191
  */
189
192
  each?: WorkflowNode;
190
193
  /**
191
- * Selector key into the fork input (parsed as JSON) locating the array to
192
- * fan out over. When omitted, the input string itself is parsed as a JSON
194
+ * Selector key into the inParallel input (parsed as JSON) locating the array
195
+ * to fan out over. When omitted, the input string itself is parsed as a JSON
193
196
  * array. Only meaningful with `each`.
194
197
  */
195
198
  over?: string;
@@ -202,14 +205,14 @@ export interface SpawnWorkflowNode extends WorkflowNodeBase {
202
205
  timeout?: number;
203
206
  /**
204
207
  * Memory layers the child runs with, by registered name (resolved from
205
- * `HydrationContext.layers`, like `provide`). Omit to inherit the parent's
206
- * layers — the default spawn behaviour. Naming layers here REPLACES the
207
- * inherited set for the child, so list every layer the child needs.
208
+ * `HydrationContext.layers`, like `withContext`). Omit to inherit the
209
+ * parent's layers — the default spawn behaviour. Naming layers here REPLACES
210
+ * the inherited set for the child, so list every layer the child needs.
208
211
  */
209
212
  layers?: string[];
210
213
  }
211
- export interface ProvideWorkflowNode extends WorkflowNodeBase {
212
- kind: 'provide';
214
+ export interface WithContextWorkflowNode extends WorkflowNodeBase {
215
+ kind: 'withContext';
213
216
  child: WorkflowNode;
214
217
  layers: string[];
215
218
  }
@@ -223,10 +226,10 @@ export interface SequenceWorkflowNode extends WorkflowNodeBase {
223
226
  kind: 'sequence';
224
227
  steps: WorkflowNode[];
225
228
  }
226
- export interface EveryWorkflowNode extends WorkflowNodeBase {
227
- kind: 'every';
229
+ export interface ScheduleWorkflowNode extends WorkflowNodeBase {
230
+ kind: 'schedule';
228
231
  step: WorkflowNode;
229
- ms: number;
232
+ interval: number;
230
233
  onError?: 'continue' | 'fail';
231
234
  }
232
235
  /**
@@ -256,7 +259,7 @@ export interface SubflowWorkflowNode extends WorkflowNodeBase {
256
259
  input?: string;
257
260
  }
258
261
  /** @public Discriminated union of all JSON-serialisable workflow node kinds. */
259
- export type WorkflowNode = LlmWorkflowNode | ToolWorkflowNode | RunWorkflowNode | BranchWorkflowNode | ForkWorkflowNode | SpawnWorkflowNode | ProvideWorkflowNode | LoopWorkflowNode | SequenceWorkflowNode | EveryWorkflowNode | SubflowWorkflowNode | SubHarnessWorkflowNode;
262
+ export type WorkflowNode = CallModelWorkflowNode | InvokeToolWorkflowNode | RunCodeWorkflowNode | ConditionalWorkflowNode | InParallelWorkflowNode | SpawnWorkflowNode | WithContextWorkflowNode | LoopWorkflowNode | SequenceWorkflowNode | ScheduleWorkflowNode | SubflowWorkflowNode | SubHarnessWorkflowNode;
260
263
  /** @public Zod schema validating a single `WorkflowNode` (any JSON-safe kind). */
261
264
  export declare const WorkflowNodeSchema: z.ZodType<WorkflowNode>;
262
265
  /** @public Top-level envelope for a JSON workflow definition. */
@@ -290,7 +293,7 @@ export interface WorkflowGraph {
290
293
  export declare function workflowGraph(root: WorkflowNode): WorkflowGraph;
291
294
  /**
292
295
  * Returns the maximum depth of a workflow tree.
293
- * Leaf nodes (`llm`, `tool`) have depth 0. Structural nodes add +1.
296
+ * Leaf nodes (`callModel`, `invokeTool`) have depth 0. Structural nodes add +1.
294
297
  * A `subflow` ref counts as a leaf — depth does not see through named refs.
295
298
  */
296
299
  export declare function workflowDepth(node: WorkflowNode): number;
@@ -2,8 +2,8 @@
2
2
  * Zod schemas for JSON-serialisable workflow definitions.
3
3
  *
4
4
  * A `WorkflowDocument` is a portable, JSON-safe representation of a noetic
5
- * step tree. It covers every step kind. The `run` node carries its body as a
6
- * code STRING (not an in-process closure) dispatched through a subprocess
5
+ * step tree. It covers every step kind. The `runCode` node carries its body as
6
+ * a code STRING (not an in-process closure) dispatched through a subprocess
7
7
  * adapter, keeping the document JSON-safe. The hydrator in
8
8
  * `@noetic-tools/core` (`builders/workflow-hydrator.ts`) converts a validated
9
9
  * document back into live `Step` objects via the existing builders.
@@ -21,11 +21,14 @@ const MaxCostPredicateSchema = z.object({
21
21
  });
22
22
  const MaxDurationPredicateSchema = z.object({
23
23
  kind: z.literal('maxDuration'),
24
- ms: z.number().positive(),
24
+ duration: z.number().positive(),
25
25
  });
26
26
  const NoToolCallsPredicateSchema = z.object({
27
27
  kind: z.literal('noToolCalls'),
28
28
  });
29
+ const NeverPredicateSchema = z.object({
30
+ kind: z.literal('never'),
31
+ });
29
32
  const OutputContainsPredicateSchema = z.object({
30
33
  kind: z.literal('outputContains'),
31
34
  marker: z.string().min(1),
@@ -54,6 +57,7 @@ export const UntilPredicateSchema = z
54
57
  MaxCostPredicateSchema,
55
58
  MaxDurationPredicateSchema,
56
59
  NoToolCallsPredicateSchema,
60
+ NeverPredicateSchema,
57
61
  OutputContainsPredicateSchema,
58
62
  OutputEqualsPredicateSchema,
59
63
  ConvergedPredicateSchema,
@@ -72,7 +76,7 @@ export const MergeStrategy = {
72
76
  First: 'first',
73
77
  Concat: 'concat',
74
78
  };
75
- /** @public Zod schema for the named merge strategy used by `fork` nodes. */
79
+ /** @public Zod schema for the named merge strategy used by `inParallel` nodes. */
76
80
  export const MergeStrategySchema = z.enum([
77
81
  'last',
78
82
  'first',
@@ -89,7 +93,7 @@ const ModelParamsSchema = z.object({
89
93
  //#endregion
90
94
  //#region Tool Entries
91
95
  /**
92
- * A uniform tool entry on an `llm` node. Every entry is an object keyed by
96
+ * A uniform tool entry on a `callModel` node. Every entry is an object keyed by
93
97
  * `type`:
94
98
  * - A CLIENT tool is `{ type: "<registered-tool-name>" }`. The hydrator
95
99
  * resolves `type` against the tool registry; `parameters` (if present) is
@@ -102,13 +106,13 @@ const ModelParamsSchema = z.object({
102
106
  * Server vs client is decided by the `type` value (a reserved `openrouter:*`
103
107
  * server-tool literal vs an arbitrary tool name), not by the entry's shape.
104
108
  */
105
- const LlmToolEntrySchema = z.object({
109
+ const CallModelToolEntrySchema = z.object({
106
110
  type: z.string().min(1),
107
111
  parameters: z.record(z.string(), z.unknown()).optional(),
108
112
  });
109
113
  //#endregion
110
114
  //#region Retry Policy
111
- /** Retry policy for a `run` node, mirroring `RetryPolicy` in `@noetic-tools/types`. */
115
+ /** Retry policy for a `runCode` node, mirroring `RetryPolicy` in `@noetic-tools/types`. */
112
116
  const RetryPolicySchema = z.object({
113
117
  maxAttempts: z.number().int().positive(),
114
118
  backoff: z.enum([
@@ -155,41 +159,41 @@ const OutputCodecRefSchema = z.object({
155
159
  codec: z.literal('openui'),
156
160
  library: z.string().min(1),
157
161
  });
158
- const LlmNodeSchema = z.object({
159
- kind: z.literal('llm'),
162
+ const CallModelNodeSchema = z.object({
163
+ kind: z.literal('callModel'),
160
164
  ...SHARED_FIELDS,
161
165
  model: z.string().optional(),
162
166
  instructions: z.string(),
163
- tools: z.array(LlmToolEntrySchema).optional(),
167
+ tools: z.array(CallModelToolEntrySchema).optional(),
164
168
  params: ModelParamsSchema.optional(),
165
169
  output: OutputCodecRefSchema.optional(),
166
170
  });
167
- const ToolNodeSchema = z.object({
168
- kind: z.literal('tool'),
171
+ const InvokeToolNodeSchema = z.object({
172
+ kind: z.literal('invokeTool'),
169
173
  ...SHARED_FIELDS,
170
174
  toolName: z.string().min(1),
171
175
  args: z.record(z.string(), z.unknown()).optional(),
172
176
  });
173
- const RunNodeSchema = z.object({
174
- kind: z.literal('run'),
177
+ const RunCodeNodeSchema = z.object({
178
+ kind: z.literal('runCode'),
175
179
  ...SHARED_FIELDS,
176
180
  execute: z.string().min(1),
177
181
  retry: RetryPolicySchema.optional(),
178
182
  subprocess: z.string().min(1).optional(),
179
183
  });
180
- const BranchRouteSchema = z.object({
184
+ const ConditionalRouteSchema = z.object({
181
185
  match: z.string().min(1),
182
186
  target: z.lazy(() => WorkflowNodeSchema),
183
187
  });
184
- const BranchNodeSchema = z.object({
185
- kind: z.literal('branch'),
188
+ const ConditionalNodeSchema = z.object({
189
+ kind: z.literal('conditional'),
186
190
  ...SHARED_FIELDS,
187
- routes: z.array(BranchRouteSchema).min(1),
191
+ routes: z.array(ConditionalRouteSchema).min(1),
188
192
  default: WorkflowNodeRef.optional(),
189
193
  });
190
- const ForkNodeSchema = z
194
+ const InParallelNodeSchema = z
191
195
  .object({
192
- kind: z.literal('fork'),
196
+ kind: z.literal('inParallel'),
193
197
  ...SHARED_FIELDS,
194
198
  mode: z.enum([
195
199
  'race',
@@ -203,7 +207,7 @@ const ForkNodeSchema = z
203
207
  concurrency: z.number().int().positive().optional(),
204
208
  })
205
209
  .refine((node) => (node.paths === undefined) !== (node.each === undefined), {
206
- message: "fork node requires exactly one of 'paths' (static) or 'each' (dynamic).",
210
+ message: "inParallel node requires exactly one of 'paths' (static) or 'each' (dynamic).",
207
211
  });
208
212
  const SpawnNodeSchema = z.object({
209
213
  kind: z.literal('spawn'),
@@ -212,8 +216,8 @@ const SpawnNodeSchema = z.object({
212
216
  timeout: z.number().positive().optional(),
213
217
  layers: z.array(z.string().min(1)).min(1).optional(),
214
218
  });
215
- const ProvideNodeSchema = z.object({
216
- kind: z.literal('provide'),
219
+ const WithContextNodeSchema = z.object({
220
+ kind: z.literal('withContext'),
217
221
  ...SHARED_FIELDS,
218
222
  child: WorkflowNodeRef,
219
223
  layers: z.array(z.string().min(1)).min(1),
@@ -230,11 +234,11 @@ const SequenceNodeSchema = z.object({
230
234
  ...SHARED_FIELDS,
231
235
  steps: z.array(WorkflowNodeRef).min(1),
232
236
  });
233
- const EveryNodeSchema = z.object({
234
- kind: z.literal('every'),
237
+ const ScheduleNodeSchema = z.object({
238
+ kind: z.literal('schedule'),
235
239
  ...SHARED_FIELDS,
236
240
  step: WorkflowNodeRef,
237
- ms: z.number().nonnegative(),
241
+ interval: z.number().nonnegative(),
238
242
  onError: z
239
243
  .enum([
240
244
  'continue',
@@ -272,16 +276,16 @@ const PiNodeSchema = subHarnessNodeSchema('pi');
272
276
  /** @public Zod schema validating a single `WorkflowNode` (any JSON-safe kind). */
273
277
  export const WorkflowNodeSchema = z
274
278
  .discriminatedUnion('kind', [
275
- LlmNodeSchema,
276
- ToolNodeSchema,
277
- RunNodeSchema,
278
- BranchNodeSchema,
279
- ForkNodeSchema,
279
+ CallModelNodeSchema,
280
+ InvokeToolNodeSchema,
281
+ RunCodeNodeSchema,
282
+ ConditionalNodeSchema,
283
+ InParallelNodeSchema,
280
284
  SpawnNodeSchema,
281
- ProvideNodeSchema,
285
+ WithContextNodeSchema,
282
286
  LoopNodeSchema,
283
287
  SequenceNodeSchema,
284
- EveryNodeSchema,
288
+ ScheduleNodeSchema,
285
289
  SubflowNodeSchema,
286
290
  ClaudeCodeNodeSchema,
287
291
  CodexNodeSchema,
@@ -310,7 +314,7 @@ function childNodes(node) {
310
314
  switch (node.kind) {
311
315
  case 'sequence':
312
316
  return node.steps;
313
- case 'fork':
317
+ case 'inParallel':
314
318
  if (node.each) {
315
319
  return [
316
320
  node.each,
@@ -318,7 +322,7 @@ function childNodes(node) {
318
322
  }
319
323
  return node.paths ?? [];
320
324
  case 'spawn':
321
- case 'provide':
325
+ case 'withContext':
322
326
  return [
323
327
  node.child,
324
328
  ];
@@ -326,11 +330,11 @@ function childNodes(node) {
326
330
  return [
327
331
  node.body,
328
332
  ];
329
- case 'every':
333
+ case 'schedule':
330
334
  return [
331
335
  node.step,
332
336
  ];
333
- case 'branch': {
337
+ case 'conditional': {
334
338
  const children = node.routes.map((r) => r.target);
335
339
  if (node.default) {
336
340
  children.push(node.default);
@@ -388,7 +392,7 @@ export function workflowGraph(root) {
388
392
  }
389
393
  /**
390
394
  * Returns the maximum depth of a workflow tree.
391
- * Leaf nodes (`llm`, `tool`) have depth 0. Structural nodes add +1.
395
+ * Leaf nodes (`callModel`, `invokeTool`) have depth 0. Structural nodes add +1.
392
396
  * A `subflow` ref counts as a leaf — depth does not see through named refs.
393
397
  */
394
398
  export function workflowDepth(node) {
@@ -54,6 +54,12 @@ export interface TokenUsage {
54
54
  input: number;
55
55
  output: number;
56
56
  total: number;
57
+ /**
58
+ * Prompt tokens served from the provider's cache, summed across every model
59
+ * call on this execution. `undefined` — not `0` — while no call has reported a
60
+ * cache figure, preserving the `RoundUsage` distinction between "nothing was
61
+ * cached" and "this provider says nothing about caching".
62
+ */
57
63
  cached?: number;
58
64
  }
59
65
  /**