@nijaru/pi-provider-compaction 0.0.10 → 0.0.11

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/README.md CHANGED
@@ -77,9 +77,9 @@ Legacy v1/v2 whole-history checkpoints remain inspectable but are never reinterp
77
77
 
78
78
  ## Diagnose portable fallback
79
79
 
80
- Run `/provider-compaction-status` to see observer/capture eligibility, estimated cache lifetime, the last selected path, elapsed time, reported input/cache/output tokens, and estimated cost (including available companion corrections). Optional outcome notifications show measured usage after a committed compaction; hypothetical savings are not presented as measured. Failed/cancelled expiry attempts remain visible in runtime status; if no checkpoint is saved, their usage cannot be attached to compaction totals through Pi's extension API. Portable fallback also appends a `pi-provider-compaction:diagnostic` session entry containing only a fixed reason string. It is not included in model context. Diagnostics never include request content, credentials, or backend error text.
80
+ Committed compaction entries retain the selected path, elapsed time, reported usage, and estimated cost. Optional outcome notifications show those measurements, not hypothetical savings. Portable fallback appends a `pi-provider-compaction:diagnostic` session entry with a fixed reason. Cancelled attempts with reported usage retain that usage in the same diagnostic record; without a saved checkpoint, Pi's extension API cannot include it in compaction totals. Diagnostics stay out of model context and never include request content, credentials, or backend error text.
81
81
 
82
- These diagnostics require the extension to be loaded when the attempt happens; they cannot explain earlier compactions retroactively. A committed native checkpoint does not by itself prove that a later request replayed it.
82
+ These records describe attempts made while the extension was loaded; they cannot explain earlier compactions retroactively. A committed native checkpoint does not by itself prove that a later request replayed it.
83
83
 
84
84
  ## Generic compaction-model override
85
85
 
