@caupulican/pi-adaptative 0.86.2 → 0.86.5
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/CHANGELOG.md +40 -0
- package/dist/core/agent-paths.d.ts +13 -0
- package/dist/core/agent-paths.d.ts.map +1 -1
- package/dist/core/agent-paths.js +23 -0
- package/dist/core/agent-paths.js.map +1 -1
- package/dist/core/autonomy/bounded-completion.d.ts +7 -0
- package/dist/core/autonomy/bounded-completion.d.ts.map +1 -1
- package/dist/core/autonomy/bounded-completion.js +12 -4
- package/dist/core/autonomy/bounded-completion.js.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.d.ts +2 -0
- package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.js +6 -3
- package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
- package/dist/core/autonomy/subagent-prompt.js +1 -1
- package/dist/core/autonomy/subagent-prompt.js.map +1 -1
- package/dist/core/background-lane-controller.d.ts +25 -2
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +67 -0
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/delegation/replay-safe-mailbox-bounds.d.ts +4 -0
- package/dist/core/delegation/replay-safe-mailbox-bounds.d.ts.map +1 -0
- package/dist/core/delegation/replay-safe-mailbox-bounds.js +20 -0
- package/dist/core/delegation/replay-safe-mailbox-bounds.js.map +1 -0
- package/dist/core/delegation/sanitized-context-fork.d.ts +25 -0
- package/dist/core/delegation/sanitized-context-fork.d.ts.map +1 -0
- package/dist/core/delegation/sanitized-context-fork.js +299 -0
- package/dist/core/delegation/sanitized-context-fork.js.map +1 -0
- package/dist/core/delegation/session-root-mailbox.d.ts +75 -0
- package/dist/core/delegation/session-root-mailbox.d.ts.map +1 -0
- package/dist/core/delegation/session-root-mailbox.js +627 -0
- package/dist/core/delegation/session-root-mailbox.js.map +1 -0
- package/dist/core/delegation/worker-agent-control-coordinator.d.ts +102 -9
- package/dist/core/delegation/worker-agent-control-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-agent-control-coordinator.js +1307 -125
- package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-agent-control.d.ts +183 -8
- package/dist/core/delegation/worker-agent-control.d.ts.map +1 -1
- package/dist/core/delegation/worker-agent-control.js +778 -48
- package/dist/core/delegation/worker-agent-control.js.map +1 -1
- package/dist/core/delegation/worker-attempt-executor.d.ts +9 -0
- package/dist/core/delegation/worker-attempt-executor.d.ts.map +1 -1
- package/dist/core/delegation/worker-attempt-executor.js +479 -214
- package/dist/core/delegation/worker-attempt-executor.js.map +1 -1
- package/dist/core/delegation/worker-authority-resolver.d.ts +9 -0
- package/dist/core/delegation/worker-authority-resolver.d.ts.map +1 -1
- package/dist/core/delegation/worker-authority-resolver.js +22 -14
- package/dist/core/delegation/worker-authority-resolver.js.map +1 -1
- package/dist/core/delegation/worker-context-fork-store.d.ts +71 -0
- package/dist/core/delegation/worker-context-fork-store.d.ts.map +1 -0
- package/dist/core/delegation/worker-context-fork-store.js +437 -0
- package/dist/core/delegation/worker-context-fork-store.js.map +1 -0
- package/dist/core/delegation/worker-context-inheritance-policy.d.ts +18 -0
- package/dist/core/delegation/worker-context-inheritance-policy.d.ts.map +1 -0
- package/dist/core/delegation/worker-context-inheritance-policy.js +28 -0
- package/dist/core/delegation/worker-context-inheritance-policy.js.map +1 -0
- package/dist/core/delegation/worker-conversation-revision.d.ts +31 -0
- package/dist/core/delegation/worker-conversation-revision.d.ts.map +1 -0
- package/dist/core/delegation/worker-conversation-revision.js +203 -0
- package/dist/core/delegation/worker-conversation-revision.js.map +1 -0
- package/dist/core/delegation/worker-conversation-store.d.ts +130 -18
- package/dist/core/delegation/worker-conversation-store.d.ts.map +1 -1
- package/dist/core/delegation/worker-conversation-store.js +1263 -79
- package/dist/core/delegation/worker-conversation-store.js.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.d.ts +29 -2
- package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.js +625 -111
- package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
- package/dist/core/delegation/worker-delegation-request.d.ts +2 -0
- package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -1
- package/dist/core/delegation/worker-delegation-request.js.map +1 -1
- package/dist/core/delegation/worker-dispatch-scheduler.d.ts +20 -1
- package/dist/core/delegation/worker-dispatch-scheduler.d.ts.map +1 -1
- package/dist/core/delegation/worker-dispatch-scheduler.js +210 -37
- package/dist/core/delegation/worker-dispatch-scheduler.js.map +1 -1
- package/dist/core/delegation/worker-fleet-limits.d.ts +38 -0
- package/dist/core/delegation/worker-fleet-limits.d.ts.map +1 -0
- package/dist/core/delegation/worker-fleet-limits.js +113 -0
- package/dist/core/delegation/worker-fleet-limits.js.map +1 -0
- package/dist/core/delegation/worker-lane-projection.d.ts +1 -0
- package/dist/core/delegation/worker-lane-projection.d.ts.map +1 -1
- package/dist/core/delegation/worker-lane-projection.js +6 -2
- package/dist/core/delegation/worker-lane-projection.js.map +1 -1
- package/dist/core/delegation/worker-lifecycle.d.ts +20 -3
- package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -1
- package/dist/core/delegation/worker-lifecycle.js +42 -18
- package/dist/core/delegation/worker-lifecycle.js.map +1 -1
- package/dist/core/delegation/worker-notification-coordinator.d.ts +4 -0
- package/dist/core/delegation/worker-notification-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-notification-coordinator.js +45 -4
- package/dist/core/delegation/worker-notification-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-provider-turn-protocol.d.ts +50 -0
- package/dist/core/delegation/worker-provider-turn-protocol.d.ts.map +1 -0
- package/dist/core/delegation/worker-provider-turn-protocol.js +185 -0
- package/dist/core/delegation/worker-provider-turn-protocol.js.map +1 -0
- package/dist/core/delegation/worker-recovery-coordinator.d.ts +45 -4
- package/dist/core/delegation/worker-recovery-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-recovery-coordinator.js +223 -17
- package/dist/core/delegation/worker-recovery-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-retry-policy.d.ts +36 -0
- package/dist/core/delegation/worker-retry-policy.d.ts.map +1 -0
- package/dist/core/delegation/worker-retry-policy.js +41 -0
- package/dist/core/delegation/worker-retry-policy.js.map +1 -0
- package/dist/core/delegation/worker-runner.d.ts +3 -1
- package/dist/core/delegation/worker-runner.d.ts.map +1 -1
- package/dist/core/delegation/worker-runner.js +4 -2
- package/dist/core/delegation/worker-runner.js.map +1 -1
- package/dist/core/delegation/worker-task-view.d.ts +43 -0
- package/dist/core/delegation/worker-task-view.d.ts.map +1 -0
- package/dist/core/delegation/worker-task-view.js +194 -0
- package/dist/core/delegation/worker-task-view.js.map +1 -0
- package/dist/core/delegation/worker-terminal-handoff-coordinator.d.ts +55 -0
- package/dist/core/delegation/worker-terminal-handoff-coordinator.d.ts.map +1 -0
- package/dist/core/delegation/worker-terminal-handoff-coordinator.js +179 -0
- package/dist/core/delegation/worker-terminal-handoff-coordinator.js.map +1 -0
- package/dist/core/delegation/worker-tree-budget-coordinator.d.ts +2 -2
- package/dist/core/delegation/worker-tree-budget-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-tree-budget-coordinator.js +12 -46
- package/dist/core/delegation/worker-tree-budget-coordinator.js.map +1 -1
- package/dist/core/keybindings.d.ts +10 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +2 -0
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/orchestration/attempt-ordering.d.ts +9 -0
- package/dist/core/orchestration/attempt-ordering.d.ts.map +1 -0
- package/dist/core/orchestration/attempt-ordering.js +29 -0
- package/dist/core/orchestration/attempt-ordering.js.map +1 -0
- package/dist/core/orchestration/capability-gateway.d.ts +19 -0
- package/dist/core/orchestration/capability-gateway.d.ts.map +1 -1
- package/dist/core/orchestration/capability-gateway.js +19 -2
- package/dist/core/orchestration/capability-gateway.js.map +1 -1
- package/dist/core/orchestration/contracts.d.ts +43 -3
- package/dist/core/orchestration/contracts.d.ts.map +1 -1
- package/dist/core/orchestration/contracts.js +24 -0
- package/dist/core/orchestration/contracts.js.map +1 -1
- package/dist/core/orchestration/delegation-ledger.d.ts +8 -3
- package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -1
- package/dist/core/orchestration/delegation-ledger.js +148 -55
- package/dist/core/orchestration/delegation-ledger.js.map +1 -1
- package/dist/core/orchestration/event-store.d.ts +6 -3
- package/dist/core/orchestration/event-store.d.ts.map +1 -1
- package/dist/core/orchestration/event-store.js +228 -30
- package/dist/core/orchestration/event-store.js.map +1 -1
- package/dist/core/orchestration/task-runtime-codecs.d.ts +31 -0
- package/dist/core/orchestration/task-runtime-codecs.d.ts.map +1 -0
- package/dist/core/orchestration/task-runtime-codecs.js +1471 -0
- package/dist/core/orchestration/task-runtime-codecs.js.map +1 -0
- package/dist/core/orchestration/task-runtime-projection.d.ts +30 -0
- package/dist/core/orchestration/task-runtime-projection.d.ts.map +1 -0
- package/dist/core/orchestration/task-runtime-projection.js +340 -0
- package/dist/core/orchestration/task-runtime-projection.js.map +1 -0
- package/dist/core/orchestration/task-runtime-reducer.d.ts +38 -0
- package/dist/core/orchestration/task-runtime-reducer.d.ts.map +1 -0
- package/dist/core/orchestration/task-runtime-reducer.js +1270 -0
- package/dist/core/orchestration/task-runtime-reducer.js.map +1 -0
- package/dist/core/orchestration/task-runtime-state.d.ts +142 -0
- package/dist/core/orchestration/task-runtime-state.d.ts.map +1 -0
- package/dist/core/orchestration/task-runtime-state.js +14 -0
- package/dist/core/orchestration/task-runtime-state.js.map +1 -0
- package/dist/core/orchestration/task-runtime.d.ts +44 -98
- package/dist/core/orchestration/task-runtime.d.ts.map +1 -1
- package/dist/core/orchestration/task-runtime.js +357 -1113
- package/dist/core/orchestration/task-runtime.js.map +1 -1
- package/dist/core/orchestration/worker-context-fork-reference.d.ts +20 -0
- package/dist/core/orchestration/worker-context-fork-reference.d.ts.map +1 -0
- package/dist/core/orchestration/worker-context-fork-reference.js +53 -0
- package/dist/core/orchestration/worker-context-fork-reference.js.map +1 -0
- package/dist/core/research/research-runner.d.ts +2 -0
- package/dist/core/research/research-runner.d.ts.map +1 -1
- package/dist/core/research/research-runner.js +1 -0
- package/dist/core/research/research-runner.js.map +1 -1
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +8 -0
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/secrets/credential-project.d.ts.map +1 -1
- package/dist/core/secrets/credential-project.js +24 -2
- package/dist/core/secrets/credential-project.js.map +1 -1
- package/dist/core/security/secret-text.d.ts +3 -0
- package/dist/core/security/secret-text.d.ts.map +1 -1
- package/dist/core/security/secret-text.js +15 -0
- package/dist/core/security/secret-text.js.map +1 -1
- package/dist/core/settings-manager.d.ts +3 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +160 -8
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tools/delegate.d.ts +31 -4
- package/dist/core/tools/delegate.d.ts.map +1 -1
- package/dist/core/tools/delegate.js +751 -98
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +1 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/activity-lane.d.ts +5 -0
- package/dist/modes/interactive/components/activity-lane.d.ts.map +1 -1
- package/dist/modes/interactive/components/activity-lane.js +133 -49
- package/dist/modes/interactive/components/activity-lane.js.map +1 -1
- package/dist/modes/interactive/components/agents-overlay.d.ts +40 -0
- package/dist/modes/interactive/components/agents-overlay.d.ts.map +1 -0
- package/dist/modes/interactive/components/agents-overlay.js +153 -0
- package/dist/modes/interactive/components/agents-overlay.js.map +1 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +18 -13
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-event-controller.d.ts +1 -1
- package/dist/modes/interactive/interactive-event-controller.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-event-controller.js +6 -3
- package/dist/modes/interactive/interactive-event-controller.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +5 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +51 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/key-handlers.d.ts +1 -0
- package/dist/modes/interactive/key-handlers.d.ts.map +1 -1
- package/dist/modes/interactive/key-handlers.js +1 -0
- package/dist/modes/interactive/key-handlers.js.map +1 -1
- package/docs/harness-architecture.md +61 -17
- package/docs/settings.md +17 -9
- package/docs/worker-profiles.md +6 -2
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { MAX_WORKER_CONTEXT_FORK_BYTES, MAX_WORKER_CONTEXT_FORK_MESSAGES, MAX_WORKER_CONTEXT_FORK_TEXT_BLOCKS, } from "../orchestration/worker-context-fork-reference.js";
|
|
2
|
+
export const SANITIZED_CONTEXT_FORK_COMPACTION_PREFIX = "The parent conversation history before this point was compacted into the following checkpoint:\n\n<summary>\n";
|
|
3
|
+
export const SANITIZED_CONTEXT_FORK_COMPACTION_SUFFIX = "\n</summary>\n\n";
|
|
4
|
+
const WORKER_CONTROL_PREFIX = /^\[Worker control worker-message-[^\]\s]+(?: [^\]]+)?\]\r?\n/;
|
|
5
|
+
const MAX_WORKER_CONTROL_PREFIX_CHARS = 2048;
|
|
6
|
+
function invalidMode() {
|
|
7
|
+
return new TypeError("Context fork mode must be none, all, or a positive safe-integer string.");
|
|
8
|
+
}
|
|
9
|
+
/** Parse the eventual tool-facing `fork_turns` wire value without choosing a default policy. */
|
|
10
|
+
export function parseSanitizedContextForkMode(value) {
|
|
11
|
+
const normalized = value.trim().toLowerCase();
|
|
12
|
+
if (normalized === "none")
|
|
13
|
+
return { kind: "none" };
|
|
14
|
+
if (normalized === "all")
|
|
15
|
+
return { kind: "all" };
|
|
16
|
+
if (!/^\d+$/.test(normalized))
|
|
17
|
+
throw invalidMode();
|
|
18
|
+
const count = Number(normalized);
|
|
19
|
+
if (!Number.isSafeInteger(count) || count <= 0)
|
|
20
|
+
throw invalidMode();
|
|
21
|
+
return { kind: "last_user_turns", count };
|
|
22
|
+
}
|
|
23
|
+
function hasCommentaryPhase(textSignature) {
|
|
24
|
+
if (!textSignature?.startsWith("{"))
|
|
25
|
+
return false;
|
|
26
|
+
try {
|
|
27
|
+
const parsed = JSON.parse(textSignature);
|
|
28
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
29
|
+
return false;
|
|
30
|
+
const phase = Object.getOwnPropertyDescriptor(parsed, "phase");
|
|
31
|
+
return phase !== undefined && "value" in phase && phase.value === "commentary";
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function sanitizedTextBlocks(content, dropCommentary) {
|
|
38
|
+
if (content.length > MAX_WORKER_CONTEXT_FORK_TEXT_BLOCKS)
|
|
39
|
+
return { kind: "oversized" };
|
|
40
|
+
const blocks = [];
|
|
41
|
+
let textBytes = 0;
|
|
42
|
+
for (const block of content) {
|
|
43
|
+
if (block.type !== "text" || !block.text.trim())
|
|
44
|
+
continue;
|
|
45
|
+
if (dropCommentary && hasCommentaryPhase(block.textSignature))
|
|
46
|
+
continue;
|
|
47
|
+
textBytes += Buffer.byteLength(block.text, "utf-8");
|
|
48
|
+
if (textBytes > MAX_WORKER_CONTEXT_FORK_BYTES)
|
|
49
|
+
return { kind: "oversized" };
|
|
50
|
+
blocks.push({ type: "text", text: block.text });
|
|
51
|
+
}
|
|
52
|
+
return { kind: "ok", blocks };
|
|
53
|
+
}
|
|
54
|
+
function isWorkerControlUserMessage(message) {
|
|
55
|
+
if (typeof message.content === "string") {
|
|
56
|
+
const newline = message.content.indexOf("\n", 0);
|
|
57
|
+
const prefixEnd = newline >= 0 ? newline + 1 : MAX_WORKER_CONTROL_PREFIX_CHARS;
|
|
58
|
+
return WORKER_CONTROL_PREFIX.test(message.content.slice(0, Math.min(prefixEnd, MAX_WORKER_CONTROL_PREFIX_CHARS)));
|
|
59
|
+
}
|
|
60
|
+
let prefix = "";
|
|
61
|
+
for (const block of message.content) {
|
|
62
|
+
if (block.type !== "text")
|
|
63
|
+
continue;
|
|
64
|
+
const remaining = MAX_WORKER_CONTROL_PREFIX_CHARS - prefix.length;
|
|
65
|
+
if (remaining <= 0)
|
|
66
|
+
return false;
|
|
67
|
+
const newline = block.text.indexOf("\n");
|
|
68
|
+
const blockPrefixEnd = newline >= 0 ? newline + 1 : block.text.length;
|
|
69
|
+
prefix += block.text.slice(0, Math.min(blockPrefixEnd, remaining));
|
|
70
|
+
if (newline >= 0)
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
return WORKER_CONTROL_PREFIX.test(prefix);
|
|
74
|
+
}
|
|
75
|
+
function userBoundaryKind(message) {
|
|
76
|
+
if (isWorkerControlUserMessage(message))
|
|
77
|
+
return "worker_control";
|
|
78
|
+
if (typeof message.content === "string") {
|
|
79
|
+
if (!message.content.trim())
|
|
80
|
+
return "unsupported";
|
|
81
|
+
return Buffer.byteLength(message.content, "utf-8") > MAX_WORKER_CONTEXT_FORK_BYTES ? "oversized" : "eligible";
|
|
82
|
+
}
|
|
83
|
+
if (message.content.length > MAX_WORKER_CONTEXT_FORK_TEXT_BLOCKS)
|
|
84
|
+
return "oversized";
|
|
85
|
+
let hasText = false;
|
|
86
|
+
let textBytes = 0;
|
|
87
|
+
for (const block of message.content) {
|
|
88
|
+
if (block.type !== "text" || !block.text.trim())
|
|
89
|
+
continue;
|
|
90
|
+
hasText = true;
|
|
91
|
+
textBytes += Buffer.byteLength(block.text, "utf-8");
|
|
92
|
+
if (textBytes > MAX_WORKER_CONTEXT_FORK_BYTES)
|
|
93
|
+
return "oversized";
|
|
94
|
+
}
|
|
95
|
+
return hasText ? "eligible" : "unsupported";
|
|
96
|
+
}
|
|
97
|
+
function sanitizeUserMessage(message) {
|
|
98
|
+
const boundary = userBoundaryKind(message);
|
|
99
|
+
if (boundary === "worker_control" || boundary === "unsupported")
|
|
100
|
+
return { kind: "drop" };
|
|
101
|
+
if (boundary === "oversized")
|
|
102
|
+
return { kind: "oversized" };
|
|
103
|
+
if (typeof message.content === "string") {
|
|
104
|
+
return { kind: "ok", message: { role: "user", content: message.content, timestamp: message.timestamp } };
|
|
105
|
+
}
|
|
106
|
+
const sanitized = sanitizedTextBlocks(message.content, false);
|
|
107
|
+
if (sanitized.kind === "oversized")
|
|
108
|
+
return sanitized;
|
|
109
|
+
if (sanitized.blocks.length === 0)
|
|
110
|
+
return { kind: "drop" };
|
|
111
|
+
return { kind: "ok", message: { role: "user", content: sanitized.blocks, timestamp: message.timestamp } };
|
|
112
|
+
}
|
|
113
|
+
function sanitizeCompactionCheckpoint(message) {
|
|
114
|
+
if (typeof message.summary !== "string" || !message.summary.trim())
|
|
115
|
+
return { kind: "invalid" };
|
|
116
|
+
const wrapperBytes = Buffer.byteLength(SANITIZED_CONTEXT_FORK_COMPACTION_PREFIX + SANITIZED_CONTEXT_FORK_COMPACTION_SUFFIX, "utf-8");
|
|
117
|
+
if (Buffer.byteLength(message.summary, "utf-8") > MAX_WORKER_CONTEXT_FORK_BYTES - wrapperBytes) {
|
|
118
|
+
return { kind: "invalid" };
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
kind: "valid",
|
|
122
|
+
text: SANITIZED_CONTEXT_FORK_COMPACTION_PREFIX + message.summary + SANITIZED_CONTEXT_FORK_COMPACTION_SUFFIX,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function attachCompactionCheckpoint(message, checkpoint) {
|
|
126
|
+
const checkpointBlock = { type: "text", text: checkpoint.text };
|
|
127
|
+
return {
|
|
128
|
+
role: "user",
|
|
129
|
+
content: typeof message.content === "string"
|
|
130
|
+
? [checkpointBlock, { type: "text", text: message.content }]
|
|
131
|
+
: [checkpointBlock, ...message.content],
|
|
132
|
+
timestamp: message.timestamp,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Resolve each durable compaction replacement onto its following real user turn. The map is capped
|
|
137
|
+
* at the maximum output size: an older association cannot be selected once that many newer mapped
|
|
138
|
+
* user messages exist, even when every selected turn contains only its user message.
|
|
139
|
+
*/
|
|
140
|
+
function compactionCheckpointsByUserIndex(messages) {
|
|
141
|
+
const checkpoints = new Map();
|
|
142
|
+
let pending;
|
|
143
|
+
for (let index = 0; index < messages.length; index++) {
|
|
144
|
+
const message = messages[index];
|
|
145
|
+
if (message.role === "compactionSummary") {
|
|
146
|
+
pending = sanitizeCompactionCheckpoint(message);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (message.role !== "user" || !pending)
|
|
150
|
+
continue;
|
|
151
|
+
const boundary = userBoundaryKind(message);
|
|
152
|
+
if (boundary === "worker_control")
|
|
153
|
+
continue;
|
|
154
|
+
if (boundary === "eligible")
|
|
155
|
+
checkpoints.set(index, pending);
|
|
156
|
+
pending = undefined;
|
|
157
|
+
if (checkpoints.size > MAX_WORKER_CONTEXT_FORK_MESSAGES) {
|
|
158
|
+
const oldest = checkpoints.keys().next().value;
|
|
159
|
+
if (oldest !== undefined)
|
|
160
|
+
checkpoints.delete(oldest);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return checkpoints;
|
|
164
|
+
}
|
|
165
|
+
function sanitizeAssistantMessage(message) {
|
|
166
|
+
// A length stop, tool request, failure, or abort is not a complete assistant answer.
|
|
167
|
+
if (message.stopReason !== "stop")
|
|
168
|
+
return { kind: "drop" };
|
|
169
|
+
const sanitized = sanitizedTextBlocks(message.content, true);
|
|
170
|
+
if (sanitized.kind === "oversized")
|
|
171
|
+
return sanitized;
|
|
172
|
+
if (sanitized.blocks.length === 0)
|
|
173
|
+
return { kind: "drop" };
|
|
174
|
+
return {
|
|
175
|
+
kind: "ok",
|
|
176
|
+
message: {
|
|
177
|
+
role: "assistant",
|
|
178
|
+
content: sanitized.blocks,
|
|
179
|
+
api: message.api,
|
|
180
|
+
provider: message.provider,
|
|
181
|
+
model: message.model,
|
|
182
|
+
usage: {
|
|
183
|
+
input: message.usage.input,
|
|
184
|
+
output: message.usage.output,
|
|
185
|
+
cacheRead: message.usage.cacheRead,
|
|
186
|
+
cacheWrite: message.usage.cacheWrite,
|
|
187
|
+
totalTokens: message.usage.totalTokens,
|
|
188
|
+
cost: {
|
|
189
|
+
input: message.usage.cost.input,
|
|
190
|
+
output: message.usage.cost.output,
|
|
191
|
+
cacheRead: message.usage.cost.cacheRead,
|
|
192
|
+
cacheWrite: message.usage.cost.cacheWrite,
|
|
193
|
+
total: message.usage.cost.total,
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
stopReason: "stop",
|
|
197
|
+
timestamp: message.timestamp,
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function serializedBytes(messages) {
|
|
202
|
+
return Buffer.byteLength(JSON.stringify(messages), "utf-8");
|
|
203
|
+
}
|
|
204
|
+
function textBlockCount(message) {
|
|
205
|
+
return typeof message.content === "string" ? 1 : message.content.length;
|
|
206
|
+
}
|
|
207
|
+
function requestedTurnCount(mode) {
|
|
208
|
+
if (mode.kind === "none")
|
|
209
|
+
return 0;
|
|
210
|
+
if (mode.kind === "all")
|
|
211
|
+
return Number.POSITIVE_INFINITY;
|
|
212
|
+
if (!Number.isSafeInteger(mode.count) || mode.count <= 0) {
|
|
213
|
+
throw new TypeError("Last-N context fork count must be a positive safe integer.");
|
|
214
|
+
}
|
|
215
|
+
return mode.count;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Select a bounded suffix of complete, sanitized user turns.
|
|
219
|
+
*
|
|
220
|
+
* Selection walks backward so an arbitrarily long source transcript never creates an unbounded
|
|
221
|
+
* second projection. Bounds drop whole oldest turns; no message text is truncated. The result is a
|
|
222
|
+
* detached chronological copy containing no tool protocol, tool results, reasoning, provider
|
|
223
|
+
* signatures, custom/system/developer messages, mailbox controls, or incomplete assistant output.
|
|
224
|
+
*/
|
|
225
|
+
export function selectSanitizedContextFork(messages, mode) {
|
|
226
|
+
const maxTurns = requestedTurnCount(mode);
|
|
227
|
+
if (maxTurns === 0)
|
|
228
|
+
return [];
|
|
229
|
+
const compactionCheckpoints = compactionCheckpointsByUserIndex(messages);
|
|
230
|
+
let selected = [];
|
|
231
|
+
let selectedTurns = 0;
|
|
232
|
+
let selectedTextBlocks = 0;
|
|
233
|
+
let reversedAssistantSuffix = [];
|
|
234
|
+
let reversedAssistantTextBlocks = 0;
|
|
235
|
+
let currentTurnOversized = false;
|
|
236
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
237
|
+
const source = messages[index];
|
|
238
|
+
if (source.role === "assistant") {
|
|
239
|
+
const sanitized = sanitizeAssistantMessage(source);
|
|
240
|
+
if (sanitized.kind === "oversized") {
|
|
241
|
+
currentTurnOversized = true;
|
|
242
|
+
reversedAssistantSuffix = [];
|
|
243
|
+
reversedAssistantTextBlocks = 0;
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
if (sanitized.kind === "drop")
|
|
247
|
+
continue;
|
|
248
|
+
if (currentTurnOversized)
|
|
249
|
+
continue;
|
|
250
|
+
const candidate = [sanitized.message, ...reversedAssistantSuffix];
|
|
251
|
+
const candidateTextBlocks = textBlockCount(sanitized.message) + reversedAssistantTextBlocks;
|
|
252
|
+
if (candidate.length >= MAX_WORKER_CONTEXT_FORK_MESSAGES ||
|
|
253
|
+
serializedBytes(candidate) >= MAX_WORKER_CONTEXT_FORK_BYTES ||
|
|
254
|
+
candidateTextBlocks >= MAX_WORKER_CONTEXT_FORK_TEXT_BLOCKS) {
|
|
255
|
+
currentTurnOversized = true;
|
|
256
|
+
reversedAssistantSuffix = [];
|
|
257
|
+
reversedAssistantTextBlocks = 0;
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
reversedAssistantSuffix = candidate;
|
|
261
|
+
reversedAssistantTextBlocks = candidateTextBlocks;
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
if (source.role !== "user")
|
|
265
|
+
continue;
|
|
266
|
+
const sanitized = sanitizeUserMessage(source);
|
|
267
|
+
if (sanitized.kind === "drop") {
|
|
268
|
+
reversedAssistantSuffix = [];
|
|
269
|
+
reversedAssistantTextBlocks = 0;
|
|
270
|
+
currentTurnOversized = false;
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
if (sanitized.kind === "oversized")
|
|
274
|
+
break;
|
|
275
|
+
const checkpoint = compactionCheckpoints.get(index);
|
|
276
|
+
if (checkpoint?.kind === "invalid")
|
|
277
|
+
break;
|
|
278
|
+
const userMessage = checkpoint ? attachCompactionCheckpoint(sanitized.message, checkpoint) : sanitized.message;
|
|
279
|
+
if (currentTurnOversized)
|
|
280
|
+
break;
|
|
281
|
+
const turn = [userMessage, ...reversedAssistantSuffix];
|
|
282
|
+
const turnTextBlocks = textBlockCount(userMessage) + reversedAssistantTextBlocks;
|
|
283
|
+
const candidate = [...turn, ...selected];
|
|
284
|
+
if (candidate.length > MAX_WORKER_CONTEXT_FORK_MESSAGES ||
|
|
285
|
+
serializedBytes(candidate) > MAX_WORKER_CONTEXT_FORK_BYTES ||
|
|
286
|
+
turnTextBlocks + selectedTextBlocks > MAX_WORKER_CONTEXT_FORK_TEXT_BLOCKS) {
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
selected = candidate;
|
|
290
|
+
selectedTurns += 1;
|
|
291
|
+
selectedTextBlocks += turnTextBlocks;
|
|
292
|
+
if (selectedTurns >= maxTurns)
|
|
293
|
+
break;
|
|
294
|
+
reversedAssistantSuffix = [];
|
|
295
|
+
reversedAssistantTextBlocks = 0;
|
|
296
|
+
}
|
|
297
|
+
return selected;
|
|
298
|
+
}
|
|
299
|
+
//# sourceMappingURL=sanitized-context-fork.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitized-context-fork.js","sourceRoot":"","sources":["../../../src/core/delegation/sanitized-context-fork.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@caupulican/pi-agent-core\";\nimport type { AssistantMessage, TextContent, UserMessage } from \"@caupulican/pi-ai\";\nimport {\n\tMAX_WORKER_CONTEXT_FORK_BYTES,\n\tMAX_WORKER_CONTEXT_FORK_MESSAGES,\n\tMAX_WORKER_CONTEXT_FORK_TEXT_BLOCKS,\n} from \"../orchestration/worker-context-fork-reference.ts\";\n\nexport const SANITIZED_CONTEXT_FORK_COMPACTION_PREFIX =\n\t\"The parent conversation history before this point was compacted into the following checkpoint:\\n\\n<summary>\\n\";\nexport const SANITIZED_CONTEXT_FORK_COMPACTION_SUFFIX = \"\\n</summary>\\n\\n\";\n\nexport type SanitizedContextForkMode = { kind: \"none\" } | { kind: \"all\" } | { kind: \"last_user_turns\"; count: number };\n\nexport type SanitizedContextForkMessage = UserMessage | AssistantMessage;\n\ntype ContextTextCandidate = AssistantMessage[\"content\"][number] | Exclude<UserMessage[\"content\"], string>[number];\n\ntype SanitizedCompactionCheckpoint = { kind: \"valid\"; text: string } | { kind: \"invalid\" };\ntype SanitizedMessageResult<T> = { kind: \"ok\"; message: T } | { kind: \"drop\" } | { kind: \"oversized\" };\ntype UserBoundaryKind = \"eligible\" | \"worker_control\" | \"unsupported\" | \"oversized\";\n\nconst WORKER_CONTROL_PREFIX = /^\\[Worker control worker-message-[^\\]\\s]+(?: [^\\]]+)?\\]\\r?\\n/;\nconst MAX_WORKER_CONTROL_PREFIX_CHARS = 2048;\n\nfunction invalidMode(): TypeError {\n\treturn new TypeError(\"Context fork mode must be none, all, or a positive safe-integer string.\");\n}\n\n/** Parse the eventual tool-facing `fork_turns` wire value without choosing a default policy. */\nexport function parseSanitizedContextForkMode(value: string): SanitizedContextForkMode {\n\tconst normalized = value.trim().toLowerCase();\n\tif (normalized === \"none\") return { kind: \"none\" };\n\tif (normalized === \"all\") return { kind: \"all\" };\n\tif (!/^\\d+$/.test(normalized)) throw invalidMode();\n\tconst count = Number(normalized);\n\tif (!Number.isSafeInteger(count) || count <= 0) throw invalidMode();\n\treturn { kind: \"last_user_turns\", count };\n}\n\nfunction hasCommentaryPhase(textSignature: string | undefined): boolean {\n\tif (!textSignature?.startsWith(\"{\")) return false;\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(textSignature);\n\t\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) return false;\n\t\tconst phase = Object.getOwnPropertyDescriptor(parsed, \"phase\");\n\t\treturn phase !== undefined && \"value\" in phase && phase.value === \"commentary\";\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction sanitizedTextBlocks(\n\tcontent: readonly ContextTextCandidate[],\n\tdropCommentary: boolean,\n): { kind: \"ok\"; blocks: TextContent[] } | { kind: \"oversized\" } {\n\tif (content.length > MAX_WORKER_CONTEXT_FORK_TEXT_BLOCKS) return { kind: \"oversized\" };\n\tconst blocks: TextContent[] = [];\n\tlet textBytes = 0;\n\tfor (const block of content) {\n\t\tif (block.type !== \"text\" || !block.text.trim()) continue;\n\t\tif (dropCommentary && hasCommentaryPhase(block.textSignature)) continue;\n\t\ttextBytes += Buffer.byteLength(block.text, \"utf-8\");\n\t\tif (textBytes > MAX_WORKER_CONTEXT_FORK_BYTES) return { kind: \"oversized\" };\n\t\tblocks.push({ type: \"text\", text: block.text });\n\t}\n\treturn { kind: \"ok\", blocks };\n}\n\nfunction isWorkerControlUserMessage(message: UserMessage): boolean {\n\tif (typeof message.content === \"string\") {\n\t\tconst newline = message.content.indexOf(\"\\n\", 0);\n\t\tconst prefixEnd = newline >= 0 ? newline + 1 : MAX_WORKER_CONTROL_PREFIX_CHARS;\n\t\treturn WORKER_CONTROL_PREFIX.test(message.content.slice(0, Math.min(prefixEnd, MAX_WORKER_CONTROL_PREFIX_CHARS)));\n\t}\n\tlet prefix = \"\";\n\tfor (const block of message.content) {\n\t\tif (block.type !== \"text\") continue;\n\t\tconst remaining = MAX_WORKER_CONTROL_PREFIX_CHARS - prefix.length;\n\t\tif (remaining <= 0) return false;\n\t\tconst newline = block.text.indexOf(\"\\n\");\n\t\tconst blockPrefixEnd = newline >= 0 ? newline + 1 : block.text.length;\n\t\tprefix += block.text.slice(0, Math.min(blockPrefixEnd, remaining));\n\t\tif (newline >= 0) break;\n\t}\n\treturn WORKER_CONTROL_PREFIX.test(prefix);\n}\n\nfunction userBoundaryKind(message: UserMessage): UserBoundaryKind {\n\tif (isWorkerControlUserMessage(message)) return \"worker_control\";\n\tif (typeof message.content === \"string\") {\n\t\tif (!message.content.trim()) return \"unsupported\";\n\t\treturn Buffer.byteLength(message.content, \"utf-8\") > MAX_WORKER_CONTEXT_FORK_BYTES ? \"oversized\" : \"eligible\";\n\t}\n\tif (message.content.length > MAX_WORKER_CONTEXT_FORK_TEXT_BLOCKS) return \"oversized\";\n\tlet hasText = false;\n\tlet textBytes = 0;\n\tfor (const block of message.content) {\n\t\tif (block.type !== \"text\" || !block.text.trim()) continue;\n\t\thasText = true;\n\t\ttextBytes += Buffer.byteLength(block.text, \"utf-8\");\n\t\tif (textBytes > MAX_WORKER_CONTEXT_FORK_BYTES) return \"oversized\";\n\t}\n\treturn hasText ? \"eligible\" : \"unsupported\";\n}\n\nfunction sanitizeUserMessage(message: UserMessage): SanitizedMessageResult<UserMessage> {\n\tconst boundary = userBoundaryKind(message);\n\tif (boundary === \"worker_control\" || boundary === \"unsupported\") return { kind: \"drop\" };\n\tif (boundary === \"oversized\") return { kind: \"oversized\" };\n\tif (typeof message.content === \"string\") {\n\t\treturn { kind: \"ok\", message: { role: \"user\", content: message.content, timestamp: message.timestamp } };\n\t}\n\tconst sanitized = sanitizedTextBlocks(message.content, false);\n\tif (sanitized.kind === \"oversized\") return sanitized;\n\tif (sanitized.blocks.length === 0) return { kind: \"drop\" };\n\treturn { kind: \"ok\", message: { role: \"user\", content: sanitized.blocks, timestamp: message.timestamp } };\n}\n\nfunction sanitizeCompactionCheckpoint(\n\tmessage: Extract<AgentMessage, { role: \"compactionSummary\" }>,\n): SanitizedCompactionCheckpoint {\n\tif (typeof message.summary !== \"string\" || !message.summary.trim()) return { kind: \"invalid\" };\n\tconst wrapperBytes = Buffer.byteLength(\n\t\tSANITIZED_CONTEXT_FORK_COMPACTION_PREFIX + SANITIZED_CONTEXT_FORK_COMPACTION_SUFFIX,\n\t\t\"utf-8\",\n\t);\n\tif (Buffer.byteLength(message.summary, \"utf-8\") > MAX_WORKER_CONTEXT_FORK_BYTES - wrapperBytes) {\n\t\treturn { kind: \"invalid\" };\n\t}\n\treturn {\n\t\tkind: \"valid\",\n\t\ttext: SANITIZED_CONTEXT_FORK_COMPACTION_PREFIX + message.summary + SANITIZED_CONTEXT_FORK_COMPACTION_SUFFIX,\n\t};\n}\n\nfunction attachCompactionCheckpoint(\n\tmessage: UserMessage,\n\tcheckpoint: Extract<SanitizedCompactionCheckpoint, { kind: \"valid\" }>,\n): UserMessage {\n\tconst checkpointBlock: TextContent = { type: \"text\", text: checkpoint.text };\n\treturn {\n\t\trole: \"user\",\n\t\tcontent:\n\t\t\ttypeof message.content === \"string\"\n\t\t\t\t? [checkpointBlock, { type: \"text\", text: message.content }]\n\t\t\t\t: [checkpointBlock, ...message.content],\n\t\ttimestamp: message.timestamp,\n\t};\n}\n\n/**\n * Resolve each durable compaction replacement onto its following real user turn. The map is capped\n * at the maximum output size: an older association cannot be selected once that many newer mapped\n * user messages exist, even when every selected turn contains only its user message.\n */\nfunction compactionCheckpointsByUserIndex(\n\tmessages: readonly AgentMessage[],\n): ReadonlyMap<number, SanitizedCompactionCheckpoint> {\n\tconst checkpoints = new Map<number, SanitizedCompactionCheckpoint>();\n\tlet pending: SanitizedCompactionCheckpoint | undefined;\n\tfor (let index = 0; index < messages.length; index++) {\n\t\tconst message = messages[index]!;\n\t\tif (message.role === \"compactionSummary\") {\n\t\t\tpending = sanitizeCompactionCheckpoint(message);\n\t\t\tcontinue;\n\t\t}\n\t\tif (message.role !== \"user\" || !pending) continue;\n\t\tconst boundary = userBoundaryKind(message);\n\t\tif (boundary === \"worker_control\") continue;\n\t\tif (boundary === \"eligible\") checkpoints.set(index, pending);\n\t\tpending = undefined;\n\t\tif (checkpoints.size > MAX_WORKER_CONTEXT_FORK_MESSAGES) {\n\t\t\tconst oldest = checkpoints.keys().next().value;\n\t\t\tif (oldest !== undefined) checkpoints.delete(oldest);\n\t\t}\n\t}\n\treturn checkpoints;\n}\n\nfunction sanitizeAssistantMessage(message: AssistantMessage): SanitizedMessageResult<AssistantMessage> {\n\t// A length stop, tool request, failure, or abort is not a complete assistant answer.\n\tif (message.stopReason !== \"stop\") return { kind: \"drop\" };\n\tconst sanitized = sanitizedTextBlocks(message.content, true);\n\tif (sanitized.kind === \"oversized\") return sanitized;\n\tif (sanitized.blocks.length === 0) return { kind: \"drop\" };\n\treturn {\n\t\tkind: \"ok\",\n\t\tmessage: {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: sanitized.blocks,\n\t\t\tapi: message.api,\n\t\t\tprovider: message.provider,\n\t\t\tmodel: message.model,\n\t\t\tusage: {\n\t\t\t\tinput: message.usage.input,\n\t\t\t\toutput: message.usage.output,\n\t\t\t\tcacheRead: message.usage.cacheRead,\n\t\t\t\tcacheWrite: message.usage.cacheWrite,\n\t\t\t\ttotalTokens: message.usage.totalTokens,\n\t\t\t\tcost: {\n\t\t\t\t\tinput: message.usage.cost.input,\n\t\t\t\t\toutput: message.usage.cost.output,\n\t\t\t\t\tcacheRead: message.usage.cost.cacheRead,\n\t\t\t\t\tcacheWrite: message.usage.cost.cacheWrite,\n\t\t\t\t\ttotal: message.usage.cost.total,\n\t\t\t\t},\n\t\t\t},\n\t\t\tstopReason: \"stop\",\n\t\t\ttimestamp: message.timestamp,\n\t\t},\n\t};\n}\n\nfunction serializedBytes(messages: readonly SanitizedContextForkMessage[]): number {\n\treturn Buffer.byteLength(JSON.stringify(messages), \"utf-8\");\n}\n\nfunction textBlockCount(message: SanitizedContextForkMessage): number {\n\treturn typeof message.content === \"string\" ? 1 : message.content.length;\n}\n\nfunction requestedTurnCount(mode: SanitizedContextForkMode): number {\n\tif (mode.kind === \"none\") return 0;\n\tif (mode.kind === \"all\") return Number.POSITIVE_INFINITY;\n\tif (!Number.isSafeInteger(mode.count) || mode.count <= 0) {\n\t\tthrow new TypeError(\"Last-N context fork count must be a positive safe integer.\");\n\t}\n\treturn mode.count;\n}\n\n/**\n * Select a bounded suffix of complete, sanitized user turns.\n *\n * Selection walks backward so an arbitrarily long source transcript never creates an unbounded\n * second projection. Bounds drop whole oldest turns; no message text is truncated. The result is a\n * detached chronological copy containing no tool protocol, tool results, reasoning, provider\n * signatures, custom/system/developer messages, mailbox controls, or incomplete assistant output.\n */\nexport function selectSanitizedContextFork(\n\tmessages: readonly AgentMessage[],\n\tmode: SanitizedContextForkMode,\n): SanitizedContextForkMessage[] {\n\tconst maxTurns = requestedTurnCount(mode);\n\tif (maxTurns === 0) return [];\n\tconst compactionCheckpoints = compactionCheckpointsByUserIndex(messages);\n\n\tlet selected: SanitizedContextForkMessage[] = [];\n\tlet selectedTurns = 0;\n\tlet selectedTextBlocks = 0;\n\tlet reversedAssistantSuffix: AssistantMessage[] = [];\n\tlet reversedAssistantTextBlocks = 0;\n\tlet currentTurnOversized = false;\n\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst source = messages[index]!;\n\t\tif (source.role === \"assistant\") {\n\t\t\tconst sanitized = sanitizeAssistantMessage(source);\n\t\t\tif (sanitized.kind === \"oversized\") {\n\t\t\t\tcurrentTurnOversized = true;\n\t\t\t\treversedAssistantSuffix = [];\n\t\t\t\treversedAssistantTextBlocks = 0;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (sanitized.kind === \"drop\") continue;\n\t\t\tif (currentTurnOversized) continue;\n\t\t\tconst candidate = [sanitized.message, ...reversedAssistantSuffix];\n\t\t\tconst candidateTextBlocks = textBlockCount(sanitized.message) + reversedAssistantTextBlocks;\n\t\t\tif (\n\t\t\t\tcandidate.length >= MAX_WORKER_CONTEXT_FORK_MESSAGES ||\n\t\t\t\tserializedBytes(candidate) >= MAX_WORKER_CONTEXT_FORK_BYTES ||\n\t\t\t\tcandidateTextBlocks >= MAX_WORKER_CONTEXT_FORK_TEXT_BLOCKS\n\t\t\t) {\n\t\t\t\tcurrentTurnOversized = true;\n\t\t\t\treversedAssistantSuffix = [];\n\t\t\t\treversedAssistantTextBlocks = 0;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\treversedAssistantSuffix = candidate;\n\t\t\treversedAssistantTextBlocks = candidateTextBlocks;\n\t\t\tcontinue;\n\t\t}\n\t\tif (source.role !== \"user\") continue;\n\t\tconst sanitized = sanitizeUserMessage(source);\n\t\tif (sanitized.kind === \"drop\") {\n\t\t\treversedAssistantSuffix = [];\n\t\t\treversedAssistantTextBlocks = 0;\n\t\t\tcurrentTurnOversized = false;\n\t\t\tcontinue;\n\t\t}\n\t\tif (sanitized.kind === \"oversized\") break;\n\n\t\tconst checkpoint = compactionCheckpoints.get(index);\n\t\tif (checkpoint?.kind === \"invalid\") break;\n\t\tconst userMessage = checkpoint ? attachCompactionCheckpoint(sanitized.message, checkpoint) : sanitized.message;\n\t\tif (currentTurnOversized) break;\n\t\tconst turn: SanitizedContextForkMessage[] = [userMessage, ...reversedAssistantSuffix];\n\t\tconst turnTextBlocks = textBlockCount(userMessage) + reversedAssistantTextBlocks;\n\t\tconst candidate = [...turn, ...selected];\n\t\tif (\n\t\t\tcandidate.length > MAX_WORKER_CONTEXT_FORK_MESSAGES ||\n\t\t\tserializedBytes(candidate) > MAX_WORKER_CONTEXT_FORK_BYTES ||\n\t\t\tturnTextBlocks + selectedTextBlocks > MAX_WORKER_CONTEXT_FORK_TEXT_BLOCKS\n\t\t) {\n\t\t\tbreak;\n\t\t}\n\t\tselected = candidate;\n\t\tselectedTurns += 1;\n\t\tselectedTextBlocks += turnTextBlocks;\n\t\tif (selectedTurns >= maxTurns) break;\n\t\treversedAssistantSuffix = [];\n\t\treversedAssistantTextBlocks = 0;\n\t}\n\n\treturn selected;\n}\n"]}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
export interface SessionRootReply {
|
|
2
|
+
messageId: string;
|
|
3
|
+
sourceAgentId: string;
|
|
4
|
+
requestMessageId: string;
|
|
5
|
+
threadId?: string;
|
|
6
|
+
content: string;
|
|
7
|
+
createdAt: string;
|
|
8
|
+
ackToken: string;
|
|
9
|
+
sourceReconciledAt?: string;
|
|
10
|
+
acknowledgedAt?: string;
|
|
11
|
+
}
|
|
12
|
+
export type SessionRootReplyAcceptance = {
|
|
13
|
+
status: "retained";
|
|
14
|
+
messageId: string;
|
|
15
|
+
reply: SessionRootReply;
|
|
16
|
+
created: boolean;
|
|
17
|
+
} | {
|
|
18
|
+
status: "completed_replay";
|
|
19
|
+
messageId: string;
|
|
20
|
+
created: false;
|
|
21
|
+
};
|
|
22
|
+
export interface SessionRootMailboxOptions {
|
|
23
|
+
agentDir: string;
|
|
24
|
+
parentSessionId: string;
|
|
25
|
+
}
|
|
26
|
+
export interface SessionRootReplyInput {
|
|
27
|
+
sourceAgentId: string;
|
|
28
|
+
requestMessageId: string;
|
|
29
|
+
threadId?: string;
|
|
30
|
+
content: string;
|
|
31
|
+
}
|
|
32
|
+
export interface SessionRootReplyQuery {
|
|
33
|
+
sourceAgentId?: string;
|
|
34
|
+
requestMessageId?: string;
|
|
35
|
+
maxMessages?: number;
|
|
36
|
+
}
|
|
37
|
+
export interface SessionRootReplyWaitOptions extends SessionRootReplyQuery {
|
|
38
|
+
timeoutMs?: number;
|
|
39
|
+
signal?: AbortSignal;
|
|
40
|
+
}
|
|
41
|
+
export interface SessionRootReplyWaitResult {
|
|
42
|
+
replies: SessionRootReply[];
|
|
43
|
+
timedOut: boolean;
|
|
44
|
+
}
|
|
45
|
+
/** Opaque host-owned sender address for root-originated reply-expected worker messages. */
|
|
46
|
+
export declare function sessionRootAddress(parentSessionId: string): string;
|
|
47
|
+
export declare function sessionRootReplyMessageId(parentSessionId: string, sourceAgentId: string, requestMessageId: string): string;
|
|
48
|
+
/** Bounded durable inbox for accepted worker replies addressed to one foreground session root. */
|
|
49
|
+
export declare class SessionRootMailbox {
|
|
50
|
+
private readonly parentSessionId;
|
|
51
|
+
private readonly file;
|
|
52
|
+
constructor(options: SessionRootMailboxOptions);
|
|
53
|
+
/** Validate and size one canonical reply without mutating durable inbox state. */
|
|
54
|
+
assertReplyInput(input: SessionRootReplyInput): void;
|
|
55
|
+
enqueueReply(input: SessionRootReplyInput): SessionRootReplyAcceptance;
|
|
56
|
+
/** Enqueue a reply whose permanent replay authority is the source worker's durable receipt. */
|
|
57
|
+
enqueueSourceOwnedReply(input: SessionRootReplyInput): SessionRootReplyAcceptance;
|
|
58
|
+
private enqueueReplyWithAuthority;
|
|
59
|
+
pendingReplies(query?: SessionRootReplyQuery): SessionRootReply[];
|
|
60
|
+
retainedReplies(): SessionRootReply[];
|
|
61
|
+
getReply(messageId: string): SessionRootReply | undefined;
|
|
62
|
+
markSourceReconciled(messageId: string): boolean;
|
|
63
|
+
releaseSourceReplayReceipt(messageId: string): boolean;
|
|
64
|
+
acknowledge(messageId: string, ackToken: string): boolean;
|
|
65
|
+
waitForReplies(options?: SessionRootReplyWaitOptions): Promise<SessionRootReplyWaitResult>;
|
|
66
|
+
/**
|
|
67
|
+
* Subscribes to process-local mutations for every mailbox instance backed by this file.
|
|
68
|
+
* Callers must unsubscribe; durable cross-process delivery remains the control owner's responsibility.
|
|
69
|
+
*/
|
|
70
|
+
subscribe(listener: () => void): () => void;
|
|
71
|
+
private notify;
|
|
72
|
+
private read;
|
|
73
|
+
private update;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=session-root-mailbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-root-mailbox.d.ts","sourceRoot":"","sources":["../../../src/core/delegation/session-root-mailbox.ts"],"names":[],"mappings":"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"}
|