@noetic-tools/core 5.2.0 → 5.4.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.
Files changed (92) hide show
  1. package/README.md +8 -6
  2. package/dist/adapters/in-memory-subprocess/step-completion.js +1 -1
  3. package/dist/adapters/openrouter.d.ts +20 -2
  4. package/dist/adapters/openrouter.js +102 -6
  5. package/dist/builders/control-flow-builders.d.ts +13 -13
  6. package/dist/builders/control-flow-builders.js +11 -11
  7. package/dist/{patterns → builders}/dynamic-workflow.d.ts +1 -1
  8. package/dist/{patterns → builders}/dynamic-workflow.js +18 -12
  9. package/dist/builders/every.d.ts +14 -14
  10. package/dist/builders/every.js +16 -16
  11. package/dist/builders/layer-provides-builders.d.ts +1 -1
  12. package/dist/builders/layer-provides-builders.js +1 -1
  13. package/dist/builders/provide-builder.d.ts +5 -12
  14. package/dist/builders/provide-builder.js +9 -10
  15. package/dist/builders/spawn-builder.d.ts +0 -2
  16. package/dist/builders/spawn-builder.js +2 -3
  17. package/dist/builders/step-builders.d.ts +66 -55
  18. package/dist/builders/step-builders.js +118 -111
  19. package/dist/builders/tool-builder.d.ts +18 -22
  20. package/dist/builders/tool-builder.js +6 -4
  21. package/dist/builders/workflow-hydrator.d.ts +3 -3
  22. package/dist/builders/workflow-hydrator.js +59 -63
  23. package/dist/builders/workflow-step.d.ts +13 -25
  24. package/dist/builders/workflow-step.js +13 -18
  25. package/dist/conditions/conditions.d.ts +2 -2
  26. package/dist/conditions/conditions.js +1 -1
  27. package/dist/harness/agent-harness.d.ts +58 -40
  28. package/dist/harness/agent-harness.js +125 -51
  29. package/dist/harness/deps/context.d.ts +1 -1
  30. package/dist/harness/deps/context.js +1 -1
  31. package/dist/harness/deps/interpreter.d.ts +1 -0
  32. package/dist/harness/deps/interpreter.js +1 -0
  33. package/dist/harness/deps/types.d.ts +2 -2
  34. package/dist/harness/model-call.d.ts +1 -1
  35. package/dist/harness/model-call.js +45 -23
  36. package/dist/index.d.ts +23 -35
  37. package/dist/index.js +10 -26
  38. package/dist/interpreter/action-deps.d.ts +2 -2
  39. package/dist/interpreter/action-deps.js +1 -1
  40. package/dist/interpreter/action-types.d.ts +1 -1
  41. package/dist/interpreter/collect-tools.js +7 -7
  42. package/dist/interpreter/context-assembly.d.ts +50 -0
  43. package/dist/interpreter/context-assembly.js +547 -0
  44. package/dist/interpreter/execute-action.d.ts +5 -5
  45. package/dist/interpreter/execute-action.js +337 -208
  46. package/dist/interpreter/execute-control.d.ts +9 -9
  47. package/dist/interpreter/execute-control.js +27 -27
  48. package/dist/interpreter/execute-sub-harness.d.ts +1 -1
  49. package/dist/interpreter/execute-sub-harness.js +7 -26
  50. package/dist/interpreter/execute.d.ts +1 -1
  51. package/dist/interpreter/execute.js +26 -25
  52. package/dist/interpreter/step-dispatcher.d.ts +1 -1
  53. package/dist/interpreter/step-dispatcher.js +3 -3
  54. package/dist/interpreter/structured-output.d.ts +14 -0
  55. package/dist/interpreter/structured-output.js +40 -0
  56. package/dist/interpreter/typeguards.d.ts +1 -1
  57. package/dist/interpreter/typeguards.js +1 -1
  58. package/dist/observability/genai-attributes.d.ts +20 -0
  59. package/dist/observability/genai-attributes.js +20 -0
  60. package/dist/portable/builders.d.ts +3 -3
  61. package/dist/portable/builders.js +6 -5
  62. package/dist/portable/context-layers.d.ts +1 -1
  63. package/dist/portable/context-layers.js +1 -1
  64. package/dist/runtime/broadcaster-utils.d.ts +1 -1
  65. package/dist/runtime/broadcaster-utils.js +1 -1
  66. package/dist/runtime/context-impl.d.ts +8 -10
  67. package/dist/runtime/context-impl.js +8 -12
  68. package/dist/runtime/durable/step-ledger.d.ts +2 -2
  69. package/dist/runtime/durable/step-ledger.js +3 -3
  70. package/dist/runtime/session-runner.d.ts +12 -1
  71. package/dist/runtime/session-runner.js +33 -1
  72. package/dist/runtime/tool-context.js +0 -2
  73. package/dist/schemas/workflow.d.ts +3 -3
  74. package/dist/schemas/workflow.js +2 -2
  75. package/dist/types/checkpoint.d.ts +11 -2
  76. package/dist/types/checkpoint.js +10 -1
  77. package/dist/{runtime → util}/detached-handle.js +1 -1
  78. package/package.json +6 -4
  79. package/schema/noetic-workflow.schema.json +24 -11
  80. package/dist/builders/context-option.d.ts +0 -23
  81. package/dist/builders/context-option.js +0 -22
  82. package/dist/deprecated.d.ts +0 -30
  83. package/dist/deprecated.js +0 -28
  84. package/dist/patterns/interview.d.ts +0 -53
  85. package/dist/patterns/interview.js +0 -113
  86. package/dist/patterns/plans.d.ts +0 -44
  87. package/dist/patterns/plans.js +0 -125
  88. package/dist/patterns/ralph-wiggum.d.ts +0 -19
  89. package/dist/patterns/ralph-wiggum.js +0 -37
  90. package/dist/patterns/react.d.ts +0 -19
  91. package/dist/patterns/react.js +0 -41
  92. /package/dist/{runtime → util}/detached-handle.d.ts +0 -0
