@noetic-tools/types 3.2.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 +3 -3
- package/dist/errors/noetic-error.js +7 -7
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/schemas/workflow.d.ts +39 -36
- package/dist/schemas/workflow.js +42 -38
- package/dist/types/common.d.ts +6 -0
- package/dist/types/context-harness.d.ts +172 -0
- package/dist/types/context.d.ts +6 -173
- package/dist/types/error.d.ts +5 -4
- package/dist/types/harness-result.d.ts +6 -0
- package/dist/types/observability.d.ts +2 -1
- package/dist/types/output-codec.d.ts +5 -5
- package/dist/types/output-codec.js +3 -3
- package/dist/types/runtime.d.ts +31 -10
- package/dist/types/steering.d.ts +2 -1
- package/dist/types/step.d.ts +36 -35
- package/dist/types/tool-context.d.ts +0 -7
- package/dist/util/message-helpers.js +8 -1
- package/package.json +1 -1
- package/dist/deprecated.d.ts +0 -39
- /package/dist/{deprecated.js → types/context-harness.js} +0 -0
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/
|
|
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 `
|
|
18
|
-
`@noetic-tools/types/contract` subpath for
|
|
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 '
|
|
47
|
-
return `
|
|
48
|
-
case '
|
|
49
|
-
return `
|
|
50
|
-
case '
|
|
51
|
-
return `
|
|
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.
|
|
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';
|
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';
|
|
@@ -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 `
|
|
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
|
-
|
|
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
|
|
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 `
|
|
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
|
|
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
|
|
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 `
|
|
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
|
|
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
|
|
131
|
-
kind: '
|
|
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
|
|
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
|
|
147
|
-
kind: '
|
|
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
|
|
153
|
-
* (which carries a closure), the JSON form carries `execute` as
|
|
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
|
|
160
|
-
kind: '
|
|
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
|
|
171
|
+
export interface ConditionalRoute {
|
|
169
172
|
match: string;
|
|
170
173
|
target: WorkflowNode;
|
|
171
174
|
}
|
|
172
|
-
export interface
|
|
173
|
-
kind: '
|
|
174
|
-
routes:
|
|
175
|
+
export interface ConditionalWorkflowNode extends WorkflowNodeBase {
|
|
176
|
+
kind: 'conditional';
|
|
177
|
+
routes: ConditionalRoute[];
|
|
175
178
|
default?: WorkflowNode;
|
|
176
179
|
}
|
|
177
|
-
export interface
|
|
178
|
-
kind: '
|
|
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
|
|
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 `
|
|
206
|
-
* layers — the default spawn behaviour. Naming layers here REPLACES
|
|
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
|
|
212
|
-
kind: '
|
|
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
|
|
227
|
-
kind: '
|
|
229
|
+
export interface ScheduleWorkflowNode extends WorkflowNodeBase {
|
|
230
|
+
kind: 'schedule';
|
|
228
231
|
step: WorkflowNode;
|
|
229
|
-
|
|
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 =
|
|
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 (`
|
|
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;
|
package/dist/schemas/workflow.js
CHANGED
|
@@ -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 `
|
|
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
|
-
|
|
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 `
|
|
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
|
|
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
|
|
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 `
|
|
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
|
|
159
|
-
kind: z.literal('
|
|
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(
|
|
167
|
+
tools: z.array(CallModelToolEntrySchema).optional(),
|
|
164
168
|
params: ModelParamsSchema.optional(),
|
|
165
169
|
output: OutputCodecRefSchema.optional(),
|
|
166
170
|
});
|
|
167
|
-
const
|
|
168
|
-
kind: z.literal('
|
|
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
|
|
174
|
-
kind: z.literal('
|
|
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
|
|
184
|
+
const ConditionalRouteSchema = z.object({
|
|
181
185
|
match: z.string().min(1),
|
|
182
186
|
target: z.lazy(() => WorkflowNodeSchema),
|
|
183
187
|
});
|
|
184
|
-
const
|
|
185
|
-
kind: z.literal('
|
|
188
|
+
const ConditionalNodeSchema = z.object({
|
|
189
|
+
kind: z.literal('conditional'),
|
|
186
190
|
...SHARED_FIELDS,
|
|
187
|
-
routes: z.array(
|
|
191
|
+
routes: z.array(ConditionalRouteSchema).min(1),
|
|
188
192
|
default: WorkflowNodeRef.optional(),
|
|
189
193
|
});
|
|
190
|
-
const
|
|
194
|
+
const InParallelNodeSchema = z
|
|
191
195
|
.object({
|
|
192
|
-
kind: z.literal('
|
|
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: "
|
|
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
|
|
216
|
-
kind: z.literal('
|
|
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
|
|
234
|
-
kind: z.literal('
|
|
237
|
+
const ScheduleNodeSchema = z.object({
|
|
238
|
+
kind: z.literal('schedule'),
|
|
235
239
|
...SHARED_FIELDS,
|
|
236
240
|
step: WorkflowNodeRef,
|
|
237
|
-
|
|
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
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
279
|
+
CallModelNodeSchema,
|
|
280
|
+
InvokeToolNodeSchema,
|
|
281
|
+
RunCodeNodeSchema,
|
|
282
|
+
ConditionalNodeSchema,
|
|
283
|
+
InParallelNodeSchema,
|
|
280
284
|
SpawnNodeSchema,
|
|
281
|
-
|
|
285
|
+
WithContextNodeSchema,
|
|
282
286
|
LoopNodeSchema,
|
|
283
287
|
SequenceNodeSchema,
|
|
284
|
-
|
|
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 '
|
|
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 '
|
|
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 '
|
|
333
|
+
case 'schedule':
|
|
330
334
|
return [
|
|
331
335
|
node.step,
|
|
332
336
|
];
|
|
333
|
-
case '
|
|
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 (`
|
|
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) {
|
package/dist/types/common.d.ts
CHANGED
|
@@ -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
|
/**
|