@noetic-tools/core 5.3.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 (82) 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 +12 -1
  4. package/dist/adapters/openrouter.js +79 -5
  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 +54 -40
  28. package/dist/harness/agent-harness.js +44 -33
  29. package/dist/harness/deps/types.d.ts +1 -1
  30. package/dist/harness/model-call.d.ts +1 -1
  31. package/dist/harness/model-call.js +23 -18
  32. package/dist/index.d.ts +21 -33
  33. package/dist/index.js +10 -26
  34. package/dist/interpreter/action-types.d.ts +1 -1
  35. package/dist/interpreter/collect-tools.js +7 -7
  36. package/dist/interpreter/execute-action.d.ts +5 -5
  37. package/dist/interpreter/execute-action.js +284 -218
  38. package/dist/interpreter/execute-control.d.ts +9 -9
  39. package/dist/interpreter/execute-control.js +27 -27
  40. package/dist/interpreter/execute-sub-harness.d.ts +1 -1
  41. package/dist/interpreter/execute-sub-harness.js +7 -26
  42. package/dist/interpreter/execute.d.ts +1 -1
  43. package/dist/interpreter/execute.js +26 -25
  44. package/dist/interpreter/step-dispatcher.d.ts +1 -1
  45. package/dist/interpreter/step-dispatcher.js +3 -3
  46. package/dist/interpreter/structured-output.d.ts +14 -0
  47. package/dist/interpreter/structured-output.js +40 -0
  48. package/dist/interpreter/typeguards.d.ts +1 -1
  49. package/dist/interpreter/typeguards.js +1 -1
  50. package/dist/portable/builders.d.ts +3 -3
  51. package/dist/portable/builders.js +6 -5
  52. package/dist/portable/context-layers.d.ts +1 -1
  53. package/dist/portable/context-layers.js +1 -1
  54. package/dist/runtime/broadcaster-utils.d.ts +1 -1
  55. package/dist/runtime/broadcaster-utils.js +1 -1
  56. package/dist/runtime/context-impl.d.ts +8 -10
  57. package/dist/runtime/context-impl.js +8 -12
  58. package/dist/runtime/durable/step-ledger.d.ts +2 -2
  59. package/dist/runtime/durable/step-ledger.js +3 -3
  60. package/dist/runtime/session-runner.d.ts +12 -1
  61. package/dist/runtime/session-runner.js +33 -1
  62. package/dist/runtime/tool-context.js +0 -2
  63. package/dist/schemas/workflow.d.ts +3 -3
  64. package/dist/schemas/workflow.js +2 -2
  65. package/dist/types/checkpoint.d.ts +11 -2
  66. package/dist/types/checkpoint.js +10 -1
  67. package/dist/{runtime → util}/detached-handle.js +1 -1
  68. package/package.json +6 -4
  69. package/schema/noetic-workflow.schema.json +24 -11
  70. package/dist/builders/context-option.d.ts +0 -23
  71. package/dist/builders/context-option.js +0 -22
  72. package/dist/deprecated.d.ts +0 -30
  73. package/dist/deprecated.js +0 -28
  74. package/dist/patterns/interview.d.ts +0 -53
  75. package/dist/patterns/interview.js +0 -113
  76. package/dist/patterns/plans.d.ts +0 -44
  77. package/dist/patterns/plans.js +0 -125
  78. package/dist/patterns/ralph-wiggum.d.ts +0 -19
  79. package/dist/patterns/ralph-wiggum.js +0 -37
  80. package/dist/patterns/react.d.ts +0 -19
  81. package/dist/patterns/react.js +0 -41
  82. /package/dist/{runtime → util}/detached-handle.d.ts +0 -0
@@ -1,6 +1,5 @@
1
1
  import { NoeticConfigError } from '@noetic-tools/types';
2
2
  import { getDefaultRegistrar } from '../types/step-registrar.js';
3
- import { resolveContextOption } from './context-option.js';
4
3
  /**
5
4
  * Creates a provide step that attaches context layers to its child without creating an isolated context.
6
5
  * Like React's Context.Provider — layers are available to all descendant steps.
@@ -10,35 +9,35 @@ import { resolveContextOption } from './context-option.js';
10
9
  * @param opts.id - Unique step identifier used in traces and error messages.
11
10
  * @param opts.child - Step to execute with the provided layers.
12
11
  * @param opts.context - Context layers to provide to descendant steps.
13
- * @returns A `StepProvide` step.
12
+ * @returns A `StepWithContext` step.
14
13
  * @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
15
14
  * @throws `NoeticConfigError` with code `MISSING_CHILD_STEP` if `child` is not provided.
16
15
  */