package/dist/index.js CHANGED
@@ -2274,30 +2274,10 @@ function pi_provider_compaction_default(pi) {
2274
2274
  let unregisterCleanup;
2275
2275
  let generation = 0;
2276
2276
  let requestSequence = 0;
2277
- let captureStatus = "no request observed";
2278
- let compactionStatus = "not attempted in this runtime";
2279
2277
  let fallbackReason;
2280
- const captureRejected = (reason) => {
2281
- captureStatus = reason;
2282
- };
2283
2278
  const fallback = (reason) => {
2284
2279
  fallbackReason = reason;
2285
- compactionStatus = `portable: ${reason}`;
2286
2280
  };
2287
- pi.registerCommand("provider-compaction-status", {
2288
- description: "Show cache/native eligibility and measured compaction usage",
2289
- handler: async (_args, context) => {
2290
- const state = cacheState(context);
2291
- const remaining = state.expiresAt === undefined ? "unknown lifetime" : `estimated ${Math.max(0, Math.ceil((state.expiresAt - Date.now()) / 1000))}s remaining (model declaration; best effort)`;
2292
- const usage = lastOutcome?.usage;
2293
- context.ui.notify(`Provider compaction
2294
- Observer: ${observer?.isInstalled() ? "installed" : "unavailable for current registration"}
2295
- Capture: ${captureStatus}
2296
- Cache: ${state.reason}; ${remaining}
2297
- Last attempt: ${compactionStatus}${lastOutcome ? `
2298
- Outcome: ${lastOutcome.path}, ${lastOutcome.elapsedMs}ms${usage ? `; input ${usage.input}, cache read ${usage.cacheRead}, write ${usage.cacheWrite}, output ${usage.output}; estimated cost $${usage.cost.total.toFixed(6)}` : "; usage unavailable"}${lastOutcome.reason ? `; ${lastOutcome.reason}` : ""}` : ""}`, "info");
2299
- }
2300
- });
2301
2281
  const invalidate = () => {
2302
2282
  generation++;
2303
2283
  runtimeId = randomUUID2();
@@ -2306,7 +2286,6 @@ Outcome: ${lastOutcome.path}, ${lastOutcome.elapsedMs}ms${usage ? `; input ${usa
2306
2286
  active = undefined;
2307
2287
  pending = undefined;
2308
2288
  expiryAttempt = undefined;
2309
- captureStatus = "invalidated by lifecycle/history/policy change";
2310
2289
  };
2311
2290
  const retire = () => {
2312
2291
  usageObservers.clear();
@@ -2396,23 +2375,12 @@ Outcome: ${lastOutcome.path}, ${lastOutcome.elapsedMs}ms${usage ? `; input ${usa
2396
2375
  return;
2397
2376
  if (compactionRequest)
2398
2377
  return;
2399
- if (!supportsNativeCompaction(model) && !supportsCachedSummary(model)) {
2400
- captureRejected("unsupported API");
2378
+ if (!supportsNativeCompaction(model) && !supportsCachedSummary(model))
2401
2379
  return;
2402
- }
2403
- if (!options.onPayload) {
2404
- if (captureStatus !== "eligible prepared request captured")
2405
- captureRejected("no payload callback");
2380
+ if (!options.onPayload || generic(owner))
2406
2381
  return;
2407
- }
2408
- if (generic(owner)) {
2409
- captureRejected("generic compaction model takes precedence");
2410
- return;
2411
- }
2412
- if (!supportedRouteOptions(model, options)) {
2413
- captureRejected("unsupported route overrides");
2382
+ if (!supportedRouteOptions(model, options))
2414
2383
  return;
2415
- }
2416
2384
  const ticket = generation;
2417
2385
  const startedAt = Date.now();
2418
2386
  const sequence = ++requestSequence;
@@ -2443,14 +2411,11 @@ Outcome: ${lastOutcome.path}, ${lastOutcome.elapsedMs}ms${usage ? `; input ${usa
2443
2411
  if (!auth.ok || generic(owner) || auth.apiKey !== options.apiKey || (auth.baseUrl ?? model.baseUrl) !== model.baseUrl || !equal(normalizedHeaders(auth.headers), normalizedHeaders(options.headers)) || !equal(auth.env ?? {}, options.env ?? {})) {
2444
2412
  active = undefined;
2445
2413
  cache = undefined;
2446
- captureRejected("resolved auth/route differs from prepared request, or generic policy changed");
2447
2414
  return payload;
2448
2415
  }
2449
2416
  const provider = owner.modelRegistry.getProvider(model.provider);
2450
- if (!provider) {
2451
- captureRejected("provider unavailable");
2417
+ if (!provider)
2452
2418
  return payload;
2453
- }
2454
2419
  const routeHash = route(model, options);
2455
2420
  if (config.cachedSummaries && supportsCachedSummary(model)) {
2456
2421
  const warming = options.maxTokens === 1 && cache && cache.authHash === routeDigest(auth) && sameCachedPrompt(cache.payload, payload) && equal(cache.context, context);
@@ -2469,11 +2434,9 @@ Outcome: ${lastOutcome.path}, ${lastOutcome.elapsedMs}ms${usage ? `; input ${usa
2469
2434
  if (!warming)
2470
2435
  cache = undefined;
2471
2436
  }
2472
- if (!supportsNativeCompaction(model)) {
2473
- captureStatus = candidate ? "eligible cached request captured" : "cached request ineligible";
2437
+ if (!supportsNativeCompaction(model))
2474
2438
  return payload;
2475
- }
2476
- const prepared = capturePreparedRequest(model, context, canonical, payload, captureRejected);
2439
+ const prepared = capturePreparedRequest(model, context, canonical, payload);
2477
2440
  if (!prepared) {
2478
2441
  active = undefined;
2479
2442
  return payload;
@@ -2502,7 +2465,6 @@ Outcome: ${lastOutcome.path}, ${lastOutcome.elapsedMs}ms${usage ? `; input ${usa
2502
2465
  active = undefined;
2503
2466
  } else
2504
2467
  active = undefined;
2505
- captureStatus = "eligible prepared request captured";
2506
2468
  snapshot = {
2507
2469
  prepared,
2508
2470
  model: structuredClone(model),
@@ -2540,7 +2502,6 @@ Outcome: ${lastOutcome.path}, ${lastOutcome.elapsedMs}ms${usage ? `; input ${usa
2540
2502
  if (!supportsNativeCompaction(context.model) && !supportsCachedSummary(context.model))
2541
2503
  return;
2542
2504
  observer = installObserver(pi, context, observe);
2543
- captureStatus = observer ? "awaiting prepared request" : "unsupported provider registration";
2544
2505
  };
2545
2506
  pi.on("session_start", (_event, context) => {
2546
2507
  retire();
@@ -2581,8 +2542,8 @@ Outcome: ${lastOutcome.path}, ${lastOutcome.elapsedMs}ms${usage ? `; input ${usa
2581
2542
  removeInvalidation();
2582
2543
  });
2583
2544
  pi.on("session_before_compact", async (event, context) => {
2584
- const began = Date.now();
2585
- compactionStatus = "preparing compaction";
2545
+ const began = Date.now(), ticket = generation;
2546
+ const sessionId = context.sessionManager.getSessionId();
2586
2547
  fallbackReason = undefined;
2587
2548
  const attempt = expiryAttempt;
2588
2549
  const capture = snapshot;
@@ -2591,7 +2552,12 @@ Outcome: ${lastOutcome.path}, ${lastOutcome.elapsedMs}ms${usage ? `; input ${usa
2591
2552
  cache = undefined;
2592
2553
  pending = undefined;
2593
2554
  const cancelled = (usage, reason = "compaction ownership or input changed") => {
2594
- lastOutcome = { path: attempt ? "expiry cancelled" : "cancelled", elapsedMs: Date.now() - began, usage, reason };
2555
+ if (usage && ticket === generation && ctx) {
2556
+ try {
2557
+ if (ctx.sessionManager.getSessionId() === sessionId)
2558
+ pi.appendEntry("pi-provider-compaction:diagnostic", { status: `${attempt ? "expiry cancelled" : "cancelled"}: ${reason}`, usage });
2559
+ } catch {}
2560
+ }
2595
2561
  return { cancel: true };
2596
2562
  };
2597
2563
  const reject = (reason) => {
@@ -2605,7 +2571,6 @@ Outcome: ${lastOutcome.path}, ${lastOutcome.elapsedMs}ms${usage ? `; input ${usa
2605
2571
  }
2606
2572
  if (!capture && !cached || !context.model || generic(context) || event.signal.aborted)
2607
2573
  return reject("no eligible snapshot, explicit model override, or aborted attempt");
2608
- const ticket = generation;
2609
2574
  const branch = context.sessionManager.getBranch();
2610
2575
  const branchHash = digest(branch);
2611
2576
  const source = cached ?? capture;
@@ -2630,7 +2595,6 @@ Outcome: ${lastOutcome.path}, ${lastOutcome.elapsedMs}ms${usage ? `; input ${usa
2630
2595
  let summaryPath = "standard";
2631
2596
  let summaryReason;
2632
2597
  if (cached) {
2633
- compactionStatus = "generating cached portable summary";
2634
2598
  compactionRequest = true;
2635
2599
  try {
2636
2600
  const result = await cachedSummary(cached, context, event.preparation, event.customInstructions, event.signal, current);
@@ -2650,7 +2614,6 @@ Outcome: ${lastOutcome.path}, ${lastOutcome.elapsedMs}ms${usage ? `; input ${usa
2650
2614
  return cancelled(attemptedUsage, summaryReason ?? "warm cache unavailable");
2651
2615
  if (!input && !attemptedUsage)
2652
2616
  return reject(summaryReason ?? fallbackReason ?? "native coverage unavailable");
2653
- compactionStatus = "generating portable summary";
2654
2617
  try {
2655
2618
  portable = await compact(event.preparation, source.model, auth.apiKey, auth.headers, event.customInstructions, event.signal, context.thinkingLevel, source.provider.streamSimple.bind(source.provider), auth.env, undefined, undefined, source.sessionId);
2656
2619
  portable = withFileTracking(portable, event.preparation);
@@ -2669,7 +2632,6 @@ Outcome: ${lastOutcome.path}, ${lastOutcome.elapsedMs}ms${usage ? `; input ${usa
2669
2632
  return { compaction: result };
2670
2633
  };
2671
2634
  if (!capture || !protocol || !input) {
2672
- compactionStatus = `${summaryPath} portable summary prepared`;
2673
2635
  return outcome(summaryPath, portable, summaryReason);
2674
2636
  }
2675
2637
  try {
@@ -2680,7 +2642,6 @@ Outcome: ${lastOutcome.path}, ${lastOutcome.elapsedMs}ms${usage ? `; input ${usa
2680
2642
  fallback("auth changed after portable generation");
2681
2643
  return outcome(summaryPath, portable, "native auth changed");
2682
2644
  }
2683
- compactionStatus = "requesting native checkpoint";
2684
2645
  let native;
2685
2646
  compactionRequest = true;
2686
2647
  try {
@@ -2742,19 +2703,12 @@ Outcome: ${lastOutcome.path}, ${lastOutcome.elapsedMs}ms${usage ? `; input ${usa
2742
2703
  pi.on("session_compact", (event, context) => {
2743
2704
  const recorded = isObject(event.compactionEntry.details) ? event.compactionEntry.details.providerCompaction : undefined;
2744
2705
  const owned = isObject(recorded) && equal(recorded, lastOutcome);
2745
- if (readNativeCompactionDetails(event.compactionEntry.details)?.version === 3)
2746
- compactionStatus = "native checkpoint committed";
2747
- else if (fallbackReason)
2748
- compactionStatus = `portable: ${fallbackReason}`;
2749
- else if (owned)
2750
- compactionStatus = `${lastOutcome.path} portable summary committed`;
2751
- else
2706
+ if (!owned && !fallbackReason && readNativeCompactionDetails(event.compactionEntry.details)?.version !== 3)
2752
2707
  fallback("another handler supplied the committed result");
2753
2708
  if (owned) {
2754
2709
  if (configuration().outcomeNotifications && lastOutcome)
2755
2710
  context.ui.notify(`Compacted via ${lastOutcome.path} in ${(lastOutcome.elapsedMs / 1000).toFixed(1)}s${lastOutcome.usage ? `; cache read ${lastOutcome.usage.cacheRead}, write ${lastOutcome.usage.cacheWrite}; estimated cost $${lastOutcome.usage.cost.total.toFixed(6)}` : ""}`, "info");
2756
- } else
2757
- lastOutcome = { path: "Pi/other handler", elapsedMs: 0, usage: event.compactionEntry.usage, reason: compactionStatus };
2711
+ }
2758
2712
  if (fallbackReason)
2759
2713
  pi.appendEntry("pi-provider-compaction:diagnostic", { status: `portable: ${fallbackReason}` });
2760
2714
  active = undefined;
@@ -2783,7 +2737,6 @@ Outcome: ${lastOutcome.path}, ${lastOutcome.elapsedMs}ms${usage ? `; input ${usa
2783
2737
  pending = undefined;
2784
2738
  snapshot = undefined;
2785
2739
  cache = undefined;
2786
- compactionStatus = "compaction failed or cancelled";
2787
2740
  });
2788
2741
  }
2789
2742
  export {
package/index.ts CHANGED
@@ -174,21 +174,9 @@ export default function (pi: ExtensionAPI): void {
174
174
  let unregisterCleanup: (() => void) | undefined;
175
175
  let generation = 0;
176
176
  let requestSequence = 0;
177
- let captureStatus = "no request observed";
178
- let compactionStatus = "not attempted in this runtime";
179
177
  let fallbackReason: string | undefined;
180
- const captureRejected = (reason: string) => { captureStatus = reason; };
181
- const fallback = (reason: string) => { fallbackReason = reason; compactionStatus = `portable: ${reason}`; };
182
- pi.registerCommand("provider-compaction-status", {
183
- description: "Show cache/native eligibility and measured compaction usage",
184
- handler: async (_args, context) => {
185
- const state = cacheState(context);
186
- const remaining = state.expiresAt === undefined ? "unknown lifetime" : `estimated ${Math.max(0, Math.ceil((state.expiresAt - Date.now()) / 1000))}s remaining (model declaration; best effort)`;
187
- const usage = lastOutcome?.usage;
188
- context.ui.notify(`Provider compaction\nObserver: ${observer?.isInstalled() ? "installed" : "unavailable for current registration"}\nCapture: ${captureStatus}\nCache: ${state.reason}; ${remaining}\nLast attempt: ${compactionStatus}${lastOutcome ? `\nOutcome: ${lastOutcome.path}, ${lastOutcome.elapsedMs}ms${usage ? `; input ${usage.input}, cache read ${usage.cacheRead}, write ${usage.cacheWrite}, output ${usage.output}; estimated cost $${usage.cost.total.toFixed(6)}` : "; usage unavailable"}${lastOutcome.reason ? `; ${lastOutcome.reason}` : ""}` : ""}`, "info");
189
- },
190
- });
191
- const invalidate = () => { generation++; runtimeId = randomUUID(); snapshot = undefined; cache = undefined; active = undefined; pending = undefined; expiryAttempt = undefined; captureStatus = "invalidated by lifecycle/history/policy change"; };
178
+ const fallback = (reason: string) => { fallbackReason = reason; };
179
+ const invalidate = () => { generation++; runtimeId = randomUUID(); snapshot = undefined; cache = undefined; active = undefined; pending = undefined; expiryAttempt = undefined; };
192
180
  const retire = () => {
193
181
  usageObservers.clear();
194
182
  invalidate();
@@ -260,17 +248,11 @@ export default function (pi: ExtensionAPI): void {
260
248
  }
261
249
  if (options.sessionId !== manager.getSessionId()) return;
262
250
  if (compactionRequest) return;
263
- if (!supportsNativeCompaction(model) && !supportsCachedSummary(model)) { captureRejected("unsupported API"); return; }
264
- if (!options.onPayload) {
265
- // The portable-summary request re-enters this observer without a payload
266
- // callback. Do not overwrite the main request's capture diagnostic.
267
- if (captureStatus !== "eligible prepared request captured") captureRejected("no payload callback");
268
- return;
269
- }
270
- if (generic(owner)) { captureRejected("generic compaction model takes precedence"); return; }
251
+ if (!supportsNativeCompaction(model) && !supportsCachedSummary(model)) return;
252
+ if (!options.onPayload || generic(owner)) return;
271
253
  // The Azure adapter also accepts API-specific overrides and process-env
272
254
  // fallbacks. Those must not silently select a route absent from our evidence.
273
- if (!supportedRouteOptions(model, options)) { captureRejected("unsupported route overrides"); return; }
255
+ if (!supportedRouteOptions(model, options)) return;
274
256
  const ticket = generation;
275
257
  const startedAt = Date.now();
276
258
  const sequence = ++requestSequence;
@@ -296,11 +278,10 @@ export default function (pi: ExtensionAPI): void {
296
278
  const normalizedHeaders = (headers: ProviderHeaders | undefined) => Object.entries(headers ?? {}).map(([name, value]) => [name.toLowerCase(), value]).sort(([a], [b]) => String(a).localeCompare(String(b)));
297
279
  if (!auth.ok || generic(owner) || auth.apiKey !== options.apiKey || (auth.baseUrl ?? model.baseUrl) !== model.baseUrl || !equal(normalizedHeaders(auth.headers), normalizedHeaders(options.headers)) || !equal(auth.env ?? {}, options.env ?? {})) {
298
280
  active = undefined; cache = undefined;
299
- captureRejected("resolved auth/route differs from prepared request, or generic policy changed");
300
281
  return payload;
301
282
  }
302
283
  const provider = owner.modelRegistry.getProvider(model.provider);
303
- if (!provider) { captureRejected("provider unavailable"); return payload; }
284
+ if (!provider) return payload;
304
285
  const routeHash = route(model, options);
305
286
  if (config.cachedSummaries && supportsCachedSummary(model)) {
306
287
  const warming = options.maxTokens === 1 && cache && cache.authHash === routeDigest(auth) && sameCachedPrompt(cache.payload, payload) && equal(cache.context, context);
@@ -310,8 +291,8 @@ export default function (pi: ExtensionAPI): void {
310
291
  }, payload);
311
292
  if (!warming) cache = undefined;
312
293
  }
313
- if (!supportsNativeCompaction(model)) { captureStatus = candidate ? "eligible cached request captured" : "cached request ineligible"; return payload; }
314
- const prepared = capturePreparedRequest(model, context, canonical, payload, captureRejected);
294
+ if (!supportsNativeCompaction(model)) return payload;
295
+ const prepared = capturePreparedRequest(model, context, canonical, payload);
315
296
  if (!prepared) { active = undefined; return payload; }
316
297
  const policyHash = digest(requestPolicy(model, prepared));
317
298
  const latest = latestCompaction(branch);
@@ -334,7 +315,6 @@ export default function (pi: ExtensionAPI): void {
334
315
  } else active = undefined;
335
316
  } else active = undefined;
336
317
  } else active = undefined;
337
- captureStatus = "eligible prepared request captured";
338
318
  snapshot = {
339
319
  prepared, model: structuredClone(model), provider,
340
320
  options: { apiKey: options.apiKey, headers: structuredClone(options.headers), env: structuredClone(options.env), fetch: options.fetch, ...(typeof (options as { serviceTier?: unknown }).serviceTier === "string" ? { serviceTier: (options as { serviceTier: string }).serviceTier } : {}) },
@@ -359,7 +339,6 @@ export default function (pi: ExtensionAPI): void {
359
339
  if (observer) { invalidate(); observer.remove(); observer = undefined; }
360
340
  if (!supportsNativeCompaction(context.model) && !supportsCachedSummary(context.model)) return;
361
341
  observer = installObserver(pi, context, observe);
362
- captureStatus = observer ? "awaiting prepared request" : "unsupported provider registration";
363
342
  };
364
343
  pi.on("session_start", (_event, context) => {
365
344
  retire();
@@ -386,15 +365,21 @@ export default function (pi: ExtensionAPI): void {
386
365
  pi.on("session_shutdown", () => { if (typeof removeInvalidation === "function") removeInvalidation(); });
387
366
 
388
367
  pi.on("session_before_compact", async (event, context) => {
389
- const began = Date.now();
390
- compactionStatus = "preparing compaction";
368
+ const began = Date.now(), ticket = generation;
369
+ const sessionId = context.sessionManager.getSessionId();
391
370
  fallbackReason = undefined;
392
371
  const attempt = expiryAttempt;
393
372
  const capture = snapshot;
394
373
  const cached = cacheState(context).available ? cache : undefined;
395
374
  snapshot = undefined; cache = undefined; pending = undefined;
396
375
  const cancelled = (usage?: Usage, reason = "compaction ownership or input changed") => {
397
- lastOutcome = { path: attempt ? "expiry cancelled" : "cancelled", elapsedMs: Date.now() - began, usage, reason };
376
+ // A cancelled attempt has no checkpoint to carry its known bill. Retain
377
+ // that usage in the existing session diagnostic, not a command-only cache.
378
+ if (usage && ticket === generation && ctx) {
379
+ try {
380
+ if (ctx.sessionManager.getSessionId() === sessionId) pi.appendEntry("pi-provider-compaction:diagnostic", { status: `${attempt ? "expiry cancelled" : "cancelled"}: ${reason}`, usage });
381
+ } catch { /* A disposed session cannot accept a diagnostic. */ }
382
+ }
398
383
  return { cancel: true as const };
399
384
  };
400
385
  const reject = (reason: string) => {
@@ -408,7 +393,6 @@ export default function (pi: ExtensionAPI): void {
408
393
  attempt.signal = event.signal;
409
394
  }
410
395
  if ((!capture && !cached) || !context.model || generic(context) || event.signal.aborted) return reject("no eligible snapshot, explicit model override, or aborted attempt");
411
- const ticket = generation;
412
396
  const branch = context.sessionManager.getBranch();
413
397
  const branchHash = digest(branch);
414
398
  const source = cached ?? capture!;
@@ -431,7 +415,6 @@ export default function (pi: ExtensionAPI): void {
431
415
  let summaryPath = "standard";
432
416
  let summaryReason: string | undefined;
433
417
  if (cached) {
434
- compactionStatus = "generating cached portable summary";
435
418
  compactionRequest = true;
436
419
  try {
437
420
  const result = await cachedSummary(cached, context, event.preparation, event.customInstructions, event.signal, current);
@@ -446,7 +429,6 @@ export default function (pi: ExtensionAPI): void {
446
429
  if (attempt) return cancelled(attemptedUsage, summaryReason ?? "warm cache unavailable");
447
430
  // Without native coverage or a dispatched cached attempt, Pi can own fallback.
448
431
  if (!input && !attemptedUsage) return reject(summaryReason ?? fallbackReason ?? "native coverage unavailable");
449
- compactionStatus = "generating portable summary";
450
432
  try {
451
433
  portable = await compact(event.preparation, source.model, auth.apiKey, auth.headers as Record<string, string> | undefined, event.customInstructions, event.signal, context.thinkingLevel, source.provider.streamSimple.bind(source.provider), auth.env, undefined, undefined, source.sessionId);
452
434
  portable = withFileTracking(portable, event.preparation);
@@ -463,14 +445,12 @@ export default function (pi: ExtensionAPI): void {
463
445
  return { compaction: result! };
464
446
  };
465
447
  if (!capture || !protocol || !input) {
466
- compactionStatus = `${summaryPath} portable summary prepared`;
467
448
  return outcome(summaryPath, portable, summaryReason);
468
449
  }
469
450
  try {
470
451
  const freshAuth = await context.modelRegistry.getApiKeyAndHeaders(context.model);
471
452
  if (!current()) return cancelled(portable.usage);
472
453
  if (!freshAuth.ok || routeDigest(freshAuth) !== capture.authHash) { fallback("auth changed after portable generation"); return outcome(summaryPath, portable, "native auth changed"); }
473
- compactionStatus = "requesting native checkpoint";
474
454
  let native: Awaited<ReturnType<typeof requestProviderCompaction>>;
475
455
  compactionRequest = true;
476
456
  try {
@@ -512,13 +492,10 @@ export default function (pi: ExtensionAPI): void {
512
492
  pi.on("session_compact", (event, context) => {
513
493
  const recorded = isObject(event.compactionEntry.details) ? event.compactionEntry.details.providerCompaction : undefined;
514
494
  const owned = isObject(recorded) && equal(recorded, lastOutcome);
515
- if (readNativeCompactionDetails(event.compactionEntry.details)?.version === 3) compactionStatus = "native checkpoint committed";
516
- else if (fallbackReason) compactionStatus = `portable: ${fallbackReason}`;
517
- else if (owned) compactionStatus = `${lastOutcome!.path} portable summary committed`;
518
- else fallback("another handler supplied the committed result");
495
+ if (!owned && !fallbackReason && readNativeCompactionDetails(event.compactionEntry.details)?.version !== 3) fallback("another handler supplied the committed result");
519
496
  if (owned) {
520
497
  if (configuration().outcomeNotifications && lastOutcome) context.ui.notify(`Compacted via ${lastOutcome.path} in ${(lastOutcome.elapsedMs / 1000).toFixed(1)}s${lastOutcome.usage ? `; cache read ${lastOutcome.usage.cacheRead}, write ${lastOutcome.usage.cacheWrite}; estimated cost $${lastOutcome.usage.cost.total.toFixed(6)}` : ""}`, "info");
521
- } else lastOutcome = { path: "Pi/other handler", elapsedMs: 0, usage: event.compactionEntry.usage, reason: compactionStatus };
498
+ }
522
499
  // Only static diagnostics are persisted, never request/auth data or error text.
523
500
  if (fallbackReason) pi.appendEntry("pi-provider-compaction:diagnostic", { status: `portable: ${fallbackReason}` });
524
501
  active = undefined; snapshot = undefined; cache = undefined;
@@ -538,5 +515,5 @@ export default function (pi: ExtensionAPI): void {
538
515
  ...(typeof candidate.capture.prepared.payload.model === "string" ? { payloadModel: candidate.capture.prepared.payload.model } : {}),
539
516
  };
540
517
  });
541
- pi.on("session_compact_failed", () => { pending = undefined; snapshot = undefined; cache = undefined; compactionStatus = "compaction failed or cancelled"; });
518
+ pi.on("session_compact_failed", () => { pending = undefined; snapshot = undefined; cache = undefined; });
542
519
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nijaru/pi-provider-compaction",
3
- "version": "0.0.10",
3
+ "version": "0.0.11",
4
4
  "type": "module",
5
5
  "description": "Provider-native context compaction adapters for Pi",
6
6
  "keywords": [