@earendil-works/pi-agent-core 0.84.3 → 0.85.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/README.md +4 -0
- package/dist/agent-loop.d.ts.map +1 -1
- package/dist/agent-loop.js +32 -25
- package/dist/agent-loop.js.map +1 -1
- package/dist/harness/agent-harness.d.ts +639 -384
- package/dist/harness/agent-harness.d.ts.map +1 -1
- package/dist/harness/agent-harness.js +5 -251
- package/dist/harness/agent-harness.js.map +1 -1
- package/dist/harness/compaction/branch-summarization.d.ts +12 -6
- package/dist/harness/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/harness/compaction/branch-summarization.js +33 -26
- package/dist/harness/compaction/branch-summarization.js.map +1 -1
- package/dist/harness/compaction/compaction.d.ts +30 -8
- package/dist/harness/compaction/compaction.d.ts.map +1 -1
- package/dist/harness/compaction/compaction.js +53 -63
- package/dist/harness/compaction/compaction.js.map +1 -1
- package/dist/harness/config.d.ts +9 -0
- package/dist/harness/config.d.ts.map +1 -0
- package/dist/harness/config.js +27 -0
- package/dist/harness/config.js.map +1 -0
- package/dist/harness/context.d.ts +9 -0
- package/dist/harness/context.d.ts.map +1 -0
- package/dist/harness/context.js +13 -0
- package/dist/harness/context.js.map +1 -0
- package/dist/harness/env/nodejs.d.ts +24 -28
- package/dist/harness/env/nodejs.d.ts.map +1 -1
- package/dist/harness/env/nodejs.js +242 -87
- package/dist/harness/env/nodejs.js.map +1 -1
- package/dist/harness/events.d.ts +20 -38
- package/dist/harness/events.d.ts.map +1 -1
- package/dist/harness/events.js +240 -55
- package/dist/harness/events.js.map +1 -1
- package/dist/harness/execution/assistant.d.ts +42 -0
- package/dist/harness/execution/assistant.d.ts.map +1 -0
- package/dist/harness/execution/assistant.js +82 -0
- package/dist/harness/execution/assistant.js.map +1 -0
- package/dist/harness/execution/effect-gate.d.ts +22 -0
- package/dist/harness/execution/effect-gate.d.ts.map +1 -0
- package/dist/harness/execution/effect-gate.js +49 -0
- package/dist/harness/execution/effect-gate.js.map +1 -0
- package/dist/harness/execution/tools.d.ts +67 -0
- package/dist/harness/execution/tools.d.ts.map +1 -0
- package/dist/harness/execution/tools.js +121 -0
- package/dist/harness/execution/tools.js.map +1 -0
- package/dist/harness/hooks.d.ts +38 -0
- package/dist/harness/hooks.d.ts.map +1 -0
- package/dist/harness/hooks.js +406 -0
- package/dist/harness/hooks.js.map +1 -0
- package/dist/harness/messages.d.ts +2 -2
- package/dist/harness/messages.d.ts.map +1 -1
- package/dist/harness/messages.js.map +1 -1
- package/dist/harness/prompt-templates.d.ts +3 -2
- package/dist/harness/prompt-templates.d.ts.map +1 -1
- package/dist/harness/prompt-templates.js +17 -17
- package/dist/harness/prompt-templates.js.map +1 -1
- package/dist/harness/result.d.ts +93 -0
- package/dist/harness/result.d.ts.map +1 -1
- package/dist/harness/result.js +40 -0
- package/dist/harness/result.js.map +1 -1
- package/dist/harness/runtime/drive/boundary.d.ts +28 -0
- package/dist/harness/runtime/drive/boundary.d.ts.map +1 -0
- package/dist/harness/runtime/drive/boundary.js +170 -0
- package/dist/harness/runtime/drive/boundary.js.map +1 -0
- package/dist/harness/runtime/drive/checkpoint.d.ts +8 -0
- package/dist/harness/runtime/drive/checkpoint.d.ts.map +1 -0
- package/dist/harness/runtime/drive/checkpoint.js +133 -0
- package/dist/harness/runtime/drive/checkpoint.js.map +1 -0
- package/dist/harness/runtime/drive/deferred.d.ts +15 -0
- package/dist/harness/runtime/drive/deferred.d.ts.map +1 -0
- package/dist/harness/runtime/drive/deferred.js +179 -0
- package/dist/harness/runtime/drive/deferred.js.map +1 -0
- package/dist/harness/runtime/drive/generation.d.ts +8 -0
- package/dist/harness/runtime/drive/generation.d.ts.map +1 -0
- package/dist/harness/runtime/drive/generation.js +205 -0
- package/dist/harness/runtime/drive/generation.js.map +1 -0
- package/dist/harness/runtime/drive/reconcile.d.ts +5 -0
- package/dist/harness/runtime/drive/reconcile.d.ts.map +1 -0
- package/dist/harness/runtime/drive/reconcile.js +140 -0
- package/dist/harness/runtime/drive/reconcile.js.map +1 -0
- package/dist/harness/runtime/drive/recovery.d.ts +8 -0
- package/dist/harness/runtime/drive/recovery.d.ts.map +1 -0
- package/dist/harness/runtime/drive/recovery.js +85 -0
- package/dist/harness/runtime/drive/recovery.js.map +1 -0
- package/dist/harness/runtime/drive/response.d.ts +23 -0
- package/dist/harness/runtime/drive/response.d.ts.map +1 -0
- package/dist/harness/runtime/drive/response.js +394 -0
- package/dist/harness/runtime/drive/response.js.map +1 -0
- package/dist/harness/runtime/drive/retry.d.ts +4 -0
- package/dist/harness/runtime/drive/retry.d.ts.map +1 -0
- package/dist/harness/runtime/drive/retry.js +37 -0
- package/dist/harness/runtime/drive/retry.js.map +1 -0
- package/dist/harness/runtime/drive/structural.d.ts +32 -0
- package/dist/harness/runtime/drive/structural.d.ts.map +1 -0
- package/dist/harness/runtime/drive/structural.js +929 -0
- package/dist/harness/runtime/drive/structural.js.map +1 -0
- package/dist/harness/runtime/drive/terminal.d.ts +7 -0
- package/dist/harness/runtime/drive/terminal.d.ts.map +1 -0
- package/dist/harness/runtime/drive/terminal.js +49 -0
- package/dist/harness/runtime/drive/terminal.js.map +1 -0
- package/dist/harness/runtime/drive/tool-placement.d.ts +14 -0
- package/dist/harness/runtime/drive/tool-placement.d.ts.map +1 -0
- package/dist/harness/runtime/drive/tool-placement.js +244 -0
- package/dist/harness/runtime/drive/tool-placement.js.map +1 -0
- package/dist/harness/runtime/drive/tools.d.ts +6 -0
- package/dist/harness/runtime/drive/tools.d.ts.map +1 -0
- package/dist/harness/runtime/drive/tools.js +449 -0
- package/dist/harness/runtime/drive/tools.js.map +1 -0
- package/dist/harness/runtime/drive.d.ts +6 -0
- package/dist/harness/runtime/drive.d.ts.map +1 -0
- package/dist/harness/runtime/drive.js +93 -0
- package/dist/harness/runtime/drive.js.map +1 -0
- package/dist/harness/runtime/harness.d.ts +59 -0
- package/dist/harness/runtime/harness.d.ts.map +1 -0
- package/dist/harness/runtime/harness.js +311 -0
- package/dist/harness/runtime/harness.js.map +1 -0
- package/dist/harness/runtime/index.d.ts +2 -0
- package/dist/harness/runtime/index.d.ts.map +1 -0
- package/dist/harness/runtime/index.js +2 -0
- package/dist/harness/runtime/index.js.map +1 -0
- package/dist/harness/runtime/lane.d.ts +101 -0
- package/dist/harness/runtime/lane.d.ts.map +1 -0
- package/dist/harness/runtime/lane.js +1575 -0
- package/dist/harness/runtime/lane.js.map +1 -0
- package/dist/harness/runtime/progress.d.ts +15 -0
- package/dist/harness/runtime/progress.d.ts.map +1 -0
- package/dist/harness/runtime/progress.js +66 -0
- package/dist/harness/runtime/progress.js.map +1 -0
- package/dist/harness/runtime/reducer.d.ts +5 -0
- package/dist/harness/runtime/reducer.d.ts.map +1 -0
- package/dist/harness/runtime/reducer.js +240 -0
- package/dist/harness/runtime/reducer.js.map +1 -0
- package/dist/harness/runtime/restore.d.ts +24 -0
- package/dist/harness/runtime/restore.d.ts.map +1 -0
- package/dist/harness/runtime/restore.js +117 -0
- package/dist/harness/runtime/restore.js.map +1 -0
- package/dist/harness/runtime/transcript.d.ts +21 -0
- package/dist/harness/runtime/transcript.d.ts.map +1 -0
- package/dist/harness/runtime/transcript.js +72 -0
- package/dist/harness/runtime/transcript.js.map +1 -0
- package/dist/harness/runtime/types.d.ts +105 -0
- package/dist/harness/runtime/types.d.ts.map +1 -0
- package/dist/harness/runtime/types.js +61 -0
- package/dist/harness/runtime/types.js.map +1 -0
- package/dist/harness/session/commit.d.ts +53 -0
- package/dist/harness/session/commit.d.ts.map +1 -0
- package/dist/harness/session/commit.js +57 -0
- package/dist/harness/session/commit.js.map +1 -0
- package/dist/harness/session/context.d.ts +6 -18
- package/dist/harness/session/context.d.ts.map +1 -1
- package/dist/harness/session/context.js +31 -49
- package/dist/harness/session/context.js.map +1 -1
- package/dist/harness/session/fork-policy.d.ts +13 -0
- package/dist/harness/session/fork-policy.d.ts.map +1 -0
- package/dist/harness/session/fork-policy.js +22 -0
- package/dist/harness/session/fork-policy.js.map +1 -0
- package/dist/harness/session/fork.d.ts +18 -0
- package/dist/harness/session/fork.d.ts.map +1 -0
- package/dist/harness/session/fork.js +127 -0
- package/dist/harness/session/fork.js.map +1 -0
- package/dist/harness/session/in-memory-storage-state.d.ts +39 -0
- package/dist/harness/session/in-memory-storage-state.d.ts.map +1 -0
- package/dist/harness/session/in-memory-storage-state.js +216 -0
- package/dist/harness/session/in-memory-storage-state.js.map +1 -0
- package/dist/harness/session/index.d.ts +9 -5
- package/dist/harness/session/index.d.ts.map +1 -1
- package/dist/harness/session/index.js +7 -4
- package/dist/harness/session/index.js.map +1 -1
- package/dist/harness/session/jsonl/codec.d.ts +19 -8
- package/dist/harness/session/jsonl/codec.d.ts.map +1 -1
- package/dist/harness/session/jsonl/codec.js +34 -218
- package/dist/harness/session/jsonl/codec.js.map +1 -1
- package/dist/harness/session/jsonl/index.d.ts +4 -0
- package/dist/harness/session/jsonl/index.d.ts.map +1 -0
- package/dist/harness/session/jsonl/index.js +4 -0
- package/dist/harness/session/jsonl/index.js.map +1 -0
- package/dist/harness/session/jsonl/legacy-v3.d.ts +18 -0
- package/dist/harness/session/jsonl/legacy-v3.d.ts.map +1 -0
- package/dist/harness/session/jsonl/legacy-v3.js +383 -0
- package/dist/harness/session/jsonl/legacy-v3.js.map +1 -0
- package/dist/harness/session/jsonl/repo.d.ts +26 -19
- package/dist/harness/session/jsonl/repo.d.ts.map +1 -1
- package/dist/harness/session/jsonl/repo.js +266 -156
- package/dist/harness/session/jsonl/repo.js.map +1 -1
- package/dist/harness/session/jsonl/storage.d.ts +39 -41
- package/dist/harness/session/jsonl/storage.d.ts.map +1 -1
- package/dist/harness/session/jsonl/storage.js +238 -181
- package/dist/harness/session/jsonl/storage.js.map +1 -1
- package/dist/harness/session/jsonl/types.d.ts +23 -22
- package/dist/harness/session/jsonl/types.d.ts.map +1 -1
- package/dist/harness/session/jsonl/types.js +2 -1
- package/dist/harness/session/jsonl/types.js.map +1 -1
- package/dist/harness/session/memory.d.ts +46 -40
- package/dist/harness/session/memory.d.ts.map +1 -1
- package/dist/harness/session/memory.js +346 -113
- package/dist/harness/session/memory.js.map +1 -1
- package/dist/harness/session/mutation-line.d.ts +8 -0
- package/dist/harness/session/mutation-line.d.ts.map +1 -0
- package/dist/harness/session/mutation-line.js +21 -0
- package/dist/harness/session/mutation-line.js.map +1 -0
- package/dist/harness/session/session.d.ts +78 -46
- package/dist/harness/session/session.d.ts.map +1 -1
- package/dist/harness/session/session.js +343 -209
- package/dist/harness/session/session.js.map +1 -1
- package/dist/harness/session/testing/benchmark/datasets.d.ts +12 -0
- package/dist/harness/session/testing/benchmark/datasets.d.ts.map +1 -0
- package/dist/harness/session/testing/benchmark/datasets.js +24 -0
- package/dist/harness/session/testing/benchmark/datasets.js.map +1 -0
- package/dist/harness/session/testing/benchmark/session-repo.d.ts +42 -0
- package/dist/harness/session/testing/benchmark/session-repo.d.ts.map +1 -0
- package/dist/harness/session/testing/benchmark/session-repo.js +127 -0
- package/dist/harness/session/testing/benchmark/session-repo.js.map +1 -0
- package/dist/harness/session/testing/benchmark/storage.d.ts +25 -0
- package/dist/harness/session/testing/benchmark/storage.d.ts.map +1 -0
- package/dist/harness/session/testing/benchmark/storage.js +114 -0
- package/dist/harness/session/testing/benchmark/storage.js.map +1 -0
- package/dist/harness/session/testing/conformance/session-repo.d.ts +21 -0
- package/dist/harness/session/testing/conformance/session-repo.d.ts.map +1 -0
- package/dist/harness/session/testing/conformance/session-repo.js +590 -0
- package/dist/harness/session/testing/conformance/session-repo.js.map +1 -0
- package/dist/harness/session/testing/conformance/storage.d.ts +4 -0
- package/dist/harness/session/testing/conformance/storage.d.ts.map +1 -0
- package/dist/harness/session/testing/conformance/storage.js +600 -0
- package/dist/harness/session/testing/conformance/storage.js.map +1 -0
- package/dist/harness/session/testing/gating-storage.d.ts +26 -0
- package/dist/harness/session/testing/gating-storage.d.ts.map +1 -0
- package/dist/harness/session/testing/gating-storage.js +100 -0
- package/dist/harness/session/testing/gating-storage.js.map +1 -0
- package/dist/harness/session/testing/index.d.ts +9 -2
- package/dist/harness/session/testing/index.d.ts.map +1 -1
- package/dist/harness/session/testing/index.js +8 -1
- package/dist/harness/session/testing/index.js.map +1 -1
- package/dist/harness/session/testing/instrumented-storage.d.ts +11 -0
- package/dist/harness/session/testing/instrumented-storage.d.ts.map +1 -0
- package/dist/harness/session/testing/instrumented-storage.js +16 -0
- package/dist/harness/session/testing/instrumented-storage.js.map +1 -0
- package/dist/harness/session/testing/storage-decorator.d.ts +20 -0
- package/dist/harness/session/testing/storage-decorator.d.ts.map +1 -0
- package/dist/harness/session/testing/storage-decorator.js +41 -0
- package/dist/harness/session/testing/storage-decorator.js.map +1 -0
- package/dist/harness/session/testing/types.d.ts +5 -7
- package/dist/harness/session/testing/types.d.ts.map +1 -1
- package/dist/harness/session/testing/types.js.map +1 -1
- package/dist/harness/session/types.d.ts +424 -259
- package/dist/harness/session/types.d.ts.map +1 -1
- package/dist/harness/session/types.js +7 -8
- package/dist/harness/session/types.js.map +1 -1
- package/dist/harness/session/values.d.ts +95 -0
- package/dist/harness/session/values.d.ts.map +1 -0
- package/dist/harness/session/values.js +81 -0
- package/dist/harness/session/values.js.map +1 -0
- package/dist/harness/skills.d.ts +3 -2
- package/dist/harness/skills.d.ts.map +1 -1
- package/dist/harness/skills.js +29 -26
- package/dist/harness/skills.js.map +1 -1
- package/dist/harness/telemetry.d.ts +64 -43
- package/dist/harness/telemetry.d.ts.map +1 -1
- package/dist/harness/telemetry.js +45 -26
- package/dist/harness/telemetry.js.map +1 -1
- package/dist/harness/tools/bash.d.ts +4 -4
- package/dist/harness/tools/bash.d.ts.map +1 -1
- package/dist/harness/tools/bash.js +66 -93
- package/dist/harness/tools/bash.js.map +1 -1
- package/dist/harness/tools/edit.d.ts.map +1 -1
- package/dist/harness/tools/edit.js +10 -10
- package/dist/harness/tools/edit.js.map +1 -1
- package/dist/harness/tools/file-mutation-queue.d.ts +2 -1
- package/dist/harness/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/harness/tools/file-mutation-queue.js +5 -5
- package/dist/harness/tools/file-mutation-queue.js.map +1 -1
- package/dist/harness/tools/path-utils.d.ts +3 -2
- package/dist/harness/tools/path-utils.d.ts.map +1 -1
- package/dist/harness/tools/path-utils.js +5 -5
- package/dist/harness/tools/path-utils.js.map +1 -1
- package/dist/harness/tools/read.d.ts +2 -1
- package/dist/harness/tools/read.d.ts.map +1 -1
- package/dist/harness/tools/read.js +4 -6
- package/dist/harness/tools/read.js.map +1 -1
- package/dist/harness/tools/write.d.ts.map +1 -1
- package/dist/harness/tools/write.js +7 -7
- package/dist/harness/tools/write.js.map +1 -1
- package/dist/harness/types.d.ts +108 -45
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/utils/adaptive-publisher.d.ts +24 -0
- package/dist/harness/utils/adaptive-publisher.d.ts.map +1 -0
- package/dist/harness/utils/adaptive-publisher.js +79 -0
- package/dist/harness/utils/adaptive-publisher.js.map +1 -0
- package/dist/harness/utils/output-capture.d.ts +31 -0
- package/dist/harness/utils/output-capture.d.ts.map +1 -0
- package/dist/harness/utils/output-capture.js +217 -0
- package/dist/harness/utils/output-capture.js.map +1 -0
- package/dist/harness/utils/shell-output.d.ts +12 -5
- package/dist/harness/utils/shell-output.d.ts.map +1 -1
- package/dist/harness/utils/shell-output.js +64 -174
- package/dist/harness/utils/shell-output.js.map +1 -1
- package/dist/harness/utils/truncate.d.ts +1 -0
- package/dist/harness/utils/truncate.d.ts.map +1 -1
- package/dist/harness/utils/truncate.js +1 -1
- package/dist/harness/utils/truncate.js.map +1 -1
- package/dist/harness/utils/usage.d.ts +4 -0
- package/dist/harness/utils/usage.d.ts.map +1 -0
- package/dist/harness/utils/usage.js +33 -0
- package/dist/harness/utils/usage.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -6
- package/dist/index.js.map +1 -1
- package/dist/proxy.d.ts +2 -0
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +40 -10
- package/dist/proxy.js.map +1 -1
- package/dist/search/index.d.ts +24 -16
- package/dist/search/index.d.ts.map +1 -1
- package/dist/search/index.js +1 -1
- package/dist/search/index.js.map +1 -1
- package/dist/types.d.ts +5 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +25 -4
- package/dist/harness/reducer.d.ts +0 -100
- package/dist/harness/reducer.d.ts.map +0 -1
- package/dist/harness/reducer.js +0 -415
- package/dist/harness/reducer.js.map +0 -1
- package/dist/harness/session/jsonl/errors.d.ts +0 -9
- package/dist/harness/session/jsonl/errors.d.ts.map +0 -1
- package/dist/harness/session/jsonl/errors.js +0 -19
- package/dist/harness/session/jsonl/errors.js.map +0 -1
- package/dist/harness/session/jsonl.d.ts +0 -3
- package/dist/harness/session/jsonl.d.ts.map +0 -1
- package/dist/harness/session/jsonl.js +0 -2
- package/dist/harness/session/jsonl.js.map +0 -1
- package/dist/harness/session/state.d.ts +0 -65
- package/dist/harness/session/state.d.ts.map +0 -1
- package/dist/harness/session/state.js +0 -319
- package/dist/harness/session/state.js.map +0 -1
- package/dist/harness/session/testing/conformance.d.ts +0 -4
- package/dist/harness/session/testing/conformance.d.ts.map +0 -1
- package/dist/harness/session/testing/conformance.js +0 -762
- package/dist/harness/session/testing/conformance.js.map +0 -1
- package/dist/search/scanning.d.ts +0 -29
- package/dist/search/scanning.d.ts.map +0 -1
- package/dist/search/scanning.js +0 -103
- package/dist/search/scanning.js.map +0 -1
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { type ToolResultMessage } from "@earendil-works/pi-ai";
|
|
2
|
+
import type { AgentToolCall, AgentToolResult } from "../../types.ts";
|
|
3
|
+
import { type Context } from "../context.ts";
|
|
4
|
+
import type { JsonValue } from "../session/types.ts";
|
|
5
|
+
import type { AgentHarnessTool, AgentHarnessToolInvocation, AgentHarnessToolUpdateCallback } from "../types.ts";
|
|
6
|
+
import type { Gate } from "./effect-gate.ts";
|
|
7
|
+
/** A tool call whose tool exists and whose prepared arguments passed validation. */
|
|
8
|
+
export interface PreparedToolCall<TContext extends object | undefined> {
|
|
9
|
+
toolCall: AgentToolCall;
|
|
10
|
+
tool: AgentHarnessTool<TContext>;
|
|
11
|
+
args: Record<string, JsonValue>;
|
|
12
|
+
}
|
|
13
|
+
/** Synthetic result produced without crossing the external tool-effect boundary. */
|
|
14
|
+
export interface ImmediateToolOutcome {
|
|
15
|
+
kind: "immediate";
|
|
16
|
+
toolCall: AgentToolCall;
|
|
17
|
+
result: AgentToolResult<unknown>;
|
|
18
|
+
isError: true;
|
|
19
|
+
terminate: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** Aggregated decision from the before-tool hook pipeline. */
|
|
22
|
+
export interface BeforeToolDecision {
|
|
23
|
+
args?: Record<string, JsonValue>;
|
|
24
|
+
block?: {
|
|
25
|
+
reason: string;
|
|
26
|
+
terminate?: boolean;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** A prepared call cleared for durable intent publication and execution. */
|
|
30
|
+
export interface ClearedToolCall<TContext extends object | undefined> {
|
|
31
|
+
toolCall: AgentToolCall;
|
|
32
|
+
tool: AgentHarnessTool<TContext>;
|
|
33
|
+
args: Record<string, JsonValue>;
|
|
34
|
+
}
|
|
35
|
+
/** Raw phase-two tool output before after-tool patching. */
|
|
36
|
+
export interface ExecutedToolCall {
|
|
37
|
+
result: AgentToolResult<unknown>;
|
|
38
|
+
isError: boolean;
|
|
39
|
+
}
|
|
40
|
+
/** Aggregated patch from the after-tool hook pipeline. */
|
|
41
|
+
export interface AfterToolPatch {
|
|
42
|
+
content?: AgentToolResult<unknown>["content"];
|
|
43
|
+
details?: JsonValue;
|
|
44
|
+
isError?: boolean;
|
|
45
|
+
usage?: AgentToolResult<unknown>["usage"];
|
|
46
|
+
terminate?: boolean;
|
|
47
|
+
}
|
|
48
|
+
/** Final tool output ready to become a durable tool-result message. */
|
|
49
|
+
export interface FinalizedToolCall {
|
|
50
|
+
toolCall: AgentToolCall;
|
|
51
|
+
result: AgentToolResult<unknown>;
|
|
52
|
+
isError: boolean;
|
|
53
|
+
terminate: boolean;
|
|
54
|
+
}
|
|
55
|
+
/** Resolve a tool, apply its deterministic argument preparation, and validate the result. */
|
|
56
|
+
export declare function prepareToolCall<TContext extends object | undefined>(call: AgentToolCall, tools: AgentHarnessTool<TContext>[]): PreparedToolCall<TContext> | ImmediateToolOutcome;
|
|
57
|
+
/** Apply an explicit hook decision and revalidate replacement arguments. */
|
|
58
|
+
export declare function applyBeforeToolDecision<TContext extends object | undefined>(prepared: PreparedToolCall<TContext>, decision: BeforeToolDecision | undefined): ClearedToolCall<TContext> | ImmediateToolOutcome;
|
|
59
|
+
/** Execute one cleared external tool effect, converting expected tool throws to error output. */
|
|
60
|
+
export declare function executeToolCall<TContext extends object | undefined>(call: ClearedToolCall<TContext>, gate: Gate, onUpdate: AgentHarnessToolUpdateCallback<unknown>, toolContext: TContext, invocation: AgentHarnessToolInvocation, context: Context): Promise<ExecutedToolCall>;
|
|
61
|
+
/** Apply an after-tool patch field by field. */
|
|
62
|
+
export declare function finalizeToolCall<TContext extends object | undefined>(call: ClearedToolCall<TContext>, executed: ExecutedToolCall, patch: AfterToolPatch | undefined): FinalizedToolCall;
|
|
63
|
+
/** Reconstruct the canonical tool result represented by a staged transcript message. */
|
|
64
|
+
export declare function toolResultFromMessage(message: ToolResultMessage<unknown>, terminate: boolean): AgentToolResult<unknown>;
|
|
65
|
+
/** Convert finalized tool output to the provider-facing transcript message. */
|
|
66
|
+
export declare function createToolResultMessage(call: FinalizedToolCall): ToolResultMessage;
|
|
67
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/harness/execution/tools.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ToolResultMessage, validateToolArguments } from \"@earendil-works/pi-ai\";\nimport type { AgentToolCall, AgentToolResult } from \"../../types.ts\";\nimport { type Context, withAbortSignal } from \"../context.ts\";\nimport type { JsonValue } from \"../session/types.ts\";\nimport type { AgentHarnessTool, AgentHarnessToolInvocation, AgentHarnessToolUpdateCallback } from \"../types.ts\";\nimport type { Gate } from \"./effect-gate.ts\";\n\n/** A tool call whose tool exists and whose prepared arguments passed validation. */\nexport interface PreparedToolCall<TContext extends object | undefined> {\n\ttoolCall: AgentToolCall;\n\ttool: AgentHarnessTool<TContext>;\n\targs: Record<string, JsonValue>;\n}\n\n/** Synthetic result produced without crossing the external tool-effect boundary. */\nexport interface ImmediateToolOutcome {\n\tkind: \"immediate\";\n\ttoolCall: AgentToolCall;\n\tresult: AgentToolResult<unknown>;\n\tisError: true;\n\tterminate: boolean;\n}\n\n/** Aggregated decision from the before-tool hook pipeline. */\nexport interface BeforeToolDecision {\n\targs?: Record<string, JsonValue>;\n\tblock?: { reason: string; terminate?: boolean };\n}\n\n/** A prepared call cleared for durable intent publication and execution. */\nexport interface ClearedToolCall<TContext extends object | undefined> {\n\ttoolCall: AgentToolCall;\n\ttool: AgentHarnessTool<TContext>;\n\targs: Record<string, JsonValue>;\n}\n\n/** Raw phase-two tool output before after-tool patching. */\nexport interface ExecutedToolCall {\n\tresult: AgentToolResult<unknown>;\n\tisError: boolean;\n}\n\n/** Aggregated patch from the after-tool hook pipeline. */\nexport interface AfterToolPatch {\n\tcontent?: AgentToolResult<unknown>[\"content\"];\n\tdetails?: JsonValue;\n\tisError?: boolean;\n\tusage?: AgentToolResult<unknown>[\"usage\"];\n\tterminate?: boolean;\n}\n\n/** Final tool output ready to become a durable tool-result message. */\nexport interface FinalizedToolCall {\n\ttoolCall: AgentToolCall;\n\tresult: AgentToolResult<unknown>;\n\tisError: boolean;\n\tterminate: boolean;\n}\n\nfunction createErrorToolResult(message: string): AgentToolResult<unknown> {\n\treturn {\n\t\tcontent: [{ type: \"text\", text: message }],\n\t\tdetails: undefined,\n\t};\n}\n\nfunction immediateError(toolCall: AgentToolCall, message: string, terminate = false): ImmediateToolOutcome {\n\treturn {\n\t\tkind: \"immediate\",\n\t\ttoolCall,\n\t\tresult: createErrorToolResult(message),\n\t\tisError: true,\n\t\tterminate,\n\t};\n}\n\n/** Resolve a tool, apply its deterministic argument preparation, and validate the result. */\nexport function prepareToolCall<TContext extends object | undefined>(\n\tcall: AgentToolCall,\n\ttools: AgentHarnessTool<TContext>[],\n): PreparedToolCall<TContext> | ImmediateToolOutcome {\n\tconst tool = tools.find((candidate) => candidate.name === call.name);\n\tif (!tool) {\n\t\treturn immediateError(call, `Tool ${JSON.stringify(call.name)} is unavailable`);\n\t}\n\n\ttry {\n\t\tconst preparedArguments = tool.prepareArguments ? tool.prepareArguments(call.arguments) : call.arguments;\n\t\tconst preparedCall: AgentToolCall =\n\t\t\tpreparedArguments === call.arguments\n\t\t\t\t? call\n\t\t\t\t: { ...call, arguments: preparedArguments as Record<string, JsonValue> };\n\t\tconst args = validateToolArguments(tool, preparedCall) as Record<string, JsonValue>;\n\t\treturn { toolCall: call, tool, args };\n\t} catch (error) {\n\t\treturn immediateError(call, error instanceof Error ? error.message : String(error));\n\t}\n}\n\n/** Apply an explicit hook decision and revalidate replacement arguments. */\nexport function applyBeforeToolDecision<TContext extends object | undefined>(\n\tprepared: PreparedToolCall<TContext>,\n\tdecision: BeforeToolDecision | undefined,\n): ClearedToolCall<TContext> | ImmediateToolOutcome {\n\tif (decision?.block) {\n\t\treturn immediateError(prepared.toolCall, decision.block.reason, decision.block.terminate === true);\n\t}\n\n\tif (!decision?.args) {\n\t\treturn { toolCall: prepared.toolCall, tool: prepared.tool, args: prepared.args };\n\t}\n\n\ttry {\n\t\tconst validatedArgs = validateToolArguments(prepared.tool, {\n\t\t\t...prepared.toolCall,\n\t\t\targuments: decision.args,\n\t\t}) as Record<string, JsonValue>;\n\t\treturn { toolCall: prepared.toolCall, tool: prepared.tool, args: validatedArgs };\n\t} catch (error) {\n\t\treturn immediateError(prepared.toolCall, error instanceof Error ? error.message : String(error));\n\t}\n}\n\n/** Execute one cleared external tool effect, converting expected tool throws to error output. */\nexport function executeToolCall<TContext extends object | undefined>(\n\tcall: ClearedToolCall<TContext>,\n\tgate: Gate,\n\tonUpdate: AgentHarnessToolUpdateCallback<unknown>,\n\ttoolContext: TContext,\n\tinvocation: AgentHarnessToolInvocation,\n\tcontext: Context,\n): Promise<ExecutedToolCall> {\n\tlet acceptingUpdates = true;\n\treturn gate.admit(async () => {\n\t\tconst admittedContext = withAbortSignal(gate.signal, context);\n\t\tadmittedContext.abortSignal?.throwIfAborted();\n\t\ttry {\n\t\t\tconst result = await call.tool.execute(\n\t\t\t\tcall.toolCall.id,\n\t\t\t\tcall.args,\n\t\t\t\t(partial, options) => {\n\t\t\t\t\tif (acceptingUpdates) onUpdate(partial, options);\n\t\t\t\t},\n\t\t\t\ttoolContext,\n\t\t\t\tinvocation,\n\t\t\t\tadmittedContext,\n\t\t\t);\n\t\t\treturn { result, isError: false };\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tresult: createErrorToolResult(error instanceof Error ? error.message : String(error)),\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t} finally {\n\t\t\tacceptingUpdates = false;\n\t\t}\n\t});\n}\n\n/** Apply an after-tool patch field by field. */\nexport function finalizeToolCall<TContext extends object | undefined>(\n\tcall: ClearedToolCall<TContext>,\n\texecuted: ExecutedToolCall,\n\tpatch: AfterToolPatch | undefined,\n): FinalizedToolCall {\n\tconst result: AgentToolResult<unknown> = patch\n\t\t? {\n\t\t\t\t...executed.result,\n\t\t\t\tcontent: patch.content === undefined ? executed.result.content : patch.content,\n\t\t\t\tdetails: patch.details === undefined ? executed.result.details : patch.details,\n\t\t\t\tusage: patch.usage === undefined ? executed.result.usage : patch.usage,\n\t\t\t\tterminate: patch.terminate === undefined ? executed.result.terminate : patch.terminate,\n\t\t\t}\n\t\t: executed.result;\n\treturn {\n\t\ttoolCall: call.toolCall,\n\t\tresult,\n\t\tisError: patch?.isError ?? executed.isError,\n\t\tterminate: result.terminate === true,\n\t};\n}\n\n/** Reconstruct the canonical tool result represented by a staged transcript message. */\nexport function toolResultFromMessage(\n\tmessage: ToolResultMessage<unknown>,\n\tterminate: boolean,\n): AgentToolResult<unknown> {\n\treturn {\n\t\tcontent: message.content,\n\t\tdetails: message.details,\n\t\t...(message.usage === undefined ? {} : { usage: message.usage }),\n\t\t...(message.addedToolNames === undefined ? {} : { addedToolNames: message.addedToolNames }),\n\t\t...(terminate ? { terminate: true } : {}),\n\t};\n}\n\n/** Convert finalized tool output to the provider-facing transcript message. */\nexport function createToolResultMessage(call: FinalizedToolCall): ToolResultMessage {\n\treturn {\n\t\trole: \"toolResult\",\n\t\ttoolCallId: call.toolCall.id,\n\t\ttoolName: call.toolCall.name,\n\t\tcontent: call.result.content ?? [],\n\t\t...(call.result.details === undefined ? {} : { details: call.result.details }),\n\t\t...(call.result.usage === undefined ? {} : { usage: call.result.usage }),\n\t\t...(call.result.addedToolNames?.length ? { addedToolNames: call.result.addedToolNames } : {}),\n\t\tisError: call.isError,\n\t\ttimestamp: Date.now(),\n\t};\n}\n"]}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { validateToolArguments } from "@earendil-works/pi-ai";
|
|
2
|
+
import { withAbortSignal } from "../context.js";
|
|
3
|
+
function createErrorToolResult(message) {
|
|
4
|
+
return {
|
|
5
|
+
content: [{ type: "text", text: message }],
|
|
6
|
+
details: undefined,
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
function immediateError(toolCall, message, terminate = false) {
|
|
10
|
+
return {
|
|
11
|
+
kind: "immediate",
|
|
12
|
+
toolCall,
|
|
13
|
+
result: createErrorToolResult(message),
|
|
14
|
+
isError: true,
|
|
15
|
+
terminate,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/** Resolve a tool, apply its deterministic argument preparation, and validate the result. */
|
|
19
|
+
export function prepareToolCall(call, tools) {
|
|
20
|
+
const tool = tools.find((candidate) => candidate.name === call.name);
|
|
21
|
+
if (!tool) {
|
|
22
|
+
return immediateError(call, `Tool ${JSON.stringify(call.name)} is unavailable`);
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const preparedArguments = tool.prepareArguments ? tool.prepareArguments(call.arguments) : call.arguments;
|
|
26
|
+
const preparedCall = preparedArguments === call.arguments
|
|
27
|
+
? call
|
|
28
|
+
: { ...call, arguments: preparedArguments };
|
|
29
|
+
const args = validateToolArguments(tool, preparedCall);
|
|
30
|
+
return { toolCall: call, tool, args };
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
return immediateError(call, error instanceof Error ? error.message : String(error));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** Apply an explicit hook decision and revalidate replacement arguments. */
|
|
37
|
+
export function applyBeforeToolDecision(prepared, decision) {
|
|
38
|
+
if (decision?.block) {
|
|
39
|
+
return immediateError(prepared.toolCall, decision.block.reason, decision.block.terminate === true);
|
|
40
|
+
}
|
|
41
|
+
if (!decision?.args) {
|
|
42
|
+
return { toolCall: prepared.toolCall, tool: prepared.tool, args: prepared.args };
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const validatedArgs = validateToolArguments(prepared.tool, {
|
|
46
|
+
...prepared.toolCall,
|
|
47
|
+
arguments: decision.args,
|
|
48
|
+
});
|
|
49
|
+
return { toolCall: prepared.toolCall, tool: prepared.tool, args: validatedArgs };
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
return immediateError(prepared.toolCall, error instanceof Error ? error.message : String(error));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** Execute one cleared external tool effect, converting expected tool throws to error output. */
|
|
56
|
+
export function executeToolCall(call, gate, onUpdate, toolContext, invocation, context) {
|
|
57
|
+
let acceptingUpdates = true;
|
|
58
|
+
return gate.admit(async () => {
|
|
59
|
+
const admittedContext = withAbortSignal(gate.signal, context);
|
|
60
|
+
admittedContext.abortSignal?.throwIfAborted();
|
|
61
|
+
try {
|
|
62
|
+
const result = await call.tool.execute(call.toolCall.id, call.args, (partial, options) => {
|
|
63
|
+
if (acceptingUpdates)
|
|
64
|
+
onUpdate(partial, options);
|
|
65
|
+
}, toolContext, invocation, admittedContext);
|
|
66
|
+
return { result, isError: false };
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
return {
|
|
70
|
+
result: createErrorToolResult(error instanceof Error ? error.message : String(error)),
|
|
71
|
+
isError: true,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
acceptingUpdates = false;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/** Apply an after-tool patch field by field. */
|
|
80
|
+
export function finalizeToolCall(call, executed, patch) {
|
|
81
|
+
const result = patch
|
|
82
|
+
? {
|
|
83
|
+
...executed.result,
|
|
84
|
+
content: patch.content === undefined ? executed.result.content : patch.content,
|
|
85
|
+
details: patch.details === undefined ? executed.result.details : patch.details,
|
|
86
|
+
usage: patch.usage === undefined ? executed.result.usage : patch.usage,
|
|
87
|
+
terminate: patch.terminate === undefined ? executed.result.terminate : patch.terminate,
|
|
88
|
+
}
|
|
89
|
+
: executed.result;
|
|
90
|
+
return {
|
|
91
|
+
toolCall: call.toolCall,
|
|
92
|
+
result,
|
|
93
|
+
isError: patch?.isError ?? executed.isError,
|
|
94
|
+
terminate: result.terminate === true,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/** Reconstruct the canonical tool result represented by a staged transcript message. */
|
|
98
|
+
export function toolResultFromMessage(message, terminate) {
|
|
99
|
+
return {
|
|
100
|
+
content: message.content,
|
|
101
|
+
details: message.details,
|
|
102
|
+
...(message.usage === undefined ? {} : { usage: message.usage }),
|
|
103
|
+
...(message.addedToolNames === undefined ? {} : { addedToolNames: message.addedToolNames }),
|
|
104
|
+
...(terminate ? { terminate: true } : {}),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/** Convert finalized tool output to the provider-facing transcript message. */
|
|
108
|
+
export function createToolResultMessage(call) {
|
|
109
|
+
return {
|
|
110
|
+
role: "toolResult",
|
|
111
|
+
toolCallId: call.toolCall.id,
|
|
112
|
+
toolName: call.toolCall.name,
|
|
113
|
+
content: call.result.content ?? [],
|
|
114
|
+
...(call.result.details === undefined ? {} : { details: call.result.details }),
|
|
115
|
+
...(call.result.usage === undefined ? {} : { usage: call.result.usage }),
|
|
116
|
+
...(call.result.addedToolNames?.length ? { addedToolNames: call.result.addedToolNames } : {}),
|
|
117
|
+
isError: call.isError,
|
|
118
|
+
timestamp: Date.now(),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../src/harness/execution/tools.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ToolResultMessage, validateToolArguments } from \"@earendil-works/pi-ai\";\nimport type { AgentToolCall, AgentToolResult } from \"../../types.ts\";\nimport { type Context, withAbortSignal } from \"../context.ts\";\nimport type { JsonValue } from \"../session/types.ts\";\nimport type { AgentHarnessTool, AgentHarnessToolInvocation, AgentHarnessToolUpdateCallback } from \"../types.ts\";\nimport type { Gate } from \"./effect-gate.ts\";\n\n/** A tool call whose tool exists and whose prepared arguments passed validation. */\nexport interface PreparedToolCall<TContext extends object | undefined> {\n\ttoolCall: AgentToolCall;\n\ttool: AgentHarnessTool<TContext>;\n\targs: Record<string, JsonValue>;\n}\n\n/** Synthetic result produced without crossing the external tool-effect boundary. */\nexport interface ImmediateToolOutcome {\n\tkind: \"immediate\";\n\ttoolCall: AgentToolCall;\n\tresult: AgentToolResult<unknown>;\n\tisError: true;\n\tterminate: boolean;\n}\n\n/** Aggregated decision from the before-tool hook pipeline. */\nexport interface BeforeToolDecision {\n\targs?: Record<string, JsonValue>;\n\tblock?: { reason: string; terminate?: boolean };\n}\n\n/** A prepared call cleared for durable intent publication and execution. */\nexport interface ClearedToolCall<TContext extends object | undefined> {\n\ttoolCall: AgentToolCall;\n\ttool: AgentHarnessTool<TContext>;\n\targs: Record<string, JsonValue>;\n}\n\n/** Raw phase-two tool output before after-tool patching. */\nexport interface ExecutedToolCall {\n\tresult: AgentToolResult<unknown>;\n\tisError: boolean;\n}\n\n/** Aggregated patch from the after-tool hook pipeline. */\nexport interface AfterToolPatch {\n\tcontent?: AgentToolResult<unknown>[\"content\"];\n\tdetails?: JsonValue;\n\tisError?: boolean;\n\tusage?: AgentToolResult<unknown>[\"usage\"];\n\tterminate?: boolean;\n}\n\n/** Final tool output ready to become a durable tool-result message. */\nexport interface FinalizedToolCall {\n\ttoolCall: AgentToolCall;\n\tresult: AgentToolResult<unknown>;\n\tisError: boolean;\n\tterminate: boolean;\n}\n\nfunction createErrorToolResult(message: string): AgentToolResult<unknown> {\n\treturn {\n\t\tcontent: [{ type: \"text\", text: message }],\n\t\tdetails: undefined,\n\t};\n}\n\nfunction immediateError(toolCall: AgentToolCall, message: string, terminate = false): ImmediateToolOutcome {\n\treturn {\n\t\tkind: \"immediate\",\n\t\ttoolCall,\n\t\tresult: createErrorToolResult(message),\n\t\tisError: true,\n\t\tterminate,\n\t};\n}\n\n/** Resolve a tool, apply its deterministic argument preparation, and validate the result. */\nexport function prepareToolCall<TContext extends object | undefined>(\n\tcall: AgentToolCall,\n\ttools: AgentHarnessTool<TContext>[],\n): PreparedToolCall<TContext> | ImmediateToolOutcome {\n\tconst tool = tools.find((candidate) => candidate.name === call.name);\n\tif (!tool) {\n\t\treturn immediateError(call, `Tool ${JSON.stringify(call.name)} is unavailable`);\n\t}\n\n\ttry {\n\t\tconst preparedArguments = tool.prepareArguments ? tool.prepareArguments(call.arguments) : call.arguments;\n\t\tconst preparedCall: AgentToolCall =\n\t\t\tpreparedArguments === call.arguments\n\t\t\t\t? call\n\t\t\t\t: { ...call, arguments: preparedArguments as Record<string, JsonValue> };\n\t\tconst args = validateToolArguments(tool, preparedCall) as Record<string, JsonValue>;\n\t\treturn { toolCall: call, tool, args };\n\t} catch (error) {\n\t\treturn immediateError(call, error instanceof Error ? error.message : String(error));\n\t}\n}\n\n/** Apply an explicit hook decision and revalidate replacement arguments. */\nexport function applyBeforeToolDecision<TContext extends object | undefined>(\n\tprepared: PreparedToolCall<TContext>,\n\tdecision: BeforeToolDecision | undefined,\n): ClearedToolCall<TContext> | ImmediateToolOutcome {\n\tif (decision?.block) {\n\t\treturn immediateError(prepared.toolCall, decision.block.reason, decision.block.terminate === true);\n\t}\n\n\tif (!decision?.args) {\n\t\treturn { toolCall: prepared.toolCall, tool: prepared.tool, args: prepared.args };\n\t}\n\n\ttry {\n\t\tconst validatedArgs = validateToolArguments(prepared.tool, {\n\t\t\t...prepared.toolCall,\n\t\t\targuments: decision.args,\n\t\t}) as Record<string, JsonValue>;\n\t\treturn { toolCall: prepared.toolCall, tool: prepared.tool, args: validatedArgs };\n\t} catch (error) {\n\t\treturn immediateError(prepared.toolCall, error instanceof Error ? error.message : String(error));\n\t}\n}\n\n/** Execute one cleared external tool effect, converting expected tool throws to error output. */\nexport function executeToolCall<TContext extends object | undefined>(\n\tcall: ClearedToolCall<TContext>,\n\tgate: Gate,\n\tonUpdate: AgentHarnessToolUpdateCallback<unknown>,\n\ttoolContext: TContext,\n\tinvocation: AgentHarnessToolInvocation,\n\tcontext: Context,\n): Promise<ExecutedToolCall> {\n\tlet acceptingUpdates = true;\n\treturn gate.admit(async () => {\n\t\tconst admittedContext = withAbortSignal(gate.signal, context);\n\t\tadmittedContext.abortSignal?.throwIfAborted();\n\t\ttry {\n\t\t\tconst result = await call.tool.execute(\n\t\t\t\tcall.toolCall.id,\n\t\t\t\tcall.args,\n\t\t\t\t(partial, options) => {\n\t\t\t\t\tif (acceptingUpdates) onUpdate(partial, options);\n\t\t\t\t},\n\t\t\t\ttoolContext,\n\t\t\t\tinvocation,\n\t\t\t\tadmittedContext,\n\t\t\t);\n\t\t\treturn { result, isError: false };\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tresult: createErrorToolResult(error instanceof Error ? error.message : String(error)),\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t} finally {\n\t\t\tacceptingUpdates = false;\n\t\t}\n\t});\n}\n\n/** Apply an after-tool patch field by field. */\nexport function finalizeToolCall<TContext extends object | undefined>(\n\tcall: ClearedToolCall<TContext>,\n\texecuted: ExecutedToolCall,\n\tpatch: AfterToolPatch | undefined,\n): FinalizedToolCall {\n\tconst result: AgentToolResult<unknown> = patch\n\t\t? {\n\t\t\t\t...executed.result,\n\t\t\t\tcontent: patch.content === undefined ? executed.result.content : patch.content,\n\t\t\t\tdetails: patch.details === undefined ? executed.result.details : patch.details,\n\t\t\t\tusage: patch.usage === undefined ? executed.result.usage : patch.usage,\n\t\t\t\tterminate: patch.terminate === undefined ? executed.result.terminate : patch.terminate,\n\t\t\t}\n\t\t: executed.result;\n\treturn {\n\t\ttoolCall: call.toolCall,\n\t\tresult,\n\t\tisError: patch?.isError ?? executed.isError,\n\t\tterminate: result.terminate === true,\n\t};\n}\n\n/** Reconstruct the canonical tool result represented by a staged transcript message. */\nexport function toolResultFromMessage(\n\tmessage: ToolResultMessage<unknown>,\n\tterminate: boolean,\n): AgentToolResult<unknown> {\n\treturn {\n\t\tcontent: message.content,\n\t\tdetails: message.details,\n\t\t...(message.usage === undefined ? {} : { usage: message.usage }),\n\t\t...(message.addedToolNames === undefined ? {} : { addedToolNames: message.addedToolNames }),\n\t\t...(terminate ? { terminate: true } : {}),\n\t};\n}\n\n/** Convert finalized tool output to the provider-facing transcript message. */\nexport function createToolResultMessage(call: FinalizedToolCall): ToolResultMessage {\n\treturn {\n\t\trole: \"toolResult\",\n\t\ttoolCallId: call.toolCall.id,\n\t\ttoolName: call.toolCall.name,\n\t\tcontent: call.result.content ?? [],\n\t\t...(call.result.details === undefined ? {} : { details: call.result.details }),\n\t\t...(call.result.usage === undefined ? {} : { usage: call.result.usage }),\n\t\t...(call.result.addedToolNames?.length ? { addedToolNames: call.result.addedToolNames } : {}),\n\t\tisError: call.isError,\n\t\ttimestamp: Date.now(),\n\t};\n}\n"]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { HookHandler, HookInvocation, HookMap, HookName, Hooks } from "./agent-harness.ts";
|
|
2
|
+
import { type Context } from "./context.ts";
|
|
3
|
+
import type { Gate } from "./execution/effect-gate.ts";
|
|
4
|
+
import type { AgentHarnessStreamOptions, AgentHarnessStreamOptionsPatch } from "./types.ts";
|
|
5
|
+
type HookErrorReporter = (error: Error, hook: HookName, lane: string, context: Context) => void | Promise<void>;
|
|
6
|
+
/** Ordered harness hook registry and aggregate runner. */
|
|
7
|
+
export declare class HookRegistry implements Hooks {
|
|
8
|
+
private readonly registrations;
|
|
9
|
+
private readonly reportError;
|
|
10
|
+
private closedError;
|
|
11
|
+
constructor(reportError: HookErrorReporter);
|
|
12
|
+
on<TName extends HookName>(name: TName, handler: HookHandler<TName>, options?: {
|
|
13
|
+
id?: string;
|
|
14
|
+
}): () => void;
|
|
15
|
+
has(name: HookName): boolean;
|
|
16
|
+
/** Invoke one accepted-operation aggregate after synchronously passing its effect gate. */
|
|
17
|
+
runWithGate<TName extends HookName>(name: TName, event: HookInvocation<TName>, gate: Gate, context: Context): Promise<HookMap[TName]["result"]>;
|
|
18
|
+
/** Invoke a tool-hook aggregate with one telemetry span per registered handler. */
|
|
19
|
+
runToolWithGate<TName extends "before_tool" | "after_tool">(name: TName, event: HookInvocation<TName>, gate: Gate, context: Context): Promise<HookMap[TName]["result"]>;
|
|
20
|
+
close(error: Error): void;
|
|
21
|
+
private runAdmitted;
|
|
22
|
+
private aggregate;
|
|
23
|
+
private beforeRun;
|
|
24
|
+
private beforeTool;
|
|
25
|
+
private transformContext;
|
|
26
|
+
private beforeRequest;
|
|
27
|
+
private beforePayload;
|
|
28
|
+
private afterResponse;
|
|
29
|
+
private afterTool;
|
|
30
|
+
private firstStructural;
|
|
31
|
+
private invokeToolRegistration;
|
|
32
|
+
private registrationsFor;
|
|
33
|
+
private invokeAllFailClosed;
|
|
34
|
+
private invokeAll;
|
|
35
|
+
}
|
|
36
|
+
export declare function applyStreamOptionsPatch(base: AgentHarnessStreamOptions, patch: AgentHarnessStreamOptionsPatch): AgentHarnessStreamOptions;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/harness/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChG,OAAO,EAAE,KAAK,OAAO,EAAmB,MAAM,cAAc,CAAC;AAC7D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAEvD,OAAO,KAAK,EAAE,yBAAyB,EAAE,8BAA8B,EAAE,MAAM,YAAY,CAAC;AAO5F,KAAK,iBAAiB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEhH,0DAA0D;AAC1D,qBAAa,YAAa,YAAW,KAAK;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA2C;IACzE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoB;IAChD,OAAO,CAAC,WAAW,CAAoB;IAEvC,YAAY,WAAW,EAAE,iBAAiB,EAEzC;IAED,EAAE,CAAC,KAAK,SAAS,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,OAAO,GAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,MAAM,IAAI,CAa9G;IAED,GAAG,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAE3B;IAED,2FAA2F;IAC3F,WAAW,CAAC,KAAK,SAAS,QAAQ,EACjC,IAAI,EAAE,KAAK,EACX,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,EAC5B,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,GACd,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAMnC;IAED,mFAAmF;IACnF,eAAe,CAAC,KAAK,SAAS,aAAa,GAAG,YAAY,EACzD,IAAI,EAAE,KAAK,EACX,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,EAC5B,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,GACd,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAUnC;IAED,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAExB;YAEa,WAAW;YAUX,SAAS;YAuCT,SAAS;YA4BT,UAAU;YAgCV,gBAAgB;YA8BhB,aAAa;YA4Bb,aAAa;YAwBb,aAAa;YAwBb,SAAS;YA2CT,eAAe;IAiC7B,OAAO,CAAC,sBAAsB;IAmC9B,OAAO,CAAC,gBAAgB;YAIV,mBAAmB;YAgBnB,SAAS;CAmBvB;AAED,wBAAgB,uBAAuB,CACtC,IAAI,EAAE,yBAAyB,EAC/B,KAAK,EAAE,8BAA8B,GACnC,yBAAyB,CAsC3B","sourcesContent":["import type { HookHandler, HookInvocation, HookMap, HookName, Hooks } from \"./agent-harness.ts\";\nimport { type Context, withAbortSignal } from \"./context.ts\";\nimport type { Gate } from \"./execution/effect-gate.ts\";\nimport { startHarnessSpan } from \"./telemetry.ts\";\nimport type { AgentHarnessStreamOptions, AgentHarnessStreamOptionsPatch } from \"./types.ts\";\n\ninterface HookRegistration {\n\tid?: string;\n\thandler: (event: unknown, context: Context) => unknown | Promise<unknown>;\n}\n\ntype HookErrorReporter = (error: Error, hook: HookName, lane: string, context: Context) => void | Promise<void>;\n\n/** Ordered harness hook registry and aggregate runner. */\nexport class HookRegistry implements Hooks {\n\tprivate readonly registrations = new Map<HookName, HookRegistration[]>();\n\tprivate readonly reportError: HookErrorReporter;\n\tprivate closedError: Error | undefined;\n\n\tconstructor(reportError: HookErrorReporter) {\n\t\tthis.reportError = reportError;\n\t}\n\n\ton<TName extends HookName>(name: TName, handler: HookHandler<TName>, options: { id?: string } = {}): () => void {\n\t\tif (this.closedError !== undefined) throw this.closedError;\n\t\tconst registrations = this.registrations.get(name) ?? [];\n\t\tconst registration: HookRegistration = {\n\t\t\t...(options.id === undefined ? {} : { id: options.id }),\n\t\t\thandler: (event, context) => handler(event as HookInvocation<TName>, context),\n\t\t};\n\t\tregistrations.push(registration);\n\t\tthis.registrations.set(name, registrations);\n\t\treturn () => {\n\t\t\tconst index = registrations.indexOf(registration);\n\t\t\tif (index !== -1) registrations.splice(index, 1);\n\t\t};\n\t}\n\n\thas(name: HookName): boolean {\n\t\treturn (this.registrations.get(name)?.length ?? 0) !== 0;\n\t}\n\n\t/** Invoke one accepted-operation aggregate after synchronously passing its effect gate. */\n\trunWithGate<TName extends HookName>(\n\t\tname: TName,\n\t\tevent: HookInvocation<TName>,\n\t\tgate: Gate,\n\t\tcontext: Context,\n\t): Promise<HookMap[TName][\"result\"]> {\n\t\treturn gate.admit(() => {\n\t\t\tconst admittedContext = withAbortSignal(gate.signal, context);\n\t\t\tadmittedContext.abortSignal?.throwIfAborted();\n\t\t\treturn this.runAdmitted(name, event, admittedContext);\n\t\t});\n\t}\n\n\t/** Invoke a tool-hook aggregate with one telemetry span per registered handler. */\n\trunToolWithGate<TName extends \"before_tool\" | \"after_tool\">(\n\t\tname: TName,\n\t\tevent: HookInvocation<TName>,\n\t\tgate: Gate,\n\t\tcontext: Context,\n\t): Promise<HookMap[TName][\"result\"]> {\n\t\treturn gate.admit(() => {\n\t\t\tconst admittedContext = withAbortSignal(gate.signal, context);\n\t\t\tadmittedContext.abortSignal?.throwIfAborted();\n\t\t\treturn (\n\t\t\t\tname === \"before_tool\"\n\t\t\t\t\t? this.beforeTool(event as HookInvocation<\"before_tool\">, admittedContext)\n\t\t\t\t\t: this.afterTool(event as HookInvocation<\"after_tool\">, admittedContext)\n\t\t\t) as Promise<HookMap[TName][\"result\"]>;\n\t\t});\n\t}\n\n\tclose(error: Error): void {\n\t\tthis.closedError ??= error;\n\t}\n\n\tprivate async runAdmitted<TName extends HookName>(\n\t\tname: TName,\n\t\tevent: HookInvocation<TName>,\n\t\tcontext: Context,\n\t): Promise<HookMap[TName][\"result\"]> {\n\t\tif (this.closedError !== undefined) throw this.closedError;\n\t\tconst result = await this.aggregate(name, event, context);\n\t\treturn result as HookMap[TName][\"result\"];\n\t}\n\n\tprivate async aggregate(name: HookName, event: HookInvocation<HookName>, context: Context): Promise<unknown> {\n\t\tswitch (name) {\n\t\t\tcase \"before_run\":\n\t\t\t\treturn this.beforeRun(event as HookInvocation<\"before_run\">, context);\n\t\t\tcase \"before_drive\":\n\t\t\t\tawait this.invokeAllFailClosed(name, event as HookInvocation<\"before_drive\">, context);\n\t\t\t\treturn undefined;\n\t\t\tcase \"before_run_end\": {\n\t\t\t\tlet followUp: string | undefined;\n\t\t\t\tawait this.invokeAll(\n\t\t\t\t\tname,\n\t\t\t\t\tevent,\n\t\t\t\t\t(value) => {\n\t\t\t\t\t\tconst result = value as HookMap[\"before_run_end\"][\"result\"];\n\t\t\t\t\t\tif (result?.followUp !== undefined) followUp = result.followUp;\n\t\t\t\t\t},\n\t\t\t\t\tcontext,\n\t\t\t\t);\n\t\t\t\treturn followUp === undefined ? undefined : { followUp };\n\t\t\t}\n\t\t\tcase \"transform_context\":\n\t\t\t\treturn this.transformContext(event as HookInvocation<\"transform_context\">, context);\n\t\t\tcase \"before_request\":\n\t\t\t\treturn this.beforeRequest(event as HookInvocation<\"before_request\">, context);\n\t\t\tcase \"before_payload\":\n\t\t\t\treturn this.beforePayload(event as HookInvocation<\"before_payload\">, context);\n\t\t\tcase \"after_response\":\n\t\t\t\treturn this.afterResponse(event as HookInvocation<\"after_response\">, context);\n\t\t\tcase \"before_tool\":\n\t\t\t\treturn this.beforeTool(event as HookInvocation<\"before_tool\">, context);\n\t\t\tcase \"after_tool\":\n\t\t\t\treturn this.afterTool(event as HookInvocation<\"after_tool\">, context);\n\t\t\tcase \"before_compaction\":\n\t\t\t\treturn this.firstStructural(name, event as HookInvocation<\"before_compaction\">, \"compaction\", context);\n\t\t\tcase \"before_navigation\":\n\t\t\t\treturn this.firstStructural(name, event as HookInvocation<\"before_navigation\">, \"summary\", context);\n\t\t}\n\t}\n\n\tprivate async beforeRun(\n\t\tevent: HookInvocation<\"before_run\">,\n\t\tcontext: Context,\n\t): Promise<HookMap[\"before_run\"][\"result\"]> {\n\t\tlet prompt = event.prompt;\n\t\tlet injected: HookMap[\"before_run\"][\"event\"][\"prompt\"] = [];\n\t\tfor (const registration of this.registrationsFor(\"before_run\")) {\n\t\t\ttry {\n\t\t\t\tconst result = (await registration.handler(\n\t\t\t\t\t{ ...event, prompt },\n\t\t\t\t\tcontext,\n\t\t\t\t)) as HookMap[\"before_run\"][\"result\"];\n\t\t\t\tif (result?.messages !== undefined) {\n\t\t\t\t\tinjected = [...injected, ...result.messages];\n\t\t\t\t\tprompt = [...prompt, ...result.messages];\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tawait this.reportError(\n\t\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\t\t\"before_run\",\n\t\t\t\t\tevent.lane,\n\t\t\t\t\tcontext,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\treturn injected.length === 0 ? undefined : { messages: injected };\n\t}\n\n\tprivate async beforeTool(\n\t\tevent: HookInvocation<\"before_tool\">,\n\t\tcontext: Context,\n\t): Promise<HookMap[\"before_tool\"][\"result\"]> {\n\t\tlet args = event.args;\n\t\tlet block: { reason: string; terminate?: boolean } | undefined;\n\t\tfor (const registration of this.registrationsFor(\"before_tool\")) {\n\t\t\ttry {\n\t\t\t\tconst result = (await this.invokeToolRegistration(\n\t\t\t\t\t\"before_tool\",\n\t\t\t\t\tregistration,\n\t\t\t\t\t{ ...event, args },\n\t\t\t\t\tcontext,\n\t\t\t\t)) as HookMap[\"before_tool\"][\"result\"];\n\t\t\t\tif (result?.args !== undefined) args = result.args;\n\t\t\t\tif (result?.block !== undefined) {\n\t\t\t\t\tblock = result.block;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconst normalized = error instanceof Error ? error : new Error(String(error));\n\t\t\t\tawait this.reportError(normalized, \"before_tool\", event.lane, context);\n\t\t\t\tblock = { reason: normalized.message };\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\t...(args === event.args ? {} : { args }),\n\t\t\t...(block === undefined ? {} : { block }),\n\t\t};\n\t}\n\n\tprivate async transformContext(\n\t\tevent: HookInvocation<\"transform_context\">,\n\t\tcontext: Context,\n\t): Promise<HookMap[\"transform_context\"][\"result\"]> {\n\t\tlet messages = event.messages;\n\t\tlet systemPrompt = event.systemPrompt;\n\t\tfor (const registration of this.registrationsFor(\"transform_context\")) {\n\t\t\ttry {\n\t\t\t\tconst result = (await registration.handler(\n\t\t\t\t\t{\n\t\t\t\t\t\t...event,\n\t\t\t\t\t\tmessages,\n\t\t\t\t\t\tsystemPrompt,\n\t\t\t\t\t},\n\t\t\t\t\tcontext,\n\t\t\t\t)) as HookMap[\"transform_context\"][\"result\"];\n\t\t\t\tif (result?.messages !== undefined) messages = result.messages;\n\t\t\t\tif (result?.systemPrompt !== undefined) systemPrompt = result.systemPrompt;\n\t\t\t} catch (error) {\n\t\t\t\tawait this.reportError(\n\t\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\t\t\"transform_context\",\n\t\t\t\t\tevent.lane,\n\t\t\t\t\tcontext,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\treturn { messages, systemPrompt };\n\t}\n\n\tprivate async beforeRequest(\n\t\tevent: HookInvocation<\"before_request\">,\n\t\tcontext: Context,\n\t): Promise<HookMap[\"before_request\"][\"result\"]> {\n\t\tlet streamOptions = event.streamOptions;\n\t\tlet changed = false;\n\t\tfor (const registration of this.registrationsFor(\"before_request\")) {\n\t\t\ttry {\n\t\t\t\tconst result = (await registration.handler(\n\t\t\t\t\t{ ...event, streamOptions },\n\t\t\t\t\tcontext,\n\t\t\t\t)) as HookMap[\"before_request\"][\"result\"];\n\t\t\t\tif (result?.streamOptions !== undefined) {\n\t\t\t\t\tstreamOptions = applyStreamOptionsPatch(streamOptions, result.streamOptions);\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tawait this.reportError(\n\t\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\t\t\"before_request\",\n\t\t\t\t\tevent.lane,\n\t\t\t\t\tcontext,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\treturn changed ? { streamOptions: createStreamOptionsPatch(event.streamOptions, streamOptions) } : undefined;\n\t}\n\n\tprivate async beforePayload(\n\t\tevent: HookInvocation<\"before_payload\">,\n\t\tcontext: Context,\n\t): Promise<HookMap[\"before_payload\"][\"result\"]> {\n\t\tlet payload = event.payload;\n\t\tfor (const registration of this.registrationsFor(\"before_payload\")) {\n\t\t\ttry {\n\t\t\t\tconst result = (await registration.handler(\n\t\t\t\t\t{ ...event, payload },\n\t\t\t\t\tcontext,\n\t\t\t\t)) as HookMap[\"before_payload\"][\"result\"];\n\t\t\t\tif (result?.payload !== undefined) payload = result.payload;\n\t\t\t} catch (error) {\n\t\t\t\tawait this.reportError(\n\t\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\t\t\"before_payload\",\n\t\t\t\t\tevent.lane,\n\t\t\t\t\tcontext,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\treturn { payload };\n\t}\n\n\tprivate async afterResponse(\n\t\tevent: HookInvocation<\"after_response\">,\n\t\tcontext: Context,\n\t): Promise<HookMap[\"after_response\"][\"result\"]> {\n\t\tlet message = event.message;\n\t\tfor (const registration of this.registrationsFor(\"after_response\")) {\n\t\t\ttry {\n\t\t\t\tconst result = (await registration.handler(\n\t\t\t\t\t{ ...event, message },\n\t\t\t\t\tcontext,\n\t\t\t\t)) as HookMap[\"after_response\"][\"result\"];\n\t\t\t\tif (result?.message !== undefined) message = result.message;\n\t\t\t} catch (error) {\n\t\t\t\tawait this.reportError(\n\t\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\t\t\"after_response\",\n\t\t\t\t\tevent.lane,\n\t\t\t\t\tcontext,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\treturn { message };\n\t}\n\n\tprivate async afterTool(\n\t\tevent: HookInvocation<\"after_tool\">,\n\t\tcontext: Context,\n\t): Promise<HookMap[\"after_tool\"][\"result\"]> {\n\t\tlet current = {\n\t\t\tcontent: event.content,\n\t\t\tdetails: event.details,\n\t\t\tisError: event.isError,\n\t\t\tusage: event.usage,\n\t\t};\n\t\tconst aggregate: NonNullable<HookMap[\"after_tool\"][\"result\"]> = {};\n\t\tfor (const registration of this.registrationsFor(\"after_tool\")) {\n\t\t\ttry {\n\t\t\t\tconst result = (await this.invokeToolRegistration(\n\t\t\t\t\t\"after_tool\",\n\t\t\t\t\tregistration,\n\t\t\t\t\t{ ...event, ...current },\n\t\t\t\t\tcontext,\n\t\t\t\t)) as HookMap[\"after_tool\"][\"result\"];\n\t\t\t\tif (result === undefined) continue;\n\t\t\t\tif (result.content !== undefined) aggregate.content = result.content;\n\t\t\t\tif (result.details !== undefined) aggregate.details = result.details;\n\t\t\t\tif (result.isError !== undefined) aggregate.isError = result.isError;\n\t\t\t\tif (result.usage !== undefined) aggregate.usage = result.usage;\n\t\t\t\tif (result.terminate !== undefined) aggregate.terminate = result.terminate;\n\t\t\t\tcurrent = {\n\t\t\t\t\tcontent: result.content === undefined ? current.content : result.content,\n\t\t\t\t\tdetails: result.details === undefined ? current.details : result.details,\n\t\t\t\t\tisError: result.isError === undefined ? current.isError : result.isError,\n\t\t\t\t\tusage: result.usage === undefined ? current.usage : result.usage,\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tawait this.reportError(\n\t\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\t\t\"after_tool\",\n\t\t\t\t\tevent.lane,\n\t\t\t\t\tcontext,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\treturn Object.keys(aggregate).length === 0 ? undefined : aggregate;\n\t}\n\n\tprivate async firstStructural(\n\t\tname: \"before_compaction\" | \"before_navigation\",\n\t\tevent: HookInvocation<\"before_compaction\"> | HookInvocation<\"before_navigation\">,\n\t\tresultField: \"compaction\" | \"summary\",\n\t\tcontext: Context,\n\t): Promise<unknown> {\n\t\tfor (const registration of this.registrationsFor(name)) {\n\t\t\ttry {\n\t\t\t\tconst value = await registration.handler(event, context);\n\t\t\t\tif (value === undefined || value === null || typeof value !== \"object\") continue;\n\t\t\t\tconst result = value as Record<string, unknown>;\n\t\t\t\tif (result.decline === true && result[resultField] !== undefined) {\n\t\t\t\t\tawait this.reportError(\n\t\t\t\t\t\tnew Error(`${name} hook cannot return both decline and ${resultField}`),\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tevent.lane,\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (result.decline === true || result[resultField] !== undefined) return value;\n\t\t\t} catch (error) {\n\t\t\t\tawait this.reportError(\n\t\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\t\tname,\n\t\t\t\t\tevent.lane,\n\t\t\t\t\tcontext,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate invokeToolRegistration(\n\t\tname: \"before_tool\" | \"after_tool\",\n\t\tregistration: HookRegistration,\n\t\tevent: HookInvocation<\"before_tool\"> | HookInvocation<\"after_tool\">,\n\t\tcontext: Context,\n\t): Promise<unknown> {\n\t\treturn startHarnessSpan(\n\t\t\t\"pi.harness.hook\",\n\t\t\t{\n\t\t\t\t\"pi.lane.name\": event.lane,\n\t\t\t\t\"pi.operation.id\": event.runId,\n\t\t\t\t\"pi.hook.name\": name,\n\t\t\t\t...(registration.id === undefined ? {} : { \"pi.hook.registration_id\": registration.id }),\n\t\t\t},\n\t\t\tasync (span, spanContext) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await registration.handler(event, spanContext);\n\t\t\t\t\tconst blocked =\n\t\t\t\t\t\tname === \"before_tool\" &&\n\t\t\t\t\t\tresult !== null &&\n\t\t\t\t\t\ttypeof result === \"object\" &&\n\t\t\t\t\t\t\"block\" in result &&\n\t\t\t\t\t\tresult.block !== undefined;\n\t\t\t\t\tspan.setAttributes({ \"pi.hook.outcome\": blocked ? \"blocked\" : \"completed\" });\n\t\t\t\t\treturn result;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tspan.setAttributes({ \"pi.hook.outcome\": \"failed\" });\n\t\t\t\t\tspan.setStatus({ status: \"error\" });\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t},\n\t\t\tcontext,\n\t\t);\n\t}\n\n\tprivate registrationsFor(name: HookName): HookRegistration[] {\n\t\treturn [...(this.registrations.get(name) ?? [])];\n\t}\n\n\tprivate async invokeAllFailClosed(\n\t\tname: \"before_drive\",\n\t\tevent: HookInvocation<\"before_drive\">,\n\t\tcontext: Context,\n\t): Promise<void> {\n\t\tfor (const registration of this.registrationsFor(name)) {\n\t\t\ttry {\n\t\t\t\tawait registration.handler(event, context);\n\t\t\t} catch (error) {\n\t\t\t\tconst normalized = error instanceof Error ? error : new Error(String(error));\n\t\t\t\tawait this.reportError(normalized, name, event.lane, context);\n\t\t\t\tthrow normalized;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async invokeAll(\n\t\tname: HookName,\n\t\tevent: HookInvocation<HookName>,\n\t\tapply: (value: unknown) => void,\n\t\tcontext: Context,\n\t): Promise<void> {\n\t\tfor (const registration of this.registrationsFor(name)) {\n\t\t\ttry {\n\t\t\t\tapply(await registration.handler(event, context));\n\t\t\t} catch (error) {\n\t\t\t\tawait this.reportError(\n\t\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\t\tname,\n\t\t\t\t\tevent.lane,\n\t\t\t\t\tcontext,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport function applyStreamOptionsPatch(\n\tbase: AgentHarnessStreamOptions,\n\tpatch: AgentHarnessStreamOptionsPatch,\n): AgentHarnessStreamOptions {\n\tconst next: AgentHarnessStreamOptions = { ...base };\n\tfor (const key of [\n\t\t\"transport\",\n\t\t\"timeoutMs\",\n\t\t\"maxRetries\",\n\t\t\"maxRetryDelayMs\",\n\t\t\"cacheRetention\",\n\t\t\"deferred\",\n\t] as const) {\n\t\tif (!(key in patch)) continue;\n\t\tconst value = patch[key];\n\t\tif (value === undefined) delete next[key];\n\t\telse Object.assign(next, { [key]: value });\n\t}\n\tif (\"headers\" in patch) {\n\t\tif (patch.headers === undefined) delete next.headers;\n\t\telse {\n\t\t\tconst headers = { ...next.headers };\n\t\t\tfor (const [key, value] of Object.entries(patch.headers)) {\n\t\t\t\tif (value === undefined) delete headers[key];\n\t\t\t\telse headers[key] = value;\n\t\t\t}\n\t\t\tnext.headers = headers;\n\t\t}\n\t}\n\tif (\"metadata\" in patch) {\n\t\tif (patch.metadata === undefined) delete next.metadata;\n\t\telse {\n\t\t\tconst metadata = { ...next.metadata };\n\t\t\tfor (const [key, value] of Object.entries(patch.metadata)) {\n\t\t\t\tif (value === undefined) delete metadata[key];\n\t\t\t\telse metadata[key] = value;\n\t\t\t}\n\t\t\tnext.metadata = metadata;\n\t\t}\n\t}\n\treturn next;\n}\n\nfunction createStreamOptionsPatch(\n\tbase: AgentHarnessStreamOptions,\n\tvalue: AgentHarnessStreamOptions,\n): AgentHarnessStreamOptionsPatch {\n\tconst patch: AgentHarnessStreamOptionsPatch = {};\n\tfor (const key of [\n\t\t\"transport\",\n\t\t\"timeoutMs\",\n\t\t\"maxRetries\",\n\t\t\"maxRetryDelayMs\",\n\t\t\"cacheRetention\",\n\t\t\"deferred\",\n\t] as const) {\n\t\tif (base[key] !== value[key]) Object.assign(patch, { [key]: value[key] });\n\t}\n\tif (base.headers !== value.headers) {\n\t\tif (value.headers === undefined) patch.headers = undefined;\n\t\telse {\n\t\t\tconst headers: Record<string, string | undefined> = {};\n\t\t\tfor (const key of Object.keys(base.headers ?? {})) {\n\t\t\t\tif (!(key in value.headers)) headers[key] = undefined;\n\t\t\t}\n\t\t\tfor (const [key, header] of Object.entries(value.headers)) {\n\t\t\t\tif (base.headers?.[key] !== header) headers[key] = header;\n\t\t\t}\n\t\t\tif (base.headers === undefined && Object.keys(headers).length === 0) patch.headers = {};\n\t\t\telse if (Object.keys(headers).length !== 0) patch.headers = headers;\n\t\t}\n\t}\n\tif (base.metadata !== value.metadata) {\n\t\tif (value.metadata === undefined) patch.metadata = undefined;\n\t\telse {\n\t\t\tconst metadata: Record<string, unknown | undefined> = {};\n\t\t\tfor (const key of Object.keys(base.metadata ?? {})) {\n\t\t\t\tif (!(key in value.metadata)) metadata[key] = undefined;\n\t\t\t}\n\t\t\tfor (const [key, metadataValue] of Object.entries(value.metadata)) {\n\t\t\t\tif (base.metadata?.[key] !== metadataValue) metadata[key] = metadataValue;\n\t\t\t}\n\t\t\tif (base.metadata === undefined && Object.keys(metadata).length === 0) patch.metadata = {};\n\t\t\telse if (Object.keys(metadata).length !== 0) patch.metadata = metadata;\n\t\t}\n\t}\n\treturn patch;\n}\n"]}
|