@noetic-tools/core 0.0.1 → 0.1.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.
- package/README.md +31 -11
- package/dist/adapters/in-memory-fs-adapter.d.ts +1 -1
- package/dist/adapters/in-memory-fs-adapter.js +1 -1
- package/dist/adapters/in-memory-shell-adapter.d.ts +1 -1
- package/dist/adapters/in-memory-subprocess/manifest-persistence.d.ts +8 -0
- package/dist/adapters/in-memory-subprocess/manifest-persistence.js +56 -0
- package/dist/adapters/in-memory-subprocess/metadata.d.ts +12 -0
- package/dist/adapters/in-memory-subprocess/metadata.js +58 -0
- package/dist/adapters/in-memory-subprocess/step-completion.d.ts +3 -0
- package/dist/adapters/in-memory-subprocess/step-completion.js +86 -0
- package/dist/adapters/in-memory-subprocess/types.d.ts +88 -0
- package/dist/adapters/in-memory-subprocess/types.js +2 -0
- package/dist/adapters/in-memory-subprocess-adapter.d.ts +12 -4
- package/dist/adapters/in-memory-subprocess-adapter.js +164 -55
- package/dist/adapters/openrouter.d.ts +16 -7
- package/dist/adapters/openrouter.js +68 -7
- package/dist/builders/channel-builder.d.ts +1 -1
- package/dist/builders/control-flow-builders.d.ts +3 -3
- package/dist/builders/control-flow-builders.js +9 -4
- package/dist/builders/every.d.ts +3 -3
- package/dist/builders/every.js +5 -2
- package/dist/builders/layer-provides-builders.d.ts +1 -32
- package/dist/builders/layer-provides-builders.js +1 -33
- package/dist/builders/loop-builder.d.ts +2 -2
- package/dist/builders/loop-builder.js +5 -2
- package/dist/builders/memory-builder.d.ts +1 -1
- package/dist/builders/memory-builder.js +1 -1
- package/dist/builders/provide-builder.d.ts +2 -2
- package/dist/builders/provide-builder.js +5 -2
- package/dist/builders/spawn-builder.d.ts +22 -9
- package/dist/builders/spawn-builder.js +17 -3
- package/dist/builders/step-builders.d.ts +51 -30
- package/dist/builders/step-builders.js +31 -12
- package/dist/builders/tool-builder.d.ts +7 -3
- package/dist/builders/tool-builder.js +3 -1
- package/dist/builders/workflow-hydrator.d.ts +38 -0
- package/dist/builders/workflow-hydrator.js +336 -0
- package/dist/conditions/conditions.d.ts +4 -4
- package/dist/conditions/conditions.js +2 -2
- package/dist/errors/noetic-error.d.ts +1 -1
- package/dist/errors/noetic-error.js +2 -0
- package/dist/{runtime → harness}/agent-harness.d.ts +65 -45
- package/dist/harness/agent-harness.js +576 -0
- package/dist/harness/deps/adapters.d.ts +4 -0
- package/dist/harness/deps/adapters.js +4 -0
- package/dist/harness/deps/interpreter.d.ts +5 -0
- package/dist/harness/deps/interpreter.js +4 -0
- package/dist/harness/deps/memory.d.ts +5 -0
- package/dist/harness/deps/memory.js +4 -0
- package/dist/harness/deps/runtime.d.ts +10 -0
- package/dist/harness/deps/runtime.js +7 -0
- package/dist/harness/deps/types.d.ts +17 -0
- package/dist/harness/deps/types.js +1 -0
- package/dist/harness/model-call.d.ts +50 -0
- package/dist/harness/model-call.js +694 -0
- package/dist/harness/model-schema.d.ts +19 -0
- package/dist/harness/model-schema.js +46 -0
- package/dist/harness/step-bootstrap.d.ts +25 -0
- package/dist/harness/step-bootstrap.js +170 -0
- package/dist/index.d.ts +114 -76
- package/dist/index.js +74 -50
- package/dist/internal-test.d.ts +4 -4
- package/dist/internal-test.js +4 -4
- package/dist/interpreter/action-deps.d.ts +12 -0
- package/dist/interpreter/action-deps.js +10 -0
- package/dist/interpreter/action-types.d.ts +8 -0
- package/dist/interpreter/action-types.js +1 -0
- package/dist/interpreter/collect-tools.d.ts +2 -2
- package/dist/interpreter/collect-tools.js +6 -2
- package/dist/interpreter/execute-action.d.ts +22 -0
- package/dist/interpreter/execute-action.js +527 -0
- package/dist/interpreter/{execute-every.d.ts → execute-control.d.ts} +8 -2
- package/dist/interpreter/execute-control.js +530 -0
- package/dist/interpreter/execute.d.ts +16 -3
- package/dist/interpreter/execute.js +154 -51
- package/dist/interpreter/message-helpers.d.ts +1 -9
- package/dist/interpreter/message-helpers.js +1 -42
- package/dist/interpreter/step-dispatcher.d.ts +61 -0
- package/dist/interpreter/step-dispatcher.js +67 -0
- package/dist/interpreter/typeguards.d.ts +8 -15
- package/dist/interpreter/typeguards.js +4 -21
- package/dist/memory/budget.d.ts +2 -2
- package/dist/memory/budget.js +1 -1
- package/dist/{runtime → memory}/exec-context-factory.d.ts +2 -2
- package/dist/{runtime → memory}/exec-context-factory.js +1 -1
- package/dist/memory/flow-schema.d.ts +52 -0
- package/dist/memory/flow-schema.js +102 -0
- package/dist/memory/function-call-utils.d.ts +1 -1
- package/dist/memory/function-call-utils.js +4 -2
- package/dist/memory/layer-api.d.ts +4 -4
- package/dist/memory/layer-api.js +2 -2
- package/dist/memory/layer-lifecycle.d.ts +6 -6
- package/dist/memory/layer-lifecycle.js +6 -6
- package/dist/memory/layer-provides.d.ts +32 -0
- package/dist/memory/layer-provides.js +33 -0
- package/dist/memory/layer-usage.d.ts +4 -3
- package/dist/memory/layer-usage.js +9 -3
- package/dist/memory/layers/durable-task-state.d.ts +8 -8
- package/dist/memory/layers/durable-task-state.js +2 -2
- package/dist/memory/layers/file-reference.d.ts +1 -1
- package/dist/memory/layers/file-reference.js +303 -247
- package/dist/memory/layers/history-window.d.ts +1 -1
- package/dist/memory/layers/history-window.js +4 -4
- package/dist/memory/layers/observational-memory.d.ts +5 -5
- package/dist/memory/layers/observational-memory.js +2 -3
- package/dist/memory/layers/plan.d.ts +2 -2
- package/dist/memory/layers/plan.js +15 -10
- package/dist/memory/layers/static-content.d.ts +2 -2
- package/dist/memory/layers/static-content.js +1 -1
- package/dist/memory/layers/steering.d.ts +7 -7
- package/dist/memory/layers/steering.js +5 -5
- package/dist/memory/layers/tool-memory-layer.d.ts +2 -2
- package/dist/memory/layers/tool-memory-layer.js +1 -1
- package/dist/memory/layers/working-memory.d.ts +7 -7
- package/dist/memory/layers/working-memory.js +4 -4
- package/dist/memory/projector.d.ts +2 -2
- package/dist/memory/scope.d.ts +1 -1
- package/dist/memory/strip-unresolved.d.ts +1 -1
- package/dist/observability/span-impl.d.ts +1 -1
- package/dist/observability/trace-exporter.d.ts +2 -2
- package/dist/observability/trace-exporter.js +1 -1
- package/dist/patterns/dynamic-workflow.d.ts +55 -0
- package/dist/patterns/dynamic-workflow.js +194 -0
- package/dist/patterns/flow.d.ts +2 -52
- package/dist/patterns/flow.js +1 -103
- package/dist/patterns/interview.d.ts +2 -2
- package/dist/patterns/interview.js +5 -5
- package/dist/patterns/plans.d.ts +6 -6
- package/dist/patterns/plans.js +4 -4
- package/dist/patterns/ralph-wiggum.d.ts +4 -4
- package/dist/patterns/ralph-wiggum.js +5 -5
- package/dist/patterns/react.d.ts +3 -3
- package/dist/patterns/react.js +5 -5
- package/dist/portable/adapters.d.ts +6 -0
- package/dist/portable/adapters.js +6 -0
- package/dist/portable/ask-user.d.ts +4 -0
- package/dist/portable/ask-user.js +2 -0
- package/dist/portable/builders.d.ts +12 -0
- package/dist/portable/builders.js +12 -0
- package/dist/portable/memory-layers.d.ts +12 -0
- package/dist/portable/memory-layers.js +12 -0
- package/dist/portable/runtime.d.ts +4 -0
- package/dist/portable/runtime.js +4 -0
- package/dist/portable/until.d.ts +4 -0
- package/dist/portable/until.js +4 -0
- package/dist/portable.d.ts +8 -26
- package/dist/portable.js +8 -34
- package/dist/runtime/broadcaster-utils.d.ts +7 -3
- package/dist/runtime/broadcaster-utils.js +11 -6
- package/dist/runtime/channel-store.d.ts +1 -1
- package/dist/runtime/channel-store.js +2 -2
- package/dist/runtime/context-deps.d.ts +4 -0
- package/dist/runtime/context-deps.js +2 -0
- package/dist/runtime/context-impl.d.ts +42 -12
- package/dist/runtime/context-impl.js +52 -5
- package/dist/runtime/context-type-deps.d.ts +14 -0
- package/dist/runtime/context-type-deps.js +1 -0
- package/dist/runtime/cwd-helpers.d.ts +1 -1
- package/dist/runtime/detached-handle.d.ts +52 -4
- package/dist/runtime/detached-handle.js +218 -14
- package/dist/runtime/durable/checkpoint-store.d.ts +38 -0
- package/dist/runtime/durable/checkpoint-store.js +101 -0
- package/dist/runtime/durable/detached-signal.d.ts +37 -0
- package/dist/runtime/durable/detached-signal.js +52 -0
- package/dist/runtime/durable/harness-checkpoints.d.ts +51 -0
- package/dist/runtime/durable/harness-checkpoints.js +104 -0
- package/dist/runtime/durable/index.d.ts +10 -0
- package/dist/runtime/durable/index.js +5 -0
- package/dist/runtime/durable/runnable-loop.d.ts +100 -0
- package/dist/runtime/durable/runnable-loop.js +90 -0
- package/dist/runtime/durable/session-seed.d.ts +28 -0
- package/dist/runtime/durable/session-seed.js +27 -0
- package/dist/runtime/durable/stall-nudge.d.ts +82 -0
- package/dist/runtime/durable/stall-nudge.js +87 -0
- package/dist/runtime/event-broadcaster.d.ts +1 -1
- package/dist/runtime/in-memory-storage.d.ts +1 -1
- package/dist/runtime/in-memory-storage.js +1 -1
- package/dist/runtime/item-log-impl.d.ts +3 -3
- package/dist/runtime/item-log-impl.js +1 -1
- package/dist/runtime/message-queue.d.ts +2 -2
- package/dist/runtime/session-runner.d.ts +7 -7
- package/dist/runtime/session-runner.js +3 -3
- package/dist/runtime/session-streams.d.ts +3 -3
- package/dist/runtime/session-streams.js +1 -1
- package/dist/runtime/step-registry.d.ts +42 -0
- package/dist/runtime/step-registry.js +77 -0
- package/dist/runtime/tool-memory.d.ts +3 -3
- package/dist/schemas/item.d.ts +1 -1
- package/dist/schemas/workflow.d.ts +139 -0
- package/dist/schemas/workflow.js +232 -0
- package/dist/types/ask-user-types.d.ts +57 -0
- package/dist/types/ask-user-types.js +74 -0
- package/dist/types/checkpoint.d.ts +98 -0
- package/dist/types/checkpoint.js +81 -0
- package/dist/types/common.d.ts +1 -50
- package/dist/types/context-parts/item-log.d.ts +6 -0
- package/dist/types/context-parts/item-log.js +1 -0
- package/dist/types/context-parts/layer-usage.d.ts +18 -0
- package/dist/types/context-parts/layer-usage.js +1 -0
- package/dist/types/context.d.ts +140 -31
- package/dist/types/error.d.ts +15 -0
- package/dist/types/harness-result.d.ts +2 -2
- package/dist/types/items.d.ts +18 -2
- package/dist/types/memory-context.d.ts +39 -0
- package/dist/types/memory-context.js +1 -0
- package/dist/types/memory.d.ts +38 -68
- package/dist/types/mutable-context.d.ts +3 -3
- package/dist/types/runtime.d.ts +14 -13
- package/dist/types/steering.d.ts +2 -2
- package/dist/types/step-registrar.d.ts +46 -0
- package/dist/types/step-registrar.js +56 -0
- package/dist/types/step.d.ts +34 -9
- package/dist/types/subprocess-adapter.d.ts +119 -3
- package/dist/types/subprocess-adapter.js +2 -0
- package/dist/types/tool-context.d.ts +6 -6
- package/dist/types/tool.d.ts +64 -0
- package/dist/types/tool.js +1 -0
- package/dist/unstable.d.ts +9 -9
- package/dist/unstable.js +7 -7
- package/dist/until/combinators.d.ts +1 -1
- package/dist/until/never.d.ts +1 -1
- package/dist/until/predicates.d.ts +13 -4
- package/dist/until/predicates.js +16 -2
- package/dist/util/message-helpers.d.ts +17 -0
- package/dist/util/message-helpers.js +64 -0
- package/package.json +6 -4
- package/dist/adapters/local-fs-adapter.d.ts +0 -3
- package/dist/adapters/local-fs-adapter.js +0 -43
- package/dist/adapters/local-shell-adapter.d.ts +0 -51
- package/dist/adapters/local-shell-adapter.js +0 -167
- package/dist/adapters/local-subprocess-adapter.d.ts +0 -16
- package/dist/adapters/local-subprocess-adapter.js +0 -187
- package/dist/conditions/index.d.ts +0 -3
- package/dist/conditions/index.js +0 -2
- package/dist/interpreter/execute-branch.d.ts +0 -3
- package/dist/interpreter/execute-branch.js +0 -10
- package/dist/interpreter/execute-every.js +0 -143
- package/dist/interpreter/execute-fork.d.ts +0 -3
- package/dist/interpreter/execute-fork.js +0 -215
- package/dist/interpreter/execute-llm.d.ts +0 -4
- package/dist/interpreter/execute-llm.js +0 -217
- package/dist/interpreter/execute-loop.d.ts +0 -3
- package/dist/interpreter/execute-loop.js +0 -171
- package/dist/interpreter/execute-provide.d.ts +0 -10
- package/dist/interpreter/execute-provide.js +0 -64
- package/dist/interpreter/execute-run.d.ts +0 -3
- package/dist/interpreter/execute-run.js +0 -39
- package/dist/interpreter/execute-spawn.d.ts +0 -11
- package/dist/interpreter/execute-spawn.js +0 -113
- package/dist/interpreter/execute-tool.d.ts +0 -5
- package/dist/interpreter/execute-tool.js +0 -81
- package/dist/runtime/agent-harness.js +0 -1170
- /package/dist/{interpreter → util}/framework-cast.d.ts +0 -0
- /package/dist/{interpreter → util}/framework-cast.js +0 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { CheckpointSchemaVersion } from '../../types/checkpoint.js';
|
|
2
|
+
import { ContextImpl } from '../context-impl.js';
|
|
3
|
+
//#endregion
|
|
4
|
+
//#region captureCheckpoint
|
|
5
|
+
/**
|
|
6
|
+
* Snapshot the execution state at a checkpoint boundary. No-op when no
|
|
7
|
+
* `CheckpointStore` is configured — zero-config harnesses preserve
|
|
8
|
+
* ephemeral semantics. Save failures are logged rather than thrown,
|
|
9
|
+
* because a checkpoint failing must never abort an otherwise-successful
|
|
10
|
+
* step.
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
export async function captureCheckpoint(h, ctx) {
|
|
15
|
+
const store = h.checkpointStore;
|
|
16
|
+
if (!store) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const impl = ctx instanceof ContextImpl ? ctx : null;
|
|
20
|
+
const frontier = impl ? impl.serialiseFrontier() : [];
|
|
21
|
+
const layers = {};
|
|
22
|
+
for (const layer of ctx.layers ?? []) {
|
|
23
|
+
const state = h.layerStateStore.get(ctx.id, layer.id);
|
|
24
|
+
if (state !== undefined) {
|
|
25
|
+
layers[layer.id] = state;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const snapshot = {
|
|
29
|
+
schemaVersion: CheckpointSchemaVersion,
|
|
30
|
+
executionId: ctx.id,
|
|
31
|
+
threadId: ctx.threadId,
|
|
32
|
+
resourceId: ctx.resourceId,
|
|
33
|
+
frontier,
|
|
34
|
+
layers,
|
|
35
|
+
cwd: {
|
|
36
|
+
current: ctx.cwdState.cwd,
|
|
37
|
+
previous: ctx.cwdState.previousCwd,
|
|
38
|
+
},
|
|
39
|
+
// Ask-user queue snapshot is empty at the core layer — the code-agent
|
|
40
|
+
// host is responsible for pushing pending prompts through this store
|
|
41
|
+
// via `AskUserService` integration. Carrying the shape from day one
|
|
42
|
+
// means future producers don't bump the schema version.
|
|
43
|
+
askUser: [],
|
|
44
|
+
itemLog: {
|
|
45
|
+
items: [
|
|
46
|
+
...ctx.itemLog.items,
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
capturedAt: new Date().toISOString(),
|
|
50
|
+
};
|
|
51
|
+
try {
|
|
52
|
+
await store.save(snapshot);
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
console.warn(`AgentHarness.checkpoint: failed to persist snapshot for execution "${ctx.id}":`, err);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region restoreFromCheckpoint
|
|
60
|
+
/**
|
|
61
|
+
* Rebuild a `Context` from a previously-persisted snapshot. Returns
|
|
62
|
+
* `null` if no snapshot is recorded for `executionId`. Layer state is
|
|
63
|
+
* replayed into `layerStateStore` keyed by the original executionId so
|
|
64
|
+
* the restored context observes the pre-crash state through
|
|
65
|
+
* `readLayerState` and the memory projectors.
|
|
66
|
+
*
|
|
67
|
+
* Preserves the original executionId on the returned context via
|
|
68
|
+
* `Object.defineProperty` — adapter correlation across crash/restart
|
|
69
|
+
* requires a stable id.
|
|
70
|
+
*
|
|
71
|
+
* @internal
|
|
72
|
+
*/
|
|
73
|
+
export async function restoreFromCheckpoint(h, executionId) {
|
|
74
|
+
const store = h.checkpointStore;
|
|
75
|
+
if (!store) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
const snapshot = await store.load(executionId);
|
|
79
|
+
if (!snapshot) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
for (const [layerId, state] of Object.entries(snapshot.layers)) {
|
|
83
|
+
h.layerStateStore.set(executionId, layerId, state);
|
|
84
|
+
}
|
|
85
|
+
const items = h.itemSchemas.parseMany(snapshot.itemLog.items);
|
|
86
|
+
const cwdInit = snapshot.cwd?.current ?? undefined;
|
|
87
|
+
const ctx = h.createContext({
|
|
88
|
+
items,
|
|
89
|
+
threadId: snapshot.threadId,
|
|
90
|
+
resourceId: snapshot.resourceId,
|
|
91
|
+
cwdInit,
|
|
92
|
+
memory: h._memory,
|
|
93
|
+
});
|
|
94
|
+
if (ctx instanceof ContextImpl) {
|
|
95
|
+
Object.defineProperty(ctx, 'id', {
|
|
96
|
+
value: executionId,
|
|
97
|
+
configurable: false,
|
|
98
|
+
writable: false,
|
|
99
|
+
enumerable: true,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return ctx;
|
|
103
|
+
}
|
|
104
|
+
//#endregion
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type { CheckpointStore, CreateCheckpointStoreOptions } from './checkpoint-store.js';
|
|
2
|
+
export { CheckpointKeys, createCheckpointStore } from './checkpoint-store.js';
|
|
3
|
+
export type { DetachedSignal } from './detached-signal.js';
|
|
4
|
+
export { createDetachedSignal } from './detached-signal.js';
|
|
5
|
+
export type { AfterFirstTurnContext, RunnableLoopHarness, RunnableLoopOpts } from './runnable-loop.js';
|
|
6
|
+
export { runnableLoop } from './runnable-loop.js';
|
|
7
|
+
export type { SessionSeedHarness } from './session-seed.js';
|
|
8
|
+
export { seedFromItems } from './session-seed.js';
|
|
9
|
+
export type { CreateNudgeMessageOpts, StallNudgeOpts } from './stall-nudge.js';
|
|
10
|
+
export { createNudgeMessage, createStallNudgeHook, DEFAULT_NUDGE_MESSAGE_TEXT, } from './stall-nudge.js';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { CheckpointKeys, createCheckpointStore } from './checkpoint-store.js';
|
|
2
|
+
export { createDetachedSignal } from './detached-signal.js';
|
|
3
|
+
export { runnableLoop } from './runnable-loop.js';
|
|
4
|
+
export { seedFromItems } from './session-seed.js';
|
|
5
|
+
export { createNudgeMessage, createStallNudgeHook, DEFAULT_NUDGE_MESSAGE_TEXT, } from './stall-nudge.js';
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drive a generic agent-harness chat session for a detached runner.
|
|
3
|
+
*
|
|
4
|
+
* The loop is intentionally minimal. A "runnable" is any harness
|
|
5
|
+
* driven through the standard `execute()` path plus a single-shot
|
|
6
|
+
* `DetachedSignal` its terminal tool resolves:
|
|
7
|
+
*
|
|
8
|
+
* 1. **Resume spawn** — when `priorItems` is non-empty, seed the
|
|
9
|
+
* session history and hand control straight to the caller's
|
|
10
|
+
* signal. The agent's prior turns are already on record; the next
|
|
11
|
+
* turn comes from external input (IPC `send` frame, autopilot
|
|
12
|
+
* respawn, etc.) rather than being re-kicked here.
|
|
13
|
+
* 2. **Fresh spawn** — when `priorItems` is empty (or omitted) and
|
|
14
|
+
* an `initialMessage` is supplied, execute that framing message
|
|
15
|
+
* as the first turn. The harness's own stream pumps persist the
|
|
16
|
+
* emitted items via whatever session store the caller wired up.
|
|
17
|
+
* 3. **Post-turn hook** — if `afterFirstTurn` is supplied, run it
|
|
18
|
+
* once the first turn has settled microtasks. The hook sees
|
|
19
|
+
* whether the signal already resolved during the turn so it can
|
|
20
|
+
* short-circuit its own logic (e.g. the stall-nudge helper skips
|
|
21
|
+
* its nudge when the agent already called a terminal tool).
|
|
22
|
+
* 4. **Await outcome** — finally, return `signal.done`. If no
|
|
23
|
+
* terminal tool ever resolves it, the signal rejects externally
|
|
24
|
+
* (SIGTERM handler, process abort) or simply never settles — the
|
|
25
|
+
* caller owns that concern.
|
|
26
|
+
*
|
|
27
|
+
* The loop has no opinions about where `priorItems` come from, how the
|
|
28
|
+
* `initialMessage` is built, or what the terminal outcome looks like.
|
|
29
|
+
* Task-specific logic (chat.jsonl reads, role framing, stall
|
|
30
|
+
* escalation) lives in the caller and composes via the `afterFirstTurn`
|
|
31
|
+
* hook.
|
|
32
|
+
*/
|
|
33
|
+
import type { HarnessResponse } from '../../types/harness-result.js';
|
|
34
|
+
import type { ExecuteInput, Item } from '../../types/items.js';
|
|
35
|
+
import type { ExecuteOptions, SessionScope } from '../../types/runtime.js';
|
|
36
|
+
import type { DetachedSignal } from './detached-signal.js';
|
|
37
|
+
/**
|
|
38
|
+
* Minimum harness surface the loop calls into. Defining this
|
|
39
|
+
* structurally keeps the loop loosely coupled — the concrete
|
|
40
|
+
* `AgentHarness<P>` already satisfies the shape, as does a test stub
|
|
41
|
+
* that only stands up `seedSessionHistory` + `execute` + `getAgentResponse`.
|
|
42
|
+
*
|
|
43
|
+
* `getAgentResponse` is REQUIRED because `execute()` only enqueues a
|
|
44
|
+
* message and returns before the turn actually runs. The loop awaits
|
|
45
|
+
* `getAgentResponse(scope)` to observe real turn completion before
|
|
46
|
+
* handing to `afterFirstTurn` — without this, stall detection fires
|
|
47
|
+
* before the agent has produced any output and flags every run as
|
|
48
|
+
* stalled.
|
|
49
|
+
*/
|
|
50
|
+
export interface RunnableLoopHarness {
|
|
51
|
+
seedSessionHistory(threadId: string, items: ReadonlyArray<Item>): void;
|
|
52
|
+
execute(input: ExecuteInput, options?: ExecuteOptions): Promise<void>;
|
|
53
|
+
getAgentResponse(scope?: SessionScope): Promise<HarnessResponse>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Read-only view the `afterFirstTurn` hook uses to decide whether the
|
|
57
|
+
* signal settled during the turn it just observed. Consumers call
|
|
58
|
+
* `signalSettled()` (not a direct property read) so a late-settle
|
|
59
|
+
* caused by microtask ordering still propagates.
|
|
60
|
+
*/
|
|
61
|
+
export interface AfterFirstTurnContext {
|
|
62
|
+
/** True if `signal.done` has resolved or rejected. */
|
|
63
|
+
signalSettled(): boolean;
|
|
64
|
+
}
|
|
65
|
+
export interface RunnableLoopOpts<TOutcome> {
|
|
66
|
+
readonly harness: RunnableLoopHarness;
|
|
67
|
+
readonly threadId: string;
|
|
68
|
+
/**
|
|
69
|
+
* Prior session items to seed before the first turn. When non-empty
|
|
70
|
+
* the loop skips `initialMessage` entirely (resume path); when empty
|
|
71
|
+
* or omitted it proceeds with the fresh-spawn sequence.
|
|
72
|
+
*/
|
|
73
|
+
readonly priorItems?: ReadonlyArray<Item>;
|
|
74
|
+
/**
|
|
75
|
+
* Developer-role framing message that kicks off a fresh run. Omit to
|
|
76
|
+
* run the loop in "seed + wait" mode where the first turn is driven
|
|
77
|
+
* externally (e.g. by an IPC client's `send` frame).
|
|
78
|
+
*/
|
|
79
|
+
readonly initialMessage?: ExecuteInput;
|
|
80
|
+
readonly signal: DetachedSignal<TOutcome>;
|
|
81
|
+
/**
|
|
82
|
+
* Optional post-turn hook. Only runs on the fresh-spawn path once
|
|
83
|
+
* `initialMessage` has settled microtasks. Receives a context whose
|
|
84
|
+
* `signalSettled()` query reflects whether the signal is already
|
|
85
|
+
* resolved/rejected so the hook can no-op when the agent already
|
|
86
|
+
* produced its terminal outcome.
|
|
87
|
+
*/
|
|
88
|
+
readonly afterFirstTurn?: (ctx: AfterFirstTurnContext) => Promise<void>;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Execute the runnable-loop lifecycle and return the final outcome by
|
|
92
|
+
* awaiting the caller-provided signal. See the module doc for the full
|
|
93
|
+
* sequence; short version:
|
|
94
|
+
*
|
|
95
|
+
* - `priorItems` present → seed + wait on signal.
|
|
96
|
+
* - `initialMessage` present → seed (if any) + execute first turn +
|
|
97
|
+
* run `afterFirstTurn` (if any) + wait on signal.
|
|
98
|
+
* - Neither present → just wait on signal (pure listener mode).
|
|
99
|
+
*/
|
|
100
|
+
export declare function runnableLoop<TOutcome>(opts: RunnableLoopOpts<TOutcome>): Promise<TOutcome>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drive a generic agent-harness chat session for a detached runner.
|
|
3
|
+
*
|
|
4
|
+
* The loop is intentionally minimal. A "runnable" is any harness
|
|
5
|
+
* driven through the standard `execute()` path plus a single-shot
|
|
6
|
+
* `DetachedSignal` its terminal tool resolves:
|
|
7
|
+
*
|
|
8
|
+
* 1. **Resume spawn** — when `priorItems` is non-empty, seed the
|
|
9
|
+
* session history and hand control straight to the caller's
|
|
10
|
+
* signal. The agent's prior turns are already on record; the next
|
|
11
|
+
* turn comes from external input (IPC `send` frame, autopilot
|
|
12
|
+
* respawn, etc.) rather than being re-kicked here.
|
|
13
|
+
* 2. **Fresh spawn** — when `priorItems` is empty (or omitted) and
|
|
14
|
+
* an `initialMessage` is supplied, execute that framing message
|
|
15
|
+
* as the first turn. The harness's own stream pumps persist the
|
|
16
|
+
* emitted items via whatever session store the caller wired up.
|
|
17
|
+
* 3. **Post-turn hook** — if `afterFirstTurn` is supplied, run it
|
|
18
|
+
* once the first turn has settled microtasks. The hook sees
|
|
19
|
+
* whether the signal already resolved during the turn so it can
|
|
20
|
+
* short-circuit its own logic (e.g. the stall-nudge helper skips
|
|
21
|
+
* its nudge when the agent already called a terminal tool).
|
|
22
|
+
* 4. **Await outcome** — finally, return `signal.done`. If no
|
|
23
|
+
* terminal tool ever resolves it, the signal rejects externally
|
|
24
|
+
* (SIGTERM handler, process abort) or simply never settles — the
|
|
25
|
+
* caller owns that concern.
|
|
26
|
+
*
|
|
27
|
+
* The loop has no opinions about where `priorItems` come from, how the
|
|
28
|
+
* `initialMessage` is built, or what the terminal outcome looks like.
|
|
29
|
+
* Task-specific logic (chat.jsonl reads, role framing, stall
|
|
30
|
+
* escalation) lives in the caller and composes via the `afterFirstTurn`
|
|
31
|
+
* hook.
|
|
32
|
+
*/
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region Public API
|
|
35
|
+
/**
|
|
36
|
+
* Execute the runnable-loop lifecycle and return the final outcome by
|
|
37
|
+
* awaiting the caller-provided signal. See the module doc for the full
|
|
38
|
+
* sequence; short version:
|
|
39
|
+
*
|
|
40
|
+
* - `priorItems` present → seed + wait on signal.
|
|
41
|
+
* - `initialMessage` present → seed (if any) + execute first turn +
|
|
42
|
+
* run `afterFirstTurn` (if any) + wait on signal.
|
|
43
|
+
* - Neither present → just wait on signal (pure listener mode).
|
|
44
|
+
*/
|
|
45
|
+
export async function runnableLoop(opts) {
|
|
46
|
+
const prior = opts.priorItems;
|
|
47
|
+
if (prior !== undefined && prior.length > 0) {
|
|
48
|
+
opts.harness.seedSessionHistory(opts.threadId, prior);
|
|
49
|
+
return opts.signal.done;
|
|
50
|
+
}
|
|
51
|
+
if (opts.initialMessage === undefined) {
|
|
52
|
+
return opts.signal.done;
|
|
53
|
+
}
|
|
54
|
+
// Track signal settlement without blocking so the `afterFirstTurn`
|
|
55
|
+
// hook can detect a synchronous resolve that fired during `execute()`
|
|
56
|
+
// without racing the deferred.
|
|
57
|
+
let signalSettled = false;
|
|
58
|
+
void opts.signal.done.then(() => {
|
|
59
|
+
signalSettled = true;
|
|
60
|
+
}, () => {
|
|
61
|
+
signalSettled = true;
|
|
62
|
+
});
|
|
63
|
+
await opts.harness.execute(opts.initialMessage, {
|
|
64
|
+
threadId: opts.threadId,
|
|
65
|
+
});
|
|
66
|
+
// `execute()` only enqueues the framing message; the turn itself runs
|
|
67
|
+
// asynchronously through the session runner. Await `getAgentResponse`
|
|
68
|
+
// to observe REAL turn completion before dispatching `afterFirstTurn`.
|
|
69
|
+
// Without this the stall-nudge hook fires before any turn output and
|
|
70
|
+
// always classifies the run as stalled. We race against `signal.done`
|
|
71
|
+
// so a terminal tool that resolves the signal mid-turn still short-
|
|
72
|
+
// circuits the wait — in that case `getAgentResponse` may not have
|
|
73
|
+
// settled yet and we skip the post-turn hook entirely since the
|
|
74
|
+
// terminal outcome has already fired.
|
|
75
|
+
await Promise.race([
|
|
76
|
+
opts.harness
|
|
77
|
+
.getAgentResponse({
|
|
78
|
+
threadId: opts.threadId,
|
|
79
|
+
})
|
|
80
|
+
.catch(() => undefined),
|
|
81
|
+
opts.signal.done.catch(() => undefined),
|
|
82
|
+
]);
|
|
83
|
+
if (opts.afterFirstTurn !== undefined) {
|
|
84
|
+
await opts.afterFirstTurn({
|
|
85
|
+
signalSettled: () => signalSettled,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return opts.signal.done;
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seed an agent harness's session history from a pre-parsed `Item[]`.
|
|
3
|
+
*
|
|
4
|
+
* Callers who have chat history on disk (JSONL, DB, etc.) read + parse
|
|
5
|
+
* the persisted format into `Item[]` themselves — this helper is
|
|
6
|
+
* deliberately path-free so it composes with any storage layer.
|
|
7
|
+
*
|
|
8
|
+
* The helper is a thin typed wrapper around `harness.seedSessionHistory`
|
|
9
|
+
* and exists so the runnable-loop (and any other caller that wants to
|
|
10
|
+
* restore a prior session) has one documented, named entrypoint rather
|
|
11
|
+
* than reaching for the harness method inline.
|
|
12
|
+
*/
|
|
13
|
+
import type { Item } from '../../types/items.js';
|
|
14
|
+
/**
|
|
15
|
+
* Minimum harness surface `seedFromItems` requires. Defined structurally
|
|
16
|
+
* so tests (and out-of-process children) can pass a stub without casts;
|
|
17
|
+
* `AgentHarness<P>` from core satisfies the shape directly.
|
|
18
|
+
*/
|
|
19
|
+
export interface SessionSeedHarness {
|
|
20
|
+
seedSessionHistory(threadId: string, items: ReadonlyArray<Item>): void;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Seed `harness`'s session for `threadId` with the given items so the
|
|
24
|
+
* next `execute()` call sees them in the item log. No-op when `items`
|
|
25
|
+
* is empty (the harness call itself is also safe to make with an empty
|
|
26
|
+
* array; short-circuiting here keeps the intent crisp).
|
|
27
|
+
*/
|
|
28
|
+
export declare function seedFromItems(harness: SessionSeedHarness, threadId: string, items: ReadonlyArray<Item>): void;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seed an agent harness's session history from a pre-parsed `Item[]`.
|
|
3
|
+
*
|
|
4
|
+
* Callers who have chat history on disk (JSONL, DB, etc.) read + parse
|
|
5
|
+
* the persisted format into `Item[]` themselves — this helper is
|
|
6
|
+
* deliberately path-free so it composes with any storage layer.
|
|
7
|
+
*
|
|
8
|
+
* The helper is a thin typed wrapper around `harness.seedSessionHistory`
|
|
9
|
+
* and exists so the runnable-loop (and any other caller that wants to
|
|
10
|
+
* restore a prior session) has one documented, named entrypoint rather
|
|
11
|
+
* than reaching for the harness method inline.
|
|
12
|
+
*/
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region Public API
|
|
15
|
+
/**
|
|
16
|
+
* Seed `harness`'s session for `threadId` with the given items so the
|
|
17
|
+
* next `execute()` call sees them in the item log. No-op when `items`
|
|
18
|
+
* is empty (the harness call itself is also safe to make with an empty
|
|
19
|
+
* array; short-circuiting here keeps the intent crisp).
|
|
20
|
+
*/
|
|
21
|
+
export function seedFromItems(harness, threadId, items) {
|
|
22
|
+
if (items.length === 0) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
harness.seedSessionHistory(threadId, items);
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Two-strike stall-nudge helper composable with `runnableLoop`.
|
|
3
|
+
*
|
|
4
|
+
* A runner's first turn can end without settling the outcome signal
|
|
5
|
+
* and without the agent asking for external input — i.e. the agent
|
|
6
|
+
* stopped without calling either a terminal tool or an ask-user-style
|
|
7
|
+
* tool. That's a soft failure: rather than wait forever, we nudge the
|
|
8
|
+
* agent once to remind it of its options. If the second turn also
|
|
9
|
+
* ends in the same stalled shape we escalate: the caller-supplied
|
|
10
|
+
* `onStall` callback records the escalation (task pause, metrics,
|
|
11
|
+
* whatever the domain demands) and we settle the signal ourselves with
|
|
12
|
+
* a canonical "stalled" outcome so the parent unwinds cleanly.
|
|
13
|
+
*
|
|
14
|
+
* The helper factors the state machine out of the loop so callers can
|
|
15
|
+
* opt in per-runner. Task-specific concerns (how "pending external
|
|
16
|
+
* input" is detected, how escalation is recorded, what outcome
|
|
17
|
+
* represents a stalled failure) stay with the caller and flow in via
|
|
18
|
+
* the config.
|
|
19
|
+
*/
|
|
20
|
+
import type { InputMessageItem } from '../../types/items.js';
|
|
21
|
+
import type { DetachedSignal } from './detached-signal.js';
|
|
22
|
+
import type { AfterFirstTurnContext, RunnableLoopHarness } from './runnable-loop.js';
|
|
23
|
+
/**
|
|
24
|
+
* Default developer-role text sent when the agent finishes a turn
|
|
25
|
+
* without calling a terminal tool or an ask-user tool. Kept short and
|
|
26
|
+
* unambiguous — the agent should be reminded of its options without
|
|
27
|
+
* being lectured. Callers may override via `createNudgeMessage(text)`.
|
|
28
|
+
*/
|
|
29
|
+
export declare const DEFAULT_NUDGE_MESSAGE_TEXT = "You finished a turn without calling a terminal tool or AskUserQuestion. If you need user input or instruction to continue, call AskUserQuestion now. Otherwise call your terminal tool to complete this phase.";
|
|
30
|
+
export interface CreateNudgeMessageOpts {
|
|
31
|
+
/** Unique id for the message so item-log dedupe can distinguish re-spawns. */
|
|
32
|
+
readonly id: string;
|
|
33
|
+
/** Override the developer-role text. Defaults to `DEFAULT_NUDGE_MESSAGE_TEXT`. */
|
|
34
|
+
readonly text?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface StallNudgeOpts<TOutcome> {
|
|
37
|
+
readonly harness: RunnableLoopHarness;
|
|
38
|
+
readonly threadId: string;
|
|
39
|
+
readonly signal: DetachedSignal<TOutcome>;
|
|
40
|
+
/**
|
|
41
|
+
* The framing message sent as the nudge. Use `createNudgeMessage`
|
|
42
|
+
* for the canonical developer-role item, or pass your own when a
|
|
43
|
+
* domain needs a custom shape.
|
|
44
|
+
*/
|
|
45
|
+
readonly nudgeMessage: InputMessageItem;
|
|
46
|
+
/**
|
|
47
|
+
* True when the agent intentionally awaits external input (e.g. an
|
|
48
|
+
* outstanding ask-user request). When true the nudge is suppressed
|
|
49
|
+
* — the agent is not stalled, it is waiting for us.
|
|
50
|
+
*/
|
|
51
|
+
hasPendingExternal(): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Record-side-effect callback fired when the agent stalls a second
|
|
54
|
+
* time. Use this to mark the task paused, emit a metric, append an
|
|
55
|
+
* event log entry — whatever the domain needs before the signal
|
|
56
|
+
* settles.
|
|
57
|
+
*/
|
|
58
|
+
onStall(): Promise<void>;
|
|
59
|
+
/** Build the outcome value the signal resolves to on stall escalation. */
|
|
60
|
+
buildStalledOutcome(): TOutcome;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Build the canonical developer-role nudge message item. Callers who
|
|
64
|
+
* want a custom framing build their own `InputMessageItem`; this
|
|
65
|
+
* helper exists so the common case stays one line.
|
|
66
|
+
*/
|
|
67
|
+
export declare function createNudgeMessage(opts: CreateNudgeMessageOpts): InputMessageItem;
|
|
68
|
+
/**
|
|
69
|
+
* Build a `runnableLoop`-compatible `afterFirstTurn` hook that
|
|
70
|
+
* implements the two-strike nudge state machine described in the
|
|
71
|
+
* module doc. The hook is a no-op when:
|
|
72
|
+
*
|
|
73
|
+
* - the signal already settled (agent called a terminal tool), or
|
|
74
|
+
* - the caller reports pending external input (`hasPendingExternal`
|
|
75
|
+
* returns true — e.g. an outstanding ask-user request).
|
|
76
|
+
*
|
|
77
|
+
* Otherwise it sends the nudge message via `harness.execute`, waits
|
|
78
|
+
* for microtasks to flush, and re-checks the same two conditions. If
|
|
79
|
+
* the agent still hasn't progressed, the hook fires `onStall` and
|
|
80
|
+
* resolves the signal with `buildStalledOutcome()`.
|
|
81
|
+
*/
|
|
82
|
+
export declare function createStallNudgeHook<TOutcome>(opts: StallNudgeOpts<TOutcome>): (ctx: AfterFirstTurnContext) => Promise<void>;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Two-strike stall-nudge helper composable with `runnableLoop`.
|
|
3
|
+
*
|
|
4
|
+
* A runner's first turn can end without settling the outcome signal
|
|
5
|
+
* and without the agent asking for external input — i.e. the agent
|
|
6
|
+
* stopped without calling either a terminal tool or an ask-user-style
|
|
7
|
+
* tool. That's a soft failure: rather than wait forever, we nudge the
|
|
8
|
+
* agent once to remind it of its options. If the second turn also
|
|
9
|
+
* ends in the same stalled shape we escalate: the caller-supplied
|
|
10
|
+
* `onStall` callback records the escalation (task pause, metrics,
|
|
11
|
+
* whatever the domain demands) and we settle the signal ourselves with
|
|
12
|
+
* a canonical "stalled" outcome so the parent unwinds cleanly.
|
|
13
|
+
*
|
|
14
|
+
* The helper factors the state machine out of the loop so callers can
|
|
15
|
+
* opt in per-runner. Task-specific concerns (how "pending external
|
|
16
|
+
* input" is detected, how escalation is recorded, what outcome
|
|
17
|
+
* represents a stalled failure) stay with the caller and flow in via
|
|
18
|
+
* the config.
|
|
19
|
+
*/
|
|
20
|
+
//#region Constants
|
|
21
|
+
/**
|
|
22
|
+
* Default developer-role text sent when the agent finishes a turn
|
|
23
|
+
* without calling a terminal tool or an ask-user tool. Kept short and
|
|
24
|
+
* unambiguous — the agent should be reminded of its options without
|
|
25
|
+
* being lectured. Callers may override via `createNudgeMessage(text)`.
|
|
26
|
+
*/
|
|
27
|
+
export const DEFAULT_NUDGE_MESSAGE_TEXT = 'You finished a turn without calling a terminal tool or AskUserQuestion. If you need user input or instruction to continue, call AskUserQuestion now. Otherwise call your terminal tool to complete this phase.';
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region Public API
|
|
30
|
+
/**
|
|
31
|
+
* Build the canonical developer-role nudge message item. Callers who
|
|
32
|
+
* want a custom framing build their own `InputMessageItem`; this
|
|
33
|
+
* helper exists so the common case stays one line.
|
|
34
|
+
*/
|
|
35
|
+
export function createNudgeMessage(opts) {
|
|
36
|
+
return {
|
|
37
|
+
id: opts.id,
|
|
38
|
+
type: 'message',
|
|
39
|
+
role: 'developer',
|
|
40
|
+
status: 'completed',
|
|
41
|
+
content: [
|
|
42
|
+
{
|
|
43
|
+
type: 'input_text',
|
|
44
|
+
text: opts.text ?? DEFAULT_NUDGE_MESSAGE_TEXT,
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Build a `runnableLoop`-compatible `afterFirstTurn` hook that
|
|
51
|
+
* implements the two-strike nudge state machine described in the
|
|
52
|
+
* module doc. The hook is a no-op when:
|
|
53
|
+
*
|
|
54
|
+
* - the signal already settled (agent called a terminal tool), or
|
|
55
|
+
* - the caller reports pending external input (`hasPendingExternal`
|
|
56
|
+
* returns true — e.g. an outstanding ask-user request).
|
|
57
|
+
*
|
|
58
|
+
* Otherwise it sends the nudge message via `harness.execute`, waits
|
|
59
|
+
* for microtasks to flush, and re-checks the same two conditions. If
|
|
60
|
+
* the agent still hasn't progressed, the hook fires `onStall` and
|
|
61
|
+
* resolves the signal with `buildStalledOutcome()`.
|
|
62
|
+
*/
|
|
63
|
+
export function createStallNudgeHook(opts) {
|
|
64
|
+
return async (ctx) => {
|
|
65
|
+
if (ctx.signalSettled()) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (opts.hasPendingExternal()) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
// First stall — send one nudge.
|
|
72
|
+
await opts.harness.execute(opts.nudgeMessage, {
|
|
73
|
+
threadId: opts.threadId,
|
|
74
|
+
});
|
|
75
|
+
await Promise.resolve();
|
|
76
|
+
if (ctx.signalSettled()) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (opts.hasPendingExternal()) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// Second stall — escalate and settle.
|
|
83
|
+
await opts.onStall();
|
|
84
|
+
opts.signal.resolve(opts.buildStalledOutcome());
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
//#endregion
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ItemSchemaRegistry } from '../schemas/item';
|
|
2
|
-
import type { ItemLog } from '../types/context';
|
|
3
|
-
import type { Item } from '../types/items';
|
|
1
|
+
import type { ItemSchemaRegistry } from '../schemas/item.js';
|
|
2
|
+
import type { ItemLog } from '../types/context-parts/item-log.js';
|
|
3
|
+
import type { Item } from '../types/items.js';
|
|
4
4
|
export declare class ItemLogImpl implements ItemLog {
|
|
5
5
|
private readonly itemSchemas;
|
|
6
6
|
private readonly _items;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ExecuteInput } from '../types/items';
|
|
2
|
-
import type { DeliveryMode, ExecuteOptions } from '../types/runtime';
|
|
1
|
+
import type { ExecuteInput } from '../types/items.js';
|
|
2
|
+
import type { DeliveryMode, ExecuteOptions } from '../types/runtime.js';
|
|
3
3
|
/** @internal A message accepted by `AgentHarness.execute()` and held until the
|
|
4
4
|
* session runner processes it. The effective `DeliveryMode` is resolved at
|
|
5
5
|
* enqueue time so the runner never has to look at harness defaults again. */
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { Context } from '../types/context';
|
|
2
|
-
import type { HarnessResponse } from '../types/harness-result';
|
|
3
|
-
import type { Item } from '../types/items';
|
|
4
|
-
import type { HarnessStatus } from '../types/runtime';
|
|
5
|
-
import { EventBroadcaster } from './event-broadcaster';
|
|
6
|
-
import type { QueuedMessage } from './message-queue';
|
|
7
|
-
import { MessageQueue } from './message-queue';
|
|
1
|
+
import type { Context } from '../types/context.js';
|
|
2
|
+
import type { HarnessResponse } from '../types/harness-result.js';
|
|
3
|
+
import type { Item } from '../types/items.js';
|
|
4
|
+
import type { HarnessStatus } from '../types/runtime.js';
|
|
5
|
+
import { EventBroadcaster } from './event-broadcaster.js';
|
|
6
|
+
import type { QueuedMessage } from './message-queue.js';
|
|
7
|
+
import { MessageQueue } from './message-queue.js';
|
|
8
8
|
/** @internal Callback the harness supplies to run a single turn against a
|
|
9
9
|
* prepared context. The runner invokes this once per turn; it returns the
|
|
10
10
|
* final text as a string and must append any produced items to `ctx.itemLog`. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { emitFrameworkEvent } from './broadcaster-utils';
|
|
2
|
-
import { EventBroadcaster } from './event-broadcaster';
|
|
3
|
-
import { MessageQueue } from './message-queue';
|
|
1
|
+
import { emitFrameworkEvent } from './broadcaster-utils.js';
|
|
2
|
+
import { EventBroadcaster } from './event-broadcaster.js';
|
|
3
|
+
import { MessageQueue } from './message-queue.js';
|
|
4
4
|
//#endregion
|
|
5
5
|
//#region Helpers
|
|
6
6
|
function inputToItems(input) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ItemSchemaRegistry } from '../schemas/item';
|
|
2
|
-
import type { StreamingItem } from '../types/harness-result';
|
|
3
|
-
import type { EventBroadcaster } from './event-broadcaster';
|
|
1
|
+
import type { ItemSchemaRegistry } from '../schemas/item.js';
|
|
2
|
+
import type { StreamingItem } from '../types/harness-result.js';
|
|
3
|
+
import type { EventBroadcaster } from './event-broadcaster.js';
|
|
4
4
|
/** @internal Yield text deltas from the session broadcaster. */
|
|
5
5
|
export declare function filterTextStream(broadcaster: EventBroadcaster): AsyncIterable<string>;
|
|
6
6
|
/** @internal Yield reasoning-token deltas from the session broadcaster. */
|