shariq-pi-extensions 0.2.31 → 0.2.33

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.
@@ -25,11 +25,11 @@ When long-running agent sessions reach context thresholds, standard compaction f
25
25
  - **Fail-Closed Validation**: Accepts only `stopReason === "stop"` and rejects tool calls, empty output, or summaries missing required section headers.
26
26
  - **Lockfile & Bundle Diff Exclusion**: Automatically excludes `package-lock.json`, `Cargo.lock`, `yarn.lock`, `pnpm-lock.yaml`, and minified assets from raw diffs, recording their status under `<modified-lockfiles-and-assets>` to preserve 100% of diff token headroom for source code.
27
27
  - **Background Daemon & Terminal Awareness**: Automatically detects running background terminals/processes and injects their status into `<active-background-processes>` so the successor agent never launches duplicate services.
28
- - **Retry Ladder**: If an attempt encounters output limits or transient reasoning timeouts:
28
+ - **Retry Ladder & Extended Prefill Timeout**: Compaction requests receive an extended 10-minute timeout (600,000ms) to accommodate large 1M context prefills. If an attempt encounters output limits or transient reasoning timeouts:
29
29
  1. Primary configured model with requested reasoning.
30
30
  2. Primary model with reasoning off (unblocks reasoning/token caps).
31
31
  3. Session model with reasoning off.
32
- 4. Graceful fallback to Pi's default compactor if all stages fail.
32
+ 4. Strict Fail-Closed Protection: If all stages fail, compaction is cancelled to preserve 100% of the conversation transcript rather than silently degrading to Pi's generic compactor.
33
33
  - **Two-Ended Head & Tail Truncation**: Preserves both the beginning (context) and end (stack traces, compiler errors, exit codes, test summaries) of tool results and command logs.
34
34
  - **100% Full-Fidelity Data Preservation**: Preserves all user-provided data, credentials, environment variables, tool inputs, and code verbatim across compactions without stripping or redaction.
35
35
  - **Deterministic 10+ Cycle Stability**: Persists machine-readable touch, dirty-file, bounded-patch, and cycle ledgers in `CompactionEntry.details`; hierarchical delta merging keeps immutable constraints while condensing obsolete history.
@@ -15,6 +15,9 @@ import {
15
15
  serializeConversationForCompaction,
16
16
  } from "./prompt.ts";
17
17
 
18
+ // Extended 10-minute timeout for large context prefills (up to 1M+ tokens on Gemini/Claude)
19
+ export const COMPACTION_TIMEOUT_MS = 10 * 60 * 1000;
20
+
18
21
  export interface DirtyFileState {
19
22
  path: string;
20
23
  status: string;
@@ -289,7 +292,8 @@ const REQUIRED_SECTION_PATTERNS = [
289
292
 
290
293
  export function validateSummaryOutput(response: AssistantMessage): string {
291
294
  if (response.stopReason !== "stop") {
292
- throw new Error(`Compaction model did not complete successfully (stopReason="${response.stopReason}").`);
295
+ const errorDetails = response.errorMessage ? `: ${response.errorMessage}` : "";
296
+ throw new Error(`Compaction model did not complete successfully (stopReason="${response.stopReason}"${errorDetails}).`);
293
297
  }
294
298
 
295
299
  // Reject accidental tool calls
@@ -483,9 +487,21 @@ export async function runSmartCompaction(
483
487
  activeIsInherited = plan.isInherited;
484
488
 
485
489
  const tokenCeiling = computeCompactionTokenCeiling(plan.model, config, reserveTokens);
490
+
491
+ const timeoutController = new AbortController();
492
+ const timeoutTimer = setTimeout(() => {
493
+ timeoutController.abort(
494
+ new Error(`Compaction stage "${plan.stageLabel}" timed out after 10 minutes.`),
495
+ );
496
+ }, COMPACTION_TIMEOUT_MS);
497
+
498
+ const stageSignal = signal
499
+ ? AbortSignal.any([signal, timeoutController.signal])
500
+ : timeoutController.signal;
501
+
486
502
  const completeOptions: Record<string, unknown> = {
487
503
  maxTokens: tokenCeiling,
488
- signal,
504
+ signal: stageSignal,
489
505
  cacheRetention: "none",
490
506
  sessionId: uuidv7(),
491
507
  };
@@ -496,7 +512,7 @@ export async function runSmartCompaction(
496
512
 
497
513
  try {
498
514
  const response = await ctx.modelRegistry.complete(plan.model, context, completeOptions as any);
499
- signal?.throwIfAborted();
515
+ stageSignal.throwIfAborted();
500
516
  if (response.usage) {
501
517
  accumulatedUsage = combineCompactionUsage(accumulatedUsage, response.usage);
502
518
  }
@@ -509,6 +525,8 @@ export async function runSmartCompaction(
509
525
  throw err instanceof Error ? err : new Error(String(err));
510
526
  }
511
527
  lastError = err instanceof Error ? err : new Error(String(err));
528
+ } finally {
529
+ clearTimeout(timeoutTimer);
512
530
  }
513
531
  }
514
532
 
@@ -57,8 +57,10 @@ export function createSmartCompactionExtension(options: SmartCompactionExtension
57
57
  throw error;
58
58
  }
59
59
  const message = error instanceof Error ? error.message : String(error);
60
- ctx.ui?.notify(`Smart Compaction failed: ${message}. Falling back to default compactor.`, "warning");
61
- return undefined;
60
+ ctx.ui?.notify(`Smart Compaction failed: ${message}. Compaction cancelled to protect context.`, "error");
61
+ // Fail-Closed: Return cancel: true so Pi aborts compaction and preserves all conversation context
62
+ // rather than silently falling back to Pi's generic compactor.
63
+ return { cancel: true };
62
64
  } finally {
63
65
  updateStatus();
64
66
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shariq-pi-extensions",
3
- "version": "0.2.31",
3
+ "version": "0.2.33",
4
4
  "description": "Cross-platform extension suite for the Pi coding agent.",
5
5
  "license": "MIT",
6
6
  "author": "Shariq Riaz",