@noetic-tools/core 3.2.0 → 4.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 +30 -26
- package/dist/harness/agent-harness.js +23 -19
- 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/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
|
@@ -146,15 +146,22 @@ function hydrateToolNode(node, ctx) {
|
|
|
146
146
|
arguments: JSON.stringify(args),
|
|
147
147
|
};
|
|
148
148
|
execCtx.itemLog.append(callItem);
|
|
149
|
+
const layerState = {
|
|
150
|
+
get: (_layerId) => undefined,
|
|
151
|
+
set: (_layerId, _state) => { },
|
|
152
|
+
};
|
|
149
153
|
const toolCtx = {
|
|
150
154
|
ctx: execCtx,
|
|
151
155
|
harness: execCtx.harness,
|
|
152
156
|
fs: execCtx.fs,
|
|
153
157
|
shell: execCtx.shell,
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
+
context: layerState,
|
|
159
|
+
// Deprecated alias — the same accessor object, as
|
|
160
|
+
// `buildToolExecutionContext` does. `Tool.execute` takes its second
|
|
161
|
+
// argument as `unknown`, so nothing here is structurally checked
|
|
162
|
+
// against `ToolExecutionContext`; the annotation above is what makes
|
|
163
|
+
// a missing field a compile error instead of a runtime `undefined`.
|
|
164
|
+
memory: layerState,
|
|
158
165
|
assembledView: execCtx.itemLog.items,
|
|
159
166
|
lastStepMeta: execCtx.lastStepMeta,
|
|
160
167
|
};
|
|
@@ -285,7 +292,7 @@ function resolveNamedLayers({ names, nodeKind, nodeId, ctx, }) {
|
|
|
285
292
|
if (!layer) {
|
|
286
293
|
throw new NoeticConfigError({
|
|
287
294
|
code: 'UNKNOWN_LAYER_REFERENCE',
|
|
288
|
-
message: `
|
|
295
|
+
message: `Context layer '${name}' referenced in ${nodeKind} node '${nodeId}' is not registered.`,
|
|
289
296
|
hint: `Available layers: ${[
|
|
290
297
|
...(ctx.layers?.keys() ?? []),
|
|
291
298
|
].join(', ') || '(none)'}. Pass named layers via HydrationContext.layers.`,
|
|
@@ -298,7 +305,7 @@ function hydrateSpawnNode(node, ctx) {
|
|
|
298
305
|
if (node.kind !== 'spawn') {
|
|
299
306
|
return frameworkCast(undefined);
|
|
300
307
|
}
|
|
301
|
-
// `
|
|
308
|
+
// `context` is left undefined when the node names no layers so the child
|
|
302
309
|
// inherits the parent's layers (spec 04). An explicit list replaces them.
|
|
303
310
|
const resolvedLayers = node.layers
|
|
304
311
|
? resolveNamedLayers({
|
|
@@ -312,7 +319,7 @@ function hydrateSpawnNode(node, ctx) {
|
|
|
312
319
|
id: node.id,
|
|
313
320
|
child: hydrateNode(node.child, ctx),
|
|
314
321
|
timeout: node.timeout,
|
|
315
|
-
|
|
322
|
+
context: resolvedLayers,
|
|
316
323
|
});
|
|
317
324
|
}
|
|
318
325
|
function hydrateProvideNode(node, ctx) {
|
|
@@ -322,7 +329,7 @@ function hydrateProvideNode(node, ctx) {
|
|
|
322
329
|
return provide({
|
|
323
330
|
id: node.id,
|
|
324
331
|
child: hydrateNode(node.child, ctx),
|
|
325
|
-
|
|
332
|
+
context: resolveNamedLayers({
|
|
326
333
|
names: node.layers,
|
|
327
334
|
nodeKind: 'provide',
|
|
328
335
|
nodeId: node.id,
|
|
@@ -401,6 +408,75 @@ function hydrateSubHarnessNode(node, ctx) {
|
|
|
401
408
|
session: node.session,
|
|
402
409
|
});
|
|
403
410
|
}
|
|
411
|
+
/**
|
|
412
|
+
* Hydrates a `subflow` node lazily: the target document resolves and hydrates
|
|
413
|
+
* on first execution, memoized. Lazy because `HydrationContext.workflows` may
|
|
414
|
+
* be a live view that gains entries after hydration, and because it keeps
|
|
415
|
+
* cycle detection path-scoped — each ref chain threads its own ancestry set,
|
|
416
|
+
* so diamond reuse of a named workflow is legal while A→B→A throws.
|
|
417
|
+
*/
|
|
418
|
+
function hydrateSubflowNode(node, ctx) {
|
|
419
|
+
if (node.kind !== 'subflow') {
|
|
420
|
+
return frameworkCast(undefined);
|
|
421
|
+
}
|
|
422
|
+
let cached;
|
|
423
|
+
const resolve = () => {
|
|
424
|
+
if (!cached) {
|
|
425
|
+
const { doc, childCtx } = resolveSubflowDocument(node, ctx);
|
|
426
|
+
cached = hydrateNode(suffixNodeIds(doc.root, `-${node.id}`), childCtx);
|
|
427
|
+
}
|
|
428
|
+
return cached;
|
|
429
|
+
};
|
|
430
|
+
return frameworkCast(step.run({
|
|
431
|
+
id: node.id,
|
|
432
|
+
execute: async (input, execCtx) => {
|
|
433
|
+
const child = resolve();
|
|
434
|
+
return stringifyResult(await ctx.executeStep(child, node.input ?? input, execCtx));
|
|
435
|
+
},
|
|
436
|
+
}));
|
|
437
|
+
}
|
|
438
|
+
function resolveSubflowDocument(node, ctx) {
|
|
439
|
+
if (node.document) {
|
|
440
|
+
// Inline documents are finite JSON trees — they cannot cycle, so they
|
|
441
|
+
// add nothing to the ancestry chain.
|
|
442
|
+
return {
|
|
443
|
+
doc: node.document,
|
|
444
|
+
childCtx: ctx,
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
const ref = node.ref ?? '';
|
|
448
|
+
const ancestry = ctx.subflowAncestry ?? new Set();
|
|
449
|
+
if (ancestry.has(ref)) {
|
|
450
|
+
throw new NoeticConfigError({
|
|
451
|
+
code: 'WORKFLOW_CYCLE',
|
|
452
|
+
message: `Sub-workflow '${ref}' referenced in subflow node '${node.id}' forms a reference cycle (${[
|
|
453
|
+
...ancestry,
|
|
454
|
+
ref,
|
|
455
|
+
].join(' -> ')}).`,
|
|
456
|
+
hint: 'A named sub-workflow may not reference itself, directly or transitively. Break the cycle or inline the document.',
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
const doc = ctx.workflows?.get(ref);
|
|
460
|
+
if (!doc) {
|
|
461
|
+
throw new NoeticConfigError({
|
|
462
|
+
code: 'UNKNOWN_WORKFLOW_REFERENCE',
|
|
463
|
+
message: `Sub-workflow '${ref}' referenced in subflow node '${node.id}' is not registered.`,
|
|
464
|
+
hint: `Pass named workflows via HydrationContext.workflows. Available: ${[
|
|
465
|
+
...(ctx.workflows?.keys() ?? []),
|
|
466
|
+
].join(', ') || '(none)'}.`,
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
return {
|
|
470
|
+
doc,
|
|
471
|
+
childCtx: {
|
|
472
|
+
...ctx,
|
|
473
|
+
subflowAncestry: new Set([
|
|
474
|
+
...ancestry,
|
|
475
|
+
ref,
|
|
476
|
+
]),
|
|
477
|
+
},
|
|
478
|
+
};
|
|
479
|
+
}
|
|
404
480
|
//#endregion
|
|
405
481
|
//#region Handler Registry
|
|
406
482
|
const NODE_HYDRATORS = {
|
|
@@ -414,6 +490,7 @@ const NODE_HYDRATORS = {
|
|
|
414
490
|
loop: hydrateLoopNode,
|
|
415
491
|
sequence: hydrateSequenceNode,
|
|
416
492
|
every: hydrateEveryNode,
|
|
493
|
+
subflow: hydrateSubflowNode,
|
|
417
494
|
'claude-code': hydrateSubHarnessNode,
|
|
418
495
|
codex: hydrateSubHarnessNode,
|
|
419
496
|
opencode: hydrateSubHarnessNode,
|
|
@@ -611,6 +688,8 @@ async function runCodeViaSubprocess(opts) {
|
|
|
611
688
|
* @throws `NoeticConfigError` with code `UNKNOWN_NODE_KIND` if the node kind is unrecognised.
|
|
612
689
|
* @throws `NoeticConfigError` with code `UNKNOWN_TOOL_REFERENCE` if a tool name cannot be resolved.
|
|
613
690
|
* @throws `NoeticConfigError` with code `UNKNOWN_UNTIL_PREDICATE` if an until predicate kind is unrecognised.
|
|
691
|
+
* @throws `NoeticConfigError` with code `UNKNOWN_WORKFLOW_REFERENCE` (at execution time) if a subflow ref names no registered workflow.
|
|
692
|
+
* @throws `NoeticConfigError` with code `WORKFLOW_CYCLE` (at execution time) if named sub-workflow refs form a cycle.
|
|
614
693
|
*/
|
|
615
694
|
export function hydrateNode(node, ctx) {
|
|
616
695
|
const hydrator = NODE_HYDRATORS[node.kind];
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `step.workflow` — runs a `WorkflowDocument` as a single composable step.
|
|
3
|
+
*
|
|
4
|
+
* Lives beside `step-builders.ts` (rather than inside it) because the hydrator
|
|
5
|
+
* imports the base `step` object; adding a hydrating builder there would create
|
|
6
|
+
* an import cycle. This module composes the public `step` namespace instead.
|
|
7
|
+
*/
|
|
8
|
+
import type { ContextData, ContextLayer } from '@noetic-tools/context';
|
|
9
|
+
import type { OutputCodec, StepRun, SubHarness, SubHarnessKind, SubprocessAdapter, Tool, WorkflowDocument } from '@noetic-tools/types';
|
|
10
|
+
import * as stepBuilders from './step-builders.js';
|
|
11
|
+
/** @public Options for `step.workflow`. */
|
|
12
|
+
export interface StepWorkflowOpts {
|
|
13
|
+
id: string;
|
|
14
|
+
/** Inline workflow document. Mutually exclusive with `ref`. */
|
|
15
|
+
document?: WorkflowDocument;
|
|
16
|
+
/** Named workflow resolved from `workflows`. Mutually exclusive with `document`. */
|
|
17
|
+
ref?: string;
|
|
18
|
+
/** Client tools the document's `llm`/`tool` nodes may reference by name. Default: none. */
|
|
19
|
+
tools?: Tool[];
|
|
20
|
+
/** Named context layers for `provide`/`spawn` nodes. */
|
|
21
|
+
layers?: ReadonlyMap<string, ContextLayer>;
|
|
22
|
+
/** Named sub-workflows for `subflow` nodes — and for resolving `ref` itself. */
|
|
23
|
+
workflows?: ReadonlyMap<string, WorkflowDocument>;
|
|
24
|
+
/** SubHarness adapters for `claude-code`/`codex`/`opencode`/`pi` nodes. */
|
|
25
|
+
subHarnesses?: ReadonlyMap<SubHarnessKind, SubHarness>;
|
|
26
|
+
/** Output codecs for `llm` nodes' `output` codec references. */
|
|
27
|
+
uiLibraries?: ReadonlyMap<string, OutputCodec>;
|
|
28
|
+
/** Resolver for named subprocess adapters on `run` nodes. */
|
|
29
|
+
resolveSubprocess?: (ref: string) => SubprocessAdapter | undefined;
|
|
30
|
+
/** `'inherit'` (default) runs in the caller's session; `'spawn'` isolates via `spawn()`. */
|
|
31
|
+
isolation?: 'inherit' | 'spawn';
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Creates a step that hydrates and executes a JSON workflow document.
|
|
35
|
+
*
|
|
36
|
+
* The document resolves lazily on first execution (so a `ref` may target a
|
|
37
|
+
* workflow registered after the step is built) and the hydrated tree is
|
|
38
|
+
* memoized across executions. When the step itself is built from a `ref`,
|
|
39
|
+
* that name seeds the subflow ancestry chain, so a self-referencing named
|
|
40
|
+
* workflow fails with `WORKFLOW_CYCLE` instead of recursing forever.
|
|
41
|
+
*
|
|
42
|
+
* @public
|
|
43
|
+
* @param opts - See `StepWorkflowOpts`.
|
|
44
|
+
* @returns A `StepRun` executing the workflow via the harness on the context.
|
|
45
|
+
* @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
|
|
46
|
+
* @throws `NoeticConfigError` with code `INVALID_WORKFLOW_SOURCE` unless exactly one of `document`/`ref` is set.
|
|
47
|
+
* @throws `NoeticConfigError` with code `MISSING_HARNESS_CONTEXT` (at execution) without `ctx.harness`.
|
|
48
|
+
* @throws `NoeticConfigError` with code `UNKNOWN_WORKFLOW_REFERENCE` (at execution) if `ref` names no registered workflow.
|
|
49
|
+
*/
|
|
50
|
+
export declare function stepWorkflow(opts: StepWorkflowOpts): StepRun<ContextData, string, string>;
|
|
51
|
+
/** @public The step builder namespace: the base builders plus `workflow`. */
|
|
52
|
+
export declare const step: {
|
|
53
|
+
readonly run: <TContext = Readonly<Record<string, Record<string, unknown>>>, I = unknown, O = unknown>(opts: stepBuilders.StepRunOpts<TContext, I, O>) => StepRun<TContext, I, O>;
|
|
54
|
+
readonly llm: <TContext = Readonly<Record<string, Record<string, unknown>>>, I = unknown, O = unknown>(opts: stepBuilders.StepLLMOpts<TContext, O>) => import("@noetic-tools/types").StepLLM<TContext, I, O>;
|
|
55
|
+
readonly tool: <TContext = Readonly<Record<string, Record<string, unknown>>>, I = unknown, O = unknown>(opts: stepBuilders.StepToolOpts<I, O>) => import("@noetic-tools/types").StepTool<TContext, I, O>;
|
|
56
|
+
readonly claudeCode: <TContext = Readonly<Record<string, Record<string, unknown>>>, I = unknown, O = unknown>(opts: stepBuilders.StepSubHarnessOpts<TContext, O>) => import("@noetic-tools/types").StepSubHarness<TContext, I, O>;
|
|
57
|
+
readonly codex: <TContext = Readonly<Record<string, Record<string, unknown>>>, I = unknown, O = unknown>(opts: stepBuilders.StepSubHarnessOpts<TContext, O>) => import("@noetic-tools/types").StepSubHarness<TContext, I, O>;
|
|
58
|
+
readonly opencode: <TContext = Readonly<Record<string, Record<string, unknown>>>, I = unknown, O = unknown>(opts: stepBuilders.StepSubHarnessOpts<TContext, O>) => import("@noetic-tools/types").StepSubHarness<TContext, I, O>;
|
|
59
|
+
readonly pi: <TContext = Readonly<Record<string, Record<string, unknown>>>, I = unknown, O = unknown>(opts: stepBuilders.StepSubHarnessOpts<TContext, O>) => import("@noetic-tools/types").StepSubHarness<TContext, I, O>;
|
|
60
|
+
readonly workflow: typeof stepWorkflow;
|
|
61
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `step.workflow` — runs a `WorkflowDocument` as a single composable step.
|
|
3
|
+
*
|
|
4
|
+
* Lives beside `step-builders.ts` (rather than inside it) because the hydrator
|
|
5
|
+
* imports the base `step` object; adding a hydrating builder there would create
|
|
6
|
+
* an import cycle. This module composes the public `step` namespace instead.
|
|
7
|
+
*/
|
|
8
|
+
import { frameworkCast, NoeticConfigError } from '@noetic-tools/types';
|
|
9
|
+
import { spawn } from './spawn-builder.js';
|
|
10
|
+
import * as stepBuilders from './step-builders.js';
|
|
11
|
+
import { hydrateWorkflow } from './workflow-hydrator.js';
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region Builder
|
|
14
|
+
/**
|
|
15
|
+
* Creates a step that hydrates and executes a JSON workflow document.
|
|
16
|
+
*
|
|
17
|
+
* The document resolves lazily on first execution (so a `ref` may target a
|
|
18
|
+
* workflow registered after the step is built) and the hydrated tree is
|
|
19
|
+
* memoized across executions. When the step itself is built from a `ref`,
|
|
20
|
+
* that name seeds the subflow ancestry chain, so a self-referencing named
|
|
21
|
+
* workflow fails with `WORKFLOW_CYCLE` instead of recursing forever.
|
|
22
|
+
*
|
|
23
|
+
* @public
|
|
24
|
+
* @param opts - See `StepWorkflowOpts`.
|
|
25
|
+
* @returns A `StepRun` executing the workflow via the harness on the context.
|
|
26
|
+
* @throws `NoeticConfigError` with code `EMPTY_STEP_ID` if `id` is empty.
|
|
27
|
+
* @throws `NoeticConfigError` with code `INVALID_WORKFLOW_SOURCE` unless exactly one of `document`/`ref` is set.
|
|
28
|
+
* @throws `NoeticConfigError` with code `MISSING_HARNESS_CONTEXT` (at execution) without `ctx.harness`.
|
|
29
|
+
* @throws `NoeticConfigError` with code `UNKNOWN_WORKFLOW_REFERENCE` (at execution) if `ref` names no registered workflow.
|
|
30
|
+
*/
|
|
31
|
+
export function stepWorkflow(opts) {
|
|
32
|
+
if (!opts.id || opts.id.trim() === '') {
|
|
33
|
+
throw new NoeticConfigError({
|
|
34
|
+
code: 'EMPTY_STEP_ID',
|
|
35
|
+
message: 'step.workflow() requires a non-empty id.',
|
|
36
|
+
hint: 'Pass a unique string as the id field, e.g. step.workflow({ id: "verify", ... }).',
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
if ((opts.document === undefined) === (opts.ref === undefined)) {
|
|
40
|
+
throw new NoeticConfigError({
|
|
41
|
+
code: 'INVALID_WORKFLOW_SOURCE',
|
|
42
|
+
message: `step.workflow('${opts.id}') requires exactly one of 'document' (inline) or 'ref' (named).`,
|
|
43
|
+
hint: "Pass document: { version: 1, root: ... } or ref: '<name>' with a workflows registry.",
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
// The hydrated tree bakes the harness's executeStep into every nested
|
|
47
|
+
// node's closure, so the cache is keyed on the harness: a step shared
|
|
48
|
+
// across sessions re-hydrates when it runs under a different harness
|
|
49
|
+
// instead of routing nested steps through the first one.
|
|
50
|
+
let cached;
|
|
51
|
+
return stepBuilders.step.run({
|
|
52
|
+
id: opts.id,
|
|
53
|
+
execute: async (input, ctx) => {
|
|
54
|
+
const harness = ctx.harness;
|
|
55
|
+
if (!harness) {
|
|
56
|
+
throw new NoeticConfigError({
|
|
57
|
+
code: 'MISSING_HARNESS_CONTEXT',
|
|
58
|
+
message: 'step.workflow requires a harness on the execution context.',
|
|
59
|
+
hint: 'Execute this step via AgentHarness.run() or ensure ctx.harness is set.',
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
const executeStep = frameworkCast(harness.run.bind(harness));
|
|
63
|
+
if (!cached || cached.harness !== harness) {
|
|
64
|
+
cached = {
|
|
65
|
+
harness,
|
|
66
|
+
step: hydrate(opts, executeStep),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return stringify(await executeStep(cached.step, input, ctx));
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/** @public The step builder namespace: the base builders plus `workflow`. */
|
|
74
|
+
export const step = {
|
|
75
|
+
...stepBuilders.step,
|
|
76
|
+
workflow: stepWorkflow,
|
|
77
|
+
};
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region Helpers
|
|
80
|
+
function hydrate(opts, executeStep) {
|
|
81
|
+
const doc = opts.document ?? (opts.ref ? opts.workflows?.get(opts.ref) : undefined);
|
|
82
|
+
if (!doc) {
|
|
83
|
+
throw new NoeticConfigError({
|
|
84
|
+
code: 'UNKNOWN_WORKFLOW_REFERENCE',
|
|
85
|
+
message: `Workflow '${opts.ref}' referenced by step.workflow('${opts.id}') is not registered.`,
|
|
86
|
+
hint: `Pass named workflows via the workflows option. Available: ${[
|
|
87
|
+
...(opts.workflows?.keys() ?? []),
|
|
88
|
+
].join(', ') || '(none)'}.`,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
const hydrationCtx = {
|
|
92
|
+
tools: new Map((opts.tools ?? []).map((t) => [
|
|
93
|
+
t.name,
|
|
94
|
+
t,
|
|
95
|
+
])),
|
|
96
|
+
executeStep,
|
|
97
|
+
layers: opts.layers,
|
|
98
|
+
workflows: opts.workflows,
|
|
99
|
+
subHarnesses: opts.subHarnesses,
|
|
100
|
+
uiLibraries: opts.uiLibraries,
|
|
101
|
+
resolveSubprocess: opts.resolveSubprocess,
|
|
102
|
+
subflowAncestry: opts.ref
|
|
103
|
+
? new Set([
|
|
104
|
+
opts.ref,
|
|
105
|
+
])
|
|
106
|
+
: undefined,
|
|
107
|
+
};
|
|
108
|
+
const hydrated = hydrateWorkflow(doc, hydrationCtx);
|
|
109
|
+
if (opts.isolation !== 'spawn') {
|
|
110
|
+
return hydrated;
|
|
111
|
+
}
|
|
112
|
+
return spawn({
|
|
113
|
+
id: `${opts.id}-spawn`,
|
|
114
|
+
child: hydrated,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function stringify(value) {
|
|
118
|
+
if (typeof value === 'string') {
|
|
119
|
+
return value;
|
|
120
|
+
}
|
|
121
|
+
if (value === null || value === undefined) {
|
|
122
|
+
return '';
|
|
123
|
+
}
|
|
124
|
+
return JSON.stringify(value);
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ContextData, StorageAdapter } from '@noetic-tools/context';
|
|
2
2
|
import type { Context, Step } from '@noetic-tools/types';
|
|
3
3
|
import type { EmbedFn } from '../types/embed.js';
|
|
4
4
|
export type Condition<I> = (input: I, ctx: Context) => Promise<boolean>;
|
|
5
|
-
export interface WhenClause<
|
|
5
|
+
export interface WhenClause<TContext = ContextData, I = unknown, O = unknown> {
|
|
6
6
|
readonly kind: 'when';
|
|
7
7
|
readonly condition: Condition<I>;
|
|
8
|
-
readonly step: Step<
|
|
8
|
+
readonly step: Step<TContext, I, O>;
|
|
9
9
|
}
|
|
10
|
-
export interface OtherwiseClause<
|
|
10
|
+
export interface OtherwiseClause<TContext = ContextData, I = unknown, O = unknown> {
|
|
11
11
|
readonly kind: 'otherwise';
|
|
12
|
-
readonly step: Step<
|
|
12
|
+
readonly step: Step<TContext, I, O>;
|
|
13
13
|
}
|
|
14
|
-
type Clause<
|
|
14
|
+
type Clause<TContext, I, O> = WhenClause<TContext, I, O> | OtherwiseClause<TContext, I, O>;
|
|
15
15
|
/**
|
|
16
16
|
* Creates a conditional clause that routes to the given step when the condition is true.
|
|
17
17
|
*
|
|
@@ -20,7 +20,7 @@ type Clause<TMemory, I, O> = WhenClause<TMemory, I, O> | OtherwiseClause<TMemory
|
|
|
20
20
|
* @param step - Step to execute when the condition matches.
|
|
21
21
|
* @returns A `WhenClause` for use in `semanticRoute`.
|
|
22
22
|
*/
|
|
23
|
-
export declare function when<
|
|
23
|
+
export declare function when<TContext = ContextData, I = unknown, O = unknown>(condition: Condition<I>, step: Step<TContext, I, O>): WhenClause<TContext, I, O>;
|
|
24
24
|
/**
|
|
25
25
|
* Creates a fallback clause that always matches, used as the last clause in `semanticRoute`.
|
|
26
26
|
*
|
|
@@ -28,7 +28,7 @@ export declare function when<TMemory = ContextMemory, I = unknown, O = unknown>(
|
|
|
28
28
|
* @param step - Step to execute when no prior `when` clause matches.
|
|
29
29
|
* @returns An `OtherwiseClause` for use in `semanticRoute`.
|
|
30
30
|
*/
|
|
31
|
-
export declare function otherwise<
|
|
31
|
+
export declare function otherwise<TContext = ContextData, I = unknown, O = unknown>(step: Step<TContext, I, O>): OtherwiseClause<TContext, I, O>;
|
|
32
32
|
/**
|
|
33
33
|
* Builds a route function from an ordered list of `when`/`otherwise` clauses.
|
|
34
34
|
* Evaluates clauses sequentially, returning the first matching step or `null`.
|
|
@@ -37,21 +37,21 @@ export declare function otherwise<TMemory = ContextMemory, I = unknown, O = unkn
|
|
|
37
37
|
* @param clauses - Ordered `WhenClause` and optional trailing `OtherwiseClause`.
|
|
38
38
|
* @returns A route function suitable for `branch({ route })`.
|
|
39
39
|
*/
|
|
40
|
-
export declare function semanticRoute<
|
|
41
|
-
interface SemanticSwitchSimple<
|
|
40
|
+
export declare function semanticRoute<TContext = ContextData, I = unknown, O = unknown>(...clauses: Clause<TContext, I, O>[]): (input: I, ctx: Context) => Promise<Step<TContext, I, O> | null>;
|
|
41
|
+
interface SemanticSwitchSimple<TContext, I, O> {
|
|
42
42
|
embed: EmbedFn;
|
|
43
|
-
cases: Record<string, Step<
|
|
44
|
-
default?: Step<
|
|
43
|
+
cases: Record<string, Step<TContext, I, O>>;
|
|
44
|
+
default?: Step<TContext, I, O>;
|
|
45
45
|
threshold?: number;
|
|
46
46
|
cache?: StorageAdapter;
|
|
47
47
|
}
|
|
48
|
-
interface SemanticSwitchAdvanced<
|
|
48
|
+
interface SemanticSwitchAdvanced<TContext, I, O> {
|
|
49
49
|
embed: EmbedFn;
|
|
50
50
|
cases: {
|
|
51
51
|
labels: string | string[];
|
|
52
|
-
step: Step<
|
|
52
|
+
step: Step<TContext, I, O>;
|
|
53
53
|
}[];
|
|
54
|
-
default?: Step<
|
|
54
|
+
default?: Step<TContext, I, O>;
|
|
55
55
|
threshold?: number;
|
|
56
56
|
cache?: StorageAdapter;
|
|
57
57
|
}
|
|
@@ -62,9 +62,9 @@ interface SemanticSwitchAdvanced<TMemory, I, O> {
|
|
|
62
62
|
* @param opts - Simple form with `Record<string, Step>` cases, or advanced form with multi-label cases.
|
|
63
63
|
* @returns A route function suitable for `branch({ route })`.
|
|
64
64
|
*/
|
|
65
|
-
export declare function semanticSwitch<
|
|
65
|
+
export declare function semanticSwitch<TContext = ContextData, I = unknown, O = unknown>(opts: SemanticSwitchSimple<TContext, I, O>): (input: I, ctx: Context) => Promise<Step<TContext, I, O> | null>;
|
|
66
66
|
/** @public */
|
|
67
|
-
export declare function semanticSwitch<
|
|
67
|
+
export declare function semanticSwitch<TContext = ContextData, I = unknown, O = unknown>(opts: SemanticSwitchAdvanced<TContext, I, O>): (input: I, ctx: Context) => Promise<Step<TContext, I, O> | null>;
|
|
68
68
|
/**
|
|
69
69
|
* Creates a condition that matches when the input embedding is within a cosine similarity threshold of a label.
|
|
70
70
|
*
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { storageGetMany } from '@noetic-tools/
|
|
1
|
+
import { storageGetMany } from '@noetic-tools/context';
|
|
2
2
|
import { createMessage, extractAssistantText, trackUsage } from '@noetic-tools/types';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { cosineSimilarity } from './cosine-similarity.js';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deprecated aliases from the "memory layer" era of the framework.
|
|
3
|
+
*
|
|
4
|
+
* The layer system assembles the model's *context window* — recall, budget
|
|
5
|
+
* allocation, history projection, the item-append pipeline — so it is named
|
|
6
|
+
* after context, not memory. Every name below still resolves to its
|
|
7
|
+
* replacement; nothing here changes behaviour.
|
|
8
|
+
*
|
|
9
|
+
* Most of these are plain pass-throughs: the alias and its replacement already
|
|
10
|
+
* live in `@noetic-tools/types` / `@noetic-tools/context`, and re-exporting
|
|
11
|
+
* carries each name's `@deprecated` pointer along with it. Only the renaming
|
|
12
|
+
* aliases — where core exports a symbol under a *different* name than its
|
|
13
|
+
* source package does — are declared here.
|
|
14
|
+
*
|
|
15
|
+
* The matching runtime aliases (the `memory:` config key on `provide`/`spawn`/
|
|
16
|
+
* `tool`/`react`/`AgentHarness`, and the `ctx.memory` accessor) are handled at
|
|
17
|
+
* their call sites — see `resolveContextOption`.
|
|
18
|
+
*
|
|
19
|
+
* Scheduled for removal in the next major of `@noetic-tools/core`.
|
|
20
|
+
*/
|
|
21
|
+
export type { ObservationalMemoryConfig, PlanMemoryConfig, TemporalMemoryConfig, WorkingMemoryConfig, WorkingMemoryState, } from '@noetic-tools/context';
|
|
22
|
+
export { observationalMemory, planMemory, temporalMemory, toolMemoryLayer, workingMemory, } from '@noetic-tools/context';
|
|
23
|
+
export type { ContextMemory, InferMemory, InferMemoryShape, MemoryCallModelRequest, MemoryConfig, MemoryHooks, MemoryLayer, MemoryScope, MemoryTraceSpan, ToolMemory, ToolMemoryDeclaration, } from '@noetic-tools/types';
|
|
24
|
+
export {
|
|
25
|
+
/**
|
|
26
|
+
* @public
|
|
27
|
+
* @deprecated Renamed to `context`. Declared here rather than re-exported
|
|
28
|
+
* because the builder itself lives in core under its new name.
|
|
29
|
+
*/
|
|
30
|
+
context as memory, } from './builders/context-builder.js';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deprecated aliases from the "memory layer" era of the framework.
|
|
3
|
+
*
|
|
4
|
+
* The layer system assembles the model's *context window* — recall, budget
|
|
5
|
+
* allocation, history projection, the item-append pipeline — so it is named
|
|
6
|
+
* after context, not memory. Every name below still resolves to its
|
|
7
|
+
* replacement; nothing here changes behaviour.
|
|
8
|
+
*
|
|
9
|
+
* Most of these are plain pass-throughs: the alias and its replacement already
|
|
10
|
+
* live in `@noetic-tools/types` / `@noetic-tools/context`, and re-exporting
|
|
11
|
+
* carries each name's `@deprecated` pointer along with it. Only the renaming
|
|
12
|
+
* aliases — where core exports a symbol under a *different* name than its
|
|
13
|
+
* source package does — are declared here.
|
|
14
|
+
*
|
|
15
|
+
* The matching runtime aliases (the `memory:` config key on `provide`/`spawn`/
|
|
16
|
+
* `tool`/`react`/`AgentHarness`, and the `ctx.memory` accessor) are handled at
|
|
17
|
+
* their call sites — see `resolveContextOption`.
|
|
18
|
+
*
|
|
19
|
+
* Scheduled for removal in the next major of `@noetic-tools/core`.
|
|
20
|
+
*/
|
|
21
|
+
export { observationalMemory, planMemory, temporalMemory, toolMemoryLayer, workingMemory, } from '@noetic-tools/context';
|
|
22
|
+
export {
|
|
23
|
+
/**
|
|
24
|
+
* @public
|
|
25
|
+
* @deprecated Renamed to `context`. Declared here rather than re-exported
|
|
26
|
+
* because the builder itself lives in core under its new name.
|
|
27
|
+
*/
|
|
28
|
+
context as memory, } from './builders/context-builder.js';
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { ItemSchemaRegistry } from '@noetic-tools/types';
|
|
2
|
+
import type { LayerStateStore, RecallCache } from './deps/context.js';
|
|
2
3
|
import type { DetachedSpawnOverrides } from './deps/interpreter.js';
|
|
3
|
-
import type { LayerStateStore, RecallCache } from './deps/memory.js';
|
|
4
4
|
import type { CheckpointStore, EventBroadcaster, RestoreCheckpointOptions, StepLedgerRetention, StepLedgerStore } from './deps/runtime.js';
|
|
5
|
-
import type { AgentConfig, AgentHarnessContract, AgentHooks, CallModelRequest, Channel, ChannelHandle, Context,
|
|
5
|
+
import type { AgentConfig, AgentHarnessContract, AgentHooks, CallModelRequest, Channel, ChannelHandle, Context, ContextData, ContextLayer, CwdState, DeliveryMode, DetachedHandle, ExecuteInput, ExecuteOptions, ExternalChannel, FsAdapter, HarnessResponse, HarnessStatus, Item, ItemSchemaExtensions, LLMResponse, LlmProviderConfig, ProjectionPolicy, RecallLayerOutput, SessionScope, ShellAdapter, Span, SteeringDecision, Step, StorageAdapter, StreamEvent, StreamingItem, SubHarnessSession, SubprocessAdapter, Tool, TraceExporter, ZodType } from './deps/types.js';
|
|
6
6
|
export { createStreamIdleWatchdog } from './model-call.js';
|
|
7
7
|
interface AgentHarnessOpts<TParams extends Record<string, unknown> = Record<string, unknown>> {
|
|
8
8
|
name: string;
|
|
9
|
-
initialStep?: Step<
|
|
10
|
-
/** Default
|
|
11
|
-
|
|
9
|
+
initialStep?: Step<ContextData, string, string>;
|
|
10
|
+
/** Default context layers applied to every context created via `createContext()` / `execute()`. */
|
|
11
|
+
context?: ContextLayer[];
|
|
12
|
+
/** @deprecated Renamed to `context`. */
|
|
13
|
+
memory?: ContextLayer[];
|
|
12
14
|
storage?: StorageAdapter;
|
|
13
15
|
hooks?: AgentHooks;
|
|
14
16
|
/**
|
|
@@ -93,8 +95,8 @@ export interface ResolvedLlmClient {
|
|
|
93
95
|
*/
|
|
94
96
|
export declare function resolveLlmClient(config: LlmProviderConfig | undefined, env: LlmEnv): ResolvedLlmClient | undefined;
|
|
95
97
|
/**
|
|
96
|
-
* Default agent harness for executing agent steps with built-in channel,
|
|
97
|
-
* Provides channel store,
|
|
98
|
+
* Default agent harness for executing agent steps with built-in channel, context, and trace support.
|
|
99
|
+
* Provides channel store, context layer lifecycle, and trace export with no external dependencies.
|
|
98
100
|
*
|
|
99
101
|
* Messages submitted via `execute()` are enqueued on a per-thread session and
|
|
100
102
|
* processed by a `SessionRunner`. Consumers observe responses via the session-
|
|
@@ -128,10 +130,10 @@ export declare class AgentHarness<TParams extends Record<string, unknown> = Reco
|
|
|
128
130
|
private readonly initialStep?;
|
|
129
131
|
/** Harness-wide tool pool merged into every context's `unifiedTools`. */
|
|
130
132
|
private readonly harnessTools;
|
|
131
|
-
/** @internal
|
|
133
|
+
/** @internal Context layers configured for this harness. Exposed non-private
|
|
132
134
|
* so free functions in `runtime/durable/` (checkpoint/restore) can read it
|
|
133
135
|
* without friend-class gymnastics. Do not access from outside core. */
|
|
134
|
-
readonly
|
|
136
|
+
readonly _contextLayers?: ContextLayer[];
|
|
135
137
|
private readonly client?;
|
|
136
138
|
private readonly channelStore;
|
|
137
139
|
private readonly callModelOverride?;
|
|
@@ -189,7 +191,7 @@ export declare class AgentHarness<TParams extends Record<string, unknown> = Reco
|
|
|
189
191
|
private getOrCreateSession;
|
|
190
192
|
private requireSession;
|
|
191
193
|
callModel(request: CallModelRequest): Promise<LLMResponse>;
|
|
192
|
-
run<I, O>(s: Step<
|
|
194
|
+
run<I, O>(s: Step<ContextData, I, O>, input: I, ctx: Context): Promise<O>;
|
|
193
195
|
/** Run all layer `init` hooks before the first step executes. Per spec 11,
|
|
194
196
|
* init MUST complete before any recall fires so layer state is populated. */
|
|
195
197
|
private initAndRun;
|
|
@@ -201,14 +203,16 @@ export declare class AgentHarness<TParams extends Record<string, unknown> = Reco
|
|
|
201
203
|
* clobber accumulated in-memory state.
|
|
202
204
|
*/
|
|
203
205
|
private ensureLayersInit;
|
|
204
|
-
detachedSpawn<I, O>(s: Step<
|
|
206
|
+
detachedSpawn<I, O>(s: Step<ContextData, I, O>, input: I, parentCtx: Context, overrides?: DetachedSpawnOverrides): DetachedHandle<O>;
|
|
205
207
|
createContext(opts?: {
|
|
206
208
|
parent?: Context;
|
|
207
209
|
items?: Item[];
|
|
208
210
|
state?: unknown;
|
|
209
211
|
threadId?: string;
|
|
210
212
|
resourceId?: string;
|
|
211
|
-
|
|
213
|
+
context?: ContextLayer[];
|
|
214
|
+
/** @deprecated Renamed to `context`. */
|
|
215
|
+
memory?: ContextLayer[];
|
|
212
216
|
/**
|
|
213
217
|
* Initial cwd for the new context. When set, takes precedence over both
|
|
214
218
|
* the parent snapshot and the harness root cwd — used by worktree
|
|
@@ -226,15 +230,15 @@ export declare class AgentHarness<TParams extends Record<string, unknown> = Reco
|
|
|
226
230
|
/** Resolves layer-provided tools and merges with step tools into ctx.unifiedTools. */
|
|
227
231
|
private setUnifiedTools;
|
|
228
232
|
private toExecCtx;
|
|
229
|
-
initLayers(layers:
|
|
230
|
-
recallLayers(layers:
|
|
233
|
+
initLayers(layers: ContextLayer[], ctx: Context, storage: StorageAdapter): Promise<void>;
|
|
234
|
+
recallLayers(layers: ContextLayer[], input: string, ctx: Context): Promise<RecallLayerOutput[]>;
|
|
231
235
|
/** Allocate per-layer recall budgets from the harness projection policy. */
|
|
232
236
|
private layerBudgets;
|
|
233
|
-
recallLayersAtomic(layers:
|
|
234
|
-
recallLayersEventual(layers:
|
|
237
|
+
recallLayersAtomic(layers: ContextLayer[], input: string, ctx: Context, budgets: Map<string, number>): Promise<RecallLayerOutput[]>;
|
|
238
|
+
recallLayersEventual(layers: ContextLayer[], input: string, ctx: Context, budgets: Map<string, number>): Promise<RecallLayerOutput[]>;
|
|
235
239
|
/**
|
|
236
240
|
* Compute the items array that would be sent to the model on the next turn —
|
|
237
|
-
* the same arrangement `executeLLM` builds: harness-level
|
|
241
|
+
* the same arrangement `executeLLM` builds: harness-level context layers'
|
|
238
242
|
* recall outputs concatenated with the session's accumulated history.
|
|
239
243
|
*
|
|
240
244
|
* Read-mostly: `recallLayers` writes layer-state snapshots to
|
|
@@ -242,8 +246,8 @@ export declare class AgentHarness<TParams extends Record<string, unknown> = Reco
|
|
|
242
246
|
* remain consistent with what the next real turn produces.
|
|
243
247
|
*/
|
|
244
248
|
previewRequestItems(scope?: SessionScope): Promise<ReadonlyArray<Item>>;
|
|
245
|
-
storeLayers(layers:
|
|
246
|
-
disposeLayers(layers:
|
|
249
|
+
storeLayers(layers: ContextLayer[], response: LLMResponse, ctx: Context): Promise<void>;
|
|
250
|
+
disposeLayers(layers: ContextLayer[], ctx: Context): Promise<void>;
|
|
247
251
|
/**
|
|
248
252
|
* Snapshot the execution state at a checkpoint boundary.
|
|
249
253
|
*
|
|
@@ -272,7 +276,7 @@ export declare class AgentHarness<TParams extends Record<string, unknown> = Reco
|
|
|
272
276
|
* checkpoint via `CheckpointStore.clear()` and start a fresh execution.
|
|
273
277
|
*
|
|
274
278
|
* `opts` is the `createContext`-shaped wiring the host attached to the
|
|
275
|
-
* original context (broadcaster, parent, state,
|
|
279
|
+
* original context (broadcaster, parent, state, context overrides). A
|
|
276
280
|
* snapshot recovers data, not live objects — pass the same wiring here or
|
|
277
281
|
* the resumed run gets an undecorated context and whatever depended on that
|
|
278
282
|
* wiring (event streaming, mid-turn injection) stops working without
|
|
@@ -300,7 +304,7 @@ export declare class AgentHarness<TParams extends Record<string, unknown> = Reco
|
|
|
300
304
|
clearCheckpoint(executionId: string): Promise<void>;
|
|
301
305
|
/**
|
|
302
306
|
* Cancel an execution: abort `ctx` and every live descendant context, then
|
|
303
|
-
* run the
|
|
307
|
+
* run the context-layer teardown for each (spec 09, Cancellation).
|
|
304
308
|
*
|
|
305
309
|
* The abort itself fans out top-down and synchronously — `ctx.abort()`
|
|
306
310
|
* cascades into every live fork path and spawn child, so no corner of the
|
|
@@ -327,10 +331,10 @@ export declare class AgentHarness<TParams extends Record<string, unknown> = Reco
|
|
|
327
331
|
createSpan(name: string, parent: Span | null): Span;
|
|
328
332
|
getLayerState<T>(executionId: string, layerId: string): T | undefined;
|
|
329
333
|
setLayerState<T>(executionId: string, layerId: string, state: T): void;
|
|
330
|
-
beforeToolCall(layers:
|
|
331
|
-
afterModelCall(layers:
|
|
332
|
-
projectHistory(layers:
|
|
333
|
-
runAppendPipeline(layers:
|
|
334
|
+
beforeToolCall(layers: ContextLayer[], toolName: string, toolArgs: unknown, ctx: Context): Promise<SteeringDecision>;
|
|
335
|
+
afterModelCall(layers: ContextLayer[], response: LLMResponse, ctx: Context): Promise<SteeringDecision>;
|
|
336
|
+
projectHistory(layers: ContextLayer[], items: ReadonlyArray<Item>, ctx: Context): Promise<ReadonlyArray<Item>>;
|
|
337
|
+
runAppendPipeline(layers: ContextLayer[], items: Item[], ctx: Context): Promise<{
|
|
334
338
|
items: Item[];
|
|
335
339
|
rerenderRequests: {
|
|
336
340
|
layerId: string;
|
|
@@ -344,7 +348,7 @@ export declare class AgentHarness<TParams extends Record<string, unknown> = Reco
|
|
|
344
348
|
slot: number;
|
|
345
349
|
timing: 'immediate' | 'batched';
|
|
346
350
|
scope: 'self' | 'slot-after' | 'all';
|
|
347
|
-
}[], layers:
|
|
351
|
+
}[], layers: ContextLayer[], ctx: Context, budgets: Map<string, number>, query?: string): Promise<{
|
|
348
352
|
layerId: string;
|
|
349
353
|
items: Item[];
|
|
350
354
|
tokenCount: number;
|