@@ -1,20 +1,20 @@
1
1
  /**
2
2
  * Converts a validated `WorkflowDocument` into a live `Step` tree.
3
3
  *
4
- * Each node kind maps to the corresponding builder (`step.llm`, `fork`,
4
+ * Each node kind maps to the corresponding builder (`callModel`, `inParallel`,
5
5
  * `loop`, etc.) so hydrated steps are indistinguishable from programmatic
6
6
  * ones — they register in the step registry, carry retry policies, etc.
7
7
  */
8
8
  import { frameworkCast, isServerToolSpec, NoeticConfigError } from '@noetic-tools/types';
9
- import { DetachedHandleImpl } from '../runtime/detached-handle.js';
10
9
  import { all, any } from '../until/combinators.js';
11
10
  import { until } from '../until/predicates.js';
12
- import { branch, fork } from './control-flow-builders.js';
13
- import { every } from './every.js';
11
+ import { DetachedHandleImpl } from '../util/detached-handle.js';
12
+ import { conditional, inParallel } from './control-flow-builders.js';
13
+ import { schedule } from './every.js';
14
14
  import { loop } from './loop-builder.js';
15
- import { provide } from './provide-builder.js';
15
+ import { withContext } from './provide-builder.js';
16
16
  import { spawn } from './spawn-builder.js';
17
- import { step } from './step-builders.js';
17
+ import { callModel, runCode, step } from './step-builders.js';
18
18
  //#endregion
19
19
  //#region Until Predicate Hydration
