@bastani/atomic 0.9.28-alpha.1 → 0.9.28-alpha.2
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 +33 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +23 -0
- package/dist/builtin/workflows/builtin/{chunk-wz8v67bn.js → chunk-aqv8ny38.js} +257 -259
- package/dist/builtin/workflows/builtin/{chunk-f61w0hpm.js → chunk-br4ac9a3.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-tecnpe8j.js → chunk-p3xmajmj.js} +438 -39
- package/dist/builtin/workflows/builtin/chunk-p6jagvyf.js +8 -0
- package/dist/builtin/workflows/builtin/goal.js +2 -2
- package/dist/builtin/workflows/builtin/index.js +4 -4
- package/dist/builtin/workflows/builtin/ralph.js +2 -2
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/authoring.d.ts +14 -0
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +107577 -106722
- package/dist/builtin/workflows/src/index.js +42284 -41141
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +16 -11
- package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +16 -1
- package/dist/cli/credential-print.d.ts +1 -1
- package/dist/cli/credential-print.d.ts.map +1 -1
- package/dist/cli/credential-print.js +2 -56
- package/dist/cli/credential-print.js.map +1 -1
- package/dist/core/agent-session-accessors.d.ts.map +1 -1
- package/dist/core/agent-session-accessors.js +6 -1
- package/dist/core/agent-session-accessors.js.map +1 -1
- package/dist/core/agent-session-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-compaction.js +20 -3
- package/dist/core/agent-session-compaction.js.map +1 -1
- package/dist/core/agent-session-events.d.ts.map +1 -1
- package/dist/core/agent-session-events.js +2 -1
- package/dist/core/agent-session-events.js.map +1 -1
- package/dist/core/agent-session-extension-bindings.d.ts +6 -0
- package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
- package/dist/core/agent-session-extension-bindings.js +87 -7
- package/dist/core/agent-session-extension-bindings.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +2 -1
- package/dist/core/agent-session-methods.d.ts.map +1 -1
- package/dist/core/agent-session-methods.js.map +1 -1
- package/dist/core/agent-session-prompt.d.ts.map +1 -1
- package/dist/core/agent-session-prompt.js +14 -1
- package/dist/core/agent-session-prompt.js.map +1 -1
- package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
- package/dist/core/agent-session-tool-registry.js +1 -0
- package/dist/core/agent-session-tool-registry.js.map +1 -1
- package/dist/core/agent-session-types.d.ts +1 -0
- package/dist/core/agent-session-types.d.ts.map +1 -1
- package/dist/core/agent-session-types.js.map +1 -1
- package/dist/core/compaction/classifier-compaction.d.ts +13 -0
- package/dist/core/compaction/classifier-compaction.d.ts.map +1 -0
- package/dist/core/compaction/classifier-compaction.js +110 -0
- package/dist/core/compaction/classifier-compaction.js.map +1 -0
- package/dist/core/compaction/compaction-boundary.d.ts.map +1 -1
- package/dist/core/compaction/compaction-boundary.js +2 -6
- package/dist/core/compaction/compaction-boundary.js.map +1 -1
- package/dist/core/compaction/compaction-runner.d.ts +16 -1
- package/dist/core/compaction/compaction-runner.d.ts.map +1 -1
- package/dist/core/compaction/compaction-runner.js +97 -12
- package/dist/core/compaction/compaction-runner.js.map +1 -1
- package/dist/core/compaction/compaction-types.d.ts +18 -1
- package/dist/core/compaction/compaction-types.d.ts.map +1 -1
- package/dist/core/compaction/compaction-types.js +1 -1
- package/dist/core/compaction/compaction-types.js.map +1 -1
- package/dist/core/compaction/fallback-planner.d.ts +1 -0
- package/dist/core/compaction/fallback-planner.d.ts.map +1 -1
- package/dist/core/compaction/fallback-planner.js +2 -0
- package/dist/core/compaction/fallback-planner.js.map +1 -1
- package/dist/core/compaction/index.d.ts +3 -0
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/index.js +3 -0
- package/dist/core/compaction/index.js.map +1 -1
- package/dist/core/compaction/model-resolver.d.ts +16 -0
- package/dist/core/compaction/model-resolver.d.ts.map +1 -0
- package/dist/core/compaction/model-resolver.js +18 -0
- package/dist/core/compaction/model-resolver.js.map +1 -0
- package/dist/core/compaction/morph-compaction.d.ts +14 -0
- package/dist/core/compaction/morph-compaction.d.ts.map +1 -0
- package/dist/core/compaction/morph-compaction.js +99 -0
- package/dist/core/compaction/morph-compaction.js.map +1 -0
- package/dist/core/compaction/pi-summary-fallback.d.ts +34 -0
- package/dist/core/compaction/pi-summary-fallback.d.ts.map +1 -0
- package/dist/core/compaction/pi-summary-fallback.js +357 -0
- package/dist/core/compaction/pi-summary-fallback.js.map +1 -0
- package/dist/core/compaction/planner-outcome.d.ts +10 -6
- package/dist/core/compaction/planner-outcome.d.ts.map +1 -1
- package/dist/core/compaction/planner-outcome.js +11 -4
- package/dist/core/compaction/planner-outcome.js.map +1 -1
- package/dist/core/compaction/range-planner-diagnostics.d.ts +3 -1
- package/dist/core/compaction/range-planner-diagnostics.d.ts.map +1 -1
- package/dist/core/compaction/range-planner-diagnostics.js +11 -0
- package/dist/core/compaction/range-planner-diagnostics.js.map +1 -1
- package/dist/core/compaction/range-planner.d.ts +3 -3
- package/dist/core/compaction/range-planner.d.ts.map +1 -1
- package/dist/core/compaction/range-planner.js +59 -28
- package/dist/core/compaction/range-planner.js.map +1 -1
- package/dist/core/compaction/region-trimming.d.ts.map +1 -1
- package/dist/core/compaction/region-trimming.js +7 -0
- package/dist/core/compaction/region-trimming.js.map +1 -1
- package/dist/core/compaction/structured-compaction-input.d.ts +19 -0
- package/dist/core/compaction/structured-compaction-input.d.ts.map +1 -0
- package/dist/core/compaction/structured-compaction-input.js +70 -0
- package/dist/core/compaction/structured-compaction-input.js.map +1 -0
- package/dist/core/compaction/transcript-serialization.d.ts +1 -0
- package/dist/core/compaction/transcript-serialization.d.ts.map +1 -1
- package/dist/core/compaction/transcript-serialization.js +26 -0
- package/dist/core/compaction/transcript-serialization.js.map +1 -1
- package/dist/core/extensions/api-types.d.ts +2 -2
- package/dist/core/extensions/api-types.d.ts.map +1 -1
- package/dist/core/extensions/api-types.js.map +1 -1
- package/dist/core/extensions/context-types.d.ts +1 -0
- package/dist/core/extensions/context-types.d.ts.map +1 -1
- package/dist/core/extensions/context-types.js.map +1 -1
- package/dist/core/extensions/loader-api.js.map +1 -1
- package/dist/core/extensions/runner-context.d.ts +10 -4
- package/dist/core/extensions/runner-context.d.ts.map +1 -1
- package/dist/core/extensions/runner-context.js +47 -3
- package/dist/core/extensions/runner-context.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +10 -3
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +31 -7
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/workflow-events.d.ts +49 -0
- package/dist/core/extensions/workflow-events.d.ts.map +1 -1
- package/dist/core/extensions/workflow-events.js.map +1 -1
- package/dist/core/extensions/workflow-run-control-hub.d.ts +16 -4
- package/dist/core/extensions/workflow-run-control-hub.d.ts.map +1 -1
- package/dist/core/extensions/workflow-run-control-hub.js +72 -1
- package/dist/core/extensions/workflow-run-control-hub.js.map +1 -1
- package/dist/core/extensions/workflow-run-control.d.ts +11 -3
- package/dist/core/extensions/workflow-run-control.d.ts.map +1 -1
- package/dist/core/extensions/workflow-run-control.js.map +1 -1
- package/dist/core/messages.d.ts +1 -0
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +5 -1
- package/dist/core/messages.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +3 -0
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/session-manager-history.d.ts.map +1 -1
- package/dist/core/session-manager-history.js +4 -2
- package/dist/core/session-manager-history.js.map +1 -1
- package/dist/core/settings-manager-basic-accessors.d.ts +2 -0
- package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
- package/dist/core/settings-manager-basic-accessors.js +29 -0
- package/dist/core/settings-manager-basic-accessors.js.map +1 -1
- package/dist/core/settings-types.d.ts +1 -0
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/transcript.d.ts +58 -0
- package/dist/core/transcript.d.ts.map +1 -0
- package/dist/core/transcript.js +185 -0
- package/dist/core/transcript.js.map +1 -0
- package/dist/extensions/herdr/index.d.ts.map +1 -1
- package/dist/extensions/herdr/index.js +15 -10
- package/dist/extensions/herdr/index.js.map +1 -1
- package/dist/extensions/herdr/pane-owner.d.ts +6 -2
- package/dist/extensions/herdr/pane-owner.d.ts.map +1 -1
- package/dist/extensions/herdr/pane-owner.js +19 -4
- package/dist/extensions/herdr/pane-owner.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/compaction-boundary-message.d.ts +2 -0
- package/dist/modes/interactive/components/compaction-boundary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-boundary-message.js +15 -3
- package/dist/modes/interactive/components/compaction-boundary-message.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-items.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector-items.js +43 -0
- package/dist/modes/interactive/components/settings-selector-items.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-types.d.ts +6 -0
- package/dist/modes/interactive/components/settings-selector-types.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector-types.js.map +1 -1
- package/dist/modes/interactive/interactive-prompt-turn.js +6 -4
- package/dist/modes/interactive/interactive-prompt-turn.js.map +1 -1
- package/dist/modes/interactive/interactive-render-chat.js +13 -1
- package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
- package/dist/modes/interactive/interactive-selectors.js +8 -0
- package/dist/modes/interactive/interactive-selectors.js.map +1 -1
- package/dist/modes/interactive/interactive-session-runtime.js +2 -0
- package/dist/modes/interactive/interactive-session-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-startup.js +1 -1
- package/dist/modes/interactive/interactive-startup.js.map +1 -1
- package/dist/utils/credential-redaction.d.ts +2 -0
- package/dist/utils/credential-redaction.d.ts.map +1 -0
- package/dist/utils/credential-redaction.js +20 -0
- package/dist/utils/credential-redaction.js.map +1 -0
- package/docs/compaction/reference.md +10 -4
- package/docs/compaction.md +40 -8
- package/docs/docs.json +1 -0
- package/docs/extensions/api-reference.md +4 -0
- package/docs/extensions/events.md +2 -2
- package/docs/providers.md +12 -1
- package/docs/sdk/reference.md +16 -1
- package/docs/sdk/web-server.md +325 -0
- package/docs/sdk.md +83 -1
- package/docs/security.md +1 -1
- package/docs/workflows/api-reference.md +71 -3
- package/docs/workflows/builtins.md +4 -0
- package/docs/workflows/operations.md +12 -4
- package/npm-shrinkwrap.json +32 -32
- package/package.json +3 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"morph-compaction.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/morph-compaction.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AAarG,MAAM,WAAW,qBAAqB;IACrC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,gBAAgB,GAAG,gBAAgB,CAAC;IACtD,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAuCD,wBAAsB,eAAe,CACpC,MAAM,EAAE,cAAc,EACtB,UAAU,EAAE,4BAA4B,EACxC,OAAO,EAAE;IACR,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;IACvB,aAAa,CAAC,EAAE,CAAC,WAAW,EAAE,qBAAqB,KAAK,IAAI,CAAC;CAC7D,GACC,OAAO,CAAC,SAAS,EAAE,CAAC,CAiDtB"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
import { Value } from "typebox/value";
|
|
3
|
+
import { redactCredentialShapes } from "../../utils/credential-redaction.js";
|
|
4
|
+
import { validateDeletedRanges } from "./deleted-ranges.js";
|
|
5
|
+
import { isProviderPolicyRefusal } from "./planner-outcome.js";
|
|
6
|
+
import { buildStructuredCompactionInput, mapMessageRanges } from "./structured-compaction-input.js";
|
|
7
|
+
const responseSchema = Type.Object({
|
|
8
|
+
messages: Type.Array(Type.Object({
|
|
9
|
+
compacted_line_ranges: Type.Array(Type.Object({ start: Type.Number(), end: Type.Number() })),
|
|
10
|
+
})),
|
|
11
|
+
});
|
|
12
|
+
const HTTP_ERROR_EXCERPT_MAX_CHARS = 500;
|
|
13
|
+
const HTTP_ERROR_BODY_MAX_BYTES = 8192;
|
|
14
|
+
async function readHttpErrorBody(response) {
|
|
15
|
+
if (!response.body)
|
|
16
|
+
return "";
|
|
17
|
+
const reader = response.body.getReader();
|
|
18
|
+
const decoder = new TextDecoder();
|
|
19
|
+
let bytes = 0;
|
|
20
|
+
let text = "";
|
|
21
|
+
try {
|
|
22
|
+
while (bytes < HTTP_ERROR_BODY_MAX_BYTES) {
|
|
23
|
+
const { done, value } = await reader.read();
|
|
24
|
+
if (done)
|
|
25
|
+
return text + decoder.decode();
|
|
26
|
+
const remaining = HTTP_ERROR_BODY_MAX_BYTES - bytes;
|
|
27
|
+
text += decoder.decode(value.subarray(0, remaining), { stream: true });
|
|
28
|
+
bytes += value.length;
|
|
29
|
+
}
|
|
30
|
+
const completeLinesEnd = Math.max(0, text.lastIndexOf("\n"));
|
|
31
|
+
return text.slice(0, completeLinesEnd);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return "";
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
await reader.cancel().catch(() => { });
|
|
38
|
+
reader.releaseLock();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function morphHttpErrorMessage(response, apiKey) {
|
|
42
|
+
const body = await readHttpErrorBody(response);
|
|
43
|
+
const excerpt = redactCredentialShapes(body.replaceAll(apiKey, "[redacted]"))
|
|
44
|
+
.replace(/[\x00-\x1f\x7f-\x9f]/g, " ")
|
|
45
|
+
.replace(/\s+/g, " ")
|
|
46
|
+
.trim()
|
|
47
|
+
.slice(0, HTTP_ERROR_EXCERPT_MAX_CHARS);
|
|
48
|
+
return `Morph compaction HTTP ${response.status}${excerpt ? `: ${excerpt}` : ""}`;
|
|
49
|
+
}
|
|
50
|
+
export async function planMorphRanges(region, parameters, options) {
|
|
51
|
+
if (options.signal?.aborted)
|
|
52
|
+
throw new Error("Compaction cancelled");
|
|
53
|
+
if (!options.apiKey)
|
|
54
|
+
throw new Error("Morph compaction requires /login morph or MORPH_API_KEY");
|
|
55
|
+
const input = buildStructuredCompactionInput(region, parameters);
|
|
56
|
+
const response = await (options.fetchFn ?? fetch)("https://api.morphllm.com/v1/compact", {
|
|
57
|
+
method: "POST",
|
|
58
|
+
headers: { Authorization: `Bearer ${options.apiKey}`, "Content-Type": "application/json" },
|
|
59
|
+
body: JSON.stringify({
|
|
60
|
+
messages: input.messages.map((message) => ({ role: message.role, content: message.lines.join("\n") })),
|
|
61
|
+
query: input.query,
|
|
62
|
+
compression_ratio: input.compression_ratio,
|
|
63
|
+
preserve_recent: 0,
|
|
64
|
+
include_markers: false,
|
|
65
|
+
}),
|
|
66
|
+
signal: options.signal,
|
|
67
|
+
});
|
|
68
|
+
if (!response.ok) {
|
|
69
|
+
const message = await morphHttpErrorMessage(response, options.apiKey);
|
|
70
|
+
options.onDiagnostics?.({
|
|
71
|
+
droppedRangeCount: 0,
|
|
72
|
+
acceptedRangeCount: 0,
|
|
73
|
+
failureCategory: isProviderPolicyRefusal(message) ? "policy_refusal" : "provider_error",
|
|
74
|
+
failureMessage: message,
|
|
75
|
+
});
|
|
76
|
+
throw new Error(message);
|
|
77
|
+
}
|
|
78
|
+
const body = await response.json();
|
|
79
|
+
if (!Value.Check(responseSchema, body) || body.messages.length !== input.messages.length)
|
|
80
|
+
throw new Error("Malformed Morph compaction response");
|
|
81
|
+
let droppedRangeCount = 0;
|
|
82
|
+
const records = body.messages.flatMap((message, index) => message.compacted_line_ranges.flatMap((range) => {
|
|
83
|
+
if (!Number.isSafeInteger(range.start) ||
|
|
84
|
+
!Number.isSafeInteger(range.end) ||
|
|
85
|
+
range.start < 1 ||
|
|
86
|
+
range.end < range.start ||
|
|
87
|
+
range.end > input.messages[index].lines.length) {
|
|
88
|
+
droppedRangeCount++;
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
return [{ id: input.messages[index].id, ...range }];
|
|
92
|
+
}));
|
|
93
|
+
options.onDiagnostics?.({ droppedRangeCount, acceptedRangeCount: records.length });
|
|
94
|
+
const ranges = validateDeletedRanges(mapMessageRanges(records, input), region);
|
|
95
|
+
if (!ranges.length)
|
|
96
|
+
throw new Error("Morph compaction produced no usable ranges");
|
|
97
|
+
return [...ranges];
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=morph-compaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"morph-compaction.js","sourceRoot":"","sources":["../../../src/core/compaction/morph-compaction.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport { Value } from \"typebox/value\";\nimport { redactCredentialShapes } from \"../../utils/credential-redaction.js\";\nimport type { LineRange, NumberedRegion, VerbatimCompactionParameters } from \"./compaction-types.js\";\nimport { validateDeletedRanges } from \"./deleted-ranges.js\";\nimport { isProviderPolicyRefusal } from \"./planner-outcome.js\";\nimport { buildStructuredCompactionInput, mapMessageRanges } from \"./structured-compaction-input.js\";\n\nconst responseSchema = Type.Object({\n\tmessages: Type.Array(\n\t\tType.Object({\n\t\t\tcompacted_line_ranges: Type.Array(Type.Object({ start: Type.Number(), end: Type.Number() })),\n\t\t}),\n\t),\n});\n\nexport interface MorphRangeDiagnostics {\n\tdroppedRangeCount: number;\n\tacceptedRangeCount: number;\n\tfailureCategory?: \"provider_error\" | \"policy_refusal\";\n\tfailureMessage?: string;\n}\n\nconst HTTP_ERROR_EXCERPT_MAX_CHARS = 500;\nconst HTTP_ERROR_BODY_MAX_BYTES = 8192;\n\nasync function readHttpErrorBody(response: Response): Promise<string> {\n\tif (!response.body) return \"\";\n\tconst reader = response.body.getReader();\n\tconst decoder = new TextDecoder();\n\tlet bytes = 0;\n\tlet text = \"\";\n\ttry {\n\t\twhile (bytes < HTTP_ERROR_BODY_MAX_BYTES) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) return text + decoder.decode();\n\t\t\tconst remaining = HTTP_ERROR_BODY_MAX_BYTES - bytes;\n\t\t\ttext += decoder.decode(value.subarray(0, remaining), { stream: true });\n\t\t\tbytes += value.length;\n\t\t}\n\t\tconst completeLinesEnd = Math.max(0, text.lastIndexOf(\"\\n\"));\n\t\treturn text.slice(0, completeLinesEnd);\n\t} catch {\n\t\treturn \"\";\n\t} finally {\n\t\tawait reader.cancel().catch(() => {});\n\t\treader.releaseLock();\n\t}\n}\n\nasync function morphHttpErrorMessage(response: Response, apiKey: string): Promise<string> {\n\tconst body = await readHttpErrorBody(response);\n\tconst excerpt = redactCredentialShapes(body.replaceAll(apiKey, \"[redacted]\"))\n\t\t.replace(/[\\x00-\\x1f\\x7f-\\x9f]/g, \" \")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim()\n\t\t.slice(0, HTTP_ERROR_EXCERPT_MAX_CHARS);\n\treturn `Morph compaction HTTP ${response.status}${excerpt ? `: ${excerpt}` : \"\"}`;\n}\n\nexport async function planMorphRanges(\n\tregion: NumberedRegion,\n\tparameters: VerbatimCompactionParameters,\n\toptions: {\n\t\tapiKey: string | undefined;\n\t\tsignal?: AbortSignal;\n\t\tfetchFn?: typeof fetch;\n\t\tonDiagnostics?: (diagnostics: MorphRangeDiagnostics) => void;\n\t},\n): Promise<LineRange[]> {\n\tif (options.signal?.aborted) throw new Error(\"Compaction cancelled\");\n\tif (!options.apiKey) throw new Error(\"Morph compaction requires /login morph or MORPH_API_KEY\");\n\tconst input = buildStructuredCompactionInput(region, parameters);\n\tconst response = await (options.fetchFn ?? fetch)(\"https://api.morphllm.com/v1/compact\", {\n\t\tmethod: \"POST\",\n\t\theaders: { Authorization: `Bearer ${options.apiKey}`, \"Content-Type\": \"application/json\" },\n\t\tbody: JSON.stringify({\n\t\t\tmessages: input.messages.map((message) => ({ role: message.role, content: message.lines.join(\"\\n\") })),\n\t\t\tquery: input.query,\n\t\t\tcompression_ratio: input.compression_ratio,\n\t\t\tpreserve_recent: 0,\n\t\t\tinclude_markers: false,\n\t\t}),\n\t\tsignal: options.signal,\n\t});\n\tif (!response.ok) {\n\t\tconst message = await morphHttpErrorMessage(response, options.apiKey);\n\t\toptions.onDiagnostics?.({\n\t\t\tdroppedRangeCount: 0,\n\t\t\tacceptedRangeCount: 0,\n\t\t\tfailureCategory: isProviderPolicyRefusal(message) ? \"policy_refusal\" : \"provider_error\",\n\t\t\tfailureMessage: message,\n\t\t});\n\t\tthrow new Error(message);\n\t}\n\tconst body: Static<typeof responseSchema> = await response.json();\n\tif (!Value.Check(responseSchema, body) || body.messages.length !== input.messages.length)\n\t\tthrow new Error(\"Malformed Morph compaction response\");\n\tlet droppedRangeCount = 0;\n\tconst records = body.messages.flatMap((message, index) =>\n\t\tmessage.compacted_line_ranges.flatMap((range) => {\n\t\t\tif (\n\t\t\t\t!Number.isSafeInteger(range.start) ||\n\t\t\t\t!Number.isSafeInteger(range.end) ||\n\t\t\t\trange.start < 1 ||\n\t\t\t\trange.end < range.start ||\n\t\t\t\trange.end > input.messages[index].lines.length\n\t\t\t) {\n\t\t\t\tdroppedRangeCount++;\n\t\t\t\treturn [];\n\t\t\t}\n\t\t\treturn [{ id: input.messages[index].id, ...range }];\n\t\t}),\n\t);\n\toptions.onDiagnostics?.({ droppedRangeCount, acceptedRangeCount: records.length });\n\tconst ranges = validateDeletedRanges(mapMessageRanges(records, input), region);\n\tif (!ranges.length) throw new Error(\"Morph compaction produced no usable ranges\");\n\treturn [...ranges];\n}\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Usage } from "@bastani/pi-ai/compat";
|
|
2
|
+
import type { AgentMessage } from "@earendil-works/pi-agent-core";
|
|
3
|
+
import { type SessionEntry } from "../session-manager.ts";
|
|
4
|
+
import type { BorrowedPlanner } from "./compaction-types.js";
|
|
5
|
+
import { type RangePlannerOptions } from "./range-planner.js";
|
|
6
|
+
import { type FileOperations } from "./utils.ts";
|
|
7
|
+
export interface PiSummarySettings {
|
|
8
|
+
reserveTokens: number;
|
|
9
|
+
keepRecentTokens?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface PiSummaryPreparation {
|
|
12
|
+
firstKeptEntryId: string;
|
|
13
|
+
messagesToSummarize: AgentMessage[];
|
|
14
|
+
turnPrefixMessages: AgentMessage[];
|
|
15
|
+
previousSummary?: string;
|
|
16
|
+
tokensBefore: number;
|
|
17
|
+
keptTailTokens: number;
|
|
18
|
+
fileOps: FileOperations;
|
|
19
|
+
settings: PiSummarySettings;
|
|
20
|
+
}
|
|
21
|
+
export interface PiSummaryResult {
|
|
22
|
+
summary: string;
|
|
23
|
+
firstKeptEntryId: string;
|
|
24
|
+
tokensBefore: number;
|
|
25
|
+
tokensAfter: number;
|
|
26
|
+
readFiles: string[];
|
|
27
|
+
modifiedFiles: string[];
|
|
28
|
+
usage: Usage;
|
|
29
|
+
}
|
|
30
|
+
export declare function preparePiSummaryCompaction(pathEntries: SessionEntry[], settings: PiSummarySettings): PiSummaryPreparation | undefined;
|
|
31
|
+
export declare function runPiSummaryFallback(entries: SessionEntry[], settings: PiSummarySettings, planner: BorrowedPlanner, options: RangePlannerOptions & {
|
|
32
|
+
signal?: AbortSignal;
|
|
33
|
+
}): Promise<PiSummaryResult>;
|
|
34
|
+
//# sourceMappingURL=pi-summary-fallback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-summary-fallback.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/pi-summary-fallback.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAoB,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAElE,OAAO,EAGN,KAAK,YAAY,EAEjB,MAAM,uBAAuB,CAAC;AAI/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,OAAO,EAAuB,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEnF,OAAO,EAIN,KAAK,cAAc,EAInB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,iBAAiB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B;AACD,MAAM,WAAW,oBAAoB;IACpC,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,YAAY,EAAE,CAAC;IACpC,kBAAkB,EAAE,YAAY,EAAE,CAAC;IACnC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,cAAc,CAAC;IACxB,QAAQ,EAAE,iBAAiB,CAAC;CAC5B;AACD,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,KAAK,EAAE,KAAK,CAAC;CACb;AA0DD,wBAAgB,0BAA0B,CACzC,WAAW,EAAE,YAAY,EAAE,EAC3B,QAAQ,EAAE,iBAAiB,GACzB,oBAAoB,GAAG,SAAS,CAgHlC;AAwFD,wBAAsB,oBAAoB,CACzC,OAAO,EAAE,YAAY,EAAE,EACvB,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,mBAAmB,GAAG;IAAE,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,GACrD,OAAO,CAAC,eAAe,CAAC,CA+G1B"}
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { normalizeContext, retryAssistantCall, uuidv7 } from "@bastani/pi-ai";
|
|
2
|
+
import { convertToLlm } from "../messages.js";
|
|
3
|
+
import { buildSessionProjection, sessionEntryToContextMessages, } from "../session-manager.js";
|
|
4
|
+
import { applyContextEdit, buildContextEntries, collectContextEdits } from "../session-manager-history.js";
|
|
5
|
+
import { combineUsage } from "../usage-totals.js";
|
|
6
|
+
import { estimateProjectedContextTokens } from "./compaction.js";
|
|
7
|
+
import { classifyPlannerFailure, isProviderPolicyRefusalResponse, syntheticErrorResponse } from "./planner-outcome.js";
|
|
8
|
+
import { plannerRequestModel } from "./range-planner.js";
|
|
9
|
+
import { writeDiagnosticSidecar } from "./range-planner-diagnostics.js";
|
|
10
|
+
import { computeFileLists, createFileOps, extractFileOpsFromMessage, formatFileOperations, SUMMARIZATION_SYSTEM_PROMPT, serializeConversation, } from "./utils.js";
|
|
11
|
+
function estimatePiContentChars(content) {
|
|
12
|
+
if (typeof content === "string")
|
|
13
|
+
return content.length;
|
|
14
|
+
let chars = 0;
|
|
15
|
+
for (const block of content) {
|
|
16
|
+
if (block.type === "text" && block.text)
|
|
17
|
+
chars += block.text.length;
|
|
18
|
+
else if (block.type === "image")
|
|
19
|
+
chars += 4800;
|
|
20
|
+
}
|
|
21
|
+
return chars;
|
|
22
|
+
}
|
|
23
|
+
function estimatePiTokens(message) {
|
|
24
|
+
let chars = 0;
|
|
25
|
+
switch (message.role) {
|
|
26
|
+
case "system":
|
|
27
|
+
chars = estimatePiContentChars(message.content);
|
|
28
|
+
for (const section of Object.values(message.sections ?? {}))
|
|
29
|
+
if (section)
|
|
30
|
+
chars += section.length;
|
|
31
|
+
if (message.toolsAdded)
|
|
32
|
+
chars += JSON.stringify(message.toolsAdded).length;
|
|
33
|
+
break;
|
|
34
|
+
case "user":
|
|
35
|
+
case "custom":
|
|
36
|
+
case "toolResult":
|
|
37
|
+
chars = estimatePiContentChars(message.content);
|
|
38
|
+
break;
|
|
39
|
+
case "assistant":
|
|
40
|
+
for (const block of message.content) {
|
|
41
|
+
if (block.type === "text")
|
|
42
|
+
chars += block.text.length;
|
|
43
|
+
else if (block.type === "thinking")
|
|
44
|
+
chars += block.thinking.length;
|
|
45
|
+
else if (block.type === "toolCall")
|
|
46
|
+
chars += block.name.length + JSON.stringify(block.arguments).length;
|
|
47
|
+
}
|
|
48
|
+
break;
|
|
49
|
+
case "bashExecution":
|
|
50
|
+
chars = message.command.length + message.output.length;
|
|
51
|
+
break;
|
|
52
|
+
case "branchSummary":
|
|
53
|
+
chars = message.summary.length;
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
return Math.ceil(chars / 4);
|
|
57
|
+
}
|
|
58
|
+
function startsTurn(entry) {
|
|
59
|
+
return (entry.sourceEntry.type !== "compaction" &&
|
|
60
|
+
entry.messages.some((message) => message.role === "user" ||
|
|
61
|
+
message.role === "bashExecution" ||
|
|
62
|
+
message.role === "custom" ||
|
|
63
|
+
message.role === "branchSummary"));
|
|
64
|
+
}
|
|
65
|
+
function conversationMessages(entry) {
|
|
66
|
+
return entry.sourceEntry.type === "compaction" ? [] : entry.messages.filter((message) => message.role !== "system");
|
|
67
|
+
}
|
|
68
|
+
export function preparePiSummaryCompaction(pathEntries, settings) {
|
|
69
|
+
if (pathEntries.at(-1)?.type === "compaction")
|
|
70
|
+
return undefined;
|
|
71
|
+
const projection = buildSessionProjection(pathEntries);
|
|
72
|
+
const contextEntries = buildContextEntries(pathEntries);
|
|
73
|
+
const edits = collectContextEdits(contextEntries);
|
|
74
|
+
const entries = contextEntries.map((sourceEntry) => {
|
|
75
|
+
const messages = sessionEntryToContextMessages(sourceEntry);
|
|
76
|
+
const edit = edits.get(sourceEntry.id);
|
|
77
|
+
return { sourceEntry, messages: edit ? applyContextEdit(messages, edit) : messages };
|
|
78
|
+
});
|
|
79
|
+
const previousIndex = entries.findIndex((entry) => entry.sourceEntry.type === "compaction" && entry.messages.length > 0);
|
|
80
|
+
const previous = previousIndex >= 0 ? entries[previousIndex].sourceEntry : undefined;
|
|
81
|
+
const start = previousIndex >= 0 ? previousIndex + 1 : 0;
|
|
82
|
+
const cutPoints = [];
|
|
83
|
+
for (let index = start; index < entries.length; index++) {
|
|
84
|
+
const entry = entries[index];
|
|
85
|
+
if (entry.sourceEntry.type !== "compaction" &&
|
|
86
|
+
entry.messages.some((message) => message.role !== "toolResult" && message.role !== "system"))
|
|
87
|
+
cutPoints.push(index);
|
|
88
|
+
}
|
|
89
|
+
if (cutPoints.length === 0)
|
|
90
|
+
return undefined;
|
|
91
|
+
let cut = cutPoints[0];
|
|
92
|
+
let tokens = 0;
|
|
93
|
+
let exceededBudget = false;
|
|
94
|
+
for (let index = entries.length - 1; index >= start; index--) {
|
|
95
|
+
const count = entries[index].messages.reduce((sum, message) => sum + estimatePiTokens(message), 0);
|
|
96
|
+
if (count === 0)
|
|
97
|
+
continue;
|
|
98
|
+
tokens += count;
|
|
99
|
+
if (tokens >= (settings.keepRecentTokens ?? 20000)) {
|
|
100
|
+
exceededBudget = true;
|
|
101
|
+
cut = cutPoints.find((candidate) => candidate >= index) ?? cutPoints[cutPoints.length - 1];
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const suffix = entries.slice(cut + 1);
|
|
106
|
+
const intrinsicallyVisible = (entry) => entry.sourceEntry.type !== "context_edit" && sessionEntryToContextMessages(entry.sourceEntry).length > 0;
|
|
107
|
+
const omitted = (entry) => intrinsicallyVisible(entry) && entry.messages.length === 0;
|
|
108
|
+
const omittedIds = new Set(suffix.filter(omitted).map((entry) => entry.sourceEntry.id));
|
|
109
|
+
const externalReplacement = suffix.some((entry) => entry.sourceEntry.type === "context_edit" &&
|
|
110
|
+
entry.sourceEntry.replacement !== null &&
|
|
111
|
+
!omittedIds.has(entry.sourceEntry.targetId));
|
|
112
|
+
if (exceededBudget &&
|
|
113
|
+
!externalReplacement &&
|
|
114
|
+
suffix.some((entry) => entry.sourceEntry.type === "message" && entry.sourceEntry.message.role === "assistant" && omitted(entry)) &&
|
|
115
|
+
suffix.every((entry) => entry.sourceEntry.type !== "compaction" && (!intrinsicallyVisible(entry) || omitted(entry))))
|
|
116
|
+
cut++;
|
|
117
|
+
while (cut > start && entries[cut - 1].sourceEntry.type !== "compaction" && entries[cut - 1].messages.length === 0)
|
|
118
|
+
cut--;
|
|
119
|
+
let turnStart = -1;
|
|
120
|
+
if (!startsTurn(entries[cut])) {
|
|
121
|
+
for (let index = cut; index >= start; index--)
|
|
122
|
+
if (startsTurn(entries[index])) {
|
|
123
|
+
turnStart = index;
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const messagesToSummarize = entries.slice(start, turnStart >= 0 ? turnStart : cut).flatMap(conversationMessages);
|
|
128
|
+
const turnPrefixMessages = turnStart >= 0 ? entries.slice(turnStart, cut).flatMap(conversationMessages) : [];
|
|
129
|
+
if (messagesToSummarize.length === 0 && turnPrefixMessages.length === 0)
|
|
130
|
+
return undefined;
|
|
131
|
+
const fileOps = createFileOps();
|
|
132
|
+
if (previous?.type === "compaction" &&
|
|
133
|
+
!previous.fromHook &&
|
|
134
|
+
previous.details &&
|
|
135
|
+
typeof previous.details === "object") {
|
|
136
|
+
const previousDetails = "summary" in previous.details &&
|
|
137
|
+
typeof previous.details.summary === "object" &&
|
|
138
|
+
previous.details.summary !== null
|
|
139
|
+
? previous.details.summary
|
|
140
|
+
: previous.details;
|
|
141
|
+
for (const [key, target] of [
|
|
142
|
+
["readFiles", fileOps.read],
|
|
143
|
+
["modifiedFiles", fileOps.edited],
|
|
144
|
+
]) {
|
|
145
|
+
if (key in previousDetails) {
|
|
146
|
+
const files = previousDetails[key];
|
|
147
|
+
if (Array.isArray(files))
|
|
148
|
+
for (const file of files)
|
|
149
|
+
if (typeof file === "string")
|
|
150
|
+
target.add(file);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
for (const message of [...messagesToSummarize, ...turnPrefixMessages])
|
|
155
|
+
extractFileOpsFromMessage(message, fileOps);
|
|
156
|
+
return {
|
|
157
|
+
firstKeptEntryId: entries[cut].sourceEntry.id,
|
|
158
|
+
messagesToSummarize,
|
|
159
|
+
turnPrefixMessages,
|
|
160
|
+
previousSummary: previous?.type === "compaction" ? previous.summary : undefined,
|
|
161
|
+
tokensBefore: estimateProjectedContextTokens(projection, pathEntries).tokens,
|
|
162
|
+
keptTailTokens: entries
|
|
163
|
+
.slice(cut)
|
|
164
|
+
.flatMap((entry) => entry.messages)
|
|
165
|
+
.reduce((sum, message) => sum + estimatePiTokens(message), 0),
|
|
166
|
+
fileOps,
|
|
167
|
+
settings,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
const SUMMARIZATION_PROMPT = `The messages above are a conversation to summarize. Create a structured context checkpoint summary that another LLM will use to continue the work.
|
|
171
|
+
|
|
172
|
+
Use this EXACT format:
|
|
173
|
+
|
|
174
|
+
## Goal
|
|
175
|
+
[What is the user trying to accomplish? Can be multiple items if the session covers different tasks.]
|
|
176
|
+
|
|
177
|
+
## Constraints & Preferences
|
|
178
|
+
- [Any constraints, preferences, or requirements mentioned by user]
|
|
179
|
+
- [Or "(none)" if none were mentioned]
|
|
180
|
+
|
|
181
|
+
## Progress
|
|
182
|
+
### Done
|
|
183
|
+
- [x] [Completed tasks/changes]
|
|
184
|
+
|
|
185
|
+
### In Progress
|
|
186
|
+
- [ ] [Current work]
|
|
187
|
+
|
|
188
|
+
### Blocked
|
|
189
|
+
- [Issues preventing progress, if any]
|
|
190
|
+
|
|
191
|
+
## Key Decisions
|
|
192
|
+
- **[Decision]**: [Brief rationale]
|
|
193
|
+
|
|
194
|
+
## Next Steps
|
|
195
|
+
1. [Ordered list of what should happen next]
|
|
196
|
+
|
|
197
|
+
## Critical Context
|
|
198
|
+
- [Any data, examples, or references needed to continue]
|
|
199
|
+
- [Or "(none)" if not applicable]
|
|
200
|
+
|
|
201
|
+
Keep each section concise. Preserve exact file paths, function names, and error messages.`;
|
|
202
|
+
const UPDATE_SUMMARIZATION_PROMPT = `The messages above are NEW conversation messages to incorporate into the existing summary provided in <previous-summary> tags.
|
|
203
|
+
|
|
204
|
+
Update the existing structured summary with new information. RULES:
|
|
205
|
+
- PRESERVE all existing information from the previous summary
|
|
206
|
+
- ADD new progress, decisions, and context from the new messages
|
|
207
|
+
- UPDATE the Progress section: move items from "In Progress" to "Done" when completed
|
|
208
|
+
- UPDATE "Next Steps" based on what was accomplished
|
|
209
|
+
- PRESERVE exact file paths, function names, and error messages
|
|
210
|
+
- If something is no longer relevant, you may remove it
|
|
211
|
+
|
|
212
|
+
Use this EXACT format:
|
|
213
|
+
|
|
214
|
+
## Goal
|
|
215
|
+
[Preserve existing goals, add new ones if the task expanded]
|
|
216
|
+
|
|
217
|
+
## Constraints & Preferences
|
|
218
|
+
- [Preserve existing, add new ones discovered]
|
|
219
|
+
|
|
220
|
+
## Progress
|
|
221
|
+
### Done
|
|
222
|
+
- [x] [Include previously done items AND newly completed items]
|
|
223
|
+
|
|
224
|
+
### In Progress
|
|
225
|
+
- [ ] [Current work - update based on progress]
|
|
226
|
+
|
|
227
|
+
### Blocked
|
|
228
|
+
- [Current blockers - remove if resolved]
|
|
229
|
+
|
|
230
|
+
## Key Decisions
|
|
231
|
+
- **[Decision]**: [Brief rationale] (preserve all previous, add new)
|
|
232
|
+
|
|
233
|
+
## Next Steps
|
|
234
|
+
1. [Update based on current state]
|
|
235
|
+
|
|
236
|
+
## Critical Context
|
|
237
|
+
- [Preserve important context, add new if needed]
|
|
238
|
+
|
|
239
|
+
Keep each section concise. Preserve exact file paths, function names, and error messages.`;
|
|
240
|
+
const TURN_PREFIX_SUMMARIZATION_PROMPT = `The messages above are earlier context from an ongoing conversation. Later messages are stored separately and do not need to be reconstructed.
|
|
241
|
+
|
|
242
|
+
Create a concise checkpoint of the user's request and the progress shown above. This checkpoint will be placed before the later messages so the conversation can continue with the necessary context.
|
|
243
|
+
|
|
244
|
+
## Original Request
|
|
245
|
+
[What did the user ask for?]
|
|
246
|
+
|
|
247
|
+
## Progress So Far
|
|
248
|
+
- [Key decisions and work completed in these messages]
|
|
249
|
+
|
|
250
|
+
## Context Needed to Continue
|
|
251
|
+
- [Information from these messages needed to understand the later work]
|
|
252
|
+
|
|
253
|
+
Only summarize information explicitly present above. Do not infer or recreate later messages.`;
|
|
254
|
+
export async function runPiSummaryFallback(entries, settings, planner, options) {
|
|
255
|
+
const preparation = preparePiSummaryCompaction(entries, settings);
|
|
256
|
+
if (!preparation)
|
|
257
|
+
throw new Error("No compactable history for pi summary fallback");
|
|
258
|
+
const model = plannerRequestModel(planner);
|
|
259
|
+
const summarize = async (messages, prefix, previousSummary) => {
|
|
260
|
+
const text = serializeConversation(convertToLlm(messages));
|
|
261
|
+
const prompt = prefix
|
|
262
|
+
? `# Conversation\n${text}\n\n# Instructions\n${TURN_PREFIX_SUMMARIZATION_PROMPT}`
|
|
263
|
+
: `<conversation>\n${text}\n</conversation>\n\n${previousSummary ? `<previous-summary>\n${previousSummary}\n</previous-summary>\n\n` : ""}${previousSummary ? UPDATE_SUMMARIZATION_PROMPT : SUMMARIZATION_PROMPT}`;
|
|
264
|
+
const context = normalizeContext({
|
|
265
|
+
systemPrompt: SUMMARIZATION_SYSTEM_PROMPT,
|
|
266
|
+
messages: [{ role: "user", content: [{ type: "text", text: prompt }], timestamp: Date.now() }],
|
|
267
|
+
});
|
|
268
|
+
const requestMaxTokens = Math.min(Math.floor((prefix ? 0.5 : 0.8) * settings.reserveTokens), model.maxTokens > 0 ? model.maxTokens : Number.POSITIVE_INFINITY);
|
|
269
|
+
const sessionId = uuidv7();
|
|
270
|
+
let refusal;
|
|
271
|
+
const response = await retryAssistantCall(async () => {
|
|
272
|
+
let result;
|
|
273
|
+
try {
|
|
274
|
+
result = await (await options.streamFn(model, context, {
|
|
275
|
+
apiKey: planner.auth.apiKey,
|
|
276
|
+
headers: planner.auth.headers,
|
|
277
|
+
signal: options.signal,
|
|
278
|
+
cacheRetention: "none",
|
|
279
|
+
sessionId,
|
|
280
|
+
maxTokens: requestMaxTokens,
|
|
281
|
+
...(model.reasoning && planner.budget.reasoning && planner.budget.reasoning !== "off"
|
|
282
|
+
? { reasoning: planner.budget.reasoning }
|
|
283
|
+
: {}),
|
|
284
|
+
})).result();
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
if (options.signal?.aborted)
|
|
288
|
+
throw new Error("Compaction cancelled");
|
|
289
|
+
result = syntheticErrorResponse(model, error instanceof Error ? error.message : String(error));
|
|
290
|
+
}
|
|
291
|
+
options.onUsage?.(result.usage);
|
|
292
|
+
if (isProviderPolicyRefusalResponse(result)) {
|
|
293
|
+
refusal = result;
|
|
294
|
+
return { ...result, stopReason: "stop" };
|
|
295
|
+
}
|
|
296
|
+
return result;
|
|
297
|
+
}, options.retry, options.signal, options.callbacks);
|
|
298
|
+
if (options.signal?.aborted || response.stopReason === "aborted")
|
|
299
|
+
throw new Error("Compaction cancelled");
|
|
300
|
+
if (refusal || response.stopReason === "error") {
|
|
301
|
+
const failedResponse = refusal ?? response;
|
|
302
|
+
const failureMessage = `Summarization failed: ${failedResponse.errorMessage || (refusal ? "The model refused to complete the request" : "Unknown error")}`;
|
|
303
|
+
const failure = classifyPlannerFailure(failedResponse, model.contextWindow);
|
|
304
|
+
const diagnosticPath = writeDiagnosticSidecar({
|
|
305
|
+
sessionFilePath: options.sessionFilePath,
|
|
306
|
+
model,
|
|
307
|
+
requestMaxTokens,
|
|
308
|
+
response: failedResponse,
|
|
309
|
+
rawResponseText: failedResponse.content
|
|
310
|
+
.filter((block) => block.type === "text")
|
|
311
|
+
.map((block) => block.text)
|
|
312
|
+
.join(""),
|
|
313
|
+
failureCategory: failure === "overflow" ? "context_overflow" : failure,
|
|
314
|
+
failureMessage,
|
|
315
|
+
});
|
|
316
|
+
throw new Error(diagnosticPath ? `${failureMessage} (diagnostic: ${diagnosticPath})` : failureMessage);
|
|
317
|
+
}
|
|
318
|
+
if (response.stopReason === "length")
|
|
319
|
+
throw new Error("Summarization failed: generation hit the token cap and the summary is incomplete");
|
|
320
|
+
if (response.content.some((block) => block.type === "toolCall"))
|
|
321
|
+
throw new Error("Summarization attempted to call a tool");
|
|
322
|
+
const summary = response.content
|
|
323
|
+
.filter((block) => block.type === "text")
|
|
324
|
+
.map((block) => block.text)
|
|
325
|
+
.join("\n");
|
|
326
|
+
if (!summary.trim())
|
|
327
|
+
throw new Error("Summarization returned empty text");
|
|
328
|
+
return { text: summary, usage: response.usage };
|
|
329
|
+
};
|
|
330
|
+
let summary;
|
|
331
|
+
let usage;
|
|
332
|
+
if (preparation.turnPrefixMessages.length > 0) {
|
|
333
|
+
const history = preparation.messagesToSummarize.length > 0
|
|
334
|
+
? await summarize(preparation.messagesToSummarize, false, preparation.previousSummary)
|
|
335
|
+
: undefined;
|
|
336
|
+
const prefix = await summarize(preparation.turnPrefixMessages, true);
|
|
337
|
+
summary = `${history?.text ?? preparation.previousSummary ?? "No prior history."}\n\n---\n\n**Turn Context (split turn):**\n\n${prefix.text}`;
|
|
338
|
+
usage = history ? combineUsage(history.usage, prefix.usage) : prefix.usage;
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
const result = await summarize(preparation.messagesToSummarize, false, preparation.previousSummary);
|
|
342
|
+
summary = result.text;
|
|
343
|
+
usage = result.usage;
|
|
344
|
+
}
|
|
345
|
+
const { readFiles, modifiedFiles } = computeFileLists(preparation.fileOps);
|
|
346
|
+
summary += formatFileOperations(readFiles, modifiedFiles);
|
|
347
|
+
return {
|
|
348
|
+
summary,
|
|
349
|
+
firstKeptEntryId: preparation.firstKeptEntryId,
|
|
350
|
+
tokensBefore: preparation.tokensBefore,
|
|
351
|
+
tokensAfter: Math.ceil(summary.length / 4) + preparation.keptTailTokens,
|
|
352
|
+
readFiles,
|
|
353
|
+
modifiedFiles,
|
|
354
|
+
usage,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
//# sourceMappingURL=pi-summary-fallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-summary-fallback.js","sourceRoot":"","sources":["../../../src/core/compaction/pi-summary-fallback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAG9E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EACN,sBAAsB,EAGtB,6BAA6B,GAC7B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAC3G,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,8BAA8B,EAAE,MAAM,iBAAiB,CAAC;AAEjE,OAAO,EAAE,sBAAsB,EAAE,+BAA+B,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACvH,OAAO,EAAE,mBAAmB,EAA4B,MAAM,oBAAoB,CAAC;AACnF,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EACN,gBAAgB,EAChB,aAAa,EACb,yBAAyB,EAEzB,oBAAoB,EACpB,2BAA2B,EAC3B,qBAAqB,GACrB,MAAM,YAAY,CAAC;AA0BpB,SAAS,sBAAsB,CAAC,OAA4D;IAC3F,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC,MAAM,CAAC;IACvD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI;YAAE,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;aAC/D,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO;YAAE,KAAK,IAAI,IAAI,CAAC;IAChD,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAqB;IAC9C,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACtB,KAAK,QAAQ;YACZ,KAAK,GAAG,sBAAsB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAChD,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;gBAAE,IAAI,OAAO;oBAAE,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;YAClG,IAAI,OAAO,CAAC,UAAU;gBAAE,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC;YAC3E,MAAM;QACP,KAAK,MAAM,CAAC;QACZ,KAAK,QAAQ,CAAC;QACd,KAAK,YAAY;YAChB,KAAK,GAAG,sBAAsB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAChD,MAAM;QACP,KAAK,WAAW;YACf,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACrC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;oBAAE,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;qBACjD,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;oBAAE,KAAK,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;qBAC9D,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;oBAAE,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;YACzG,CAAC;YACD,MAAM;QACP,KAAK,eAAe;YACnB,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;YACvD,MAAM;QACP,KAAK,eAAe;YACnB,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;YAC/B,MAAM;IACR,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,UAAU,CAAC,KAA4B;IAC/C,OAAO,CACN,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,YAAY;QACvC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAClB,CAAC,OAAO,EAAE,EAAE,CACX,OAAO,CAAC,IAAI,KAAK,MAAM;YACvB,OAAO,CAAC,IAAI,KAAK,eAAe;YAChC,OAAO,CAAC,IAAI,KAAK,QAAQ;YACzB,OAAO,CAAC,IAAI,KAAK,eAAe,CACjC,CACD,CAAC;AACH,CAAC;AACD,SAAS,oBAAoB,CAAC,KAA4B;IACzD,OAAO,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;AACrH,CAAC;AAED,MAAM,UAAU,0BAA0B,CACzC,WAA2B,EAC3B,QAA2B;IAE3B,IAAI,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,YAAY;QAAE,OAAO,SAAS,CAAC;IAChE,MAAM,UAAU,GAAG,sBAAsB,CAAC,WAAW,CAAC,CAAC;IACvD,MAAM,cAAc,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,mBAAmB,CAAC,cAAc,CAAC,CAAC;IAClD,MAAM,OAAO,GAA4B,cAAc,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE;QAC3E,MAAM,QAAQ,GAAG,6BAA6B,CAAC,WAAW,CAAC,CAAC;QAC5D,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACvC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACtF,CAAC,CAAC,CAAC;IACH,MAAM,aAAa,GAAG,OAAO,CAAC,SAAS,CACtC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAC/E,CAAC;IACF,MAAM,QAAQ,GAAG,aAAa,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;IACrF,MAAM,KAAK,GAAG,aAAa,IAAI,CAAC,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzD,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,KAAK,IAAI,KAAK,GAAG,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QACzD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7B,IACC,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,YAAY;YACvC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,YAAY,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC;YAE5F,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC7C,IAAI,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IACvB,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,cAAc,GAAG,KAAK,CAAC;IAC3B,KAAK,IAAI,KAAK,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC;QAC9D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,GAAG,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;QACnG,IAAI,KAAK,KAAK,CAAC;YAAE,SAAS;QAC1B,MAAM,IAAI,KAAK,CAAC;QAChB,IAAI,MAAM,IAAI,CAAC,QAAQ,CAAC,gBAAgB,IAAI,KAAK,CAAC,EAAE,CAAC;YACpD,cAAc,GAAG,IAAI,CAAC;YACtB,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,IAAI,KAAK,CAAC,IAAI,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC3F,MAAM;QACP,CAAC;IACF,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IACtC,MAAM,oBAAoB,GAAG,CAAC,KAA4B,EAAW,EAAE,CACtE,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,cAAc,IAAI,6BAA6B,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1G,MAAM,OAAO,GAAG,CAAC,KAA4B,EAAW,EAAE,CACzD,oBAAoB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;IACxF,MAAM,mBAAmB,GAAG,MAAM,CAAC,IAAI,CACtC,CAAC,KAAK,EAAE,EAAE,CACT,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,cAAc;QACzC,KAAK,CAAC,WAAW,CAAC,WAAW,KAAK,IAAI;QACtC,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAC5C,CAAC;IACF,IACC,cAAc;QACd,CAAC,mBAAmB;QACpB,MAAM,CAAC,IAAI,CACV,CAAC,KAAK,EAAE,EAAE,CACT,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,CAAC,KAAK,CAAC,CACzG;QACD,MAAM,CAAC,KAAK,CACX,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,CAAC,oBAAoB,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CACtG;QAED,GAAG,EAAE,CAAC;IACP,OAAO,GAAG,GAAG,KAAK,IAAI,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,KAAK,YAAY,IAAI,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QACjH,GAAG,EAAE,CAAC;IACP,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC;IACnB,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAC/B,KAAK,IAAI,KAAK,GAAG,GAAG,EAAE,KAAK,IAAI,KAAK,EAAE,KAAK,EAAE;YAC5C,IAAI,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBAChC,SAAS,GAAG,KAAK,CAAC;gBAClB,MAAM;YACP,CAAC;IACH,CAAC;IACD,MAAM,mBAAmB,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACjH,MAAM,kBAAkB,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7G,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1F,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAChC,IACC,QAAQ,EAAE,IAAI,KAAK,YAAY;QAC/B,CAAC,QAAQ,CAAC,QAAQ;QAClB,QAAQ,CAAC,OAAO;QAChB,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ,EACnC,CAAC;QACF,MAAM,eAAe,GACpB,SAAS,IAAI,QAAQ,CAAC,OAAO;YAC7B,OAAO,QAAQ,CAAC,OAAO,CAAC,OAAO,KAAK,QAAQ;YAC5C,QAAQ,CAAC,OAAO,CAAC,OAAO,KAAK,IAAI;YAChC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO;YAC1B,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;QACrB,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI;YAC3B,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,CAAC;YAC3B,CAAC,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC;SACxB,EAAE,CAAC;YACZ,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;gBAC5B,MAAM,KAAK,GAAI,eAAsE,CAAC,GAAG,CAAC,CAAC;gBAC3F,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;oBAAE,KAAK,MAAM,IAAI,IAAI,KAAK;wBAAE,IAAI,OAAO,IAAI,KAAK,QAAQ;4BAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACpG,CAAC;QACF,CAAC;IACF,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,CAAC,GAAG,mBAAmB,EAAE,GAAG,kBAAkB,CAAC;QAAE,yBAAyB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACnH,OAAO;QACN,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,EAAE;QAC7C,mBAAmB;QACnB,kBAAkB;QAClB,eAAe,EAAE,QAAQ,EAAE,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;QAC/E,YAAY,EAAE,8BAA8B,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,MAAM;QAC5E,cAAc,EAAE,OAAO;aACrB,KAAK,CAAC,GAAG,CAAC;aACV,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC;aAClC,MAAM,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,GAAG,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC9D,OAAO;QACP,QAAQ;KACR,CAAC;AACH,CAAC;AAED,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0FA+B6D,CAAC;AAE3F,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0FAqCsD,CAAC;AAC3F,MAAM,gCAAgC,GAAG;;;;;;;;;;;;;8FAaqD,CAAC;AAE/F,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACzC,OAAuB,EACvB,QAA2B,EAC3B,OAAwB,EACxB,OAAuD;IAEvD,MAAM,WAAW,GAAG,0BAA0B,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAClE,IAAI,CAAC,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACpF,MAAM,KAAK,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,KAAK,EACtB,QAAwB,EACxB,MAAe,EACf,eAAwB,EACkB,EAAE;QAC5C,MAAM,IAAI,GAAG,qBAAqB,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC3D,MAAM,MAAM,GAAG,MAAM;YACpB,CAAC,CAAC,mBAAmB,IAAI,uBAAuB,gCAAgC,EAAE;YAClF,CAAC,CAAC,mBAAmB,IAAI,wBAAwB,eAAe,CAAC,CAAC,CAAC,uBAAuB,eAAe,2BAA2B,CAAC,CAAC,CAAC,EAAE,GAAG,eAAe,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,oBAAoB,EAAE,CAAC;QACpN,MAAM,OAAO,GAAG,gBAAgB,CAAC;YAChC,YAAY,EAAE,2BAA2B;YACzC,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;SAC9F,CAAC,CAAC;QACH,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAChC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,EACzD,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAChE,CAAC;QACF,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC;QAC3B,IAAI,OAAqC,CAAC;QAC1C,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CACxC,KAAK,IAAI,EAAE;YACV,IAAI,MAAwB,CAAC;YAC7B,IAAI,CAAC;gBACJ,MAAM,GAAG,MAAM,CACd,MAAM,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE;oBACtC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM;oBAC3B,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO;oBAC7B,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,cAAc,EAAE,MAAM;oBACtB,SAAS;oBACT,SAAS,EAAE,gBAAgB;oBAC3B,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,SAAS,KAAK,KAAK;wBACpF,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE;wBACzC,CAAC,CAAC,EAAE,CAAC;iBACN,CAAC,CACF,CAAC,MAAM,EAAE,CAAC;YACZ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO;oBAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;gBACrE,MAAM,GAAG,sBAAsB,CAAC,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAChG,CAAC;YACD,OAAO,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAChC,IAAI,+BAA+B,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC7C,OAAO,GAAG,MAAM,CAAC;gBACjB,OAAO,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;YAC1C,CAAC;YACD,OAAO,MAAM,CAAC;QACf,CAAC,EACD,OAAO,CAAC,KAAK,EACb,OAAO,CAAC,MAAM,EACd,OAAO,CAAC,SAAS,CACjB,CAAC;QACF,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,IAAI,QAAQ,CAAC,UAAU,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC1G,IAAI,OAAO,IAAI,QAAQ,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;YAChD,MAAM,cAAc,GAAG,OAAO,IAAI,QAAQ,CAAC;YAC3C,MAAM,cAAc,GAAG,yBAAyB,cAAc,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,2CAA2C,CAAC,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC;YAC3J,MAAM,OAAO,GAAG,sBAAsB,CAAC,cAAc,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;YAC5E,MAAM,cAAc,GAAG,sBAAsB,CAAC;gBAC7C,eAAe,EAAE,OAAO,CAAC,eAAe;gBACxC,KAAK;gBACL,gBAAgB;gBAChB,QAAQ,EAAE,cAAc;gBACxB,eAAe,EAAE,cAAc,CAAC,OAAO;qBACrC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC;qBACxC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;qBAC1B,IAAI,CAAC,EAAE,CAAC;gBACV,eAAe,EAAE,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,OAAO;gBACtE,cAAc;aACd,CAAC,CAAC;YACH,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,cAAc,iBAAiB,cAAc,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;QACxG,CAAC;QACD,IAAI,QAAQ,CAAC,UAAU,KAAK,QAAQ;YACnC,MAAM,IAAI,KAAK,CAAC,kFAAkF,CAAC,CAAC;QACrG,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC;YAC9D,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC3D,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO;aAC9B,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC;aACxC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;aAC1B,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QAC1E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC;IACjD,CAAC,CAAC;IACF,IAAI,OAAe,CAAC;IACpB,IAAI,KAAY,CAAC;IACjB,IAAI,WAAW,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,OAAO,GACZ,WAAW,CAAC,mBAAmB,CAAC,MAAM,GAAG,CAAC;YACzC,CAAC,CAAC,MAAM,SAAS,CAAC,WAAW,CAAC,mBAAmB,EAAE,KAAK,EAAE,WAAW,CAAC,eAAe,CAAC;YACtF,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;QACrE,OAAO,GAAG,GAAG,OAAO,EAAE,IAAI,IAAI,WAAW,CAAC,eAAe,IAAI,mBAAmB,gDAAgD,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9I,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;IAC5E,CAAC;SAAM,CAAC;QACP,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,mBAAmB,EAAE,KAAK,EAAE,WAAW,CAAC,eAAe,CAAC,CAAC;QACpG,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC;QACtB,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IACtB,CAAC;IACD,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,gBAAgB,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC3E,OAAO,IAAI,oBAAoB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IAC1D,OAAO;QACN,OAAO;QACP,gBAAgB,EAAE,WAAW,CAAC,gBAAgB;QAC9C,YAAY,EAAE,WAAW,CAAC,YAAY;QACtC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,cAAc;QACvE,SAAS;QACT,aAAa;QACb,KAAK;KACL,CAAC;AACH,CAAC","sourcesContent":["import { normalizeContext, retryAssistantCall, uuidv7 } from \"@bastani/pi-ai\";\nimport type { AssistantMessage, Usage } from \"@bastani/pi-ai/compat\";\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport { convertToLlm } from \"../messages.ts\";\nimport {\n\tbuildSessionProjection,\n\ttype ProjectedSessionEntry,\n\ttype SessionEntry,\n\tsessionEntryToContextMessages,\n} from \"../session-manager.ts\";\nimport { applyContextEdit, buildContextEntries, collectContextEdits } from \"../session-manager-history.ts\";\nimport { combineUsage } from \"../usage-totals.ts\";\nimport { estimateProjectedContextTokens } from \"./compaction.ts\";\nimport type { BorrowedPlanner } from \"./compaction-types.js\";\nimport { classifyPlannerFailure, isProviderPolicyRefusalResponse, syntheticErrorResponse } from \"./planner-outcome.js\";\nimport { plannerRequestModel, type RangePlannerOptions } from \"./range-planner.js\";\nimport { writeDiagnosticSidecar } from \"./range-planner-diagnostics.js\";\nimport {\n\tcomputeFileLists,\n\tcreateFileOps,\n\textractFileOpsFromMessage,\n\ttype FileOperations,\n\tformatFileOperations,\n\tSUMMARIZATION_SYSTEM_PROMPT,\n\tserializeConversation,\n} from \"./utils.ts\";\n\nexport interface PiSummarySettings {\n\treserveTokens: number;\n\tkeepRecentTokens?: number;\n}\nexport interface PiSummaryPreparation {\n\tfirstKeptEntryId: string;\n\tmessagesToSummarize: AgentMessage[];\n\tturnPrefixMessages: AgentMessage[];\n\tpreviousSummary?: string;\n\ttokensBefore: number;\n\tkeptTailTokens: number;\n\tfileOps: FileOperations;\n\tsettings: PiSummarySettings;\n}\nexport interface PiSummaryResult {\n\tsummary: string;\n\tfirstKeptEntryId: string;\n\ttokensBefore: number;\n\ttokensAfter: number;\n\treadFiles: string[];\n\tmodifiedFiles: string[];\n\tusage: Usage;\n}\n\nfunction estimatePiContentChars(content: string | readonly { type: string; text?: string }[]): number {\n\tif (typeof content === \"string\") return content.length;\n\tlet chars = 0;\n\tfor (const block of content) {\n\t\tif (block.type === \"text\" && block.text) chars += block.text.length;\n\t\telse if (block.type === \"image\") chars += 4800;\n\t}\n\treturn chars;\n}\n\nfunction estimatePiTokens(message: AgentMessage): number {\n\tlet chars = 0;\n\tswitch (message.role) {\n\t\tcase \"system\":\n\t\t\tchars = estimatePiContentChars(message.content);\n\t\t\tfor (const section of Object.values(message.sections ?? {})) if (section) chars += section.length;\n\t\t\tif (message.toolsAdded) chars += JSON.stringify(message.toolsAdded).length;\n\t\t\tbreak;\n\t\tcase \"user\":\n\t\tcase \"custom\":\n\t\tcase \"toolResult\":\n\t\t\tchars = estimatePiContentChars(message.content);\n\t\t\tbreak;\n\t\tcase \"assistant\":\n\t\t\tfor (const block of message.content) {\n\t\t\t\tif (block.type === \"text\") chars += block.text.length;\n\t\t\t\telse if (block.type === \"thinking\") chars += block.thinking.length;\n\t\t\t\telse if (block.type === \"toolCall\") chars += block.name.length + JSON.stringify(block.arguments).length;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase \"bashExecution\":\n\t\t\tchars = message.command.length + message.output.length;\n\t\t\tbreak;\n\t\tcase \"branchSummary\":\n\t\t\tchars = message.summary.length;\n\t\t\tbreak;\n\t}\n\treturn Math.ceil(chars / 4);\n}\n\nfunction startsTurn(entry: ProjectedSessionEntry): boolean {\n\treturn (\n\t\tentry.sourceEntry.type !== \"compaction\" &&\n\t\tentry.messages.some(\n\t\t\t(message) =>\n\t\t\t\tmessage.role === \"user\" ||\n\t\t\t\tmessage.role === \"bashExecution\" ||\n\t\t\t\tmessage.role === \"custom\" ||\n\t\t\t\tmessage.role === \"branchSummary\",\n\t\t)\n\t);\n}\nfunction conversationMessages(entry: ProjectedSessionEntry): AgentMessage[] {\n\treturn entry.sourceEntry.type === \"compaction\" ? [] : entry.messages.filter((message) => message.role !== \"system\");\n}\n\nexport function preparePiSummaryCompaction(\n\tpathEntries: SessionEntry[],\n\tsettings: PiSummarySettings,\n): PiSummaryPreparation | undefined {\n\tif (pathEntries.at(-1)?.type === \"compaction\") return undefined;\n\tconst projection = buildSessionProjection(pathEntries);\n\tconst contextEntries = buildContextEntries(pathEntries);\n\tconst edits = collectContextEdits(contextEntries);\n\tconst entries: ProjectedSessionEntry[] = contextEntries.map((sourceEntry) => {\n\t\tconst messages = sessionEntryToContextMessages(sourceEntry);\n\t\tconst edit = edits.get(sourceEntry.id);\n\t\treturn { sourceEntry, messages: edit ? applyContextEdit(messages, edit) : messages };\n\t});\n\tconst previousIndex = entries.findIndex(\n\t\t(entry) => entry.sourceEntry.type === \"compaction\" && entry.messages.length > 0,\n\t);\n\tconst previous = previousIndex >= 0 ? entries[previousIndex].sourceEntry : undefined;\n\tconst start = previousIndex >= 0 ? previousIndex + 1 : 0;\n\tconst cutPoints: number[] = [];\n\tfor (let index = start; index < entries.length; index++) {\n\t\tconst entry = entries[index];\n\t\tif (\n\t\t\tentry.sourceEntry.type !== \"compaction\" &&\n\t\t\tentry.messages.some((message) => message.role !== \"toolResult\" && message.role !== \"system\")\n\t\t)\n\t\t\tcutPoints.push(index);\n\t}\n\tif (cutPoints.length === 0) return undefined;\n\tlet cut = cutPoints[0];\n\tlet tokens = 0;\n\tlet exceededBudget = false;\n\tfor (let index = entries.length - 1; index >= start; index--) {\n\t\tconst count = entries[index].messages.reduce((sum, message) => sum + estimatePiTokens(message), 0);\n\t\tif (count === 0) continue;\n\t\ttokens += count;\n\t\tif (tokens >= (settings.keepRecentTokens ?? 20000)) {\n\t\t\texceededBudget = true;\n\t\t\tcut = cutPoints.find((candidate) => candidate >= index) ?? cutPoints[cutPoints.length - 1];\n\t\t\tbreak;\n\t\t}\n\t}\n\tconst suffix = entries.slice(cut + 1);\n\tconst intrinsicallyVisible = (entry: ProjectedSessionEntry): boolean =>\n\t\tentry.sourceEntry.type !== \"context_edit\" && sessionEntryToContextMessages(entry.sourceEntry).length > 0;\n\tconst omitted = (entry: ProjectedSessionEntry): boolean =>\n\t\tintrinsicallyVisible(entry) && entry.messages.length === 0;\n\tconst omittedIds = new Set(suffix.filter(omitted).map((entry) => entry.sourceEntry.id));\n\tconst externalReplacement = suffix.some(\n\t\t(entry) =>\n\t\t\tentry.sourceEntry.type === \"context_edit\" &&\n\t\t\tentry.sourceEntry.replacement !== null &&\n\t\t\t!omittedIds.has(entry.sourceEntry.targetId),\n\t);\n\tif (\n\t\texceededBudget &&\n\t\t!externalReplacement &&\n\t\tsuffix.some(\n\t\t\t(entry) =>\n\t\t\t\tentry.sourceEntry.type === \"message\" && entry.sourceEntry.message.role === \"assistant\" && omitted(entry),\n\t\t) &&\n\t\tsuffix.every(\n\t\t\t(entry) => entry.sourceEntry.type !== \"compaction\" && (!intrinsicallyVisible(entry) || omitted(entry)),\n\t\t)\n\t)\n\t\tcut++;\n\twhile (cut > start && entries[cut - 1].sourceEntry.type !== \"compaction\" && entries[cut - 1].messages.length === 0)\n\t\tcut--;\n\tlet turnStart = -1;\n\tif (!startsTurn(entries[cut])) {\n\t\tfor (let index = cut; index >= start; index--)\n\t\t\tif (startsTurn(entries[index])) {\n\t\t\t\tturnStart = index;\n\t\t\t\tbreak;\n\t\t\t}\n\t}\n\tconst messagesToSummarize = entries.slice(start, turnStart >= 0 ? turnStart : cut).flatMap(conversationMessages);\n\tconst turnPrefixMessages = turnStart >= 0 ? entries.slice(turnStart, cut).flatMap(conversationMessages) : [];\n\tif (messagesToSummarize.length === 0 && turnPrefixMessages.length === 0) return undefined;\n\tconst fileOps = createFileOps();\n\tif (\n\t\tprevious?.type === \"compaction\" &&\n\t\t!previous.fromHook &&\n\t\tprevious.details &&\n\t\ttypeof previous.details === \"object\"\n\t) {\n\t\tconst previousDetails =\n\t\t\t\"summary\" in previous.details &&\n\t\t\ttypeof previous.details.summary === \"object\" &&\n\t\t\tprevious.details.summary !== null\n\t\t\t\t? previous.details.summary\n\t\t\t\t: previous.details;\n\t\tfor (const [key, target] of [\n\t\t\t[\"readFiles\", fileOps.read],\n\t\t\t[\"modifiedFiles\", fileOps.edited],\n\t\t] as const) {\n\t\t\tif (key in previousDetails) {\n\t\t\t\tconst files = (previousDetails as { readFiles?: string[]; modifiedFiles?: string[] })[key];\n\t\t\t\tif (Array.isArray(files)) for (const file of files) if (typeof file === \"string\") target.add(file);\n\t\t\t}\n\t\t}\n\t}\n\tfor (const message of [...messagesToSummarize, ...turnPrefixMessages]) extractFileOpsFromMessage(message, fileOps);\n\treturn {\n\t\tfirstKeptEntryId: entries[cut].sourceEntry.id,\n\t\tmessagesToSummarize,\n\t\tturnPrefixMessages,\n\t\tpreviousSummary: previous?.type === \"compaction\" ? previous.summary : undefined,\n\t\ttokensBefore: estimateProjectedContextTokens(projection, pathEntries).tokens,\n\t\tkeptTailTokens: entries\n\t\t\t.slice(cut)\n\t\t\t.flatMap((entry) => entry.messages)\n\t\t\t.reduce((sum, message) => sum + estimatePiTokens(message), 0),\n\t\tfileOps,\n\t\tsettings,\n\t};\n}\n\nconst SUMMARIZATION_PROMPT = `The messages above are a conversation to summarize. Create a structured context checkpoint summary that another LLM will use to continue the work.\n\nUse this EXACT format:\n\n## Goal\n[What is the user trying to accomplish? Can be multiple items if the session covers different tasks.]\n\n## Constraints & Preferences\n- [Any constraints, preferences, or requirements mentioned by user]\n- [Or \"(none)\" if none were mentioned]\n\n## Progress\n### Done\n- [x] [Completed tasks/changes]\n\n### In Progress\n- [ ] [Current work]\n\n### Blocked\n- [Issues preventing progress, if any]\n\n## Key Decisions\n- **[Decision]**: [Brief rationale]\n\n## Next Steps\n1. [Ordered list of what should happen next]\n\n## Critical Context\n- [Any data, examples, or references needed to continue]\n- [Or \"(none)\" if not applicable]\n\nKeep each section concise. Preserve exact file paths, function names, and error messages.`;\n\nconst UPDATE_SUMMARIZATION_PROMPT = `The messages above are NEW conversation messages to incorporate into the existing summary provided in <previous-summary> tags.\n\nUpdate the existing structured summary with new information. RULES:\n- PRESERVE all existing information from the previous summary\n- ADD new progress, decisions, and context from the new messages\n- UPDATE the Progress section: move items from \"In Progress\" to \"Done\" when completed\n- UPDATE \"Next Steps\" based on what was accomplished\n- PRESERVE exact file paths, function names, and error messages\n- If something is no longer relevant, you may remove it\n\nUse this EXACT format:\n\n## Goal\n[Preserve existing goals, add new ones if the task expanded]\n\n## Constraints & Preferences\n- [Preserve existing, add new ones discovered]\n\n## Progress\n### Done\n- [x] [Include previously done items AND newly completed items]\n\n### In Progress\n- [ ] [Current work - update based on progress]\n\n### Blocked\n- [Current blockers - remove if resolved]\n\n## Key Decisions\n- **[Decision]**: [Brief rationale] (preserve all previous, add new)\n\n## Next Steps\n1. [Update based on current state]\n\n## Critical Context\n- [Preserve important context, add new if needed]\n\nKeep each section concise. Preserve exact file paths, function names, and error messages.`;\nconst TURN_PREFIX_SUMMARIZATION_PROMPT = `The messages above are earlier context from an ongoing conversation. Later messages are stored separately and do not need to be reconstructed.\n\nCreate a concise checkpoint of the user's request and the progress shown above. This checkpoint will be placed before the later messages so the conversation can continue with the necessary context.\n\n## Original Request\n[What did the user ask for?]\n\n## Progress So Far\n- [Key decisions and work completed in these messages]\n\n## Context Needed to Continue\n- [Information from these messages needed to understand the later work]\n\nOnly summarize information explicitly present above. Do not infer or recreate later messages.`;\n\nexport async function runPiSummaryFallback(\n\tentries: SessionEntry[],\n\tsettings: PiSummarySettings,\n\tplanner: BorrowedPlanner,\n\toptions: RangePlannerOptions & { signal?: AbortSignal },\n): Promise<PiSummaryResult> {\n\tconst preparation = preparePiSummaryCompaction(entries, settings);\n\tif (!preparation) throw new Error(\"No compactable history for pi summary fallback\");\n\tconst model = plannerRequestModel(planner);\n\tconst summarize = async (\n\t\tmessages: AgentMessage[],\n\t\tprefix: boolean,\n\t\tpreviousSummary?: string,\n\t): Promise<{ text: string; usage: Usage }> => {\n\t\tconst text = serializeConversation(convertToLlm(messages));\n\t\tconst prompt = prefix\n\t\t\t? `# Conversation\\n${text}\\n\\n# Instructions\\n${TURN_PREFIX_SUMMARIZATION_PROMPT}`\n\t\t\t: `<conversation>\\n${text}\\n</conversation>\\n\\n${previousSummary ? `<previous-summary>\\n${previousSummary}\\n</previous-summary>\\n\\n` : \"\"}${previousSummary ? UPDATE_SUMMARIZATION_PROMPT : SUMMARIZATION_PROMPT}`;\n\t\tconst context = normalizeContext({\n\t\t\tsystemPrompt: SUMMARIZATION_SYSTEM_PROMPT,\n\t\t\tmessages: [{ role: \"user\", content: [{ type: \"text\", text: prompt }], timestamp: Date.now() }],\n\t\t});\n\t\tconst requestMaxTokens = Math.min(\n\t\t\tMath.floor((prefix ? 0.5 : 0.8) * settings.reserveTokens),\n\t\t\tmodel.maxTokens > 0 ? model.maxTokens : Number.POSITIVE_INFINITY,\n\t\t);\n\t\tconst sessionId = uuidv7();\n\t\tlet refusal: AssistantMessage | undefined;\n\t\tconst response = await retryAssistantCall(\n\t\t\tasync () => {\n\t\t\t\tlet result: AssistantMessage;\n\t\t\t\ttry {\n\t\t\t\t\tresult = await (\n\t\t\t\t\t\tawait options.streamFn(model, context, {\n\t\t\t\t\t\t\tapiKey: planner.auth.apiKey,\n\t\t\t\t\t\t\theaders: planner.auth.headers,\n\t\t\t\t\t\t\tsignal: options.signal,\n\t\t\t\t\t\t\tcacheRetention: \"none\",\n\t\t\t\t\t\t\tsessionId,\n\t\t\t\t\t\t\tmaxTokens: requestMaxTokens,\n\t\t\t\t\t\t\t...(model.reasoning && planner.budget.reasoning && planner.budget.reasoning !== \"off\"\n\t\t\t\t\t\t\t\t? { reasoning: planner.budget.reasoning }\n\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t})\n\t\t\t\t\t).result();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (options.signal?.aborted) throw new Error(\"Compaction cancelled\");\n\t\t\t\t\tresult = syntheticErrorResponse(model, error instanceof Error ? error.message : String(error));\n\t\t\t\t}\n\t\t\t\toptions.onUsage?.(result.usage);\n\t\t\t\tif (isProviderPolicyRefusalResponse(result)) {\n\t\t\t\t\trefusal = result;\n\t\t\t\t\treturn { ...result, stopReason: \"stop\" };\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t},\n\t\t\toptions.retry,\n\t\t\toptions.signal,\n\t\t\toptions.callbacks,\n\t\t);\n\t\tif (options.signal?.aborted || response.stopReason === \"aborted\") throw new Error(\"Compaction cancelled\");\n\t\tif (refusal || response.stopReason === \"error\") {\n\t\t\tconst failedResponse = refusal ?? response;\n\t\t\tconst failureMessage = `Summarization failed: ${failedResponse.errorMessage || (refusal ? \"The model refused to complete the request\" : \"Unknown error\")}`;\n\t\t\tconst failure = classifyPlannerFailure(failedResponse, model.contextWindow);\n\t\t\tconst diagnosticPath = writeDiagnosticSidecar({\n\t\t\t\tsessionFilePath: options.sessionFilePath,\n\t\t\t\tmodel,\n\t\t\t\trequestMaxTokens,\n\t\t\t\tresponse: failedResponse,\n\t\t\t\trawResponseText: failedResponse.content\n\t\t\t\t\t.filter((block) => block.type === \"text\")\n\t\t\t\t\t.map((block) => block.text)\n\t\t\t\t\t.join(\"\"),\n\t\t\t\tfailureCategory: failure === \"overflow\" ? \"context_overflow\" : failure,\n\t\t\t\tfailureMessage,\n\t\t\t});\n\t\t\tthrow new Error(diagnosticPath ? `${failureMessage} (diagnostic: ${diagnosticPath})` : failureMessage);\n\t\t}\n\t\tif (response.stopReason === \"length\")\n\t\t\tthrow new Error(\"Summarization failed: generation hit the token cap and the summary is incomplete\");\n\t\tif (response.content.some((block) => block.type === \"toolCall\"))\n\t\t\tthrow new Error(\"Summarization attempted to call a tool\");\n\t\tconst summary = response.content\n\t\t\t.filter((block) => block.type === \"text\")\n\t\t\t.map((block) => block.text)\n\t\t\t.join(\"\\n\");\n\t\tif (!summary.trim()) throw new Error(\"Summarization returned empty text\");\n\t\treturn { text: summary, usage: response.usage };\n\t};\n\tlet summary: string;\n\tlet usage: Usage;\n\tif (preparation.turnPrefixMessages.length > 0) {\n\t\tconst history =\n\t\t\tpreparation.messagesToSummarize.length > 0\n\t\t\t\t? await summarize(preparation.messagesToSummarize, false, preparation.previousSummary)\n\t\t\t\t: undefined;\n\t\tconst prefix = await summarize(preparation.turnPrefixMessages, true);\n\t\tsummary = `${history?.text ?? preparation.previousSummary ?? \"No prior history.\"}\\n\\n---\\n\\n**Turn Context (split turn):**\\n\\n${prefix.text}`;\n\t\tusage = history ? combineUsage(history.usage, prefix.usage) : prefix.usage;\n\t} else {\n\t\tconst result = await summarize(preparation.messagesToSummarize, false, preparation.previousSummary);\n\t\tsummary = result.text;\n\t\tusage = result.usage;\n\t}\n\tconst { readFiles, modifiedFiles } = computeFileLists(preparation.fileOps);\n\tsummary += formatFileOperations(readFiles, modifiedFiles);\n\treturn {\n\t\tsummary,\n\t\tfirstKeptEntryId: preparation.firstKeptEntryId,\n\t\ttokensBefore: preparation.tokensBefore,\n\t\ttokensAfter: Math.ceil(summary.length / 4) + preparation.keptTailTokens,\n\t\treadFiles,\n\t\tmodifiedFiles,\n\t\tusage,\n\t};\n}\n"]}
|
|
@@ -44,6 +44,10 @@ export type PlannerOutcome = {
|
|
|
44
44
|
} | {
|
|
45
45
|
kind: "overflowed";
|
|
46
46
|
diagnosticPath?: string;
|
|
47
|
+
} | {
|
|
48
|
+
kind: "policyRefusal";
|
|
49
|
+
message: string;
|
|
50
|
+
diagnosticPath?: string;
|
|
47
51
|
} | {
|
|
48
52
|
kind: "providerError";
|
|
49
53
|
message: string;
|
|
@@ -51,21 +55,21 @@ export type PlannerOutcome = {
|
|
|
51
55
|
};
|
|
52
56
|
/** A planner outcome that cannot produce a boundary and must advance the ladder. */
|
|
53
57
|
export type TerminalPlannerOutcome = Extract<PlannerOutcome, {
|
|
54
|
-
kind: "rateLimited" | "unusable" | "overflowed" | "providerError";
|
|
58
|
+
kind: "rateLimited" | "unusable" | "overflowed" | "providerError" | "policyRefusal";
|
|
55
59
|
}>;
|
|
56
60
|
/** Whether this outcome produced validated deletion ranges. */
|
|
57
61
|
export declare function isPlannerSuccess(outcome: PlannerOutcome): outcome is Extract<PlannerOutcome, {
|
|
58
62
|
kind: "ranked" | "recovered";
|
|
59
63
|
}>;
|
|
60
64
|
/** How a failed planner response is classified before an outcome is built. */
|
|
61
|
-
export type PlannerFailureClass = "overflow" | "quota" | "rate_limited" | "provider_error";
|
|
65
|
+
export type PlannerFailureClass = "overflow" | "quota" | "rate_limited" | "policy_refusal" | "provider_error";
|
|
66
|
+
export declare function isProviderPolicyRefusal(message: string): boolean;
|
|
67
|
+
export declare function isProviderPolicyRefusalResponse(response: AssistantMessage): boolean;
|
|
62
68
|
/**
|
|
63
69
|
* Classify one failed planner response.
|
|
64
70
|
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
* Quota/billing exhaustion then wins over transient throttling, matching pi-ai's
|
|
68
|
-
* own precedence.
|
|
71
|
+
* Policy refusal wins before overflow, quota, and retryable-provider matching.
|
|
72
|
+
* Context overflow is recoverable by trimming; quota wins over throttling.
|
|
69
73
|
*/
|
|
70
74
|
export declare function classifyPlannerFailure(response: AssistantMessage, contextWindow: number): PlannerFailureClass;
|
|
71
75
|
/** Build a synthetic error response so a thrown transport failure classifies identically. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planner-outcome.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/planner-outcome.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAEhF,sDAAsD;AACtD,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,cAAc,CAAC;AAEzD,6CAA6C;AAC7C,MAAM,MAAM,cAAc,GACvB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,YAAY,EAAE,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,YAAY,EAAE,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GACrE;IACA,IAAI,EAAE,aAAa,CAAC;IACpB;;;;;;OAMG;IACH,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACvB,GACD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,yBAAyB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,GACnG;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE,oFAAoF;AACpF,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAC3C,cAAc,EACd;IAAE,IAAI,EAAE,aAAa,GAAG,UAAU,GAAG,YAAY,GAAG,eAAe,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"planner-outcome.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/planner-outcome.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAEhF,sDAAsD;AACtD,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,cAAc,CAAC;AAEzD,6CAA6C;AAC7C,MAAM,MAAM,cAAc,GACvB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,YAAY,EAAE,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,YAAY,EAAE,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GACrE;IACA,IAAI,EAAE,aAAa,CAAC;IACpB;;;;;;OAMG;IACH,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACvB,GACD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,yBAAyB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,GACnG;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,GACnE;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE,oFAAoF;AACpF,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAC3C,cAAc,EACd;IAAE,IAAI,EAAE,aAAa,GAAG,UAAU,GAAG,YAAY,GAAG,eAAe,GAAG,eAAe,CAAA;CAAE,CACvF,CAAC;AAEF,+DAA+D;AAC/D,wBAAgB,gBAAgB,CAC/B,OAAO,EAAE,cAAc,GACrB,OAAO,IAAI,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,QAAQ,GAAG,WAAW,CAAA;CAAE,CAAC,CAEtE;AA6DD,8EAA8E;AAC9E,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,OAAO,GAAG,cAAc,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;AAE9G,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAOhE;AAED,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAEnF;AACD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,GAAG,mBAAmB,CAO7G;AAED,6FAA6F;AAC7F,wBAAgB,sBAAsB,CACrC,KAAK,EAAE;IAAE,GAAG,EAAE,GAAG,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,EACjD,YAAY,EAAE,MAAM,GAClB,gBAAgB,CAmBlB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,eAAe,EAAE,OAAO,GAAG,OAAO,CAEhG"}
|