@noetic-tools/core 3.2.0 → 5.0.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.
- package/dist/adapters/in-memory-subprocess/manifest-persistence.d.ts +1 -1
- package/dist/adapters/in-memory-subprocess/types.d.ts +1 -1
- package/dist/adapters/openrouter.d.ts +2 -2
- package/dist/adapters/openrouter.js +2 -2
- package/dist/builders/context-builder.d.ts +11 -0
- package/dist/builders/context-builder.js +15 -0
- package/dist/builders/context-option.d.ts +23 -0
- package/dist/builders/context-option.js +22 -0
- package/dist/builders/control-flow-builders.d.ts +19 -19
- package/dist/builders/every.d.ts +4 -4
- package/dist/builders/layer-provides-builders.d.ts +1 -1
- package/dist/builders/layer-provides-builders.js +1 -1
- package/dist/builders/loop-builder.d.ts +3 -3
- package/dist/builders/provide-builder.d.ts +14 -7
- package/dist/builders/provide-builder.js +15 -4
- package/dist/builders/spawn-builder.d.ts +8 -6
- package/dist/builders/spawn-builder.js +7 -2
- package/dist/builders/step-builders.d.ts +19 -20
- package/dist/builders/tool-builder.d.ts +9 -5
- package/dist/builders/tool-builder.js +3 -2
- package/dist/builders/workflow-hydrator.d.ts +17 -4
- package/dist/builders/workflow-hydrator.js +87 -8
- package/dist/builders/workflow-step.d.ts +61 -0
- package/dist/builders/workflow-step.js +126 -0
- package/dist/conditions/conditions.d.ts +17 -17
- package/dist/conditions/conditions.js +1 -1
- package/dist/deprecated.d.ts +30 -0
- package/dist/deprecated.js +28 -0
- package/dist/harness/agent-harness.d.ts +42 -26
- package/dist/harness/agent-harness.js +68 -21
- package/dist/harness/deps/{memory.d.ts → context.d.ts} +2 -2
- package/dist/harness/deps/{memory.js → context.js} +1 -1
- package/dist/harness/deps/types.d.ts +1 -1
- package/dist/harness/model-schema.d.ts +2 -2
- package/dist/index.d.ts +21 -17
- package/dist/index.js +14 -8
- package/dist/interpreter/action-deps.d.ts +3 -3
- package/dist/interpreter/action-deps.js +2 -2
- package/dist/interpreter/action-types.d.ts +1 -1
- package/dist/interpreter/collect-tools.d.ts +1 -1
- package/dist/interpreter/execute-action.d.ts +10 -10
- package/dist/interpreter/execute-action.js +13 -13
- package/dist/interpreter/execute-control.d.ts +4 -4
- package/dist/interpreter/execute-control.js +1 -1
- package/dist/interpreter/execute-sub-harness.d.ts +1 -1
- package/dist/interpreter/execute.d.ts +3 -3
- package/dist/interpreter/execute.js +78 -31
- package/dist/interpreter/step-dispatcher.d.ts +3 -3
- package/dist/interpreter/sub-harness-events.d.ts +2 -2
- package/dist/interpreter/typeguards.d.ts +4 -4
- package/dist/patterns/dynamic-workflow.d.ts +7 -4
- package/dist/patterns/dynamic-workflow.js +2 -0
- package/dist/patterns/interview.d.ts +2 -2
- package/dist/patterns/plans.d.ts +5 -5
- package/dist/patterns/ralph-wiggum.d.ts +2 -2
- package/dist/patterns/react.d.ts +7 -5
- package/dist/patterns/react.js +6 -4
- package/dist/portable/builders.js +2 -0
- package/dist/portable/context-layers.d.ts +8 -0
- package/dist/portable/context-layers.js +8 -0
- package/dist/portable.d.ts +2 -2
- package/dist/portable.js +2 -2
- package/dist/runtime/channel-store.d.ts +33 -0
- package/dist/runtime/channel-store.js +297 -11
- package/dist/runtime/context-deps.d.ts +2 -2
- package/dist/runtime/context-deps.js +1 -1
- package/dist/runtime/context-impl.d.ts +10 -8
- package/dist/runtime/context-impl.js +11 -7
- package/dist/runtime/context-type-deps.d.ts +1 -1
- package/dist/runtime/durable/checkpoint-store.d.ts +1 -1
- package/dist/runtime/durable/harness-checkpoints.d.ts +2 -3
- package/dist/runtime/durable/harness-checkpoints.js +2 -3
- package/dist/runtime/durable/step-ledger.d.ts +1 -1
- package/dist/runtime/durable/step-ledger.js +1 -1
- package/dist/runtime/in-memory-storage.d.ts +1 -1
- package/dist/runtime/session-runner.d.ts +1 -1
- package/dist/runtime/step-registry.d.ts +3 -3
- package/dist/runtime/{tool-memory.d.ts → tool-context.d.ts} +1 -2
- package/dist/runtime/{tool-memory.js → tool-context.js} +5 -2
- package/dist/runtime/tool-ui.d.ts +1 -1
- package/dist/runtime/tool-ui.js +1 -1
- package/dist/schemas/workflow.d.ts +5 -279
- package/dist/schemas/workflow.js +4 -376
- package/dist/types/mutable-context.d.ts +2 -2
- package/dist/types/step-registrar.d.ts +1 -1
- package/dist/unstable.d.ts +5 -5
- package/dist/unstable.js +3 -3
- package/dist/until/predicates.d.ts +1 -1
- package/package.json +4 -4
- package/schema/noetic-workflow.schema.json +28 -0
- package/dist/builders/memory-builder.d.ts +0 -11
- package/dist/builders/memory-builder.js +0 -15
- package/dist/patterns/flow.d.ts +0 -2
- package/dist/patterns/flow.js +0 -1
- package/dist/portable/memory-layers.d.ts +0 -8
- package/dist/portable/memory-layers.js +0 -8
|
@@ -4,7 +4,7 @@ import type { Step, Tool } from '@noetic-tools/types';
|
|
|
4
4
|
* declared on LLM steps. Used to build the unified tool set
|
|
5
5
|
* that gets sent with every LLM call for prompt cache efficiency.
|
|
6
6
|
*/
|
|
7
|
-
export declare function collectAllTools<
|
|
7
|
+
export declare function collectAllTools<TContext = unknown, I = unknown, O = unknown>(step: Step<TContext, I, O>): Tool[];
|
|
8
8
|
/**
|
|
9
9
|
* Deduplicates tools by name, keeping the first occurrence.
|
|
10
10
|
*/
|
|
@@ -2,31 +2,31 @@
|
|
|
2
2
|
* Action step handlers: run, llm, spawn, provide, tool.
|
|
3
3
|
*/
|
|
4
4
|
import type { ItemSchemaRegistry, LayerStateStore } from './action-deps.js';
|
|
5
|
-
import type { AgentHarnessContract, Context,
|
|
6
|
-
export declare function executeRun<
|
|
5
|
+
import type { AgentHarnessContract, Context, ContextLayer, ExecuteStepFn, StepLLM, StepProvide, StepRun, StepSpawn, StepTool } from './action-types.js';
|
|
6
|
+
export declare function executeRun<TContext, I, O>(step: StepRun<TContext, I, O>, input: I, ctx: Context<TContext>): Promise<O>;
|
|
7
7
|
/**
|
|
8
8
|
* Resolves a `Lazy<T>` step field. If the value is a function, it is invoked
|
|
9
9
|
* with the current context; otherwise the value is returned as-is. Supports
|
|
10
10
|
* both sync and async getters.
|
|
11
11
|
*
|
|
12
12
|
* Lazy fields let a step inspect `ctx.harness.config.params`, `ctx.unifiedTools`,
|
|
13
|
-
* or
|
|
13
|
+
* or context layer state to produce per-execution values (model, instructions,
|
|
14
14
|
* tools) without baking them in at build time.
|
|
15
15
|
*/
|
|
16
|
-
export declare function resolveLazy<T,
|
|
17
|
-
export declare function executeLLM<
|
|
16
|
+
export declare function resolveLazy<T, TContext>(value: T | ((ctx: Context<TContext>) => T | Promise<T>), ctx: Context<TContext>): Promise<T>;
|
|
17
|
+
export declare function executeLLM<TContext, I, O>(step: StepLLM<TContext, I, O>, input: I, ctx: Context<TContext>, layers?: ContextLayer[]): Promise<O>;
|
|
18
18
|
export interface ExecuteSpawnOpts {
|
|
19
19
|
layerStore?: LayerStateStore;
|
|
20
|
-
parentLayers?:
|
|
20
|
+
parentLayers?: ContextLayer[];
|
|
21
21
|
itemSchemas?: ItemSchemaRegistry;
|
|
22
22
|
}
|
|
23
|
-
export declare function executeSpawn<
|
|
23
|
+
export declare function executeSpawn<TContext, I, O>(step: StepSpawn<TContext, I, O>, input: I, ctx: Context<TContext>, executeStep: ExecuteStepFn, opts?: ExecuteSpawnOpts): Promise<O>;
|
|
24
24
|
/**
|
|
25
|
-
* Executes a provide step by attaching
|
|
25
|
+
* Executes a provide step by attaching context layers to the current context
|
|
26
26
|
* without creating an isolated child context.
|
|
27
27
|
*
|
|
28
28
|
* Unlike spawn, provide does not create a new itemLog or clone state.
|
|
29
29
|
* Events flow through to the parent in real-time.
|
|
30
30
|
*/
|
|
31
|
-
export declare function executeProvide<
|
|
32
|
-
export declare function executeTool<
|
|
31
|
+
export declare function executeProvide<TContext, I, O>(step: StepProvide<TContext, I, O>, input: I, ctx: Context<TContext>, executeStep: ExecuteStepFn): Promise<O>;
|
|
32
|
+
export declare function executeTool<TContext, I, O>(step: StepTool<TContext, I, O>, input: I, ctx: Context<TContext>, harness: AgentHarnessContract, layers?: ContextLayer[]): Promise<O>;
|
|
@@ -93,7 +93,7 @@ function mergeRecallResults(base, overrides, slotOf) {
|
|
|
93
93
|
* both sync and async getters.
|
|
94
94
|
*
|
|
95
95
|
* Lazy fields let a step inspect `ctx.harness.config.params`, `ctx.unifiedTools`,
|
|
96
|
-
* or
|
|
96
|
+
* or context layer state to produce per-execution values (model, instructions,
|
|
97
97
|
* tools) without baking them in at build time.
|
|
98
98
|
*/
|
|
99
99
|
export async function resolveLazy(value, ctx) {
|
|
@@ -266,7 +266,7 @@ export async function executeLLM(step, input, ctx, layers) {
|
|
|
266
266
|
const hasLayers = layers !== undefined && layers.length > 0;
|
|
267
267
|
// Resolve lazy step fields up-front. Function-form getters run once per
|
|
268
268
|
// step execution with the live context, so `ctx.harness.config.params`,
|
|
269
|
-
// `ctx.unifiedTools`, and
|
|
269
|
+
// `ctx.unifiedTools`, and context layer state are all visible at resolution.
|
|
270
270
|
const resolvedModel = await resolveLazy(step.model, ctx);
|
|
271
271
|
if (!resolvedModel || resolvedModel.trim() === '') {
|
|
272
272
|
throw new NoeticConfigError({
|
|
@@ -509,19 +509,19 @@ export async function executeLLM(step, input, ctx, layers) {
|
|
|
509
509
|
retriesExhausted: true,
|
|
510
510
|
});
|
|
511
511
|
}
|
|
512
|
-
function
|
|
512
|
+
function isContextConfig(value) {
|
|
513
513
|
return typeof value === 'object' && value !== null && 'layers' in value;
|
|
514
514
|
}
|
|
515
515
|
function resolveLayersForSpawn(step, parentLayers) {
|
|
516
|
-
if (!step.
|
|
516
|
+
if (!step.context) {
|
|
517
517
|
return parentLayers ?? [];
|
|
518
518
|
}
|
|
519
|
-
if (
|
|
519
|
+
if (isContextConfig(step.context)) {
|
|
520
520
|
return [
|
|
521
|
-
...step.
|
|
521
|
+
...step.context.layers,
|
|
522
522
|
];
|
|
523
523
|
}
|
|
524
|
-
return step.
|
|
524
|
+
return step.context;
|
|
525
525
|
}
|
|
526
526
|
async function collectSpawnItems({ layers, parentExecutionCtx, childExecutionCtx, layerStore, itemSchemas = defaultItemSchemaRegistry, }) {
|
|
527
527
|
const spawnResults = await spawnLayers({
|
|
@@ -563,7 +563,7 @@ export async function executeSpawn(step, input, ctx, executeStep, opts) {
|
|
|
563
563
|
});
|
|
564
564
|
const layerStore = opts?.layerStore;
|
|
565
565
|
const hasLayers = layers.length > 0 && layerStore !== undefined;
|
|
566
|
-
// Collect items from
|
|
566
|
+
// Collect items from context layers via onSpawn hooks
|
|
567
567
|
let childItems = [];
|
|
568
568
|
let parentExecutionCtx;
|
|
569
569
|
if (hasLayers) {
|
|
@@ -594,7 +594,7 @@ export async function executeSpawn(step, input, ctx, executeStep, opts) {
|
|
|
594
594
|
// Create child context — empty by default, layers provide items via onSpawn.
|
|
595
595
|
// `id: childId` keeps the ContextImpl's id in sync with the executionId
|
|
596
596
|
// used by spawnLayers/returnLayers in the layer-state store, so writes via
|
|
597
|
-
// `ctx.
|
|
597
|
+
// `ctx.context[layerId]` and spawn-boundary hooks read from the same key.
|
|
598
598
|
const childCtx = new ContextImpl({
|
|
599
599
|
harness: baseCtx.harness,
|
|
600
600
|
parent: baseCtx,
|
|
@@ -648,12 +648,12 @@ export async function executeSpawn(step, input, ctx, executeStep, opts) {
|
|
|
648
648
|
//#endregion
|
|
649
649
|
//#region provide
|
|
650
650
|
function resolveLayers(step) {
|
|
651
|
-
if (
|
|
651
|
+
if (isContextConfig(step.context)) {
|
|
652
652
|
return [
|
|
653
|
-
...step.
|
|
653
|
+
...step.context.layers,
|
|
654
654
|
];
|
|
655
655
|
}
|
|
656
|
-
return step.
|
|
656
|
+
return step.context;
|
|
657
657
|
}
|
|
658
658
|
function mergeLayers(existing, provided) {
|
|
659
659
|
if (!existing || existing.length === 0) {
|
|
@@ -668,7 +668,7 @@ function mergeLayers(existing, provided) {
|
|
|
668
668
|
];
|
|
669
669
|
}
|
|
670
670
|
/**
|
|
671
|
-
* Executes a provide step by attaching
|
|
671
|
+
* Executes a provide step by attaching context layers to the current context
|
|
672
672
|
* without creating an isolated child context.
|
|
673
673
|
*
|
|
674
674
|
* Unlike spawn, provide does not create a new itemLog or clone state.
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { Context, ExecuteStepFn, StepBranch, StepEvery, StepFork, StepLoop } from '@noetic-tools/types';
|
|
5
5
|
import type { ItemSchemaRegistry, LayerStateStore } from './action-deps.js';
|
|
6
|
-
export declare function executeBranch<
|
|
6
|
+
export declare function executeBranch<TContext, I, O>(step: StepBranch<TContext, I, O>, input: I, ctx: Context<TContext>, executeStep: ExecuteStepFn): Promise<O>;
|
|
7
7
|
/** Layer-boundary wiring supplied by the interpreter (see `buildSpawnOpts`). */
|
|
8
8
|
export interface ExecuteForkOpts {
|
|
9
9
|
layerStore?: LayerStateStore;
|
|
10
10
|
itemSchemas?: ItemSchemaRegistry;
|
|
11
11
|
}
|
|
12
|
-
export declare function executeFork<
|
|
13
|
-
export declare function executeLoop<
|
|
12
|
+
export declare function executeFork<TContext, I, O>(step: StepFork<TContext, I, O>, input: I, ctx: Context<TContext>, rawExecuteStep: ExecuteStepFn, opts?: ExecuteForkOpts): Promise<O>;
|
|
13
|
+
export declare function executeLoop<TContext, I, O>(step: StepLoop<TContext, I, O>, input: I, ctx: Context<TContext>, executeStep: ExecuteStepFn): Promise<O>;
|
|
14
14
|
/**
|
|
15
15
|
* Executes an `every` step: runs the body step forever, paced by `ms ± jitter`,
|
|
16
16
|
* woken early by `wakeOn`. Throws `cancelled` when the context is aborted.
|
|
@@ -23,4 +23,4 @@ export declare function executeLoop<TMemory, I, O>(step: StepLoop<TMemory, I, O>
|
|
|
23
23
|
* The body's output is discarded — `every` runs forever and does not accumulate
|
|
24
24
|
* iteration outputs. Only ever returns by throwing on cancellation or `fail`.
|
|
25
25
|
*/
|
|
26
|
-
export declare function executeEvery<
|
|
26
|
+
export declare function executeEvery<TContext, I, O>(step: StepEvery<TContext, I, O>, input: I, ctx: Context<TContext>, executeStep: ExecuteStepFn): Promise<O>;
|
|
@@ -44,7 +44,7 @@ function createChildContexts(ctx, count, stepId) {
|
|
|
44
44
|
channelStore,
|
|
45
45
|
cwdState: snapshotCwdState(ctx),
|
|
46
46
|
// Layers and the harness tool pool cross the fork boundary: without
|
|
47
|
-
// them an `llm` step inside a path would run with no
|
|
47
|
+
// them an `llm` step inside a path would run with no context
|
|
48
48
|
// projection and no layer tools, and a nested `spawn` would have no
|
|
49
49
|
// parent layers to inherit. Per-path layer STATE is still isolated —
|
|
50
50
|
// see `createForkLayerBridge`.
|
|
@@ -5,4 +5,4 @@
|
|
|
5
5
|
* `executeLLM`.
|
|
6
6
|
*/
|
|
7
7
|
import type { Context, StepSubHarness } from '@noetic-tools/types';
|
|
8
|
-
export declare function executeSubHarness<
|
|
8
|
+
export declare function executeSubHarness<TContext, I, O>(step: StepSubHarness<TContext, I, O>, input: I, ctx: Context<TContext>): Promise<O>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ContextData } from '@noetic-tools/context';
|
|
2
2
|
import type { Context, Step } from '@noetic-tools/types';
|
|
3
3
|
/**
|
|
4
4
|
* @internal
|
|
@@ -12,7 +12,7 @@ import type { Context, Step } from '@noetic-tools/types';
|
|
|
12
12
|
* through the adapter as normal, so per-step overrides on descendants
|
|
13
13
|
* continue to work.
|
|
14
14
|
*/
|
|
15
|
-
export declare function executeNoAdapter<
|
|
15
|
+
export declare function executeNoAdapter<TContext, I, O>(step: Step<TContext, I, O>, input: I, ctx: Context<TContext>): Promise<O>;
|
|
16
16
|
/**
|
|
17
17
|
* Executes a step within the interpreter, dispatching to the appropriate handler by step kind.
|
|
18
18
|
*
|
|
@@ -23,4 +23,4 @@ export declare function executeNoAdapter<TMemory, I, O>(step: Step<TMemory, I, O
|
|
|
23
23
|
* @throws `NoeticError` with kind `step_failed` if max depth is exceeded or an unknown step kind is encountered.
|
|
24
24
|
* @throws `NoeticError` with kind `cancelled` if the context is aborted.
|
|
25
25
|
*/
|
|
26
|
-
export declare function execute<
|
|
26
|
+
export declare function execute<TContext = ContextData, I = unknown, O = unknown>(step: Step<TContext, I, O>, input: I, ctx: Context<TContext>): Promise<O>;
|
|
@@ -112,6 +112,65 @@ export async function executeNoAdapter(step, input, ctx) {
|
|
|
112
112
|
return execute(step, input, ctx);
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Resume path: when a previous run recorded this exact step at `ledgerPath`,
|
|
117
|
+
* replay its output instead of re-running. Held as a helper (rather than inline
|
|
118
|
+
* in `execute`) so the resume branch stays flat: it pops the frontier itself —
|
|
119
|
+
* the caller returns before the normal `leaveStep` runs — and emits
|
|
120
|
+
* `step_replayed`. Returns `{ hit: false }` when there is nothing to replay so
|
|
121
|
+
* the caller dispatches the step normally.
|
|
122
|
+
*/
|
|
123
|
+
function replayFromLedger(opts) {
|
|
124
|
+
const { ledger, ledgerPath, impl, step, broadcaster, agentName } = opts;
|
|
125
|
+
if (!ledger || ledgerPath === undefined || ledger.isEmpty) {
|
|
126
|
+
return {
|
|
127
|
+
hit: false,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
const replayed = ledger.take(ledgerPath, {
|
|
131
|
+
id: step.id,
|
|
132
|
+
kind: step.kind,
|
|
133
|
+
});
|
|
134
|
+
if (!replayed) {
|
|
135
|
+
return {
|
|
136
|
+
hit: false,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
if (impl && step.id.length > 0) {
|
|
140
|
+
impl.leaveStep(step.id);
|
|
141
|
+
}
|
|
142
|
+
emitFrameworkEvent({
|
|
143
|
+
broadcaster,
|
|
144
|
+
agentName,
|
|
145
|
+
eventType: 'step_replayed',
|
|
146
|
+
data: {
|
|
147
|
+
stepId: step.id,
|
|
148
|
+
kind: step.kind,
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
return {
|
|
152
|
+
hit: true,
|
|
153
|
+
output: frameworkCast(replayed.output),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Record a completed step's output so a resumed run replays it rather than
|
|
158
|
+
* re-executing. A no-op without a ledger or ledger path. Only successes reach
|
|
159
|
+
* here — a step that threw skips this call in `execute` and runs again on resume.
|
|
160
|
+
*/
|
|
161
|
+
async function recordToLedger(opts) {
|
|
162
|
+
const { ledger, ledgerPath, step, output } = opts;
|
|
163
|
+
if (!ledger || ledgerPath === undefined) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
await ledger.record({
|
|
167
|
+
path: ledgerPath,
|
|
168
|
+
stepId: step.id,
|
|
169
|
+
kind: step.kind,
|
|
170
|
+
output,
|
|
171
|
+
completedAt: new Date().toISOString(),
|
|
172
|
+
});
|
|
173
|
+
}
|
|
115
174
|
//#endregion
|
|
116
175
|
/**
|
|
117
176
|
* Executes a step within the interpreter, dispatching to the appropriate handler by step kind.
|
|
@@ -173,30 +232,21 @@ export async function execute(step, input, ctx) {
|
|
|
173
232
|
});
|
|
174
233
|
}
|
|
175
234
|
/* Resume: a previous run that completed this exact step replays its recorded
|
|
176
|
-
* output instead of re-running it.
|
|
177
|
-
* record below, because `leaveStep` pops the path
|
|
235
|
+
* output instead of re-running it. `ledgerPath`/`ledger` are captured before
|
|
236
|
+
* dispatch and reused by the record below, because `leaveStep` pops the path
|
|
237
|
+
* on the way out. */
|
|
178
238
|
const ledgerPath = impl && step.id.length > 0 ? impl.currentPath() : undefined;
|
|
179
239
|
const ledger = impl?.ledger;
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
broadcaster,
|
|
191
|
-
agentName,
|
|
192
|
-
eventType: 'step_replayed',
|
|
193
|
-
data: {
|
|
194
|
-
stepId: step.id,
|
|
195
|
-
kind: step.kind,
|
|
196
|
-
},
|
|
197
|
-
});
|
|
198
|
-
return frameworkCast(replayed.output);
|
|
199
|
-
}
|
|
240
|
+
const replay = replayFromLedger({
|
|
241
|
+
ledger,
|
|
242
|
+
ledgerPath,
|
|
243
|
+
impl,
|
|
244
|
+
step,
|
|
245
|
+
broadcaster,
|
|
246
|
+
agentName,
|
|
247
|
+
});
|
|
248
|
+
if (replay.hit) {
|
|
249
|
+
return replay.output;
|
|
200
250
|
}
|
|
201
251
|
let result;
|
|
202
252
|
try {
|
|
@@ -272,15 +322,12 @@ export async function execute(step, input, ctx) {
|
|
|
272
322
|
/* Record the completed step so a resumed run replays this output rather than
|
|
273
323
|
* re-running the step. Only successes are recorded: a step that threw must run
|
|
274
324
|
* again. */
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
completedAt: new Date().toISOString(),
|
|
282
|
-
});
|
|
283
|
-
}
|
|
325
|
+
await recordToLedger({
|
|
326
|
+
ledger,
|
|
327
|
+
ledgerPath,
|
|
328
|
+
step,
|
|
329
|
+
output: result,
|
|
330
|
+
});
|
|
284
331
|
/* Durability boundary (spec 23): snapshot after each completed step, so a crash
|
|
285
332
|
* lands on a checkpoint that includes the item-log and layer-state mutations this
|
|
286
333
|
* step produced. A no-op unless the harness has a CheckpointStore, and a failing
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ContextData } from '@noetic-tools/context';
|
|
2
2
|
import type { Context, DetachedHandle, Step, SubprocessAdapter } from '@noetic-tools/types';
|
|
3
3
|
/**
|
|
4
4
|
* Resolve the subprocess adapter used for a given step dispatch.
|
|
@@ -10,7 +10,7 @@ import type { Context, DetachedHandle, Step, SubprocessAdapter } from '@noetic-t
|
|
|
10
10
|
*
|
|
11
11
|
* @internal
|
|
12
12
|
*/
|
|
13
|
-
export declare function resolveStepAdapter<
|
|
13
|
+
export declare function resolveStepAdapter<TContext, I, O>(step: Step<TContext, I, O>, callOverride: SubprocessAdapter | undefined, fallback: SubprocessAdapter): SubprocessAdapter;
|
|
14
14
|
/**
|
|
15
15
|
* Minimum harness surface the dispatcher needs. `AgentHarness` satisfies
|
|
16
16
|
* this shape — kept structural so tests can pass a stub.
|
|
@@ -55,4 +55,4 @@ export interface DetachedSpawnOverrides {
|
|
|
55
55
|
*
|
|
56
56
|
* @internal
|
|
57
57
|
*/
|
|
58
|
-
export declare function dispatchStepThroughAdapter<I, O>(h: StepDispatchHandle, s: Step<
|
|
58
|
+
export declare function dispatchStepThroughAdapter<I, O>(h: StepDispatchHandle, s: Step<ContextData, I, O>, input: I, parentCtx: Context, overrides?: DetachedSpawnOverrides): DetachedHandle<O>;
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* a result without streaming any text/tool parts, the result's content is
|
|
13
13
|
* synthesized into events.
|
|
14
14
|
*/
|
|
15
|
-
import type { Context,
|
|
15
|
+
import type { Context, ContextData, StepSubHarness, SubHarnessStreamPart, SubHarnessTurnResult } from '@noetic-tools/types';
|
|
16
16
|
export declare class SubHarnessEventBridge {
|
|
17
17
|
private readonly broadcaster?;
|
|
18
18
|
private readonly agentName;
|
|
@@ -25,7 +25,7 @@ export declare class SubHarnessEventBridge {
|
|
|
25
25
|
private messageOutputIndex;
|
|
26
26
|
private sawText;
|
|
27
27
|
private sawToolCall;
|
|
28
|
-
constructor(step: Pick<StepSubHarness, 'id' | 'kind' | 'emit'>, ctx: Context<
|
|
28
|
+
constructor(step: Pick<StepSubHarness, 'id' | 'kind' | 'emit'>, ctx: Context<ContextData>);
|
|
29
29
|
/**
|
|
30
30
|
* Open the turn on the event surface. Emits `response.created` so every turn
|
|
31
31
|
* always brackets with a lifecycle marker — even a custom adapter that
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ContextData } from '@noetic-tools/context';
|
|
2
2
|
import type { Context, FunctionCallItem, Item } from '@noetic-tools/types';
|
|
3
3
|
import type { ChannelStore } from '../runtime/channel-store.js';
|
|
4
4
|
import { ContextImpl } from '../runtime/context-impl.js';
|
|
5
5
|
import type { MutableContext } from '../types/mutable-context.js';
|
|
6
6
|
export { isAssistantMessage, isOutputText, isUserMessage } from '@noetic-tools/types';
|
|
7
|
-
export declare function isMutableContext(ctx: Context<
|
|
8
|
-
export declare function isContextImpl(ctx: Context<
|
|
7
|
+
export declare function isMutableContext(ctx: Context<ContextData>): ctx is MutableContext;
|
|
8
|
+
export declare function isContextImpl(ctx: Context<ContextData>): ctx is ContextImpl;
|
|
9
9
|
/**
|
|
10
10
|
* Co-located with `isContextImpl` so the import of `ContextImpl` flows through
|
|
11
11
|
* the same module other interpreters pull it from, sidestepping a circular
|
|
12
12
|
* TDZ when this helper is used by `executeEvery` in `execute-control.ts`.
|
|
13
13
|
*/
|
|
14
|
-
export declare function getContextChannelStore<
|
|
14
|
+
export declare function getContextChannelStore<TContext>(ctx: Context<TContext>): ChannelStore | undefined;
|
|
15
15
|
export declare function isFunctionCall(item: Item): item is FunctionCallItem;
|
|
16
16
|
declare function assertNever(_value: never): never;
|
|
17
17
|
export { assertNever };
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* Pattern that lets an LLM generate a workflow as JSON during execution,
|
|
3
3
|
* then hydrates and runs it within the same harness session.
|
|
4
4
|
*/
|
|
5
|
-
import type {
|
|
5
|
+
import type { ContextData, ContextLayer } from '@noetic-tools/context';
|
|
6
6
|
import type { AgentHarnessContract, Context, Step, Tool } from '@noetic-tools/types';
|
|
7
|
+
import type { WorkflowDocument } from '../schemas/workflow.js';
|
|
7
8
|
/** @public Options for creating a dynamic workflow step. */
|
|
8
9
|
export interface DynamicWorkflowOpts {
|
|
9
10
|
model?: string;
|
|
@@ -25,7 +26,7 @@ export interface DynamicWorkflowOpts {
|
|
|
25
26
|
* @param opts.maxRevisions - Retries with error feedback on validation failure. Default: 3.
|
|
26
27
|
* @returns A `Step` that dynamically plans and executes.
|
|
27
28
|
*/
|
|
28
|
-
export declare function dynamicWorkflow(opts: DynamicWorkflowOpts): Step<
|
|
29
|
+
export declare function dynamicWorkflow(opts: DynamicWorkflowOpts): Step<ContextData, string, string>;
|
|
29
30
|
/** @public Options for `parseAndRunWorkflow`. */
|
|
30
31
|
export interface ParseAndRunWorkflowOpts {
|
|
31
32
|
json: unknown;
|
|
@@ -35,11 +36,13 @@ export interface ParseAndRunWorkflowOpts {
|
|
|
35
36
|
input?: string;
|
|
36
37
|
maxDepth?: number;
|
|
37
38
|
/**
|
|
38
|
-
*
|
|
39
|
+
* Context layers the document's `provide` / `spawn` nodes may reference by name.
|
|
39
40
|
* Without a registry those nodes resolve to NO layers rather than failing, so a
|
|
40
41
|
* host that runs layer-bearing workflows must pass its layers here.
|
|
41
42
|
*/
|
|
42
|
-
layers?: ReadonlyMap<string,
|
|
43
|
+
layers?: ReadonlyMap<string, ContextLayer>;
|
|
44
|
+
/** Named sub-workflows the document's `subflow` nodes may reference via `ref`. */
|
|
45
|
+
workflows?: ReadonlyMap<string, WorkflowDocument>;
|
|
43
46
|
}
|
|
44
47
|
/**
|
|
45
48
|
* Parses raw JSON into a `WorkflowDocument`, hydrates it into a live step
|
|
@@ -28,6 +28,7 @@ A WorkflowNode is one of:
|
|
|
28
28
|
- { "kind": "loop", "id": "<unique>", "body": <WorkflowNode>, "until": { "kind": "maxSteps", "n": <number> } }
|
|
29
29
|
- { "kind": "branch", "id": "<unique>", "routes": [{ "match": "<substring>", "target": <WorkflowNode> }], "default": <WorkflowNode> }
|
|
30
30
|
- { "kind": "spawn", "id": "<unique>", "child": <WorkflowNode> }
|
|
31
|
+
- { "kind": "subflow", "id": "<unique>", "document": { "version": 1, "root": <WorkflowNode> } } (an inline sub-workflow run as one step; only emit the inline form — named refs require a registry this planner does not provide)
|
|
31
32
|
- { "kind": "claude-code"|"codex"|"opencode"|"pi", "id": "<unique>", "prompt": "<turn prompt>", "settings": { "model": "<optional>", "permissionMode": "<optional>" } }
|
|
32
33
|
|
|
33
34
|
SubHarness nodes (claude-code, codex, opencode, pi) delegate a turn to an external coding agent; only emit one if a matching harness adapter is registered for the workflow.
|
|
@@ -143,6 +144,7 @@ export async function parseAndRunWorkflow(opts) {
|
|
|
143
144
|
tools: buildToolMap(opts.tools),
|
|
144
145
|
executeStep,
|
|
145
146
|
layers: opts.layers,
|
|
147
|
+
workflows: opts.workflows,
|
|
146
148
|
};
|
|
147
149
|
const hydrated = hydrateWorkflow(parseResult.doc, hydrationCtx);
|
|
148
150
|
const runSpan = beginWorkflowRunSpan(opts.harness, opts.ctx, parseResult.doc);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ContextData } from '@noetic-tools/context';
|
|
2
2
|
import type { Step } from '@noetic-tools/types';
|
|
3
3
|
import type { ZodType } from 'zod';
|
|
4
4
|
/** @public Answer captured by the host for a single interview question. */
|
|
@@ -50,4 +50,4 @@ export interface InterviewOpts<Q, C> {
|
|
|
50
50
|
* @returns A `Step` whose output is `InterviewResult<Q, C>` — either the completion envelope or
|
|
51
51
|
* `maxQuestions` when the budget is exhausted before the model emits `complete`.
|
|
52
52
|
*/
|
|
53
|
-
export declare function interview<Q, C>(opts: InterviewOpts<Q, C>): Step<
|
|
53
|
+
export declare function interview<Q, C>(opts: InterviewOpts<Q, C>): Step<ContextData, string, InterviewResult<Q, C>>;
|
package/dist/patterns/plans.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ContextData } from '@noetic-tools/context';
|
|
2
2
|
import type { Context, ExecuteStepFn, Step } from '@noetic-tools/types';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
export interface PlanNode {
|
|
@@ -26,7 +26,7 @@ export interface PlanConstraints {
|
|
|
26
26
|
* @param executeStep - Optional step executor for non-run step kinds.
|
|
27
27
|
* @returns A compiled `Step` ready for execution.
|
|
28
28
|
*/
|
|
29
|
-
export declare function compilePlan<O, A = unknown>(plan: PlanNode, agents: Record<string, (prompt: string) => Step<
|
|
29
|
+
export declare function compilePlan<O, A = unknown>(plan: PlanNode, agents: Record<string, (prompt: string) => Step<ContextData, string, A>>, constraints?: PlanConstraints, executeStep?: ExecuteStepFn): Step<ContextData, string, O>;
|
|
30
30
|
/**
|
|
31
31
|
* Creates a step that dynamically generates a plan via a planner step and executes it,
|
|
32
32
|
* retrying with error feedback up to `maxRevisions` times on failure.
|
|
@@ -36,9 +36,9 @@ export declare function compilePlan<O, A = unknown>(plan: PlanNode, agents: Reco
|
|
|
36
36
|
* @returns A `Step` that adaptively plans and executes.
|
|
37
37
|
*/
|
|
38
38
|
export declare function adaptivePlan<O, A = unknown>(opts: {
|
|
39
|
-
planner: Step<
|
|
40
|
-
agents: Record<string, (prompt: string) => Step<
|
|
39
|
+
planner: Step<ContextData, string, PlanNode>;
|
|
40
|
+
agents: Record<string, (prompt: string) => Step<ContextData, string, A>>;
|
|
41
41
|
constraints?: PlanConstraints;
|
|
42
42
|
maxRevisions: number;
|
|
43
43
|
executeStep?: ExecuteStepFn;
|
|
44
|
-
}): Step<
|
|
44
|
+
}): Step<ContextData, string, O>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ContextData } from '@noetic-tools/context';
|
|
2
2
|
import type { StepLoop, Tool } from '@noetic-tools/types';
|
|
3
3
|
import type { VerifyFn } from '../until/predicates.js';
|
|
4
4
|
/**
|
|
@@ -16,4 +16,4 @@ export declare function ralphWiggum(opts: {
|
|
|
16
16
|
verify: VerifyFn;
|
|
17
17
|
maxIterations?: number;
|
|
18
18
|
innerMaxSteps?: number;
|
|
19
|
-
}): StepLoop<
|
|
19
|
+
}): StepLoop<ContextData, string, string>;
|
package/dist/patterns/react.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ContextConfig, ContextData, ContextLayer } from '@noetic-tools/context';
|
|
2
2
|
import type { StepLoop, StepSpawn, Tool } from '@noetic-tools/types';
|
|
3
3
|
/**
|
|
4
4
|
* Creates a ReAct (Reason + Act) agent loop: an LLM step with tools iterated until no tool calls or limits are hit.
|
|
5
5
|
*
|
|
6
6
|
* @public
|
|
7
|
-
* @param opts - Model, tools, optional instructions, step/cost limits, and
|
|
8
|
-
* @returns A `StepLoop` (no
|
|
7
|
+
* @param opts - Model, tools, optional instructions, step/cost limits, and context layers.
|
|
8
|
+
* @returns A `StepLoop` (no context layers) or `StepSpawn` wrapping a loop (with them).
|
|
9
9
|
*/
|
|
10
10
|
export declare function react(opts: {
|
|
11
11
|
model: string;
|
|
@@ -13,5 +13,7 @@ export declare function react(opts: {
|
|
|
13
13
|
tools: Tool[];
|
|
14
14
|
maxSteps?: number;
|
|
15
15
|
maxCost?: number;
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
context?: ContextConfig | ContextLayer[];
|
|
17
|
+
/** @deprecated Renamed to `context`. */
|
|
18
|
+
memory?: ContextConfig | ContextLayer[];
|
|
19
|
+
}): StepLoop<ContextData, string, string> | StepSpawn<ContextData, string, string>;
|
package/dist/patterns/react.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolveContextOption } from '../builders/context-option.js';
|
|
1
2
|
import { loop } from '../builders/loop-builder.js';
|
|
2
3
|
import { spawn } from '../builders/spawn-builder.js';
|
|
3
4
|
import { step } from '../builders/step-builders.js';
|
|
@@ -7,8 +8,8 @@ import { until } from '../until/predicates.js';
|
|
|
7
8
|
* Creates a ReAct (Reason + Act) agent loop: an LLM step with tools iterated until no tool calls or limits are hit.
|
|
8
9
|
*
|
|
9
10
|
* @public
|
|
10
|
-
* @param opts - Model, tools, optional instructions, step/cost limits, and
|
|
11
|
-
* @returns A `StepLoop` (no
|
|
11
|
+
* @param opts - Model, tools, optional instructions, step/cost limits, and context layers.
|
|
12
|
+
* @returns A `StepLoop` (no context layers) or `StepSpawn` wrapping a loop (with them).
|
|
12
13
|
*/
|
|
13
14
|
export function react(opts) {
|
|
14
15
|
const llmStep = step.llm({
|
|
@@ -28,12 +29,13 @@ export function react(opts) {
|
|
|
28
29
|
]
|
|
29
30
|
: [])),
|
|
30
31
|
});
|
|
31
|
-
|
|
32
|
+
const layers = resolveContextOption(opts);
|
|
33
|
+
if (!layers) {
|
|
32
34
|
return loopStep;
|
|
33
35
|
}
|
|
34
36
|
return spawn({
|
|
35
37
|
id: 'react-agent',
|
|
36
38
|
child: loopStep,
|
|
37
|
-
|
|
39
|
+
context: layers,
|
|
38
40
|
});
|
|
39
41
|
}
|
|
@@ -6,6 +6,8 @@ export { layerData, layerFn } from '../builders/layer-provides-builders.js';
|
|
|
6
6
|
export { loop } from '../builders/loop-builder.js';
|
|
7
7
|
/** @public */
|
|
8
8
|
export { spawn } from '../builders/spawn-builder.js';
|
|
9
|
+
// The base namespace, without `step.workflow` — the portable surface stays
|
|
10
|
+
// free of the hydrator so restricted runtimes don't pull it in.
|
|
9
11
|
/** @public */
|
|
10
12
|
export { step } from '../builders/step-builders.js';
|
|
11
13
|
/** @public */
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** @public */
|
|
2
|
+
/** @public */
|
|
3
|
+
/** @public */
|
|
4
|
+
/** @public */
|
|
5
|
+
/** @public */
|
|
6
|
+
/** @public */
|
|
7
|
+
/** @public */
|
|
8
|
+
export { durableTaskState, historyWindow, observationalContext, planContext, temporalContext, toolContextLayer, workingMemoryContext, } from '@noetic-tools/context';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** @public */
|
|
2
|
+
/** @public */
|
|
3
|
+
/** @public */
|
|
4
|
+
/** @public */
|
|
5
|
+
/** @public */
|
|
6
|
+
/** @public */
|
|
7
|
+
/** @public */
|
|
8
|
+
export { durableTaskState, historyWindow, observationalContext, planContext, temporalContext, toolContextLayer, workingMemoryContext, } from '@noetic-tools/context';
|
package/dist/portable.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/** @public */
|
|
2
|
-
export { Slot } from '@noetic-tools/
|
|
2
|
+
export { Slot } from '@noetic-tools/context';
|
|
3
3
|
export * from './portable/adapters.js';
|
|
4
4
|
export * from './portable/ask-user.js';
|
|
5
5
|
export * from './portable/builders.js';
|
|
6
|
-
export * from './portable/
|
|
6
|
+
export * from './portable/context-layers.js';
|
|
7
7
|
export * from './portable/runtime.js';
|
|
8
8
|
export * from './portable/until.js';
|
package/dist/portable.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/** @public */
|
|
2
|
-
export { Slot } from '@noetic-tools/
|
|
2
|
+
export { Slot } from '@noetic-tools/context';
|
|
3
3
|
export * from './portable/adapters.js';
|
|
4
4
|
export * from './portable/ask-user.js';
|
|
5
5
|
export * from './portable/builders.js';
|
|
6
|
-
export * from './portable/
|
|
6
|
+
export * from './portable/context-layers.js';
|
|
7
7
|
export * from './portable/runtime.js';
|
|
8
8
|
export * from './portable/until.js';
|