@noetic-tools/core 5.3.0 → 5.4.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.
Files changed (94) 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/acp-agent-tool.d.ts +67 -0
  6. package/dist/builders/acp-agent-tool.js +87 -0
  7. package/dist/builders/control-flow-builders.d.ts +13 -13
  8. package/dist/builders/control-flow-builders.js +11 -11
  9. package/dist/{patterns → builders}/dynamic-workflow.d.ts +1 -1
  10. package/dist/{patterns → builders}/dynamic-workflow.js +20 -14
  11. package/dist/builders/every.d.ts +14 -14
  12. package/dist/builders/every.js +16 -16
  13. package/dist/builders/layer-provides-builders.d.ts +1 -1
  14. package/dist/builders/layer-provides-builders.js +1 -1
  15. package/dist/builders/provide-builder.d.ts +5 -12
  16. package/dist/builders/provide-builder.js +9 -10
  17. package/dist/builders/spawn-builder.d.ts +0 -2
  18. package/dist/builders/spawn-builder.js +2 -3
  19. package/dist/builders/step-builders.d.ts +103 -92
  20. package/dist/builders/step-builders.js +146 -163
  21. package/dist/builders/tool-builder.d.ts +18 -22
  22. package/dist/builders/tool-builder.js +6 -4
  23. package/dist/builders/workflow-hydrator.d.ts +11 -7
  24. package/dist/builders/workflow-hydrator.js +75 -87
  25. package/dist/builders/workflow-step.d.ts +15 -27
  26. package/dist/builders/workflow-step.js +14 -19
  27. package/dist/conditions/conditions.d.ts +2 -2
  28. package/dist/conditions/conditions.js +1 -1
  29. package/dist/harness/agent-harness.d.ts +89 -46
  30. package/dist/harness/agent-harness.js +93 -39
  31. package/dist/harness/deps/types.d.ts +1 -1
  32. package/dist/harness/model-call.d.ts +1 -1
  33. package/dist/harness/model-call.js +23 -18
  34. package/dist/index.d.ts +27 -35
  35. package/dist/index.js +13 -29
  36. package/dist/interpreter/acp-events.d.ts +67 -0
  37. package/dist/interpreter/acp-events.js +256 -0
  38. package/dist/interpreter/acp-history.d.ts +22 -0
  39. package/dist/interpreter/acp-history.js +58 -0
  40. package/dist/interpreter/action-types.d.ts +1 -1
  41. package/dist/interpreter/collect-tools.js +10 -13
  42. package/dist/interpreter/execute-acp-agent.d.ts +10 -0
  43. package/dist/interpreter/execute-acp-agent.js +505 -0
  44. package/dist/interpreter/execute-action.d.ts +5 -5
  45. package/dist/interpreter/execute-action.js +284 -218
  46. package/dist/interpreter/execute-control.d.ts +9 -9
  47. package/dist/interpreter/execute-control.js +27 -27
  48. package/dist/interpreter/execute.d.ts +1 -1
  49. package/dist/interpreter/execute.js +29 -35
  50. package/dist/interpreter/step-dispatcher.d.ts +1 -1
  51. package/dist/interpreter/step-dispatcher.js +3 -3
  52. package/dist/interpreter/structured-output.d.ts +14 -0
  53. package/dist/interpreter/structured-output.js +40 -0
  54. package/dist/interpreter/typeguards.d.ts +1 -1
  55. package/dist/interpreter/typeguards.js +1 -1
  56. package/dist/portable/builders.d.ts +5 -3
  57. package/dist/portable/builders.js +8 -5
  58. package/dist/portable/context-layers.d.ts +1 -1
  59. package/dist/portable/context-layers.js +1 -1
  60. package/dist/runtime/acp-session-store.d.ts +75 -0
  61. package/dist/runtime/acp-session-store.js +0 -0
  62. package/dist/runtime/broadcaster-utils.d.ts +1 -1
  63. package/dist/runtime/broadcaster-utils.js +1 -1
  64. package/dist/runtime/context-impl.d.ts +8 -10
  65. package/dist/runtime/context-impl.js +8 -12
  66. package/dist/runtime/durable/step-ledger.d.ts +2 -2
  67. package/dist/runtime/durable/step-ledger.js +3 -3
  68. package/dist/runtime/session-runner.d.ts +12 -1
  69. package/dist/runtime/session-runner.js +33 -1
  70. package/dist/runtime/tool-context.js +0 -2
  71. package/dist/schemas/workflow.d.ts +3 -3
  72. package/dist/schemas/workflow.js +2 -2
  73. package/dist/types/checkpoint.d.ts +11 -2
  74. package/dist/types/checkpoint.js +10 -1
  75. package/dist/{runtime → util}/detached-handle.js +1 -1
  76. package/package.json +6 -4
  77. package/schema/noetic-workflow.schema.json +239 -260
  78. package/dist/builders/context-option.d.ts +0 -23
  79. package/dist/builders/context-option.js +0 -22
  80. package/dist/deprecated.d.ts +0 -30
  81. package/dist/deprecated.js +0 -28
  82. package/dist/interpreter/execute-sub-harness.d.ts +0 -8
  83. package/dist/interpreter/execute-sub-harness.js +0 -241
  84. package/dist/interpreter/sub-harness-events.d.ts +0 -48
  85. package/dist/interpreter/sub-harness-events.js +0 -208
  86. package/dist/patterns/interview.d.ts +0 -53
  87. package/dist/patterns/interview.js +0 -113
  88. package/dist/patterns/plans.d.ts +0 -44
  89. package/dist/patterns/plans.js +0 -125
  90. package/dist/patterns/ralph-wiggum.d.ts +0 -19
  91. package/dist/patterns/ralph-wiggum.js +0 -37
  92. package/dist/patterns/react.d.ts +0 -19
  93. package/dist/patterns/react.js +0 -41
  94. /package/dist/{runtime → util}/detached-handle.d.ts +0 -0