17
- export function provide(opts) {
16
+ export function withContext(opts) {
18
17
  if (!opts.id?.trim()) {
19
18
  throw new NoeticConfigError({
20
19
  code: 'EMPTY_STEP_ID',
21
- message: 'provide() requires a non-empty id.',
22
- hint: 'Pass a unique string as the id field, e.g. provide({ id: "my-provider", ... }).',
20
+ message: 'withContext() requires a non-empty id.',
21
+ hint: 'Pass a unique string as the id field, e.g. withContext({ id: "my-provider", ... }).',
23
22
  });
24
23
  }
25
24
  if (!opts.child) {
26
25
  throw new NoeticConfigError({
27
26
  code: 'MISSING_CHILD_STEP',
28
- message: 'provide() requires a child step.',
27
+ message: 'withContext() requires a child step.',
29
28
  hint: 'Provide a child step to execute with the provided context layers.',
30
29
  });
31
30
  }
32
- const layers = resolveContextOption(opts);
31
+ const layers = opts.context;
33
32
  if (!layers) {
34
33
  throw new NoeticConfigError({
35
34
  code: 'MISSING_CONTEXT_LAYERS',
36
- message: 'provide() requires context layers.',
37
- hint: 'Pass context: [workingMemoryContext()]. The `memory` key is the deprecated spelling of `context`.',
35
+ message: 'withContext() requires context layers.',
36
+ hint: 'Pass context: [scratchpad()].',
38
37
  });
39
38
  }
40
39
  const built = {
41
- kind: 'provide',
40
+ kind: 'withContext',
42
41
  id: opts.id,
43
42
  child: opts.child,
44
43
  context: layers,
@@ -4,8 +4,6 @@ interface SpawnOpts<TContext, I, O> {
4
4
  id: string;
5
5
  child: Step<TContext, I, O>;
6
6
  context?: ContextConfig | ContextLayer[];
7
- /** @deprecated Renamed to `context`. */
8
- memory?: ContextConfig | ContextLayer[];
9
7
  timeout?: number;
10
8
  /**
11
9
  * Optional per-step subprocess adapter override. The interpreter routes
@@ -1,6 +1,5 @@
1
1
  import { NoeticConfigError } from '@noetic-tools/types';
2
2
  import { getDefaultRegistrar } from '../types/step-registrar.js';
3
- import { resolveContextOption } from './context-option.js';
4
3
  //#endregion
5
4
  //#region Public API
6
5
  /**
@@ -38,12 +37,12 @@ export function spawn(opts) {
38
37
  kind: 'spawn',
39
38
  id: opts.id,
40
39
  child: opts.child,
41
- context: resolveContextOption(opts),
40
+ context: opts.context,
42
41
  timeout: opts.timeout,
43
42
  subprocess: opts.subprocess,
44
43
  };
45
44
  getDefaultRegistrar().register(built);
46
- // Ensure the child is addressable by id — builders for `run`/`llm`/`tool`
45
+ // Ensure the child is addressable by id — builders for `runCode`/`callModel`/`invokeTool`
47
46
  // self-register, but a caller can construct a step literal and pass it as
48
47
  // `child` without going through a builder.
49
48
  getDefaultRegistrar().register(opts.child);
@@ -1,7 +1,6 @@
1
1
  import type { ContextData } from '@noetic-tools/context';
2
- import type { Context, Lazy, ModelParams, OutputCodec, RetryPolicy, ServerToolSpec, StepLLM, StepRun, StepSubHarness, StepTool, SubHarness, SubHarnessSessionPolicy, SubHarnessSettings, SubprocessAdapter, Tool } from '@noetic-tools/types';
3
- import type { ZodType } from 'zod';
4
- export interface StepRunOpts<TContext, I, O> {
2
+ import type { Context, Lazy, ModelParams, OutputCodec, RetryPolicy, ServerToolSpec, StandardSchemaV1, StepCallModel, StepInvokeTool, StepRunCode, StepSubHarness, SubHarness, SubHarnessSessionPolicy, SubHarnessSettings, SubprocessAdapter, Tool } from '@noetic-tools/types';
3
+ export interface RunCodeOpts<TContext, I, O> {
5
4
  id: string;
6
5
  execute: (input: I, ctx: Context<TContext>) => Promise<O>;
7
6
  retry?: RetryPolicy;
@@ -12,7 +11,7 @@ export interface StepRunOpts<TContext, I, O> {
12
11
  */
13
12
  subprocess?: SubprocessAdapter;
14
13
  }
15
- export interface StepLLMOpts<TContext, O> {
14
+ export interface CallModelOpts<TContext, O> {
16
15
  id: string;
17
16
  /** Model id. Eager string or `(ctx) => string` getter (resolved at step execution). */
18
17
  model: Lazy<string, TContext>;
@@ -24,14 +23,19 @@ export interface StepLLMOpts<TContext, O> {
24
23
  * server tool the provider executes, e.g. web search/fetch).
25
24
  */
26
25
  tools?: Lazy<(Tool | ServerToolSpec)[] | undefined, TContext>;
27
- /** Structured output: a Zod schema or a streaming `OutputCodec` (e.g. OpenUI Lang). */
28
- output?: ZodType<O> | OutputCodec<O>;
26
+ /** Structured output: a Standard Schema (Zod, Valibot, …) or a streaming `OutputCodec` (e.g. OpenUI Lang). */
27
+ output?: StandardSchemaV1<unknown, O> | OutputCodec<O>;
28
+ /**
29
+ * Explicit raw JSON Schema override sent to the model. For non-Zod schemas,
30
+ * it takes precedence over StandardJSONSchemaV1 conversion.
31
+ */
32
+ outputJsonSchema?: Record<string, unknown>;
29
33
  params?: ModelParams;
30
34
  emit?: boolean | ((eventType: string, data: Record<string, unknown>) => boolean);
31
35
  }
32
- export interface StepToolOpts<I, O> {
36
+ export interface InvokeToolOpts<I, O> {
33
37
  id: string;
34
- tool: Tool<ZodType<I>, ZodType<O>>;
38
+ tool: Tool<StandardSchemaV1<unknown, I>, StandardSchemaV1<unknown, O>>;
35
39
  args?: Partial<I>;
36
40
  }
37
41
  export interface StepSubHarnessOpts<TContext, O> {
@@ -44,58 +48,65 @@ export interface StepSubHarnessOpts<TContext, O> {
44
48
  settings?: SubHarnessSettings;
45
49
  /** System instructions applied on the first message of a fresh session. */
46
50
  instructions?: Lazy<string | undefined, TContext>;
47
- /** Optional Zod schema; when set the assistant text is JSON-parsed and validated. */
48
- output?: ZodType<O>;
51
+ /** Optional Standard Schema; when set the assistant text is JSON-parsed and validated. */
52
+ output?: StandardSchemaV1<unknown, O>;
49
53
  /** Session reuse + teardown policy across steps. */
50
54
  session?: SubHarnessSessionPolicy;
51
55
  emit?: boolean | ((eventType: string, data: Record<string, unknown>) => boolean);
52
56
  }
57
+ /**
58
+ * Creates a pure async computation step.
59
+ *
60
+ * @public
61
+ * @param opts.id - Unique step identifier used in traces and error messages.
62
+ * @param opts.execute - Async function `(input, ctx) => output` that performs the work.
63
+ * @param opts.retry - Optional retry policy controlling attempts, backoff, and delay.
64
+ * @param opts.subprocess - Optional per-step subprocess adapter override.
65
+ * @returns A `StepRunCode` that can be composed into larger pipelines. The step
66
+ * is auto-registered in the shared step registry so the subprocess
67
+ * adapter can dispatch it by id.
68
+ * @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
69
+ * @throws `NoeticConfigError` with code `MISSING_EXECUTE_FUNCTION` if `execute` is not provided.
70
+ * @throws `NoeticConfigError` with code `DUPLICATE_STEP_ID` if another step with the same id is already registered with a different body.
71
+ */
72
+ export declare function runCode<TContext = ContextData, I = unknown, O = unknown>(opts: RunCodeOpts<TContext, I, O>): StepRunCode<TContext, I, O>;
73
+ /**
74
+ * Creates a model call step with optional tools and structured output.
75
+ *
76
+ * @public
77
+ * @param opts.id - Unique step identifier used in traces and error messages.
78
+ * @param opts.model - Model identifier, eager string or `(ctx) => string` getter (resolved at step execution time).
79
+ * @param opts.instructions - Optional system prompt; eager string or `(ctx) => string | undefined` getter.
80
+ * @param opts.tools - Optional tools; eager array or `(ctx) => Tool[] | undefined` getter.
81
+ * @param opts.output - Optional Zod schema enabling structured output parsing.
82
+ * @param opts.params - Optional model parameters (temperature, topP, maxTokens, stopSequences).
83
+ * @returns A `StepCallModel` that can be composed into larger pipelines. The step
84
+ * is auto-registered in the shared step registry.
85
+ * @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
86
+ * @throws `NoeticConfigError` with code `MISSING_MODEL` if an eager `model` string is empty. Function-form models are validated at step execution.
87
+ */
88
+ export declare function callModel<TContext = ContextData, I = unknown, O = unknown>(opts: CallModelOpts<TContext, O>): StepCallModel<TContext, I, O>;
89
+ /**
90
+ * Creates a tool execution step that invokes a typed tool definition.
91
+ *
92
+ * @public
93
+ * @param opts.id - Unique step identifier used in traces and error messages.
94
+ * @param opts.tool - The tool definition with typed input/output schemas.
95
+ * @param opts.args - Optional partial args that override or supplement model-provided arguments.
96
+ * @returns A `StepInvokeTool` that can be composed into larger pipelines. The step
97
+ * is auto-registered in the shared step registry.
98
+ * @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
99
+ * @throws `NoeticConfigError` with code `MISSING_TOOL` if `tool` is not provided.
100
+ */
101
+ export declare function invokeTool<TContext = ContextData, I = unknown, O = unknown>(opts: InvokeToolOpts<I, O>): StepInvokeTool<TContext, I, O>;
102
+ /**
103
+ * The sub-harness step builder namespace. Unlike the flattened base builders
104
+ * (`runCode`, `callModel`, `invokeTool`), the coding-agent harness builders
105
+ * stay grouped under `step` — their `step.<harness>()` API is unchanged.
106
+ *
107
+ * @public
108
+ */
53
109
  export declare const step: {
54
- /**
55
- * Creates a pure async computation step.
56
- *
57
- * @public
58
- * @param opts.id - Unique step identifier used in traces and error messages.
59
- * @param opts.execute - Async function `(input, ctx) => output` that performs the work.
60
- * @param opts.retry - Optional retry policy controlling attempts, backoff, and delay.
61
- * @param opts.subprocess - Optional per-step subprocess adapter override.
62
- * @returns A `StepRun` that can be composed into larger pipelines. The step
63
- * is auto-registered in the shared step registry so the subprocess
64
- * adapter can dispatch it by id.
65
- * @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
66
- * @throws `NoeticConfigError` with code `MISSING_EXECUTE_FUNCTION` if `execute` is not provided.
67
- * @throws `NoeticConfigError` with code `DUPLICATE_STEP_ID` if another step with the same id is already registered with a different body.
68
- */
69
- run<TContext = ContextData, I = unknown, O = unknown>(opts: StepRunOpts<TContext, I, O>): StepRun<TContext, I, O>;
70
- /**
71
- * Creates an LLM model call step with optional tools and structured output.
72
- *
73
- * @public
74
- * @param opts.id - Unique step identifier used in traces and error messages.
75
- * @param opts.model - Model identifier, eager string or `(ctx) => string` getter (resolved at step execution time).
76
- * @param opts.instructions - Optional system prompt; eager string or `(ctx) => string | undefined` getter.
77
- * @param opts.tools - Optional tools; eager array or `(ctx) => Tool[] | undefined` getter.
78
- * @param opts.output - Optional Zod schema enabling structured output parsing.
79
- * @param opts.params - Optional model parameters (temperature, topP, maxTokens, stopSequences).
80
- * @returns A `StepLLM` that can be composed into larger pipelines. The step
81
- * is auto-registered in the shared step registry.
82
- * @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
83
- * @throws `NoeticConfigError` with code `MISSING_MODEL` if an eager `model` string is empty. Function-form models are validated at step execution.
84
- */
85
- llm<TContext = ContextData, I = unknown, O = unknown>(opts: StepLLMOpts<TContext, O>): StepLLM<TContext, I, O>;
86
- /**
87
- * Creates a tool execution step that invokes a typed tool definition.
88
- *
89
- * @public
90
- * @param opts.id - Unique step identifier used in traces and error messages.
91
- * @param opts.tool - The tool definition with typed input/output schemas.
92
- * @param opts.args - Optional partial args that override or supplement LLM-provided arguments.
93
- * @returns A `StepTool` that can be composed into larger pipelines. The step
94
- * is auto-registered in the shared step registry.
95
- * @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
96
- * @throws `NoeticConfigError` with code `MISSING_TOOL` if `tool` is not provided.
97
- */
98
- tool<TContext = ContextData, I = unknown, O = unknown>(opts: StepToolOpts<I, O>): StepTool<TContext, I, O>;
99
110
  /**
100
111
  * Creates a step that delegates a turn to the Claude Code harness.
101
112
  *
@@ -41,118 +41,125 @@ function buildSubHarnessStep(kind, builderName, opts) {
41
41
  }
42
42
  //#endregion
43
43
  //#region Builders
44
+ /**
45
+ * Creates a pure async computation step.
46
+ *
47
+ * @public
48
+ * @param opts.id - Unique step identifier used in traces and error messages.
49
+ * @param opts.execute - Async function `(input, ctx) => output` that performs the work.
50
+ * @param opts.retry - Optional retry policy controlling attempts, backoff, and delay.
51
+ * @param opts.subprocess - Optional per-step subprocess adapter override.
52
+ * @returns A `StepRunCode` that can be composed into larger pipelines. The step
53
+ * is auto-registered in the shared step registry so the subprocess
54
+ * adapter can dispatch it by id.
55
+ * @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
56
+ * @throws `NoeticConfigError` with code `MISSING_EXECUTE_FUNCTION` if `execute` is not provided.
57
+ * @throws `NoeticConfigError` with code `DUPLICATE_STEP_ID` if another step with the same id is already registered with a different body.
58
+ */
59
+ export function runCode(opts) {
60
+ if (!opts.id || opts.id.trim() === '') {
61
+ throw new NoeticConfigError({
62
+ code: 'EMPTY_STEP_ID',
63
+ message: 'runCode() requires a non-empty id.',
64
+ hint: 'Pass a unique string as the id field, e.g. runCode({ id: "my-step", ... }).',
65
+ });
66
+ }
67
+ if (!opts.execute) {
68
+ throw new NoeticConfigError({
69
+ code: 'MISSING_EXECUTE_FUNCTION',
70
+ message: 'runCode() requires an execute function.',
71
+ hint: 'Provide an async execute function, e.g. execute: async (input, ctx) => result.',
72
+ });
73
+ }
74
+ const built = {
75
+ kind: 'runCode',
76
+ ...opts,
77
+ };
78
+ getDefaultRegistrar().register(built);
79
+ return built;
80
+ }
81
+ /**
82
+ * Creates a model call step with optional tools and structured output.
83
+ *
84
+ * @public
85
+ * @param opts.id - Unique step identifier used in traces and error messages.
86
+ * @param opts.model - Model identifier, eager string or `(ctx) => string` getter (resolved at step execution time).
87
+ * @param opts.instructions - Optional system prompt; eager string or `(ctx) => string | undefined` getter.
88
+ * @param opts.tools - Optional tools; eager array or `(ctx) => Tool[] | undefined` getter.
89
+ * @param opts.output - Optional Zod schema enabling structured output parsing.
90
+ * @param opts.params - Optional model parameters (temperature, topP, maxTokens, stopSequences).
91
+ * @returns A `StepCallModel` that can be composed into larger pipelines. The step
92
+ * is auto-registered in the shared step registry.
93
+ * @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
94
+ * @throws `NoeticConfigError` with code `MISSING_MODEL` if an eager `model` string is empty. Function-form models are validated at step execution.
95
+ */
96
+ export function callModel(opts) {
97
+ if (!opts.id || opts.id.trim() === '') {
98
+ throw new NoeticConfigError({
99
+ code: 'EMPTY_STEP_ID',
100
+ message: 'callModel() requires a non-empty id.',
101
+ hint: 'Pass a unique string as the id field, e.g. callModel({ id: "my-llm", ... }).',
102
+ });
103
+ }
104
+ // Only validate eager models here. Function-form models are validated
105
+ // post-resolution in executeCallModel so the same MISSING_MODEL error surfaces
106
+ // whether the caller passes a string or a getter.
107
+ if (typeof opts.model === 'string' && opts.model.trim() === '') {
108
+ throw new NoeticConfigError({
109
+ code: 'MISSING_MODEL',
110
+ message: 'callModel() requires a non-empty model.',
111
+ hint: "Pass a model identifier, e.g. model: 'anthropic/claude-sonnet-4-20250514'.",
112
+ });
113
+ }
114
+ const built = {
115
+ kind: 'callModel',
116
+ ...opts,
117
+ };
118
+ getDefaultRegistrar().register(built);
119
+ return built;
120
+ }
121
+ /**
122
+ * Creates a tool execution step that invokes a typed tool definition.
123
+ *
124
+ * @public
125
+ * @param opts.id - Unique step identifier used in traces and error messages.
126
+ * @param opts.tool - The tool definition with typed input/output schemas.
127
+ * @param opts.args - Optional partial args that override or supplement model-provided arguments.
128
+ * @returns A `StepInvokeTool` that can be composed into larger pipelines. The step
129
+ * is auto-registered in the shared step registry.
130
+ * @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
131
+ * @throws `NoeticConfigError` with code `MISSING_TOOL` if `tool` is not provided.
132
+ */
133
+ export function invokeTool(opts) {
134
+ if (!opts.id || opts.id.trim() === '') {
135
+ throw new NoeticConfigError({
136
+ code: 'EMPTY_STEP_ID',
137
+ message: 'invokeTool() requires a non-empty id.',
138
+ hint: 'Pass a unique string as the id field, e.g. invokeTool({ id: "my-tool", ... }).',
139
+ });
140
+ }
141
+ if (!opts.tool) {
142
+ throw new NoeticConfigError({
143
+ code: 'MISSING_TOOL',
144
+ message: 'invokeTool() requires a tool.',
145
+ hint: 'Provide a tool definition created with the tool() builder.',
146
+ });
147
+ }
148
+ const built = {
149
+ kind: 'invokeTool',
150
+ ...opts,
151
+ };
152
+ getDefaultRegistrar().register(built);
153
+ return built;
154
+ }
155
+ /**
156
+ * The sub-harness step builder namespace. Unlike the flattened base builders
157
+ * (`runCode`, `callModel`, `invokeTool`), the coding-agent harness builders
158
+ * stay grouped under `step` — their `step.<harness>()` API is unchanged.
159
+ *
160
+ * @public
161
+ */
44
162
  export const step = {
45
- /**
46
- * Creates a pure async computation step.
47
- *
48
- * @public
49
- * @param opts.id - Unique step identifier used in traces and error messages.
50
- * @param opts.execute - Async function `(input, ctx) => output` that performs the work.
51
- * @param opts.retry - Optional retry policy controlling attempts, backoff, and delay.
52
- * @param opts.subprocess - Optional per-step subprocess adapter override.
53
- * @returns A `StepRun` that can be composed into larger pipelines. The step
54
- * is auto-registered in the shared step registry so the subprocess
55
- * adapter can dispatch it by id.
56
- * @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
57
- * @throws `NoeticConfigError` with code `MISSING_EXECUTE_FUNCTION` if `execute` is not provided.
58
- * @throws `NoeticConfigError` with code `DUPLICATE_STEP_ID` if another step with the same id is already registered with a different body.
59
- */
60
- run(opts) {
61
- if (!opts.id || opts.id.trim() === '') {
62
- throw new NoeticConfigError({
63
- code: 'EMPTY_STEP_ID',
64
- message: 'step.run() requires a non-empty id.',
65
- hint: 'Pass a unique string as the id field, e.g. step.run({ id: "my-step", ... }).',
66
- });
67
- }
68
- if (!opts.execute) {
69
- throw new NoeticConfigError({
70
- code: 'MISSING_EXECUTE_FUNCTION',
71
- message: 'step.run() requires an execute function.',
72
- hint: 'Provide an async execute function, e.g. execute: async (input, ctx) => result.',
73
- });
74
- }
75
- const built = {
76
- kind: 'run',
77
- ...opts,
78
- };
79
- getDefaultRegistrar().register(built);
80
- return built;
81
- },
82
- /**
83
- * Creates an LLM model call step with optional tools and structured output.
84
- *
85
- * @public
86
- * @param opts.id - Unique step identifier used in traces and error messages.
87
- * @param opts.model - Model identifier, eager string or `(ctx) => string` getter (resolved at step execution time).
88
- * @param opts.instructions - Optional system prompt; eager string or `(ctx) => string | undefined` getter.
89
- * @param opts.tools - Optional tools; eager array or `(ctx) => Tool[] | undefined` getter.
90
- * @param opts.output - Optional Zod schema enabling structured output parsing.
91
- * @param opts.params - Optional model parameters (temperature, topP, maxTokens, stopSequences).
92
- * @returns A `StepLLM` that can be composed into larger pipelines. The step
93
- * is auto-registered in the shared step registry.
94
- * @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
95
- * @throws `NoeticConfigError` with code `MISSING_MODEL` if an eager `model` string is empty. Function-form models are validated at step execution.
96
- */
97
- llm(opts) {
98
- if (!opts.id || opts.id.trim() === '') {
99
- throw new NoeticConfigError({
100
- code: 'EMPTY_STEP_ID',
101
- message: 'step.llm() requires a non-empty id.',
102
- hint: 'Pass a unique string as the id field, e.g. step.llm({ id: "my-llm", ... }).',
103
- });
104
- }
105
- // Only validate eager models here. Function-form models are validated
106
- // post-resolution in executeLLM so the same MISSING_MODEL error surfaces
107
- // whether the caller passes a string or a getter.
108
- if (typeof opts.model === 'string' && opts.model.trim() === '') {
109
- throw new NoeticConfigError({
110
- code: 'MISSING_MODEL',
111
- message: 'step.llm() requires a non-empty model.',
112
- hint: "Pass a model identifier, e.g. model: 'anthropic/claude-sonnet-4-20250514'.",
113
- });
114
- }
115
- const built = {
116
- kind: 'llm',
117
- ...opts,
118
- };
119
- getDefaultRegistrar().register(built);
120
- return built;
121
- },
122
- /**
123
- * Creates a tool execution step that invokes a typed tool definition.
124
- *
125
- * @public
126
- * @param opts.id - Unique step identifier used in traces and error messages.
127
- * @param opts.tool - The tool definition with typed input/output schemas.
128
- * @param opts.args - Optional partial args that override or supplement LLM-provided arguments.
129
- * @returns A `StepTool` that can be composed into larger pipelines. The step
130
- * is auto-registered in the shared step registry.
131
- * @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
132
- * @throws `NoeticConfigError` with code `MISSING_TOOL` if `tool` is not provided.
133
- */
134
- tool(opts) {
135
- if (!opts.id || opts.id.trim() === '') {
136
- throw new NoeticConfigError({
137
- code: 'EMPTY_STEP_ID',
138
- message: 'step.tool() requires a non-empty id.',
139
- hint: 'Pass a unique string as the id field, e.g. step.tool({ id: "my-tool", ... }).',
140
- });
141
- }
142
- if (!opts.tool) {
143
- throw new NoeticConfigError({
144
- code: 'MISSING_TOOL',
145
- message: 'step.tool() requires a tool.',
146
- hint: 'Provide a tool definition created with the tool() builder.',
147
- });
148
- }
149
- const built = {
150
- kind: 'tool',
151
- ...opts,
152
- };
153
- getDefaultRegistrar().register(built);
154
- return built;
155
- },
156
163
  /**
157
164
  * Creates a step that delegates a turn to the Claude Code harness.
158
165
  *
@@ -1,6 +1,5 @@
1
- import type { FunctionCallItem, FunctionCallOutputItem, Item, ItemSchemaExtensions, Tool, ToolContextDeclaration, ToolExecutionContext, ToolResultExtensionItem, ToolUiDeclaration } from '@noetic-tools/types';
2
- import type { ZodTypeAny, z } from 'zod';
3
- interface ToolConfig<I extends ZodTypeAny, O extends ZodTypeAny> {
1
+ import type { FunctionCallItem, FunctionCallOutputItem, InferSchemaOutput, InputSchemaConfig, Item, ItemSchemaExtensions, StandardSchemaV1, Tool, ToolContextDeclaration, ToolExecutionContext, ToolResultExtensionItem, ToolUiDeclaration } from '@noetic-tools/types';
2
+ type ToolConfig<I extends StandardSchemaV1, O extends StandardSchemaV1> = {
4
3
  name: string;
5
4
  description: string;
6
5
  input: I;
@@ -9,21 +8,19 @@ interface ToolConfig<I extends ZodTypeAny, O extends ZodTypeAny> {
9
8
  decorateResultItem?: (params: {
10
9
  baseItem: FunctionCallOutputItem;
11
10
  callItem: FunctionCallItem;
12
- args: z.infer<I>;
13
- result: z.infer<O> | undefined;
11
+ args: InferSchemaOutput<I>;
12
+ result: InferSchemaOutput<O> | undefined;
14
13
  output: string;
15
14
  error?: boolean;
16
15
  }) => Item | ToolResultExtensionItem;
17
- execute: (args: z.infer<I>, toolCtx: ToolExecutionContext) => Promise<z.infer<O>>;
16
+ execute: (args: InferSchemaOutput<I>, toolCtx: ToolExecutionContext) => Promise<InferSchemaOutput<O>>;
18
17
  needsApproval?: boolean;
19
- /** Optional context declaration — the runtime generates a ContextLayer from this via toolContextLayer(). */
18
+ /** Optional context declaration — the runtime generates a ContextLayer from this via toolCalls(). */
20
19
  context?: ToolContextDeclaration;
21
- /** @deprecated Renamed to `context`. */
22
- memory?: ToolContextDeclaration;
23
20
  /** Optional UI declaration — the runtime emits the rendered fragments at call/progress/result points. */
24
21
  ui?: ToolUiDeclaration<I, O>;
25
- }
26
- interface GeneratorToolConfig<I extends ZodTypeAny, E extends ZodTypeAny, O extends ZodTypeAny> {
22
+ } & InputSchemaConfig<I>;
23
+ type GeneratorToolConfig<I extends StandardSchemaV1, E extends StandardSchemaV1, O extends StandardSchemaV1> = {
27
24
  name: string;
28
25
  description: string;
29
26
  input: I;
@@ -33,30 +30,29 @@ interface GeneratorToolConfig<I extends ZodTypeAny, E extends ZodTypeAny, O exte
33
30
  decorateResultItem?: (params: {
34
31
  baseItem: FunctionCallOutputItem;
35
32
  callItem: FunctionCallItem;
36
- args: z.infer<I>;
37
- result: z.infer<O> | undefined;
33
+ args: InferSchemaOutput<I>;
34
+ result: InferSchemaOutput<O> | undefined;
38
35
  output: string;
39
36
  error?: boolean;
40
37
  }) => Item | ToolResultExtensionItem;
41
- execute: (args: z.infer<I>, toolCtx: ToolExecutionContext) => AsyncGenerator<z.infer<E>, z.infer<O>>;
38
+ execute: (args: InferSchemaOutput<I>, toolCtx: ToolExecutionContext) => AsyncGenerator<InferSchemaOutput<E>, InferSchemaOutput<O>>;
42
39
  needsApproval?: boolean;
43
- /** Optional context declaration — the runtime generates a ContextLayer from this via toolContextLayer(). */
40
+ /** Optional context declaration — the runtime generates a ContextLayer from this via toolCalls(). */
44
41
  context?: ToolContextDeclaration;
45
- /** @deprecated Renamed to `context`. */
46
- memory?: ToolContextDeclaration;
47
42
  /** Optional UI declaration — the runtime emits the rendered fragments at call/progress/result points. */
48
- ui?: ToolUiDeclaration<I, O, z.infer<E>>;
49
- }
43
+ ui?: ToolUiDeclaration<I, O, InferSchemaOutput<E>>;
44
+ } & InputSchemaConfig<I>;
50
45
  /**
51
- * Creates a typed Tool with Zod schema inference for input and output.
46
+ * Creates a typed Tool with Standard Schema inference for input and output.
47
+ * Accepts Zod, Valibot, or any Standard Schema v1 implementation.
52
48
  *
53
49
  * @public
54
50
  */
55
- export declare function tool<I extends ZodTypeAny, O extends ZodTypeAny>(config: ToolConfig<I, O>): Tool<I, O>;
51
+ export declare function tool<I extends StandardSchemaV1, O extends StandardSchemaV1>(config: ToolConfig<I, O>): Tool<I, O>;
56
52
  /**
57
53
  * Creates a typed Tool that can stream progress events before returning a final output.
58
54
  *
59
55
  * @public
60
56
  */
61
- export declare function toolWithGenerator<I extends ZodTypeAny, E extends ZodTypeAny, O extends ZodTypeAny>(config: GeneratorToolConfig<I, E, O>): Tool<I, O>;
57
+ export declare function toolWithGenerator<I extends StandardSchemaV1, E extends StandardSchemaV1, O extends StandardSchemaV1>(config: GeneratorToolConfig<I, E, O>): Tool<I, O>;
62
58
  export {};
@@ -1,5 +1,4 @@
1
1
  import { NoeticConfigError } from '@noetic-tools/types';
2
- import { resolveContextOption } from './context-option.js';
3
2
  //#endregion
4
3
  //#region Helpers
5
4
  function validateToolConfig(name, execute) {
@@ -21,7 +20,8 @@ function validateToolConfig(name, execute) {
21
20
  //#endregion
22
21
  //#region Public API
23
22
  /**
24
- * Creates a typed Tool with Zod schema inference for input and output.
23
+ * Creates a typed Tool with Standard Schema inference for input and output.
24
+ * Accepts Zod, Valibot, or any Standard Schema v1 implementation.
25
25
  *
26
26
  * @public
27
27
  */
@@ -32,11 +32,12 @@ export function tool(config) {
32
32
  description: config.description,
33
33
  input: config.input,
34
34
  output: config.output,
35
+ inputJsonSchema: config.inputJsonSchema,
35
36
  itemSchemas: config.itemSchemas,
36
37
  decorateResultItem: config.decorateResultItem,
37
38
  execute: config.execute,
38
39
  needsApproval: config.needsApproval,
39
- context: resolveContextOption(config),
40
+ context: config.context,
40
41
  ui: config.ui,
41
42
  };
42
43
  }
@@ -53,11 +54,12 @@ export function toolWithGenerator(config) {
53
54
  input: config.input,
54
55
  event: config.event,
55
56
  output: config.output,
57
+ inputJsonSchema: config.inputJsonSchema,
56
58
  itemSchemas: config.itemSchemas,
57
59
  decorateResultItem: config.decorateResultItem,
58
60
  execute: config.execute,
59
61
  needsApproval: config.needsApproval,
60
- context: resolveContextOption(config),
62
+ context: config.context,
61
63
  ui: config.ui,
62
64
  };
63
65
  }
@@ -1,7 +1,7 @@
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
  */
@@ -16,14 +16,14 @@ export interface HydrationContext {
16
16
  /** SubHarness adapters keyed by harness id, resolving `claude-code`/`codex`/… nodes. */
17
17
  subHarnesses?: ReadonlyMap<SubHarnessKind, SubHarness>;
18
18
  /**
19
- * Output codecs keyed by the `library` ref an `llm` node's `output` codec
19
+ * Output codecs keyed by the `library` ref a `callModel` node's `output` codec
20
20
  * reference names — the live codec built from a component library, e.g.
21
21
  * `new Map([['dashboard-lib', openUi(dashboardLibrary)]])` from
22
22
  * `@noetic-tools/openui`. Resolved the same way sub-harness adapters are.
23
23
  */
24
24
  uiLibraries?: ReadonlyMap<string, OutputCodec>;
25
25
  /**
26
- * Resolves a named subprocess adapter ref declared on a `run` node's
26
+ * Resolves a named subprocess adapter ref declared on a `runCode` node's
27
27
  * `subprocess` field. When a node omits the ref, the step falls back to
28
28
  * `ctx.subprocess` at execution time.
29
29
  */