@caupulican/pi-adaptative 0.93.17 → 0.93.19
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 +23 -0
- package/dist/core/agent-session.d.ts +1 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +22 -12
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction-controller.d.ts +22 -0
- package/dist/core/compaction-controller.d.ts.map +1 -1
- package/dist/core/compaction-controller.js +191 -30
- package/dist/core/compaction-controller.js.map +1 -1
- package/dist/core/compaction-support.d.ts.map +1 -1
- package/dist/core/compaction-support.js +21 -1
- package/dist/core/compaction-support.js.map +1 -1
- package/dist/core/delegation/worker-agent-control-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-agent-control-coordinator.js +1 -0
- package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-agent-control.d.ts +2 -0
- package/dist/core/delegation/worker-agent-control.d.ts.map +1 -1
- package/dist/core/delegation/worker-agent-control.js.map +1 -1
- package/dist/core/foreground-lifecycle-adapter.d.ts +27 -0
- package/dist/core/foreground-lifecycle-adapter.d.ts.map +1 -0
- package/dist/core/foreground-lifecycle-adapter.js +61 -0
- package/dist/core/foreground-lifecycle-adapter.js.map +1 -0
- package/dist/core/foreground-lifecycle-controller.d.ts +48 -0
- package/dist/core/foreground-lifecycle-controller.d.ts.map +1 -0
- package/dist/core/foreground-lifecycle-controller.js +404 -0
- package/dist/core/foreground-lifecycle-controller.js.map +1 -0
- package/dist/core/foreground-recovery-controller.d.ts +3 -0
- package/dist/core/foreground-recovery-controller.d.ts.map +1 -1
- package/dist/core/foreground-recovery-controller.js +15 -1
- package/dist/core/foreground-recovery-controller.js.map +1 -1
- package/dist/core/goals/goal-state.d.ts.map +1 -1
- package/dist/core/goals/goal-state.js +9 -2
- package/dist/core/goals/goal-state.js.map +1 -1
- package/dist/core/keybindings.d.ts +2 -2
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +2 -2
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/memory/memory-manager.d.ts +22 -0
- package/dist/core/memory/memory-manager.d.ts.map +1 -1
- package/dist/core/memory/memory-manager.js +108 -49
- package/dist/core/memory/memory-manager.js.map +1 -1
- package/dist/core/model-router/session-buffer.d.ts +10 -2
- package/dist/core/model-router/session-buffer.d.ts.map +1 -1
- package/dist/core/model-router/session-buffer.js +35 -9
- package/dist/core/model-router/session-buffer.js.map +1 -1
- package/dist/core/model-router-controller.d.ts +20 -2
- package/dist/core/model-router-controller.d.ts.map +1 -1
- package/dist/core/model-router-controller.js +70 -17
- package/dist/core/model-router-controller.js.map +1 -1
- package/dist/core/provider-request-runtime-controller.d.ts +12 -1
- package/dist/core/provider-request-runtime-controller.d.ts.map +1 -1
- package/dist/core/provider-request-runtime-controller.js +45 -2
- package/dist/core/provider-request-runtime-controller.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +3 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tools/delegate.d.ts.map +1 -1
- package/dist/core/tools/delegate.js +4 -2
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +1 -3
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +10 -20
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/tool-group.d.ts +3 -0
- package/dist/modes/interactive/components/tool-group.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-group.js +25 -0
- package/dist/modes/interactive/components/tool-group.js.map +1 -1
- package/dist/modes/interactive/components/transcript-overlay.d.ts +13 -0
- package/dist/modes/interactive/components/transcript-overlay.d.ts.map +1 -0
- package/dist/modes/interactive/components/transcript-overlay.js +35 -0
- package/dist/modes/interactive/components/transcript-overlay.js.map +1 -0
- package/dist/modes/interactive/components/tree-selector.d.ts +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +7 -4
- package/dist/modes/interactive/components/tree-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 +2 -1
- package/dist/modes/interactive/interactive-event-controller.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +9 -7
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +70 -99
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/runtime-status-controller.d.ts +40 -0
- package/dist/modes/interactive/runtime-status-controller.d.ts.map +1 -0
- package/dist/modes/interactive/runtime-status-controller.js +147 -0
- package/dist/modes/interactive/runtime-status-controller.js.map +1 -0
- package/dist/modes/interactive/runtime-status.d.ts +15 -0
- package/dist/modes/interactive/runtime-status.d.ts.map +1 -0
- package/dist/modes/interactive/runtime-status.js +18 -0
- package/dist/modes/interactive/runtime-status.js.map +1 -0
- package/docs/json.md +1 -1
- package/docs/keybindings.md +2 -1
- package/docs/session-format.md +59 -4
- 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
|
@@ -94,6 +94,7 @@ export declare class CompactionController {
|
|
|
94
94
|
private manualAbortController;
|
|
95
95
|
private autoAbortController;
|
|
96
96
|
private autoRunPromise;
|
|
97
|
+
private activeCompactionLifecycle;
|
|
97
98
|
private overflowRecoveryAttempted;
|
|
98
99
|
private providerRecoveryAttempted;
|
|
99
100
|
private ineffectiveThresholdFrontier;
|
|
@@ -101,6 +102,25 @@ export declare class CompactionController {
|
|
|
101
102
|
constructor(deps: CompactionControllerDeps);
|
|
102
103
|
private buildCompactionInstructions;
|
|
103
104
|
isRunning(): boolean;
|
|
105
|
+
private buildExecutionOptions;
|
|
106
|
+
/**
|
|
107
|
+
* Open the durable compaction transaction only after deterministic preparation has produced its cut.
|
|
108
|
+
* The caller must invoke this before extension or provider work begins. A failed append deliberately
|
|
109
|
+
* leaves no active lifecycle, so the caller fails closed before starting summarization.
|
|
110
|
+
*/
|
|
111
|
+
private beginCompactionLifecycle;
|
|
112
|
+
private recordAppliedCompaction;
|
|
113
|
+
/**
|
|
114
|
+
* Lifecycle records are durable bookkeeping and must not become compaction input or alter the
|
|
115
|
+
* loop's trailing-compaction guard. They remain in the real branch so recovery can inspect them.
|
|
116
|
+
*/
|
|
117
|
+
private getCompactionBranch;
|
|
118
|
+
/**
|
|
119
|
+
* Close the one transaction for this compaction retry ladder. The marker is attempted at most once;
|
|
120
|
+
* an append failure is allowed to propagate because success must never be inferred from an unrecorded
|
|
121
|
+
* terminal. A successful terminal always points at the canonical persisted compaction entry.
|
|
122
|
+
*/
|
|
123
|
+
private finishCompactionLifecycle;
|
|
104
124
|
resetOverflowRecovery(): void;
|
|
105
125
|
admitProviderRequest(input: ProviderRequestCompactionInput): Promise<ProviderRequestCompactionDecision>;
|
|
106
126
|
abort(): void;
|
|
@@ -109,6 +129,8 @@ export declare class CompactionController {
|
|
|
109
129
|
private runManualCompaction;
|
|
110
130
|
check(assistantMessage: AssistantMessage, skipAbortedCheck?: boolean): Promise<boolean>;
|
|
111
131
|
measureLiveContextTokens(): number;
|
|
132
|
+
/** Prefer authoritative branch order; timestamps are only a fallback for reconstructed messages. */
|
|
133
|
+
private isAssistantFromBeforeCompaction;
|
|
112
134
|
get isCompacting(): boolean;
|
|
113
135
|
runAuto(reason: AutoCompactionReason, willRetry: boolean, options?: AutoCompactionRunOptions): Promise<boolean>;
|
|
114
136
|
private runAutoOnce;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compaction-controller.d.ts","sourceRoot":"","sources":["../../src/core/compaction-controller.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"compaction-controller.d.ts","sourceRoot":"","sources":["../../src/core/compaction-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
1
2
|
import { assessCompactionNeed, calculateContextTokens, compact, createDeterministicCompaction, estimateContextTokens, prepareCompaction, shouldCompact, } from "@caupulican/pi-agent-core/compaction/compaction";
|
|
2
3
|
import { runCompactionLoop } from "@caupulican/pi-agent-core/compaction/loop";
|
|
3
|
-
import { createCustomMessage } from "@caupulican/pi-agent-core/messages";
|
|
4
|
+
import { convertToLlm, createCustomMessage } from "@caupulican/pi-agent-core/messages";
|
|
4
5
|
import { estimateProviderRequestTokens } from "@caupulican/pi-agent-core/provider-request-estimator";
|
|
5
6
|
import { projectToolsForProvider } from "@caupulican/pi-agent-core/provider-tool-projection";
|
|
6
7
|
import { classifyFailure, computeRetryDelayMs, DEFAULT_RETRY_POLICY, sleepAbortable, } from "@caupulican/pi-agent-core/reliability";
|
|
7
|
-
import { getLatestCompactionEntry } from "@caupulican/pi-agent-core/session";
|
|
8
|
+
import { getLatestCompactionEntry, isSessionLifecycleEntry, } from "@caupulican/pi-agent-core/session";
|
|
8
9
|
import { isContextOverflow } from "@caupulican/pi-ai/overflow";
|
|
9
10
|
import { materializeProviderRequest } from "@caupulican/pi-ai/stream";
|
|
10
11
|
import { formatNoModelSelectedMessage } from "./auth-guidance.js";
|
|
@@ -19,6 +20,16 @@ const COMPACTION_RETRY_PREPARATION_OPTIONS = { allowTrailingCompactionAsPrevious
|
|
|
19
20
|
const INEFFECTIVE_THRESHOLD_SKIP_REASON = "previous auto-compaction did not restore headroom; waiting for materially new compactable history";
|
|
20
21
|
const PROVIDER_RECOVERY_CONTINUATION_CUSTOM_TYPE = "provider_recovery_continuation";
|
|
21
22
|
const PROVIDER_RECOVERY_CONTINUATION = "Continue the latest owner request from the compacted checkpoint.";
|
|
23
|
+
function boundedCompactionLifecycleError(error) {
|
|
24
|
+
const message = error instanceof Error ? error.message : typeof error === "string" ? error : "compaction failed";
|
|
25
|
+
const sanitized = message
|
|
26
|
+
.replace(/[\u0000-\u001F\u007F]/g, " ")
|
|
27
|
+
.replace(/\s+/g, " ")
|
|
28
|
+
.trim();
|
|
29
|
+
if (!sanitized)
|
|
30
|
+
return "compaction failed";
|
|
31
|
+
return sanitized.length > 500 ? `${sanitized.slice(0, 500)}…` : sanitized;
|
|
32
|
+
}
|
|
22
33
|
function formatRequestTokenBreakdown(input) {
|
|
23
34
|
const total = Math.max(0, Math.ceil(input.requestTokens));
|
|
24
35
|
const nonCompactable = Math.max(0, Math.min(total, Math.ceil(input.nonCompactableTokens)));
|
|
@@ -72,6 +83,90 @@ export class CompactionController {
|
|
|
72
83
|
this.autoAbortController !== undefined ||
|
|
73
84
|
this.autoRunPromise !== undefined);
|
|
74
85
|
}
|
|
86
|
+
buildExecutionOptions(preparation, settings, compactionModel, sessionModel, chunked) {
|
|
87
|
+
const options = { chunked };
|
|
88
|
+
const reusesSessionLane = settings.strategy === "session-replacement" &&
|
|
89
|
+
compactionModel.provider === sessionModel.provider &&
|
|
90
|
+
compactionModel.id === sessionModel.id &&
|
|
91
|
+
compactionModel.api === sessionModel.api &&
|
|
92
|
+
compactionModel.baseUrl === sessionModel.baseUrl;
|
|
93
|
+
if (!reusesSessionLane)
|
|
94
|
+
return options;
|
|
95
|
+
const request = materializeProviderRequest({
|
|
96
|
+
systemPrompt: this.deps.agent.state.systemPrompt,
|
|
97
|
+
messages: convertToLlm(preparation.messagesToSummarize),
|
|
98
|
+
tools: projectToolsForProvider(this.deps.agent.state.tools),
|
|
99
|
+
}, { textToolCallProtocol: this.deps.agent.textToolCallProtocol });
|
|
100
|
+
options.structuredRequest = {
|
|
101
|
+
context: request.context,
|
|
102
|
+
sessionId: this.deps.sessionManager.getSessionId(),
|
|
103
|
+
cacheRetention: "short",
|
|
104
|
+
};
|
|
105
|
+
return options;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Open the durable compaction transaction only after deterministic preparation has produced its cut.
|
|
109
|
+
* The caller must invoke this before extension or provider work begins. A failed append deliberately
|
|
110
|
+
* leaves no active lifecycle, so the caller fails closed before starting summarization.
|
|
111
|
+
*/
|
|
112
|
+
beginCompactionLifecycle(preparation) {
|
|
113
|
+
if (this.activeCompactionLifecycle)
|
|
114
|
+
return;
|
|
115
|
+
const compactionId = randomUUID();
|
|
116
|
+
this.deps.sessionManager.appendCompactionStart(compactionId, preparation.firstKeptEntryId, preparation.tokensBefore);
|
|
117
|
+
this.activeCompactionLifecycle = { compactionId, endAttempted: false };
|
|
118
|
+
}
|
|
119
|
+
recordAppliedCompaction(compactionEntryId) {
|
|
120
|
+
if (this.activeCompactionLifecycle)
|
|
121
|
+
this.activeCompactionLifecycle.latestCompactionEntryId = compactionEntryId;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Lifecycle records are durable bookkeeping and must not become compaction input or alter the
|
|
125
|
+
* loop's trailing-compaction guard. They remain in the real branch so recovery can inspect them.
|
|
126
|
+
*/
|
|
127
|
+
getCompactionBranch() {
|
|
128
|
+
return this.deps.sessionManager.getBranch().filter((entry) => !isSessionLifecycleEntry(entry));
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Close the one transaction for this compaction retry ladder. The marker is attempted at most once;
|
|
132
|
+
* an append failure is allowed to propagate because success must never be inferred from an unrecorded
|
|
133
|
+
* terminal. A successful terminal always points at the canonical persisted compaction entry.
|
|
134
|
+
*/
|
|
135
|
+
finishCompactionLifecycle(outcome, error) {
|
|
136
|
+
const lifecycle = this.activeCompactionLifecycle;
|
|
137
|
+
if (!lifecycle || lifecycle.endAttempted)
|
|
138
|
+
return;
|
|
139
|
+
lifecycle.endAttempted = true;
|
|
140
|
+
let terminalOutcome = outcome;
|
|
141
|
+
let terminalError = error === undefined ? undefined : boundedCompactionLifecycleError(error);
|
|
142
|
+
let invalidSuccess = false;
|
|
143
|
+
if (terminalOutcome === "success" && !lifecycle.latestCompactionEntryId) {
|
|
144
|
+
terminalOutcome = "failure";
|
|
145
|
+
terminalError = "compaction succeeded without a persisted compaction entry";
|
|
146
|
+
invalidSuccess = true;
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
if (terminalOutcome === "success") {
|
|
150
|
+
this.deps.sessionManager.appendCompactionEnd(lifecycle.compactionId, terminalOutcome, {
|
|
151
|
+
compactionEntryId: lifecycle.latestCompactionEntryId,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
else if (terminalError) {
|
|
155
|
+
this.deps.sessionManager.appendCompactionEnd(lifecycle.compactionId, terminalOutcome, {
|
|
156
|
+
error: terminalError,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
this.deps.sessionManager.appendCompactionEnd(lifecycle.compactionId, terminalOutcome);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
finally {
|
|
164
|
+
if (this.activeCompactionLifecycle === lifecycle)
|
|
165
|
+
this.activeCompactionLifecycle = undefined;
|
|
166
|
+
}
|
|
167
|
+
if (invalidSuccess)
|
|
168
|
+
throw new Error(terminalError);
|
|
169
|
+
}
|
|
75
170
|
resetOverflowRecovery() {
|
|
76
171
|
this.overflowRecoveryAttempted = false;
|
|
77
172
|
this.providerRecoveryAttempted = false;
|
|
@@ -176,6 +271,12 @@ export class CompactionController {
|
|
|
176
271
|
primaryError = error;
|
|
177
272
|
const message = error instanceof Error ? error.message : String(error);
|
|
178
273
|
const aborted = message === "Compaction cancelled" || (error instanceof Error && error.name === "AbortError");
|
|
274
|
+
try {
|
|
275
|
+
this.finishCompactionLifecycle(aborted ? "cancelled" : "failure", aborted ? undefined : error);
|
|
276
|
+
}
|
|
277
|
+
catch (lifecycleError) {
|
|
278
|
+
primaryError = new AggregateError([primaryError, lifecycleError], "Compaction failed and its durable lifecycle terminal could not be recorded");
|
|
279
|
+
}
|
|
179
280
|
this.deps.emit({
|
|
180
281
|
type: "compaction_end",
|
|
181
282
|
reason: "manual",
|
|
@@ -222,7 +323,7 @@ export class CompactionController {
|
|
|
222
323
|
await this.deps.getRequestAuth(selectedCompactionModel);
|
|
223
324
|
const selectionReason = this.deps.getSelectionReason() ?? "unknown";
|
|
224
325
|
const settings = this.deps.getAdaptedSettings();
|
|
225
|
-
const initialBranch = this.
|
|
326
|
+
const initialBranch = this.getCompactionBranch();
|
|
226
327
|
const initialPreparation = prepareCompaction(initialBranch, settings);
|
|
227
328
|
if (!initialPreparation) {
|
|
228
329
|
const lastEntry = initialBranch[initialBranch.length - 1];
|
|
@@ -230,6 +331,7 @@ export class CompactionController {
|
|
|
230
331
|
throw new Error("Already compacted");
|
|
231
332
|
throw new Error("Nothing to compact (session too small)");
|
|
232
333
|
}
|
|
334
|
+
this.beginCompactionLifecycle(initialPreparation);
|
|
233
335
|
// Resolve once for the complete retry ladder. Provider hooks can perform durable flushes and
|
|
234
336
|
// must not be repeated for every summarizer/gate retry.
|
|
235
337
|
const effectiveInstructions = await this.buildCompactionInstructions(customInstructions);
|
|
@@ -237,7 +339,8 @@ export class CompactionController {
|
|
|
237
339
|
if (extension.cancelled)
|
|
238
340
|
throw new Error("Compaction cancelled");
|
|
239
341
|
if (extension.result) {
|
|
240
|
-
await this.applyResult(extension.result, true);
|
|
342
|
+
this.recordAppliedCompaction(await this.applyResult(extension.result, true));
|
|
343
|
+
this.finishCompactionLifecycle("success");
|
|
241
344
|
this.deps.emit({
|
|
242
345
|
type: "compaction_end",
|
|
243
346
|
reason: "manual",
|
|
@@ -252,7 +355,7 @@ export class CompactionController {
|
|
|
252
355
|
measureLiveTokens: () => Math.max(this.deps.estimateCurrentContextTokens(this.deps.agent.state.messages), 1),
|
|
253
356
|
shouldCompact: () => true,
|
|
254
357
|
getPostApplyMargin: () => 0,
|
|
255
|
-
getBranch: () => this.
|
|
358
|
+
getBranch: () => this.getCompactionBranch(),
|
|
256
359
|
getBaseKeepRecentTokens: () => settings.keepRecentTokens,
|
|
257
360
|
resolveModelAndAuth: async (modelTier) => {
|
|
258
361
|
const model = modelTier === "cheap" ? selectedCompactionModel : sessionModel;
|
|
@@ -263,7 +366,7 @@ export class CompactionController {
|
|
|
263
366
|
if (!preparation)
|
|
264
367
|
throw new Error("Nothing to compact (session too small)");
|
|
265
368
|
const compactionThinkingLevel = this.deps.resolveThinkingLevel(model, sessionModel);
|
|
266
|
-
const result = await this.deps.compactWithRetry(() => compact(preparation, model, apiKey, headers, effectiveInstructions, signal, compactionThinkingLevel, this.deps.agent.streamFn, this.deps.buildPreDigest(),
|
|
369
|
+
const result = await this.deps.compactWithRetry(() => compact(preparation, model, apiKey, headers, effectiveInstructions, signal, compactionThinkingLevel, this.deps.agent.streamFn, this.deps.buildPreDigest(), this.buildExecutionOptions(preparation, settings, model, sessionModel, params.chunked)), signal, model.provider);
|
|
267
370
|
return { result };
|
|
268
371
|
},
|
|
269
372
|
buildDeterministicCheckpoint: (params) => {
|
|
@@ -275,7 +378,7 @@ export class CompactionController {
|
|
|
275
378
|
apply: async (result) => {
|
|
276
379
|
if (signal.aborted)
|
|
277
380
|
throw new Error("Compaction cancelled");
|
|
278
|
-
await this.applyResult(result, false);
|
|
381
|
+
this.recordAppliedCompaction(await this.applyResult(result, false));
|
|
279
382
|
appliedResult = result;
|
|
280
383
|
},
|
|
281
384
|
verifyPostApplyEffect: () => false,
|
|
@@ -295,6 +398,7 @@ export class CompactionController {
|
|
|
295
398
|
if (outcome.kind === "skip" || !appliedResult) {
|
|
296
399
|
throw new Error(outcome.kind === "skip" ? outcome.reason : "Compaction failed");
|
|
297
400
|
}
|
|
401
|
+
this.finishCompactionLifecycle("success");
|
|
298
402
|
this.deps.emit({
|
|
299
403
|
type: "compaction_end",
|
|
300
404
|
reason: "manual",
|
|
@@ -314,7 +418,7 @@ export class CompactionController {
|
|
|
314
418
|
const contextWindow = model?.contextWindow ?? 0;
|
|
315
419
|
const sameModel = model && assistantMessage.provider === model.provider && assistantMessage.model === model.id;
|
|
316
420
|
const compactionEntry = getLatestCompactionEntry(this.deps.sessionManager.getBranch());
|
|
317
|
-
const assistantIsFromBeforeCompaction =
|
|
421
|
+
const assistantIsFromBeforeCompaction = this.isAssistantFromBeforeCompaction(assistantMessage, compactionEntry);
|
|
318
422
|
if (assistantIsFromBeforeCompaction)
|
|
319
423
|
return false;
|
|
320
424
|
if (sameModel && isContextOverflow(assistantMessage, contextWindow)) {
|
|
@@ -350,9 +454,7 @@ export class CompactionController {
|
|
|
350
454
|
if (estimate.lastUsageIndex === null)
|
|
351
455
|
return false;
|
|
352
456
|
const usageMessage = messages[estimate.lastUsageIndex];
|
|
353
|
-
if (compactionEntry
|
|
354
|
-
usageMessage.role === "assistant" &&
|
|
355
|
-
usageMessage.timestamp <= new Date(compactionEntry.timestamp).getTime()) {
|
|
457
|
+
if (usageMessage.role === "assistant" && this.isAssistantFromBeforeCompaction(usageMessage, compactionEntry)) {
|
|
356
458
|
return false;
|
|
357
459
|
}
|
|
358
460
|
contextTokens = estimate.tokens;
|
|
@@ -362,9 +464,7 @@ export class CompactionController {
|
|
|
362
464
|
const estimate = estimateContextTokens(this.deps.agent.state.messages);
|
|
363
465
|
if (estimate.lastUsageIndex !== null) {
|
|
364
466
|
const usageMessage = this.deps.agent.state.messages[estimate.lastUsageIndex];
|
|
365
|
-
const usageIsPostCompaction = !(
|
|
366
|
-
usageMessage.role === "assistant" &&
|
|
367
|
-
usageMessage.timestamp <= new Date(compactionEntry.timestamp).getTime());
|
|
467
|
+
const usageIsPostCompaction = !(usageMessage.role === "assistant" && this.isAssistantFromBeforeCompaction(usageMessage, compactionEntry));
|
|
368
468
|
if (usageIsPostCompaction)
|
|
369
469
|
contextTokens = Math.max(contextTokens, estimate.tokens);
|
|
370
470
|
}
|
|
@@ -385,11 +485,27 @@ export class CompactionController {
|
|
|
385
485
|
return estimatedTokens;
|
|
386
486
|
}
|
|
387
487
|
const compactionEntry = getLatestCompactionEntry(this.deps.sessionManager.getBranch());
|
|
388
|
-
if (
|
|
488
|
+
if (this.isAssistantFromBeforeCompaction(assistantMessage, compactionEntry)) {
|
|
389
489
|
return estimatedTokens;
|
|
390
490
|
}
|
|
391
491
|
return Math.max(calculateContextTokens(assistantMessage.usage), estimatedTokens);
|
|
392
492
|
}
|
|
493
|
+
/** Prefer authoritative branch order; timestamps are only a fallback for reconstructed messages. */
|
|
494
|
+
isAssistantFromBeforeCompaction(assistantMessage, compactionEntry) {
|
|
495
|
+
if (!compactionEntry)
|
|
496
|
+
return false;
|
|
497
|
+
const branch = this.deps.sessionManager.getBranch();
|
|
498
|
+
const compactionPosition = branch.findIndex((entry) => entry.id === compactionEntry.id);
|
|
499
|
+
if (compactionPosition >= 0) {
|
|
500
|
+
for (let position = branch.length - 1; position >= 0; position--) {
|
|
501
|
+
const entry = branch[position];
|
|
502
|
+
if (entry?.type === "message" && entry.message === assistantMessage) {
|
|
503
|
+
return position < compactionPosition;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
return assistantMessage.timestamp <= new Date(compactionEntry.timestamp).getTime();
|
|
508
|
+
}
|
|
393
509
|
get isCompacting() {
|
|
394
510
|
return this.isRunning();
|
|
395
511
|
}
|
|
@@ -421,6 +537,8 @@ export class CompactionController {
|
|
|
421
537
|
let fromExtension = false;
|
|
422
538
|
let lastCompaction;
|
|
423
539
|
let extensionCancelled = false;
|
|
540
|
+
let effectiveInstructions;
|
|
541
|
+
let effectiveInstructionsReady = false;
|
|
424
542
|
try {
|
|
425
543
|
if (!model) {
|
|
426
544
|
this.deps.emit({
|
|
@@ -435,10 +553,20 @@ export class CompactionController {
|
|
|
435
553
|
}
|
|
436
554
|
const contextWindow = model.contextWindow;
|
|
437
555
|
const margin = Math.max(0, Math.floor(0.01 * contextWindow));
|
|
438
|
-
//
|
|
439
|
-
|
|
556
|
+
// When the caller supplied the exact request total (or recovery makes compaction mandatory),
|
|
557
|
+
// open the transaction before model/auth resolution. Threshold runs without an admitted total
|
|
558
|
+
// stay lazy so a changing live measurement cannot create a marker for a later no-op skip.
|
|
559
|
+
const canPreflight = reason !== "threshold" || options.initialTokens !== undefined;
|
|
560
|
+
const preflightShouldCompact = reason !== "threshold" ||
|
|
561
|
+
(options.initialTokens !== undefined &&
|
|
562
|
+
shouldCompact(options.initialTokens, contextWindow, settings, model.autoCompactionTriggerTokens));
|
|
563
|
+
if (canPreflight && preflightShouldCompact) {
|
|
564
|
+
const preflightPreparation = prepareCompaction(this.getCompactionBranch(), settings, options.allowTrailingCompactionAsPrevious ? COMPACTION_RETRY_PREPARATION_OPTIONS : undefined);
|
|
565
|
+
if (preflightPreparation)
|
|
566
|
+
this.beginCompactionLifecycle(preflightPreparation);
|
|
567
|
+
}
|
|
440
568
|
const outcome = await runCompactionLoop({
|
|
441
|
-
getBranch: () => this.
|
|
569
|
+
getBranch: () => this.getCompactionBranch(),
|
|
442
570
|
measureLiveTokens: () => options.initialTokens ?? this.deps.measureLiveContextTokens(),
|
|
443
571
|
shouldCompact: reason === "threshold"
|
|
444
572
|
? (tokens) => shouldCompact(tokens, contextWindow, settings, model.autoCompactionTriggerTokens)
|
|
@@ -454,6 +582,12 @@ export class CompactionController {
|
|
|
454
582
|
}, COMPACTION_RETRY_PREPARATION_OPTIONS);
|
|
455
583
|
if (!preparation)
|
|
456
584
|
throw new Error("already compacted");
|
|
585
|
+
this.beginCompactionLifecycle(preparation);
|
|
586
|
+
// One event-driven handoff per compaction run; every retry reuses this bounded value.
|
|
587
|
+
if (!effectiveInstructionsReady) {
|
|
588
|
+
effectiveInstructions = await this.buildCompactionInstructions();
|
|
589
|
+
effectiveInstructionsReady = true;
|
|
590
|
+
}
|
|
457
591
|
const compactionThinkingLevel = this.deps.resolveThinkingLevel(compactModel, model);
|
|
458
592
|
const extension = await this.getExtensionCompaction(preparation, branchEntries, effectiveInstructions, signal);
|
|
459
593
|
if (extension.cancelled) {
|
|
@@ -464,19 +598,20 @@ export class CompactionController {
|
|
|
464
598
|
fromExtension = true;
|
|
465
599
|
return { result: extension.result };
|
|
466
600
|
}
|
|
467
|
-
const result = await this.deps.compactWithRetry(() => compact(preparation, compactModel, apiKey, headers, effectiveInstructions, signal, compactionThinkingLevel, this.deps.agent.streamFn, this.deps.buildPreDigest(),
|
|
601
|
+
const result = await this.deps.compactWithRetry(() => compact(preparation, compactModel, apiKey, headers, effectiveInstructions, signal, compactionThinkingLevel, this.deps.agent.streamFn, this.deps.buildPreDigest(), this.buildExecutionOptions(preparation, settings, compactModel, model, params.chunked)), signal, compactModel.provider);
|
|
468
602
|
return { result };
|
|
469
603
|
},
|
|
470
604
|
buildDeterministicCheckpoint: (params) => {
|
|
471
|
-
const preparation = prepareCompaction(this.
|
|
605
|
+
const preparation = prepareCompaction(this.getCompactionBranch(), { ...settings, keepRecentTokens: params.keepRecentTokens }, COMPACTION_RETRY_PREPARATION_OPTIONS);
|
|
472
606
|
if (!preparation)
|
|
473
607
|
throw new Error("already compacted");
|
|
608
|
+
this.beginCompactionLifecycle(preparation);
|
|
474
609
|
fromExtension = false;
|
|
475
610
|
return { result: createDeterministicCompaction(preparation) };
|
|
476
611
|
},
|
|
477
612
|
apply: async (result) => {
|
|
478
613
|
lastCompaction = result;
|
|
479
|
-
await this.applyResult(result, fromExtension);
|
|
614
|
+
this.recordAppliedCompaction(await this.applyResult(result, fromExtension));
|
|
480
615
|
},
|
|
481
616
|
verifyPostApplyEffect: reason !== "threshold" || options.singlePass ? () => false : undefined,
|
|
482
617
|
allowTrailingCompactionAsPrevious: options.allowTrailingCompactionAsPrevious,
|
|
@@ -490,6 +625,7 @@ export class CompactionController {
|
|
|
490
625
|
signal,
|
|
491
626
|
});
|
|
492
627
|
if (outcome.kind === "skip") {
|
|
628
|
+
this.finishCompactionLifecycle("failure", outcome.reason);
|
|
493
629
|
this.deps.emit({
|
|
494
630
|
type: "compaction_end",
|
|
495
631
|
reason,
|
|
@@ -502,12 +638,14 @@ export class CompactionController {
|
|
|
502
638
|
}
|
|
503
639
|
if (outcome.kind === "failed") {
|
|
504
640
|
if (outcome.reason === "aborted") {
|
|
641
|
+
this.finishCompactionLifecycle("cancelled");
|
|
505
642
|
this.deps.emit({ type: "compaction_end", reason, result: undefined, aborted: true, willRetry: false });
|
|
506
643
|
return hadQueuedMessages || this.deps.agent.hasQueuedMessages();
|
|
507
644
|
}
|
|
508
645
|
throw new Error(outcome.reason);
|
|
509
646
|
}
|
|
510
647
|
if (extensionCancelled || signal.aborted) {
|
|
648
|
+
this.finishCompactionLifecycle("cancelled");
|
|
511
649
|
this.deps.emit({ type: "compaction_end", reason, result: undefined, aborted: true, willRetry: false });
|
|
512
650
|
return hadQueuedMessages || this.deps.agent.hasQueuedMessages();
|
|
513
651
|
}
|
|
@@ -524,24 +662,29 @@ export class CompactionController {
|
|
|
524
662
|
if (reason === "provider_recovery")
|
|
525
663
|
this.appendProviderRecoveryContinuation();
|
|
526
664
|
}
|
|
665
|
+
this.finishCompactionLifecycle("success");
|
|
527
666
|
this.deps.emit({ type: "compaction_end", reason, result, aborted: false, willRetry });
|
|
528
667
|
if (willRetry)
|
|
529
668
|
return true;
|
|
530
669
|
return hadQueuedMessages || this.deps.agent.hasQueuedMessages();
|
|
531
670
|
}
|
|
532
671
|
catch (error) {
|
|
533
|
-
const errorMessage = error
|
|
672
|
+
const errorMessage = boundedCompactionLifecycleError(error);
|
|
673
|
+
const aborted = extensionCancelled || signal.aborted || errorMessage === "Compaction cancelled";
|
|
674
|
+
this.finishCompactionLifecycle(aborted ? "cancelled" : "failure", aborted ? undefined : error);
|
|
534
675
|
this.deps.emit({
|
|
535
676
|
type: "compaction_end",
|
|
536
677
|
reason,
|
|
537
678
|
result: undefined,
|
|
538
|
-
aborted
|
|
679
|
+
aborted,
|
|
539
680
|
willRetry: false,
|
|
540
|
-
errorMessage:
|
|
541
|
-
?
|
|
542
|
-
: reason === "
|
|
543
|
-
? `
|
|
544
|
-
:
|
|
681
|
+
errorMessage: aborted
|
|
682
|
+
? undefined
|
|
683
|
+
: reason === "overflow"
|
|
684
|
+
? `Context overflow recovery failed: ${errorMessage}`
|
|
685
|
+
: reason === "provider_recovery"
|
|
686
|
+
? `Provider failure recovery failed: ${errorMessage}`
|
|
687
|
+
: `Auto-compaction failed: ${errorMessage}`,
|
|
545
688
|
});
|
|
546
689
|
return hadQueuedMessages || this.deps.agent.hasQueuedMessages();
|
|
547
690
|
}
|
|
@@ -644,10 +787,27 @@ export class CompactionController {
|
|
|
644
787
|
customInstructions,
|
|
645
788
|
signal,
|
|
646
789
|
}));
|
|
647
|
-
|
|
790
|
+
const result = extensionResult?.compaction;
|
|
791
|
+
return {
|
|
792
|
+
cancelled: extensionResult?.cancel === true,
|
|
793
|
+
result: result && preparation.retention
|
|
794
|
+
? {
|
|
795
|
+
...result,
|
|
796
|
+
firstKeptEntryId: preparation.firstKeptEntryId,
|
|
797
|
+
retention: preparation.retention,
|
|
798
|
+
}
|
|
799
|
+
: result,
|
|
800
|
+
};
|
|
648
801
|
}
|
|
649
802
|
async applyResult(result, fromExtension) {
|
|
650
|
-
this.deps.sessionManager.
|
|
803
|
+
const sessionFile = this.deps.sessionManager.getSessionFile();
|
|
804
|
+
if (result.retention?.mode === "original-user" && sessionFile) {
|
|
805
|
+
const transcriptPointer = `Full pre-compaction transcript: ${sessionFile}`;
|
|
806
|
+
if (!result.summary.includes(transcriptPointer)) {
|
|
807
|
+
result.summary = `${result.summary.trimEnd()}\n\n${transcriptPointer}`;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
const compactionEntryId = this.deps.sessionManager.appendCompaction(result.summary, result.firstKeptEntryId, result.tokensBefore, result.details, fromExtension, result.usage, result.retention);
|
|
651
811
|
this.deps.refreshAfterCompaction();
|
|
652
812
|
const savedEntry = this.deps.sessionManager
|
|
653
813
|
.getEntries()
|
|
@@ -659,6 +819,7 @@ export class CompactionController {
|
|
|
659
819
|
fromExtension,
|
|
660
820
|
});
|
|
661
821
|
}
|
|
822
|
+
return compactionEntryId;
|
|
662
823
|
}
|
|
663
824
|
}
|
|
664
825
|
//# sourceMappingURL=compaction-controller.js.map
|