@@ -1,199 +1,182 @@
1
1
  import { NoeticConfigError } from '@noetic-tools/types';
2
2
  import { getDefaultRegistrar } from '../types/step-registrar.js';
3
3
  //#endregion
4
- //#region SubHarness builder helper
4
+ //#region ACP agent builder helper
5
5
  /**
6
- * Shared construction for every harness step kind. Each `step.<kind>()` is a
7
- * thin wrapper so the kinds stay individually typed while the validation and
8
- * registration live in one place.
6
+ * Validation shared by `step.acpAgent`. Kept separate from the builder so the
7
+ * checks stay readable and the builder stays a one-liner.
9
8
  */
10
- function buildSubHarnessStep(kind, builderName, opts) {
9
+ function validateAcpAgentOpts(opts) {
11
10
  if (!opts.id || opts.id.trim() === '') {
12
11
  throw new NoeticConfigError({
13
12
  code: 'EMPTY_STEP_ID',
14
- message: `${builderName}() requires a non-empty id.`,
15
- hint: `Pass a unique string as the id field, e.g. ${builderName}({ id: "review", ... }).`,
13
+ message: 'step.acpAgent() requires a non-empty id.',
14
+ hint: 'Pass a unique string as the id field, e.g. step.acpAgent({ id: "review", ... }).',
16
15
  });
17
16
  }
18
- if (!opts.harness) {
17
+ if (!opts.agent) {
19
18
  throw new NoeticConfigError({
20
- code: 'MISSING_SUB_HARNESS',
21
- message: `${builderName}() requires a harness adapter.`,
22
- hint: `Pass a harness factory result, e.g. harness: ${builderName.replace('step.', '')}({ model }).`,
19
+ code: 'MISSING_ACP_AGENT',
20
+ message: 'step.acpAgent() requires an agent adapter.',
21
+ hint: 'Pass an agent factory result, e.g. agent: claudeCode() from @noetic-tools/acp.',
23
22
  });
24
23
  }
25
- // Eager adapters are validated now; function-form adapters are validated
26
- // post-resolution in executeSubHarness so the same SUB_HARNESS_KIND_MISMATCH
27
- // error surfaces whether the caller passes an adapter or a getter.
28
- if (typeof opts.harness !== 'function' && opts.harness.harnessId !== kind) {
24
+ // Presence, not emptiness: an empty `prompt` is a valid way to say "use the
25
+ // step's runtime input as the prompt", which the handler supports.
26
+ if (opts.prompt === undefined && opts.content === undefined) {
29
27
  throw new NoeticConfigError({
30
- code: 'SUB_HARNESS_KIND_MISMATCH',
31
- message: `${builderName}() was given a '${opts.harness.harnessId}' harness.`,
32
- hint: `Use the matching builder, e.g. step.${opts.harness.harnessId}({ ... }).`,
28
+ code: 'MISSING_PROMPT',
29
+ message: 'step.acpAgent() requires a prompt or content blocks.',
30
+ hint: 'Pass `prompt` for plain text, or `content` for image/audio/resource blocks.',
31
+ });
32
+ }
33
+ }
34
+ //#endregion
35
+ //#region Builders
36
+ /**
37
+ * Creates a pure async computation step.
38
+ *
39
+ * @public
40
+ * @param opts.id - Unique step identifier used in traces and error messages.
41
+ * @param opts.execute - Async function `(input, ctx) => output` that performs the work.
42
+ * @param opts.retry - Optional retry policy controlling attempts, backoff, and delay.
43
+ * @param opts.subprocess - Optional per-step subprocess adapter override.
44
+ * @returns A `StepRunCode` that can be composed into larger pipelines. The step
45
+ * is auto-registered in the shared step registry so the subprocess
46
+ * adapter can dispatch it by id.
47
+ * @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
48
+ * @throws `NoeticConfigError` with code `MISSING_EXECUTE_FUNCTION` if `execute` is not provided.
49
+ * @throws `NoeticConfigError` with code `DUPLICATE_STEP_ID` if another step with the same id is already registered with a different body.
50
+ */
51
+ export function runCode(opts) {
52
+ if (!opts.id || opts.id.trim() === '') {
53
+ throw new NoeticConfigError({
54
+ code: 'EMPTY_STEP_ID',
55
+ message: 'runCode() requires a non-empty id.',
56
+ hint: 'Pass a unique string as the id field, e.g. runCode({ id: "my-step", ... }).',
57
+ });
58
+ }
59
+ if (!opts.execute) {
60
+ throw new NoeticConfigError({
61
+ code: 'MISSING_EXECUTE_FUNCTION',
62
+ message: 'runCode() requires an execute function.',
63
+ hint: 'Provide an async execute function, e.g. execute: async (input, ctx) => result.',
33
64
  });
34
65
  }
35
66
  const built = {
36
- kind,
67
+ kind: 'runCode',
37
68
  ...opts,
38
69
  };
39
70
  getDefaultRegistrar().register(built);
40
71
  return built;
41
72
  }
42
- //#endregion
43
- //#region Builders
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 function callModel(opts) {
89
+ if (!opts.id || opts.id.trim() === '') {
90
+ throw new NoeticConfigError({
91
+ code: 'EMPTY_STEP_ID',
92
+ message: 'callModel() requires a non-empty id.',
93
+ hint: 'Pass a unique string as the id field, e.g. callModel({ id: "my-llm", ... }).',
94
+ });
95
+ }
96
+ // Only validate eager models here. Function-form models are validated
97
+ // post-resolution in executeCallModel so the same MISSING_MODEL error surfaces
98
+ // whether the caller passes a string or a getter.
99
+ if (typeof opts.model === 'string' && opts.model.trim() === '') {
100
+ throw new NoeticConfigError({
101
+ code: 'MISSING_MODEL',
102
+ message: 'callModel() requires a non-empty model.',
103
+ hint: "Pass a model identifier, e.g. model: 'anthropic/claude-sonnet-4-20250514'.",
104
+ });
105
+ }
106
+ const built = {
107
+ kind: 'callModel',
108
+ ...opts,
109
+ };
110
+ getDefaultRegistrar().register(built);
111
+ return built;
112
+ }
113
+ /**
114
+ * Creates a tool execution step that invokes a typed tool definition.
115
+ *
116
+ * @public
117
+ * @param opts.id - Unique step identifier used in traces and error messages.
118
+ * @param opts.tool - The tool definition with typed input/output schemas.
119
+ * @param opts.args - Optional partial args that override or supplement model-provided arguments.
120
+ * @returns A `StepInvokeTool` that can be composed into larger pipelines. The step
121
+ * is auto-registered in the shared step registry.
122
+ * @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
123
+ * @throws `NoeticConfigError` with code `MISSING_TOOL` if `tool` is not provided.
124
+ */
125
+ export function invokeTool(opts) {
126
+ if (!opts.id || opts.id.trim() === '') {
127
+ throw new NoeticConfigError({
128
+ code: 'EMPTY_STEP_ID',
129
+ message: 'invokeTool() requires a non-empty id.',
130
+ hint: 'Pass a unique string as the id field, e.g. invokeTool({ id: "my-tool", ... }).',
131
+ });
132
+ }
133
+ if (!opts.tool) {
134
+ throw new NoeticConfigError({
135
+ code: 'MISSING_TOOL',
136
+ message: 'invokeTool() requires a tool.',
137
+ hint: 'Provide a tool definition created with the tool() builder.',
138
+ });
139
+ }
140
+ const built = {
141
+ kind: 'invokeTool',
142
+ ...opts,
143
+ };
144
+ getDefaultRegistrar().register(built);
145
+ return built;
146
+ }
147
+ /**
148
+ * The ACP step builder namespace. Unlike the flattened base builders
149
+ * (`runCode`, `callModel`, `invokeTool`), the coding-agent builder stays
150
+ * grouped under `step`.
151
+ *
152
+ * @public
153
+ */
44
154
  export const step = {
45
155
  /**
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.
156
+ * Creates a step that delegates a turn to an external coding agent over the
157
+ * Agent Client Protocol.
84
158
  *
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.
159
+ * One builder covers every ACP-speaking agent: the agent itself is supplied
160
+ * as an adapter, so adding an agent never changes this API or the published
161
+ * workflow schema.
124
162
  *
125
163
  * @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.
164
+ * @param opts.id - Unique step identifier.
165
+ * @param opts.agent - An agent adapter, e.g. `claudeCode()` from `@noetic-tools/acp`.
166
+ * @param opts.prompt - The turn prompt; eager string or `(ctx) => string` getter.
167
+ * @param opts.permissions - Declarative policy answering the agent's permission requests.
168
+ * @param opts.output - Optional Standard Schema enabling structured output parsing.
169
+ * @returns A `StepAcpAgent`, auto-registered in the step registry.
170
+ * @throws `NoeticConfigError` `EMPTY_STEP_ID` / `MISSING_ACP_AGENT` / `MISSING_PROMPT`.
133
171
  */
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
- }
172
+ acpAgent(opts) {
173
+ validateAcpAgentOpts(opts);
149
174
  const built = {
150
- kind: 'tool',
175
+ kind: 'acp-agent',
151
176
  ...opts,
152
177
  };
153
178
  getDefaultRegistrar().register(built);
154
179
  return built;
155
180
  },
156
- /**
157
- * Creates a step that delegates a turn to the Claude Code harness.
158
- *
159
- * @public
160
- * @param opts.id - Unique step identifier.
161
- * @param opts.harness - A `claudeCode(...)` adapter from `@noetic-tools/sub-harness-claude-code`.
162
- * @param opts.prompt - The turn prompt; eager string or `(ctx) => string` getter.
163
- * @param opts.settings - Shared harness settings (model, permission mode, …).
164
- * @param opts.output - Optional Zod schema enabling structured output parsing.
165
- * @returns A `StepSubHarness` of kind `claude-code`, auto-registered in the step registry.
166
- * @throws `NoeticConfigError` `EMPTY_STEP_ID` / `MISSING_SUB_HARNESS` / `SUB_HARNESS_KIND_MISMATCH`.
167
- */
168
- claudeCode(opts) {
169
- return buildSubHarnessStep('claude-code', 'step.claudeCode', opts);
170
- },
171
- /**
172
- * Creates a step that delegates a turn to the Codex harness.
173
- * @public
174
- * @param opts - See {@link step.claudeCode}; `opts.harness` is a `codex(...)` adapter.
175
- * @returns A `StepSubHarness` of kind `codex`.
176
- */
177
- codex(opts) {
178
- return buildSubHarnessStep('codex', 'step.codex', opts);
179
- },
180
- /**
181
- * Creates a step that delegates a turn to the opencode harness.
182
- * @public
183
- * @param opts - See {@link step.claudeCode}; `opts.harness` is an `opencode(...)` adapter.
184
- * @returns A `StepSubHarness` of kind `opencode`.
185
- */
186
- opencode(opts) {
187
- return buildSubHarnessStep('opencode', 'step.opencode', opts);
188
- },
189
- /**
190
- * Creates a step that delegates a turn to the pi harness.
191
- * @public
192
- * @param opts - See {@link step.claudeCode}; `opts.harness` is a `pi(...)` adapter.
193
- * @returns A `StepSubHarness` of kind `pi`.
194
- */
195
- pi(opts) {
196
- return buildSubHarnessStep('pi', 'step.pi', opts);
197
- },
198
181
  };
199
182
  //#endregion
@@ -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,29 +1,33 @@
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 type { ContextData, ContextLayer } from '@noetic-tools/context';
9
- import type { ExecuteStepFn, OutputCodec, Step, SubHarness, SubHarnessKind, SubprocessAdapter, Tool } from '@noetic-tools/types';
9
+ import type { AcpAgent, ExecuteStepFn, OutputCodec, Step, SubprocessAdapter, Tool } from '@noetic-tools/types';
10
10
  import type { WorkflowDocument, WorkflowNode } from '../schemas/workflow.js';
11
11
  /** @public Context required to hydrate a JSON workflow into live steps. */
12
12
  export interface HydrationContext {
13
13
  tools: ReadonlyMap<string, Tool>;
14
14
  executeStep: ExecuteStepFn;
15
15
  layers?: ReadonlyMap<string, ContextLayer>;
16
- /** SubHarness adapters keyed by harness id, resolving `claude-code`/`codex`/… nodes. */
17
- subHarnesses?: ReadonlyMap<SubHarnessKind, SubHarness>;
18
16
  /**
19
- * Output codecs keyed by the `library` ref an `llm` node's `output` codec
17
+ * ACP agent adapters keyed by `agentId`, resolving an `acp-agent` node's
18
+ * `agent` field. An OPEN registry — supporting a new agent needs no schema
19
+ * change, only another entry here.
20
+ */
21
+ acpAgents?: ReadonlyMap<string, AcpAgent>;
22
+ /**
23
+ * Output codecs keyed by the `library` ref a `callModel` node's `output` codec
20
24
  * reference names — the live codec built from a component library, e.g.
21
25
  * `new Map([['dashboard-lib', openUi(dashboardLibrary)]])` from
22
- * `@noetic-tools/openui`. Resolved the same way sub-harness adapters are.
26
+ * `@noetic-tools/openui`. Resolved the same way ACP agent adapters are.
23
27
  */
24
28
  uiLibraries?: ReadonlyMap<string, OutputCodec>;
25
29
  /**
26
- * Resolves a named subprocess adapter ref declared on a `run` node's
30
+ * Resolves a named subprocess adapter ref declared on a `runCode` node's
27
31
  * `subprocess` field. When a node omits the ref, the step falls back to
28
32
  * `ctx.subprocess` at execution time.
29
33
  */