@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.
Files changed (104) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/core/agent-session.d.ts +1 -0
  3. package/dist/core/agent-session.d.ts.map +1 -1
  4. package/dist/core/agent-session.js +22 -12
  5. package/dist/core/agent-session.js.map +1 -1
  6. package/dist/core/compaction-controller.d.ts +22 -0
  7. package/dist/core/compaction-controller.d.ts.map +1 -1
  8. package/dist/core/compaction-controller.js +191 -30
  9. package/dist/core/compaction-controller.js.map +1 -1
  10. package/dist/core/compaction-support.d.ts.map +1 -1
  11. package/dist/core/compaction-support.js +21 -1
  12. package/dist/core/compaction-support.js.map +1 -1
  13. package/dist/core/delegation/worker-agent-control-coordinator.d.ts.map +1 -1
  14. package/dist/core/delegation/worker-agent-control-coordinator.js +1 -0
  15. package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -1
  16. package/dist/core/delegation/worker-agent-control.d.ts +2 -0
  17. package/dist/core/delegation/worker-agent-control.d.ts.map +1 -1
  18. package/dist/core/delegation/worker-agent-control.js.map +1 -1
  19. package/dist/core/foreground-lifecycle-adapter.d.ts +27 -0
  20. package/dist/core/foreground-lifecycle-adapter.d.ts.map +1 -0
  21. package/dist/core/foreground-lifecycle-adapter.js +61 -0
  22. package/dist/core/foreground-lifecycle-adapter.js.map +1 -0
  23. package/dist/core/foreground-lifecycle-controller.d.ts +48 -0
  24. package/dist/core/foreground-lifecycle-controller.d.ts.map +1 -0
  25. package/dist/core/foreground-lifecycle-controller.js +404 -0
  26. package/dist/core/foreground-lifecycle-controller.js.map +1 -0
  27. package/dist/core/foreground-recovery-controller.d.ts +3 -0
  28. package/dist/core/foreground-recovery-controller.d.ts.map +1 -1
  29. package/dist/core/foreground-recovery-controller.js +15 -1
  30. package/dist/core/foreground-recovery-controller.js.map +1 -1
  31. package/dist/core/goals/goal-state.d.ts.map +1 -1
  32. package/dist/core/goals/goal-state.js +9 -2
  33. package/dist/core/goals/goal-state.js.map +1 -1
  34. package/dist/core/keybindings.d.ts +2 -2
  35. package/dist/core/keybindings.d.ts.map +1 -1
  36. package/dist/core/keybindings.js +2 -2
  37. package/dist/core/keybindings.js.map +1 -1
  38. package/dist/core/memory/memory-manager.d.ts +22 -0
  39. package/dist/core/memory/memory-manager.d.ts.map +1 -1
  40. package/dist/core/memory/memory-manager.js +108 -49
  41. package/dist/core/memory/memory-manager.js.map +1 -1
  42. package/dist/core/model-router/session-buffer.d.ts +10 -2
  43. package/dist/core/model-router/session-buffer.d.ts.map +1 -1
  44. package/dist/core/model-router/session-buffer.js +35 -9
  45. package/dist/core/model-router/session-buffer.js.map +1 -1
  46. package/dist/core/model-router-controller.d.ts +20 -2
  47. package/dist/core/model-router-controller.d.ts.map +1 -1
  48. package/dist/core/model-router-controller.js +70 -17
  49. package/dist/core/model-router-controller.js.map +1 -1
  50. package/dist/core/provider-request-runtime-controller.d.ts +12 -1
  51. package/dist/core/provider-request-runtime-controller.d.ts.map +1 -1
  52. package/dist/core/provider-request-runtime-controller.js +45 -2
  53. package/dist/core/provider-request-runtime-controller.js.map +1 -1
  54. package/dist/core/settings-manager.d.ts +1 -0
  55. package/dist/core/settings-manager.d.ts.map +1 -1
  56. package/dist/core/settings-manager.js +3 -0
  57. package/dist/core/settings-manager.js.map +1 -1
  58. package/dist/core/tools/delegate.d.ts.map +1 -1
  59. package/dist/core/tools/delegate.js +4 -2
  60. package/dist/core/tools/delegate.js.map +1 -1
  61. package/dist/modes/interactive/components/assistant-message.d.ts +1 -3
  62. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  63. package/dist/modes/interactive/components/assistant-message.js +10 -20
  64. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  65. package/dist/modes/interactive/components/tool-group.d.ts +3 -0
  66. package/dist/modes/interactive/components/tool-group.d.ts.map +1 -1
  67. package/dist/modes/interactive/components/tool-group.js +25 -0
  68. package/dist/modes/interactive/components/tool-group.js.map +1 -1
  69. package/dist/modes/interactive/components/transcript-overlay.d.ts +13 -0
  70. package/dist/modes/interactive/components/transcript-overlay.d.ts.map +1 -0
  71. package/dist/modes/interactive/components/transcript-overlay.js +35 -0
  72. package/dist/modes/interactive/components/transcript-overlay.js.map +1 -0
  73. package/dist/modes/interactive/components/tree-selector.d.ts +1 -1
  74. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  75. package/dist/modes/interactive/components/tree-selector.js +7 -4
  76. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  77. package/dist/modes/interactive/interactive-event-controller.d.ts +1 -1
  78. package/dist/modes/interactive/interactive-event-controller.d.ts.map +1 -1
  79. package/dist/modes/interactive/interactive-event-controller.js +2 -1
  80. package/dist/modes/interactive/interactive-event-controller.js.map +1 -1
  81. package/dist/modes/interactive/interactive-mode.d.ts +9 -7
  82. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  83. package/dist/modes/interactive/interactive-mode.js +70 -99
  84. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  85. package/dist/modes/interactive/runtime-status-controller.d.ts +40 -0
  86. package/dist/modes/interactive/runtime-status-controller.d.ts.map +1 -0
  87. package/dist/modes/interactive/runtime-status-controller.js +147 -0
  88. package/dist/modes/interactive/runtime-status-controller.js.map +1 -0
  89. package/dist/modes/interactive/runtime-status.d.ts +15 -0
  90. package/dist/modes/interactive/runtime-status.d.ts.map +1 -0
  91. package/dist/modes/interactive/runtime-status.js +18 -0
  92. package/dist/modes/interactive/runtime-status.js.map +1 -0
  93. package/docs/json.md +1 -1
  94. package/docs/keybindings.md +2 -1
  95. package/docs/session-format.md +59 -4
  96. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  97. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  98. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  99. package/examples/extensions/sandbox/package-lock.json +2 -2
  100. package/examples/extensions/sandbox/package.json +1 -1
  101. package/examples/extensions/with-deps/package-lock.json +2 -2
  102. package/examples/extensions/with-deps/package.json +1 -1
  103. package/npm-shrinkwrap.json +12 -12
  104. 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":"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"}
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.deps.sessionManager.getBranch();
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.deps.sessionManager.getBranch(),
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(), { chunked: params.chunked }), signal, model.provider);
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 = compactionEntry !== null && assistantMessage.timestamp <= new Date(compactionEntry.timestamp).getTime();
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 = !(compactionEntry &&
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 (compactionEntry && assistantMessage.timestamp <= new Date(compactionEntry.timestamp).getTime()) {
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
- // One event-driven handoff per compaction run; every retry reuses this bounded value.
439
- const effectiveInstructions = await this.buildCompactionInstructions();
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.deps.sessionManager.getBranch(),
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(), { chunked: params.chunked }), signal, compactModel.provider);
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.deps.sessionManager.getBranch(), { ...settings, keepRecentTokens: params.keepRecentTokens }, COMPACTION_RETRY_PREPARATION_OPTIONS);
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 instanceof Error ? error.message : "compaction failed";
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: false,
679
+ aborted,
539
680
  willRetry: false,
540
- errorMessage: reason === "overflow"
541
- ? `Context overflow recovery failed: ${errorMessage}`
542
- : reason === "provider_recovery"
543
- ? `Provider failure recovery failed: ${errorMessage}`
544
- : `Auto-compaction failed: ${errorMessage}`,
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
- return { cancelled: extensionResult?.cancel === true, result: extensionResult?.compaction };
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.appendCompaction(result.summary, result.firstKeptEntryId, result.tokensBefore, result.details, fromExtension, result.usage);
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