20
20
  function hydrateUntilPredicate(pred) {
@@ -24,9 +24,11 @@ function hydrateUntilPredicate(pred) {
24
24
  case 'maxCost':
25
25
  return until.maxCost(pred.usd);
26
26
  case 'maxDuration':
27
- return until.maxDuration(pred.ms);
27
+ return until.maxDuration(pred.duration);
28
28
  case 'noToolCalls':
29
29
  return until.noToolCalls();
30
+ case 'never':
31
+ return until.never();
30
32
  case 'outputContains':
31
33
  return until.outputContains(pred.marker);
32
34
  case 'outputEquals':
@@ -43,7 +45,7 @@ function hydrateUntilPredicate(pred) {
43
45
  throw new NoeticConfigError({
44
46
  code: 'UNKNOWN_UNTIL_PREDICATE',
45
47
  message: `Unknown until predicate kind: '${frameworkCast(pred).kind}'.`,
46
- hint: 'Supported kinds: maxSteps, maxCost, maxDuration, noToolCalls, outputContains, outputEquals, converged, any, all.',
48
+ hint: 'Supported kinds: maxSteps, maxCost, maxDuration, noToolCalls, never, outputContains, outputEquals, converged, any, all.',
47
49
  });
48
50
  }
49
51
  }
@@ -58,7 +60,7 @@ function hydrateUntilPredicate(pred) {
58
60
  * kinds combine into one `tools` array; the interpreter partitions them again
59
61
  * at execution.
60
62
  */
61
- function resolveLlmTools(entries, registry) {
63
+ function resolveCallModelTools(entries, registry) {
62
64
  const toolNames = [];
63
65
  const serverSpecs = [];
64
66
  for (const entry of entries ?? []) {
@@ -74,12 +76,12 @@ function resolveLlmTools(entries, registry) {
74
76
  ...serverSpecs,
75
77
  ];
76
78
  }
77
- function hydrateLlmNode(node, ctx) {
78
- if (node.kind !== 'llm') {
79
+ function hydrateCallModelNode(node, ctx) {
80
+ if (node.kind !== 'callModel') {
79
81
  return frameworkCast(undefined);
80
82
  }
81
- const combined = resolveLlmTools(node.tools, ctx.tools);
82
- return step.llm({
83
+ const combined = resolveCallModelTools(node.tools, ctx.tools);
84
+ return callModel({
83
85
  id: node.id,
84
86
  model: node.model ?? 'openai/gpt-4o',
85
87
  instructions: node.instructions,
@@ -89,7 +91,7 @@ function hydrateLlmNode(node, ctx) {
89
91
  });
90
92
  }
91
93
  /**
92
- * Resolve an `llm` node's `output` codec reference to a live `OutputCodec`.
94
+ * Resolve a `callModel` node's `output` codec reference to a live `OutputCodec`.
93
95
  *
94
96
  * Hydrated steps are typed `<string, string>` (the JSON boundary erases output
95
97
  * types), so the resolved codec is cast to the step's erased output type — the
@@ -118,8 +120,8 @@ function resolveOutputCodec(ref, nodeId, ctx) {
118
120
  hint: `Pass output codecs via HydrationContext.uiLibraries, e.g. new Map([['${ref.library}', openUi(myLibrary)]]) from @noetic-tools/openui. Available: ${availableLibraries(ctx)}`,
119
121
  });
120
122
  }
121
- function hydrateToolNode(node, ctx) {
122
- if (node.kind !== 'tool') {
123
+ function hydrateInvokeToolNode(node, ctx) {
124
+ if (node.kind !== 'invokeTool') {
123
125
  return frameworkCast(undefined);
124
126
  }
125
127
  const resolved = ctx.tools.get(node.toolName);
@@ -132,7 +134,7 @@ function hydrateToolNode(node, ctx) {
132
134
  ].join(', ') || '(none)'}`,
133
135
  });
134
136
  }
135
- return frameworkCast(step.run({
137
+ return frameworkCast(runCode({
136
138
  id: node.id,
137
139
  execute: async (_input, execCtx) => {
138
140
  const args = node.args ?? {};
@@ -156,12 +158,6 @@ function hydrateToolNode(node, ctx) {
156
158
  fs: execCtx.fs,
157
159
  shell: execCtx.shell,
158
160
  context: layerState,
159
- // Deprecated alias — the same accessor object, as
160
- // `buildToolExecutionContext` does. `Tool.execute` takes its second
161
- // argument as `unknown`, so nothing here is structurally checked
162
- // against `ToolExecutionContext`; the annotation above is what makes
163
- // a missing field a compile error instead of a runtime `undefined`.
164
- memory: layerState,
165
161
  assembledView: execCtx.itemLog.items,
166
162
  lastStepMeta: execCtx.lastStepMeta,
167
163
  };
@@ -170,13 +166,13 @@ function hydrateToolNode(node, ctx) {
170
166
  },
171
167
  }));
172
168
  }
173
- function hydrateRunNode(node, ctx) {
174
- if (node.kind !== 'run') {
169
+ function hydrateRunCodeNode(node, ctx) {
170
+ if (node.kind !== 'runCode') {
175
171
  return frameworkCast(undefined);
176
172
  }
177
173
  const code = node.execute;
178
174
  const subprocessRef = node.subprocess;
179
- return frameworkCast(step.run({
175
+ return frameworkCast(runCode({
180
176
  id: node.id,
181
177
  retry: node.retry,
182
178
  execute: async (input, execCtx) => {
@@ -195,8 +191,8 @@ function hydrateRunNode(node, ctx) {
195
191
  },
196
192
  }));
197
193
  }
198
- function hydrateBranchNode(node, ctx) {
199
- if (node.kind !== 'branch') {
194
+ function hydrateConditionalNode(node, ctx) {
195
+ if (node.kind !== 'conditional') {
200
196
  return frameworkCast(undefined);
201
197
  }
202
198
  const hydratedRoutes = node.routes.map((r) => ({
@@ -208,7 +204,7 @@ function hydrateBranchNode(node, ctx) {
208
204
  if (defaultTarget) {
209
205
  allTargets.push(defaultTarget);
210
206
  }
211
- return branch({
207
+ return conditional({
212
208
  id: node.id,
213
209
  route: (input) => {
214
210
  const trimmed = input.trim().toLowerCase();
@@ -222,12 +218,12 @@ function hydrateBranchNode(node, ctx) {
222
218
  _optimizable: frameworkCast(allTargets),
223
219
  });
224
220
  }
225
- function hydrateForkNode(node, ctx) {
226
- if (node.kind !== 'fork') {
221
+ function hydrateInParallelNode(node, ctx) {
222
+ if (node.kind !== 'inParallel') {
227
223
  return frameworkCast(undefined);
228
224
  }
229
- // Static fork: paths are known at hydration time and feed the optimizer.
230
- // Dynamic fork (`each`): paths are produced per fork-input at runtime, one
225
+ // Static inParallel: paths are known at hydration time and feed the optimizer.
226
+ // Dynamic inParallel (`each`): paths are produced per inParallel-input at runtime, one
231
227
  // child per array item, so they cannot be pre-computed or optimized.
232
228
  const dynamic = node.each !== undefined;
233
229
  const eachTemplate = node.each;
@@ -247,7 +243,7 @@ function hydrateForkNode(node, ctx) {
247
243
  };
248
244
  const optimizable = dynamic ? undefined : frameworkCast(staticPaths);
249
245
  if (node.mode === 'race') {
250
- return fork({
246
+ return inParallel({
251
247
  id: node.id,
252
248
  mode: 'race',
253
249
  paths: pathsFactory,
@@ -257,7 +253,7 @@ function hydrateForkNode(node, ctx) {
257
253
  }
258
254
  const mergeFn = buildMerge(node.merge ?? 'last');
259
255
  if (node.mode === 'settle') {
260
- return fork({
256
+ return inParallel({
261
257
  id: node.id,
262
258
  mode: 'settle',
263
259
  paths: pathsFactory,
@@ -269,7 +265,7 @@ function hydrateForkNode(node, ctx) {
269
265
  _optimizable: optimizable,
270
266
  });
271
267
  }
272
- return fork({
268
+ return inParallel({
273
269
  id: node.id,
274
270
  mode: 'all',
275
271
  paths: pathsFactory,
@@ -279,7 +275,7 @@ function hydrateForkNode(node, ctx) {
279
275
  });
280
276
  }
281
277
  /**
282
- * Resolves layer names declared on a `provide` / `spawn` node against the
278
+ * Resolves layer names declared on a `withContext` / `spawn` node against the
283
279
  * registry on `HydrationContext.layers`. Returns `[]` when no registry was
284
280
  * supplied — the host runs with its harness-default layers in that case.
285
281
  */
@@ -322,16 +318,16 @@ function hydrateSpawnNode(node, ctx) {
322
318
  context: resolvedLayers,
323
319
  });
324
320
  }
325
- function hydrateProvideNode(node, ctx) {
326
- if (node.kind !== 'provide') {
321
+ function hydrateWithContextNode(node, ctx) {
322
+ if (node.kind !== 'withContext') {
327
323
  return frameworkCast(undefined);
328
324
  }
329
- return provide({
325
+ return withContext({
330
326
  id: node.id,
331
327
  child: hydrateNode(node.child, ctx),
332
328
  context: resolveNamedLayers({
333
329
  names: node.layers,
334
- nodeKind: 'provide',
330
+ nodeKind: 'withContext',
335
331
  nodeId: node.id,
336
332
  ctx,
337
333
  }),
@@ -355,7 +351,7 @@ function hydrateSequenceNode(node, ctx) {
355
351
  return frameworkCast(undefined);
356
352
  }
357
353
  const children = node.steps.map((s) => hydrateNode(s, ctx));
358
- return frameworkCast(step.run({
354
+ return frameworkCast(runCode({
359
355
  id: node.id,
360
356
  execute: async (input, execCtx) => {
361
357
  let current = input;
@@ -367,14 +363,14 @@ function hydrateSequenceNode(node, ctx) {
367
363
  },
368
364
  }));
369
365
  }
370
- function hydrateEveryNode(node, ctx) {
371
- if (node.kind !== 'every') {
366
+ function hydrateScheduleNode(node, ctx) {
367
+ if (node.kind !== 'schedule') {
372
368
  return frameworkCast(undefined);
373
369
  }
374
- return every({
370
+ return schedule({
375
371
  id: node.id,
376
372
  step: hydrateNode(node.step, ctx),
377
- ms: node.ms,
373
+ interval: node.interval,
378
374
  onError: node.onError,
379
375
  });
380
376
  }
@@ -427,7 +423,7 @@ function hydrateSubflowNode(node, ctx) {
427
423
  }
428
424
  return cached;
429
425
  };
430
- return frameworkCast(step.run({
426
+ return frameworkCast(runCode({
431
427
  id: node.id,
432
428
  execute: async (input, execCtx) => {
433
429
  const child = resolve();
@@ -480,16 +476,16 @@ function resolveSubflowDocument(node, ctx) {
480
476
  //#endregion
481
477
  //#region Handler Registry
482
478
  const NODE_HYDRATORS = {
483
- llm: hydrateLlmNode,
484
- tool: hydrateToolNode,
485
- run: hydrateRunNode,
486
- branch: hydrateBranchNode,
487
- fork: hydrateForkNode,
479
+ callModel: hydrateCallModelNode,
480
+ invokeTool: hydrateInvokeToolNode,
481
+ runCode: hydrateRunCodeNode,
482
+ conditional: hydrateConditionalNode,
483
+ inParallel: hydrateInParallelNode,
488
484
  spawn: hydrateSpawnNode,
489
- provide: hydrateProvideNode,
485
+ withContext: hydrateWithContextNode,
490
486
  loop: hydrateLoopNode,
491
487
  sequence: hydrateSequenceNode,
492
- every: hydrateEveryNode,
488
+ schedule: hydrateScheduleNode,
493
489
  subflow: hydrateSubflowNode,
494
490
  'claude-code': hydrateSubHarnessNode,
495
491
  codex: hydrateSubHarnessNode,
@@ -537,7 +533,7 @@ function stringifyResult(value) {
537
533
  //#endregion
538
534
  //#region Dynamic Fork Helpers
539
535
  /**
540
- * Parses the fork input (a JSON string) and locates the array to fan out over.
536
+ * Parses the inParallel input (a JSON string) and locates the array to fan out over.
541
537
  * When `over` is set, reads that property off the parsed object; otherwise the
542
538
  * parsed value itself must be an array.
543
539
  */
@@ -549,15 +545,15 @@ function selectArray(input, over, nodeId) {
549
545
  catch {
550
546
  throw new NoeticConfigError({
551
547
  code: 'INVALID_FORK_INPUT',
552
- message: `Dynamic fork '${nodeId}' could not parse its input as JSON.`,
553
- hint: 'A dynamic fork (with `each`) expects its input to be a JSON array (or a JSON object when `over` is set).',
548
+ message: `Dynamic inParallel '${nodeId}' could not parse its input as JSON.`,
549
+ hint: 'A dynamic inParallel (with `each`) expects its input to be a JSON array (or a JSON object when `over` is set).',
554
550
  });
555
551
  }
556
552
  const candidate = over === undefined ? parsed : frameworkCast(parsed)?.[over];
557
553
  if (!Array.isArray(candidate)) {
558
554
  throw new NoeticConfigError({
559
555
  code: 'INVALID_FORK_INPUT',
560
- message: `Dynamic fork '${nodeId}' did not resolve an array${over ? ` at key '${over}'` : ''}.`,
556
+ message: `Dynamic inParallel '${nodeId}' did not resolve an array${over ? ` at key '${over}'` : ''}.`,
561
557
  hint: over
562
558
  ? `Ensure the input JSON object has an array at '${over}'.`
563
559
  : 'Ensure the input is a JSON array, or set `over` to select an array property.',
@@ -566,15 +562,15 @@ function selectArray(input, over, nodeId) {
566
562
  return candidate;
567
563
  }
568
564
  /**
569
- * Builds one fork path for a single dynamic-fork item. The item is injected as
570
- * the body's input (forks pass the same fork-input to every path), and the
565
+ * Builds one inParallel path for a single dynamic fan-out item. The item is injected as
566
+ * the body's input (inParallel steps pass the same input to every path), and the
571
567
  * template's node ids are suffixed with `-${i}` so each instantiation has
572
568
  * unique ids for tracing and step-registry uniqueness.
573
569
  */
574
570
  function buildPerItemStep(opts) {
575
571
  const { forkId, eachTemplate, item, index, ctx } = opts;
576
572
  const hydratedEach = hydrateNode(suffixNodeIds(eachTemplate, `-${index}`), ctx);
577
- return frameworkCast(step.run({
573
+ return frameworkCast(runCode({
578
574
  id: `${forkId}-item-${index}`,
579
575
  execute: async (_input, execCtx) => {
580
576
  const itemInput = JSON.stringify(item);
@@ -621,7 +617,7 @@ function suffixNodeIds(node, suffix) {
621
617
  //#endregion
622
618
  //#region Run Node Helpers
623
619
  /**
624
- * Resolves the subprocess adapter for a `run` node. When the node names an
620
+ * Resolves the subprocess adapter for a `runCode` node. When the node names an
625
621
  * adapter ref, the host must supply a `resolveSubprocess` resolver; otherwise
626
622
  * the step falls back to the harness adapter on the execution context.
627
623
  */
@@ -641,7 +637,7 @@ function resolveSubprocessAdapter(opts) {
641
637
  return resolved;
642
638
  }
643
639
  /**
644
- * Dispatches a `run` node's code string through a subprocess adapter: ships the
640
+ * Dispatches a `runCode` node's code string through a subprocess adapter: ships the
645
641
  * code plus the JSON-stringified input as a process request (input on stdin),
646
642
  * waits for the handle to settle, and returns the captured stdout as the step
647
643
  * output. A non-zero exit / failed handle surfaces as a thrown error.
@@ -1,31 +1,30 @@
1
1
  /**
2
- * `step.workflow` — runs a `WorkflowDocument` as a single composable step.
2
+ * `workflow` — runs a `WorkflowDocument` as a single composable step.
3
3
  *
4
4
  * Lives beside `step-builders.ts` (rather than inside it) because the hydrator
5
- * imports the base `step` object; adding a hydrating builder there would create
6
- * an import cycle. This module composes the public `step` namespace instead.
5
+ * imports the base builders; adding a hydrating builder there would create an
6
+ * import cycle.
7
7
  */
8
8
  import type { ContextData, ContextLayer } from '@noetic-tools/context';
9
- import type { OutputCodec, StepRun, SubHarness, SubHarnessKind, SubprocessAdapter, Tool, WorkflowDocument } from '@noetic-tools/types';
10
- import * as stepBuilders from './step-builders.js';
11
- /** @public Options for `step.workflow`. */
12
- export interface StepWorkflowOpts {
9
+ import type { OutputCodec, StepRunCode, SubHarness, SubHarnessKind, SubprocessAdapter, Tool, WorkflowDocument } from '@noetic-tools/types';
10
+ /** @public Options for `workflow`. */
11
+ export interface WorkflowOpts {
13
12
  id: string;
14
13
  /** Inline workflow document. Mutually exclusive with `ref`. */
15
14
  document?: WorkflowDocument;
16
15
  /** Named workflow resolved from `workflows`. Mutually exclusive with `document`. */
17
16
  ref?: string;
18
- /** Client tools the document's `llm`/`tool` nodes may reference by name. Default: none. */
17
+ /** Client tools the document's `callModel`/`invokeTool` nodes may reference by name. Default: none. */
19
18
  tools?: Tool[];
20
- /** Named context layers for `provide`/`spawn` nodes. */
19
+ /** Named context layers for `withContext`/`spawn` nodes. */
21
20
  layers?: ReadonlyMap<string, ContextLayer>;
22
21
  /** Named sub-workflows for `subflow` nodes — and for resolving `ref` itself. */
23
22
  workflows?: ReadonlyMap<string, WorkflowDocument>;
24
23
  /** SubHarness adapters for `claude-code`/`codex`/`opencode`/`pi` nodes. */
25
24
  subHarnesses?: ReadonlyMap<SubHarnessKind, SubHarness>;
26
- /** Output codecs for `llm` nodes' `output` codec references. */
25
+ /** Output codecs for `callModel` nodes' `output` codec references. */
27
26
  uiLibraries?: ReadonlyMap<string, OutputCodec>;
28
- /** Resolver for named subprocess adapters on `run` nodes. */
27
+ /** Resolver for named subprocess adapters on `runCode` nodes. */
29
28
  resolveSubprocess?: (ref: string) => SubprocessAdapter | undefined;
30
29
  /** `'inherit'` (default) runs in the caller's session; `'spawn'` isolates via `spawn()`. */
31
30
  isolation?: 'inherit' | 'spawn';
@@ -40,22 +39,11 @@ export interface StepWorkflowOpts {
40
39
  * workflow fails with `WORKFLOW_CYCLE` instead of recursing forever.
41
40
  *
42
41
  * @public
43
- * @param opts - See `StepWorkflowOpts`.
44
- * @returns A `StepRun` executing the workflow via the harness on the context.
42
+ * @param opts - See `WorkflowOpts`.
43
+ * @returns A `StepRunCode` executing the workflow via the harness on the context.
45
44
  * @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
46
45
  * @throws `NoeticConfigError` with code `INVALID_WORKFLOW_SOURCE` unless exactly one of `document`/`ref` is set.
47
46
  * @throws `NoeticConfigError` with code `MISSING_HARNESS_CONTEXT` (at execution) without `ctx.harness`.
48
47
  * @throws `NoeticConfigError` with code `UNKNOWN_WORKFLOW_REFERENCE` (at execution) if `ref` names no registered workflow.
49
48
  */
50
- export declare function stepWorkflow(opts: StepWorkflowOpts): StepRun<ContextData, string, string>;
51
- /** @public The step builder namespace: the base builders plus `workflow`. */
52
- export declare const step: {
53
- readonly run: <TContext = Readonly<Record<string, Record<string, unknown>>>, I = unknown, O = unknown>(opts: stepBuilders.StepRunOpts<TContext, I, O>) => StepRun<TContext, I, O>;
54
- readonly llm: <TContext = Readonly<Record<string, Record<string, unknown>>>, I = unknown, O = unknown>(opts: stepBuilders.StepLLMOpts<TContext, O>) => import("@noetic-tools/types").StepLLM<TContext, I, O>;
55
- readonly tool: <TContext = Readonly<Record<string, Record<string, unknown>>>, I = unknown, O = unknown>(opts: stepBuilders.StepToolOpts<I, O>) => import("@noetic-tools/types").StepTool<TContext, I, O>;
56
- readonly claudeCode: <TContext = Readonly<Record<string, Record<string, unknown>>>, I = unknown, O = unknown>(opts: stepBuilders.StepSubHarnessOpts<TContext, O>) => import("@noetic-tools/types").StepSubHarness<TContext, I, O>;
57
- readonly codex: <TContext = Readonly<Record<string, Record<string, unknown>>>, I = unknown, O = unknown>(opts: stepBuilders.StepSubHarnessOpts<TContext, O>) => import("@noetic-tools/types").StepSubHarness<TContext, I, O>;
58
- readonly opencode: <TContext = Readonly<Record<string, Record<string, unknown>>>, I = unknown, O = unknown>(opts: stepBuilders.StepSubHarnessOpts<TContext, O>) => import("@noetic-tools/types").StepSubHarness<TContext, I, O>;
59
- readonly pi: <TContext = Readonly<Record<string, Record<string, unknown>>>, I = unknown, O = unknown>(opts: stepBuilders.StepSubHarnessOpts<TContext, O>) => import("@noetic-tools/types").StepSubHarness<TContext, I, O>;
60
- readonly workflow: typeof stepWorkflow;
61
- };
49
+ export declare function workflow(opts: WorkflowOpts): StepRunCode<ContextData, string, string>;
@@ -1,13 +1,13 @@
1
1
  /**
2
- * `step.workflow` — runs a `WorkflowDocument` as a single composable step.
2
+ * `workflow` — runs a `WorkflowDocument` as a single composable step.
3
3
  *
4
4
  * Lives beside `step-builders.ts` (rather than inside it) because the hydrator
5
- * imports the base `step` object; adding a hydrating builder there would create
6
- * an import cycle. This module composes the public `step` namespace instead.
5
+ * imports the base builders; adding a hydrating builder there would create an
6
+ * import cycle.
7
7
  */
8
8
  import { frameworkCast, NoeticConfigError } from '@noetic-tools/types';
9
9
  import { spawn } from './spawn-builder.js';
10
- import * as stepBuilders from './step-builders.js';
10
+ import { runCode } from './step-builders.js';
11
11
  import { hydrateWorkflow } from './workflow-hydrator.js';
12
12
  //#endregion
13
13
  //#region Builder
@@ -21,25 +21,25 @@ import { hydrateWorkflow } from './workflow-hydrator.js';
21
21
  * workflow fails with `WORKFLOW_CYCLE` instead of recursing forever.
22
22
  *
23
23
  * @public
24
- * @param opts - See `StepWorkflowOpts`.
25
- * @returns A `StepRun` executing the workflow via the harness on the context.
24
+ * @param opts - See `WorkflowOpts`.
25
+ * @returns A `StepRunCode` executing the workflow via the harness on the context.
26
26
  * @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
27
27
  * @throws `NoeticConfigError` with code `INVALID_WORKFLOW_SOURCE` unless exactly one of `document`/`ref` is set.
28
28
  * @throws `NoeticConfigError` with code `MISSING_HARNESS_CONTEXT` (at execution) without `ctx.harness`.
29
29
  * @throws `NoeticConfigError` with code `UNKNOWN_WORKFLOW_REFERENCE` (at execution) if `ref` names no registered workflow.
30
30
  */
31
- export function stepWorkflow(opts) {
31
+ export function workflow(opts) {
32
32
  if (!opts.id || opts.id.trim() === '') {
33
33
  throw new NoeticConfigError({
34
34
  code: 'EMPTY_STEP_ID',
35
- message: 'step.workflow() requires a non-empty id.',
36
- hint: 'Pass a unique string as the id field, e.g. step.workflow({ id: "verify", ... }).',
35
+ message: 'workflow() requires a non-empty id.',
36
+ hint: 'Pass a unique string as the id field, e.g. workflow({ id: "verify", ... }).',
37
37
  });
38
38
  }
39
39
  if ((opts.document === undefined) === (opts.ref === undefined)) {
40
40
  throw new NoeticConfigError({
41
41
  code: 'INVALID_WORKFLOW_SOURCE',
42
- message: `step.workflow('${opts.id}') requires exactly one of 'document' (inline) or 'ref' (named).`,
42
+ message: `workflow('${opts.id}') requires exactly one of 'document' (inline) or 'ref' (named).`,
43
43
  hint: "Pass document: { version: 1, root: ... } or ref: '<name>' with a workflows registry.",
44
44
  });
45
45
  }
@@ -48,14 +48,14 @@ export function stepWorkflow(opts) {
48
48
  // across sessions re-hydrates when it runs under a different harness
49
49
  // instead of routing nested steps through the first one.
50
50
  let cached;
51
- return stepBuilders.step.run({
51
+ return runCode({
52
52
  id: opts.id,
53
53
  execute: async (input, ctx) => {
54
54
  const harness = ctx.harness;
55
55
  if (!harness) {
56
56
  throw new NoeticConfigError({
57
57
  code: 'MISSING_HARNESS_CONTEXT',
58
- message: 'step.workflow requires a harness on the execution context.',
58
+ message: 'workflow requires a harness on the execution context.',
59
59
  hint: 'Execute this step via AgentHarness.run() or ensure ctx.harness is set.',
60
60
  });
61
61
  }
@@ -70,11 +70,6 @@ export function stepWorkflow(opts) {
70
70
  },
71
71
  });
72
72
  }
73
- /** @public The step builder namespace: the base builders plus `workflow`. */
74
- export const step = {
75
- ...stepBuilders.step,
76
- workflow: stepWorkflow,
77
- };
78
73
  //#endregion
79
74
  //#region Helpers
80
75
  function hydrate(opts, executeStep) {
@@ -82,7 +77,7 @@ function hydrate(opts, executeStep) {
82
77
  if (!doc) {
83
78
  throw new NoeticConfigError({
84
79
  code: 'UNKNOWN_WORKFLOW_REFERENCE',
85
- message: `Workflow '${opts.ref}' referenced by step.workflow('${opts.id}') is not registered.`,
80
+ message: `Workflow '${opts.ref}' referenced by workflow('${opts.id}') is not registered.`,
86
81
  hint: `Pass named workflows via the workflows option. Available: ${[
87
82
  ...(opts.workflows?.keys() ?? []),
88
83
  ].join(', ') || '(none)'}.`,
@@ -35,7 +35,7 @@ export declare function otherwise<TContext = ContextData, I = unknown, O = unkno
35
35
  *
36
36
  * @public
37
37
  * @param clauses - Ordered `WhenClause` and optional trailing `OtherwiseClause`.
38
- * @returns A route function suitable for `branch({ route })`.
38
+ * @returns A route function suitable for `conditional({ route })`.
39
39
  */
40
40
  export declare function semanticRoute<TContext = ContextData, I = unknown, O = unknown>(...clauses: Clause<TContext, I, O>[]): (input: I, ctx: Context) => Promise<Step<TContext, I, O> | null>;
41
41
  interface SemanticSwitchSimple<TContext, I, O> {
@@ -60,7 +60,7 @@ interface SemanticSwitchAdvanced<TContext, I, O> {
60
60
  *
61
61
  * @public
62
62
  * @param opts - Simple form with `Record<string, Step>` cases, or advanced form with multi-label cases.
63
- * @returns A route function suitable for `branch({ route })`.
63
+ * @returns A route function suitable for `conditional({ route })`.
64
64
  */
65
65
  export declare function semanticSwitch<TContext = ContextData, I = unknown, O = unknown>(opts: SemanticSwitchSimple<TContext, I, O>): (input: I, ctx: Context) => Promise<Step<TContext, I, O> | null>;
66
66
  /** @public */
@@ -85,7 +85,7 @@ function isOtherwise(clause) {
85
85
  *
86
86
  * @public
87
87
  * @param clauses - Ordered `WhenClause` and optional trailing `OtherwiseClause`.
88
- * @returns A route function suitable for `branch({ route })`.
88
+ * @returns A route function suitable for `conditional({ route })`.
89
89
  */
90
90
  export function semanticRoute(...clauses) {
91
91
  return async (input, ctx) => {