@code-yeongyu/senpi-agent-core 2026.9.12 → 2026.9.13
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/harness/agent-harness.d.ts +639 -384
- package/dist/harness/agent-harness.d.ts.map +1 -1
- package/dist/harness/agent-harness.js +5 -250
- 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 -27
- 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 -64
- 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 +35 -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 +25 -28
- package/dist/harness/env/nodejs.d.ts.map +1 -1
- package/dist/harness/env/nodejs.js +368 -125
- 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 +233 -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 +48 -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 +404 -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 +39 -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 +173 -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 +34 -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 +302 -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 +118 -0
- package/dist/harness/runtime/lane.d.ts.map +1 -0
- package/dist/harness/runtime/lane.js +1559 -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 +50 -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 -19
- package/dist/harness/session/context.d.ts.map +1 -1
- package/dist/harness/session/context.js +31 -53
- package/dist/harness/session/context.js.map +1 -1
- package/dist/harness/session/fork-policy.d.ts +21 -0
- package/dist/harness/session/fork-policy.d.ts.map +1 -0
- package/dist/harness/session/fork-policy.js +55 -0
- package/dist/harness/session/fork-policy.js.map +1 -0
- package/dist/harness/session/fork.d.ts +16 -0
- package/dist/harness/session/fork.d.ts.map +1 -0
- package/dist/harness/session/fork.js +79 -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 +269 -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 -219
- package/dist/harness/session/jsonl/codec.js.map +1 -1
- package/dist/harness/session/jsonl/fork.d.ts +38 -0
- package/dist/harness/session/jsonl/fork.d.ts.map +1 -0
- package/dist/harness/session/jsonl/fork.js +266 -0
- package/dist/harness/session/jsonl/fork.js.map +1 -0
- 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/io.d.ts +14 -0
- package/dist/harness/session/jsonl/io.d.ts.map +1 -0
- package/dist/harness/session/jsonl/io.js +86 -0
- package/dist/harness/session/jsonl/io.js.map +1 -0
- package/dist/harness/session/jsonl/legacy-v3.d.ts +44 -0
- package/dist/harness/session/jsonl/legacy-v3.d.ts.map +1 -0
- package/dist/harness/session/jsonl/legacy-v3.js +454 -0
- package/dist/harness/session/jsonl/legacy-v3.js.map +1 -0
- package/dist/harness/session/jsonl/repo.d.ts +27 -24
- package/dist/harness/session/jsonl/repo.d.ts.map +1 -1
- package/dist/harness/session/jsonl/repo.js +276 -151
- 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 +175 -196
- 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 +44 -40
- package/dist/harness/session/memory.d.ts.map +1 -1
- package/dist/harness/session/memory.js +333 -115
- 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 +22 -0
- package/dist/harness/session/mutation-line.js.map +1 -0
- package/dist/harness/session/session.d.ts +78 -51
- package/dist/harness/session/session.d.ts.map +1 -1
- package/dist/harness/session/session.js +327 -207
- 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 +23 -0
- package/dist/harness/session/testing/conformance/session-repo.d.ts.map +1 -0
- package/dist/harness/session/testing/conformance/session-repo.js +809 -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 +103 -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 +19 -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 +40 -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 +425 -265
- package/dist/harness/session/types.d.ts.map +1 -1
- package/dist/harness/session/types.js +7 -7
- 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 +17 -13
- 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 +12 -8
- package/dist/harness/tools/write.js.map +1 -1
- package/dist/harness/types.d.ts +128 -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 +19 -5
- package/dist/harness/utils/shell-output.d.ts.map +1 -1
- package/dist/harness/utils/shell-output.js +65 -192
- 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/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 +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +27 -6
- package/dist/harness/reducer.d.ts +0 -100
- package/dist/harness/reducer.d.ts.map +0 -1
- package/dist/harness/reducer.js +0 -420
- 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 -18
- 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 -320
- 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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"}
|
|
@@ -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"}
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import { withAbortSignal } from "./context.js";
|
|
2
|
+
import { startHarnessSpan } from "./telemetry.js";
|
|
3
|
+
/** Ordered harness hook registry and aggregate runner. */
|
|
4
|
+
export class HookRegistry {
|
|
5
|
+
constructor(reportError) {
|
|
6
|
+
this.registrations = new Map();
|
|
7
|
+
this.reportError = reportError;
|
|
8
|
+
}
|
|
9
|
+
on(name, handler, options = {}) {
|
|
10
|
+
if (this.closedError !== undefined)
|
|
11
|
+
throw this.closedError;
|
|
12
|
+
const registrations = this.registrations.get(name) ?? [];
|
|
13
|
+
const registration = {
|
|
14
|
+
...(options.id === undefined ? {} : { id: options.id }),
|
|
15
|
+
handler: (event, context) => handler(event, context),
|
|
16
|
+
};
|
|
17
|
+
registrations.push(registration);
|
|
18
|
+
this.registrations.set(name, registrations);
|
|
19
|
+
return () => {
|
|
20
|
+
const index = registrations.indexOf(registration);
|
|
21
|
+
if (index !== -1)
|
|
22
|
+
registrations.splice(index, 1);
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
has(name) {
|
|
26
|
+
return (this.registrations.get(name)?.length ?? 0) !== 0;
|
|
27
|
+
}
|
|
28
|
+
/** Invoke one accepted-operation aggregate after synchronously passing its effect gate. */
|
|
29
|
+
runWithGate(name, event, gate, context) {
|
|
30
|
+
return gate.admit(() => {
|
|
31
|
+
const admittedContext = withAbortSignal(gate.signal, context);
|
|
32
|
+
admittedContext.abortSignal?.throwIfAborted();
|
|
33
|
+
return this.runAdmitted(name, event, admittedContext);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/** Invoke a tool-hook aggregate with one telemetry span per registered handler. */
|
|
37
|
+
runToolWithGate(name, event, gate, context) {
|
|
38
|
+
return gate.admit(() => {
|
|
39
|
+
const admittedContext = withAbortSignal(gate.signal, context);
|
|
40
|
+
admittedContext.abortSignal?.throwIfAborted();
|
|
41
|
+
return (name === "before_tool"
|
|
42
|
+
? this.beforeTool(event, admittedContext)
|
|
43
|
+
: this.afterTool(event, admittedContext));
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
close(error) {
|
|
47
|
+
this.closedError ??= error;
|
|
48
|
+
}
|
|
49
|
+
async runAdmitted(name, event, context) {
|
|
50
|
+
if (this.closedError !== undefined)
|
|
51
|
+
throw this.closedError;
|
|
52
|
+
const result = await this.aggregate(name, event, context);
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
async aggregate(name, event, context) {
|
|
56
|
+
switch (name) {
|
|
57
|
+
case "before_run":
|
|
58
|
+
return this.beforeRun(event, context);
|
|
59
|
+
case "before_drive":
|
|
60
|
+
await this.invokeAllFailClosed(name, event, context);
|
|
61
|
+
return undefined;
|
|
62
|
+
case "before_run_end": {
|
|
63
|
+
let followUp;
|
|
64
|
+
await this.invokeAll(name, event, (value) => {
|
|
65
|
+
const result = value;
|
|
66
|
+
if (result?.followUp !== undefined)
|
|
67
|
+
followUp = result.followUp;
|
|
68
|
+
}, context);
|
|
69
|
+
return followUp === undefined ? undefined : { followUp };
|
|
70
|
+
}
|
|
71
|
+
case "transform_context":
|
|
72
|
+
return this.transformContext(event, context);
|
|
73
|
+
case "before_request":
|
|
74
|
+
return this.beforeRequest(event, context);
|
|
75
|
+
case "before_payload":
|
|
76
|
+
return this.beforePayload(event, context);
|
|
77
|
+
case "after_response":
|
|
78
|
+
return this.afterResponse(event, context);
|
|
79
|
+
case "before_tool":
|
|
80
|
+
return this.beforeTool(event, context);
|
|
81
|
+
case "after_tool":
|
|
82
|
+
return this.afterTool(event, context);
|
|
83
|
+
case "before_compaction":
|
|
84
|
+
return this.firstStructural(name, event, "compaction", context);
|
|
85
|
+
case "before_navigation":
|
|
86
|
+
return this.firstStructural(name, event, "summary", context);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async beforeRun(event, context) {
|
|
90
|
+
let prompt = event.prompt;
|
|
91
|
+
let injected = [];
|
|
92
|
+
for (const registration of this.registrationsFor("before_run")) {
|
|
93
|
+
try {
|
|
94
|
+
const result = (await registration.handler({ ...event, prompt }, context));
|
|
95
|
+
if (result?.messages !== undefined) {
|
|
96
|
+
injected = [...injected, ...result.messages];
|
|
97
|
+
prompt = [...prompt, ...result.messages];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
await this.reportError(error instanceof Error ? error : new Error(String(error)), "before_run", event.lane, context);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return injected.length === 0 ? undefined : { messages: injected };
|
|
105
|
+
}
|
|
106
|
+
async beforeTool(event, context) {
|
|
107
|
+
let args = event.args;
|
|
108
|
+
let block;
|
|
109
|
+
for (const registration of this.registrationsFor("before_tool")) {
|
|
110
|
+
try {
|
|
111
|
+
const result = (await this.invokeToolRegistration("before_tool", registration, { ...event, args }, context));
|
|
112
|
+
if (result?.args !== undefined)
|
|
113
|
+
args = result.args;
|
|
114
|
+
if (result?.block !== undefined) {
|
|
115
|
+
block = result.block;
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
121
|
+
await this.reportError(normalized, "before_tool", event.lane, context);
|
|
122
|
+
block = { reason: normalized.message };
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
...(args === event.args ? {} : { args }),
|
|
128
|
+
...(block === undefined ? {} : { block }),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
async transformContext(event, context) {
|
|
132
|
+
let messages = event.messages;
|
|
133
|
+
let systemPrompt = event.systemPrompt;
|
|
134
|
+
for (const registration of this.registrationsFor("transform_context")) {
|
|
135
|
+
try {
|
|
136
|
+
const result = (await registration.handler({
|
|
137
|
+
...event,
|
|
138
|
+
messages,
|
|
139
|
+
systemPrompt,
|
|
140
|
+
}, context));
|
|
141
|
+
if (result?.messages !== undefined)
|
|
142
|
+
messages = result.messages;
|
|
143
|
+
if (result?.systemPrompt !== undefined)
|
|
144
|
+
systemPrompt = result.systemPrompt;
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
await this.reportError(error instanceof Error ? error : new Error(String(error)), "transform_context", event.lane, context);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return { messages, systemPrompt };
|
|
151
|
+
}
|
|
152
|
+
async beforeRequest(event, context) {
|
|
153
|
+
let streamOptions = event.streamOptions;
|
|
154
|
+
let changed = false;
|
|
155
|
+
for (const registration of this.registrationsFor("before_request")) {
|
|
156
|
+
try {
|
|
157
|
+
const result = (await registration.handler({ ...event, streamOptions }, context));
|
|
158
|
+
if (result?.streamOptions !== undefined) {
|
|
159
|
+
streamOptions = applyStreamOptionsPatch(streamOptions, result.streamOptions);
|
|
160
|
+
changed = true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
await this.reportError(error instanceof Error ? error : new Error(String(error)), "before_request", event.lane, context);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return changed ? { streamOptions: createStreamOptionsPatch(event.streamOptions, streamOptions) } : undefined;
|
|
168
|
+
}
|
|
169
|
+
async beforePayload(event, context) {
|
|
170
|
+
let payload = event.payload;
|
|
171
|
+
for (const registration of this.registrationsFor("before_payload")) {
|
|
172
|
+
try {
|
|
173
|
+
const result = (await registration.handler({ ...event, payload }, context));
|
|
174
|
+
if (result?.payload !== undefined)
|
|
175
|
+
payload = result.payload;
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
await this.reportError(error instanceof Error ? error : new Error(String(error)), "before_payload", event.lane, context);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return { payload };
|
|
182
|
+
}
|
|
183
|
+
async afterResponse(event, context) {
|
|
184
|
+
let message = event.message;
|
|
185
|
+
for (const registration of this.registrationsFor("after_response")) {
|
|
186
|
+
try {
|
|
187
|
+
const result = (await registration.handler({ ...event, message }, context));
|
|
188
|
+
if (result?.message !== undefined)
|
|
189
|
+
message = result.message;
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
await this.reportError(error instanceof Error ? error : new Error(String(error)), "after_response", event.lane, context);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return { message };
|
|
196
|
+
}
|
|
197
|
+
async afterTool(event, context) {
|
|
198
|
+
let current = {
|
|
199
|
+
content: event.content,
|
|
200
|
+
details: event.details,
|
|
201
|
+
isError: event.isError,
|
|
202
|
+
usage: event.usage,
|
|
203
|
+
};
|
|
204
|
+
const aggregate = {};
|
|
205
|
+
for (const registration of this.registrationsFor("after_tool")) {
|
|
206
|
+
try {
|
|
207
|
+
const result = (await this.invokeToolRegistration("after_tool", registration, { ...event, ...current }, context));
|
|
208
|
+
if (result === undefined)
|
|
209
|
+
continue;
|
|
210
|
+
if (result.content !== undefined)
|
|
211
|
+
aggregate.content = result.content;
|
|
212
|
+
if (result.details !== undefined)
|
|
213
|
+
aggregate.details = result.details;
|
|
214
|
+
if (result.isError !== undefined)
|
|
215
|
+
aggregate.isError = result.isError;
|
|
216
|
+
if (result.usage !== undefined)
|
|
217
|
+
aggregate.usage = result.usage;
|
|
218
|
+
if (result.terminate !== undefined)
|
|
219
|
+
aggregate.terminate = result.terminate;
|
|
220
|
+
current = {
|
|
221
|
+
content: result.content === undefined ? current.content : result.content,
|
|
222
|
+
details: result.details === undefined ? current.details : result.details,
|
|
223
|
+
isError: result.isError === undefined ? current.isError : result.isError,
|
|
224
|
+
usage: result.usage === undefined ? current.usage : result.usage,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
await this.reportError(error instanceof Error ? error : new Error(String(error)), "after_tool", event.lane, context);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return Object.keys(aggregate).length === 0 ? undefined : aggregate;
|
|
232
|
+
}
|
|
233
|
+
async firstStructural(name, event, resultField, context) {
|
|
234
|
+
for (const registration of this.registrationsFor(name)) {
|
|
235
|
+
try {
|
|
236
|
+
const value = await registration.handler(event, context);
|
|
237
|
+
if (value === undefined || value === null || typeof value !== "object")
|
|
238
|
+
continue;
|
|
239
|
+
const result = value;
|
|
240
|
+
if (result.decline === true && result[resultField] !== undefined) {
|
|
241
|
+
await this.reportError(new Error(`${name} hook cannot return both decline and ${resultField}`), name, event.lane, context);
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
if (result.decline === true || result[resultField] !== undefined)
|
|
245
|
+
return value;
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
await this.reportError(error instanceof Error ? error : new Error(String(error)), name, event.lane, context);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return undefined;
|
|
252
|
+
}
|
|
253
|
+
invokeToolRegistration(name, registration, event, context) {
|
|
254
|
+
return startHarnessSpan("pi.harness.hook", {
|
|
255
|
+
"pi.lane.name": event.lane,
|
|
256
|
+
"pi.operation.id": event.runId,
|
|
257
|
+
"pi.hook.name": name,
|
|
258
|
+
...(registration.id === undefined ? {} : { "pi.hook.registration_id": registration.id }),
|
|
259
|
+
}, async (span, spanContext) => {
|
|
260
|
+
try {
|
|
261
|
+
const result = await registration.handler(event, spanContext);
|
|
262
|
+
const blocked = name === "before_tool" &&
|
|
263
|
+
result !== null &&
|
|
264
|
+
typeof result === "object" &&
|
|
265
|
+
"block" in result &&
|
|
266
|
+
result.block !== undefined;
|
|
267
|
+
span.setAttributes({ "pi.hook.outcome": blocked ? "blocked" : "completed" });
|
|
268
|
+
return result;
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
span.setAttributes({ "pi.hook.outcome": "failed" });
|
|
272
|
+
span.setStatus({ status: "error" });
|
|
273
|
+
throw error;
|
|
274
|
+
}
|
|
275
|
+
}, context);
|
|
276
|
+
}
|
|
277
|
+
registrationsFor(name) {
|
|
278
|
+
return [...(this.registrations.get(name) ?? [])];
|
|
279
|
+
}
|
|
280
|
+
async invokeAllFailClosed(name, event, context) {
|
|
281
|
+
for (const registration of this.registrationsFor(name)) {
|
|
282
|
+
try {
|
|
283
|
+
await registration.handler(event, context);
|
|
284
|
+
}
|
|
285
|
+
catch (error) {
|
|
286
|
+
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
287
|
+
await this.reportError(normalized, name, event.lane, context);
|
|
288
|
+
throw normalized;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
async invokeAll(name, event, apply, context) {
|
|
293
|
+
for (const registration of this.registrationsFor(name)) {
|
|
294
|
+
try {
|
|
295
|
+
apply(await registration.handler(event, context));
|
|
296
|
+
}
|
|
297
|
+
catch (error) {
|
|
298
|
+
await this.reportError(error instanceof Error ? error : new Error(String(error)), name, event.lane, context);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
export function applyStreamOptionsPatch(base, patch) {
|
|
304
|
+
const next = { ...base };
|
|
305
|
+
for (const key of [
|
|
306
|
+
"transport",
|
|
307
|
+
"timeoutMs",
|
|
308
|
+
"maxRetries",
|
|
309
|
+
"maxRetryDelayMs",
|
|
310
|
+
"cacheRetention",
|
|
311
|
+
"deferred",
|
|
312
|
+
]) {
|
|
313
|
+
if (!(key in patch))
|
|
314
|
+
continue;
|
|
315
|
+
const value = patch[key];
|
|
316
|
+
if (value === undefined)
|
|
317
|
+
delete next[key];
|
|
318
|
+
else
|
|
319
|
+
Object.assign(next, { [key]: value });
|
|
320
|
+
}
|
|
321
|
+
if ("headers" in patch) {
|
|
322
|
+
if (patch.headers === undefined)
|
|
323
|
+
delete next.headers;
|
|
324
|
+
else {
|
|
325
|
+
const headers = { ...next.headers };
|
|
326
|
+
for (const [key, value] of Object.entries(patch.headers)) {
|
|
327
|
+
if (value === undefined)
|
|
328
|
+
delete headers[key];
|
|
329
|
+
else
|
|
330
|
+
headers[key] = value;
|
|
331
|
+
}
|
|
332
|
+
next.headers = headers;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
if ("metadata" in patch) {
|
|
336
|
+
if (patch.metadata === undefined)
|
|
337
|
+
delete next.metadata;
|
|
338
|
+
else {
|
|
339
|
+
const metadata = { ...next.metadata };
|
|
340
|
+
for (const [key, value] of Object.entries(patch.metadata)) {
|
|
341
|
+
if (value === undefined)
|
|
342
|
+
delete metadata[key];
|
|
343
|
+
else
|
|
344
|
+
metadata[key] = value;
|
|
345
|
+
}
|
|
346
|
+
next.metadata = metadata;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return next;
|
|
350
|
+
}
|
|
351
|
+
function createStreamOptionsPatch(base, value) {
|
|
352
|
+
const patch = {};
|
|
353
|
+
for (const key of [
|
|
354
|
+
"transport",
|
|
355
|
+
"timeoutMs",
|
|
356
|
+
"maxRetries",
|
|
357
|
+
"maxRetryDelayMs",
|
|
358
|
+
"cacheRetention",
|
|
359
|
+
"deferred",
|
|
360
|
+
]) {
|
|
361
|
+
if (base[key] !== value[key])
|
|
362
|
+
Object.assign(patch, { [key]: value[key] });
|
|
363
|
+
}
|
|
364
|
+
if (base.headers !== value.headers) {
|
|
365
|
+
if (value.headers === undefined)
|
|
366
|
+
patch.headers = undefined;
|
|
367
|
+
else {
|
|
368
|
+
const headers = {};
|
|
369
|
+
for (const key of Object.keys(base.headers ?? {})) {
|
|
370
|
+
if (!(key in value.headers))
|
|
371
|
+
headers[key] = undefined;
|
|
372
|
+
}
|
|
373
|
+
for (const [key, header] of Object.entries(value.headers)) {
|
|
374
|
+
if (base.headers?.[key] !== header)
|
|
375
|
+
headers[key] = header;
|
|
376
|
+
}
|
|
377
|
+
if (base.headers === undefined && Object.keys(headers).length === 0)
|
|
378
|
+
patch.headers = {};
|
|
379
|
+
else if (Object.keys(headers).length !== 0)
|
|
380
|
+
patch.headers = headers;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
if (base.metadata !== value.metadata) {
|
|
384
|
+
if (value.metadata === undefined)
|
|
385
|
+
patch.metadata = undefined;
|
|
386
|
+
else {
|
|
387
|
+
const metadata = {};
|
|
388
|
+
for (const key of Object.keys(base.metadata ?? {})) {
|
|
389
|
+
if (!(key in value.metadata))
|
|
390
|
+
metadata[key] = undefined;
|
|
391
|
+
}
|
|
392
|
+
for (const [key, metadataValue] of Object.entries(value.metadata)) {
|
|
393
|
+
if (base.metadata?.[key] !== metadataValue)
|
|
394
|
+
metadata[key] = metadataValue;
|
|
395
|
+
}
|
|
396
|
+
if (base.metadata === undefined && Object.keys(metadata).length === 0)
|
|
397
|
+
patch.metadata = {};
|
|
398
|
+
else if (Object.keys(metadata).length !== 0)
|
|
399
|
+
patch.metadata = metadata;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return patch;
|
|
403
|
+
}
|
|
404
|
+
//# sourceMappingURL=hooks.js.map
|