pi-mega-compact 0.6.9 → 0.7.1

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.
@@ -294,14 +294,15 @@ function readSnapshot(snapshotPath: string) {
294
294
  tier: "unknown",
295
295
  presetTier: "unknown",
296
296
  pressure: 0,
297
- config: { fastGatePct: 80, thresholdTokens: 100_000, anchorUserMessages: 1, preserveRecent: 2, auto: true, autoInlineK: 3 },
297
+ config: { fastGatePct: 80, thresholdTokens: 100_000, tierPct: null, effectiveThresholdPct: null, anchorUserMessages: 1, preserveRecent: 2, auto: true, autoInlineK: 3 },
298
298
  session: { id: null, state: null, persistedThisSession: false, lastCheckpointId: null, lastCompactedFrom: 0 },
299
299
  context: { tokens: null, percent: null, contextWindow: 0 },
300
- trigger: { armed: false, ready: false, currentTokens: null, thresholdTokens: 100_000, fastGatePct: 80 },
300
+ trigger: { armed: false, ready: false, currentTokens: null, thresholdTokens: 100_000, fastGatePct: 80, tierPct: null, effectiveThresholdPct: null },
301
301
  store: { checkpointCount: 0, totalTokenEstimate: 0, originalTokens: 0, tokensSaved: 0, injectedCount: 0, dedupHitRate: 0, storageDedupRate: 0, dedupCollapsed: 0 },
302
302
  crew: { activeAgents: 0, currentTurn: 0 },
303
303
  repo: { checkpointCount: 0, totalTokenEstimate: 0, originalTokens: 0, tokensSaved: 0, sessionCount: 0, dedupAttempts: 0, dedupCollapsed: 0, storageDedupRate: 0 },
304
304
  integrity: { regionsRetained: 0, compressedOriginalBytes: 0, duplicatesCollapsed: 0, bytesPermanentlyDeleted: 0 },
305
+ compression: { session: { tokensIn: 0, tokensOut: 0, tokensFreed: 0, compressionPct: 0, dedupPct: 0 }, repo: { tokensIn: 0, tokensOut: 0, tokensFreed: 0, compressionPct: 0, dedupPct: 0 } },
305
306
  model: undefined,
306
307
  } as Snapshot;
307
308
  }
@@ -488,9 +489,9 @@ function dashboardHtml(tierName: string): string {
488
489
  <div class="conf-grid">
489
490
  <span class="label" title="Live pressure band — climbs low→mega as context fills the window.">Tier (live)</span><span class="value" id="cf-tier">${tierName}</span>
490
491
  <span class="label" title="The env-resolved base compaction preset (low/medium/high/ultra/mega) that set the token threshold.">Preset</span><span class="value" id="cf-preset">—</span>
491
- <span class="label" title="Live pressure = currentTokens / thresholdTokens (0–100%).">Pressure</span><span class="value" id="cf-pressure">—</span>
492
- <span class="label">Threshold</span><span class="value" id="cf-threshold">—</span>
493
- <span class="label">Fast Gate</span><span class="value" id="cf-gate">—</span>
492
+ <span class="label" title="Live pressure = currentTokens / threshold — % of the model context window (threshold fires at the tier's % of window).">Pressure</span><span class="value" id="cf-pressure">—</span>
493
+ <span class="label" title="Compaction threshold = tierPct × model context window — mega-compact trims BELOW pi's native ~80% auto-compact for any model size.">Threshold</span><span class="value" id="cf-threshold">—</span>
494
+ <span class="label" title="Fast-gate arming floor — the live trim arms once context passes this % of the window.">Fast Gate</span><span class="value" id="cf-gate">—</span>
494
495
  <span class="label">Auto</span><span class="value" id="cf-auto">—</span>
495
496
  <span class="label">Anchor</span><span class="value" id="cf-anchor">—</span>
496
497
  </div>
@@ -711,7 +712,17 @@ function dashboardHtml(tierName: string): string {
711
712
  document.getElementById('cf-tier').textContent = d.tier + ' (live)';
712
713
  document.getElementById('cf-preset').textContent = d.presetTier;
713
714
  document.getElementById('cf-pressure').textContent = Math.round((d.pressure || 0) * 100) + '%';
714
- document.getElementById('cf-threshold').textContent = d.config.thresholdTokens.toLocaleString();
715
+ // (b) Threshold: show the effective token threshold AND the % of the model
716
+ // context window it represents (percentage-based tiers). d.config.tierPct
717
+ // is present on the live snapshot written by the runtime (Phase-1/2a).
718
+ var cfgPct = d.config.tierPct;
719
+ var cw = d.context.contextWindow || 0;
720
+ var thresholdTxt = d.config.thresholdTokens.toLocaleString();
721
+ if (cfgPct != null && cw > 0) {
722
+ thresholdTxt += ' (' + Math.round(cfgPct * 100) + '% of ' + cw.toLocaleString() + ')';
723
+ }
724
+ document.getElementById('cf-threshold').textContent = thresholdTxt;
725
+ // (c) Fast Gate: arming floor — live trim arms once context passes this %.
715
726
  document.getElementById('cf-gate').textContent = d.config.fastGatePct + '%';
716
727
  document.getElementById('cf-auto').textContent = d.config.auto ? 'enabled' : 'disabled';
717
728
  document.getElementById('cf-anchor').textContent = d.config.anchorUserMessages;
@@ -125,10 +125,21 @@ export function registerCommands(pi: ExtensionAPI, runtime: MegaRuntime, config:
125
125
  repoCount = listRepoRegistry(process.env.MEGACOMPACT_INDEX_DIR).length;
126
126
  } catch { /* non-fatal */ }
127
127
  const crossRepoStr = `${crossRepoInjections} cross-repo injections recorded · ${repoCount} repos indexed`;
128
+ // Effective compaction threshold = tierPct × model context window (kept
129
+ // BELOW pi's native ~80% auto-compact for any model size). Falls back to
130
+ // the boot token value when the window is unknown (custom tier / pre-
131
+ // model-select). Display matches the dashboard's percentage-based view.
132
+ const effThreshold = config.tierPct != null && ctxWindow > 0
133
+ ? Math.round(config.tierPct * ctxWindow)
134
+ : config.thresholdTokens;
135
+ const winStr = ctxWindow > 0
136
+ ? (ctxWindow >= 1_000_000 ? `${Math.round(ctxWindow / 1_000_000)}M` : `${Math.round(ctxWindow / 1_000)}k`)
137
+ : "?";
138
+ const tierPctStr = config.tierPct != null ? `${Math.round(config.tierPct * 100)}%` : "n/a";
128
139
  ctx.ui.notify(
129
140
  `[mega-compact] pct=${pct} tokens=${tokens} tier=${runtime.pressureBand} (live) preset=${config.tier} ` +
130
141
  `pressure=${Math.round(runtime.pressure * 100)}% fastGate=${config.fastGatePct}% ` +
131
- `threshold=${config.thresholdTokens} auto=${config.auto} autoInline=${config.autoInline}\n` +
142
+ `threshold=${effThreshold.toLocaleString()} (${tierPctStr} of ${winStr} window) tierPct=${config.tierPct != null ? config.tierPct.toFixed(2) : "n/a"} auto=${config.auto} autoInline=${config.autoInline}\n` +
132
143
  `[mega-compact] store: ${st.checkpointCount} chkpt · ` +
133
144
  `${st.totalTokenEstimate} tok · last=${st.lastCheckpointId ?? "—"} · ` +
134
145
  `injected=${st.injectedCount} · dedup=${(st.dedupHitRate * 100).toFixed(0)}%\n` +
@@ -30,13 +30,13 @@ import type { MegaConfig } from "./mega-config.js";
30
30
  import { recallRaptorRootSummary } from "../src/dedup/raptor/index.js";
31
31
 
32
32
  export interface NativeCompactionResult {
33
- /** Our trimmed summary + the pi entry to keep from (durable trim). */
34
- compaction: {
35
- summary: string;
36
- firstKeptEntryId: string;
37
- tokensBefore: number;
38
- estimatedTokensAfter: number;
39
- };
33
+ /** Our trimmed summary + the pi entry to keep from (durable trim). */
34
+ compaction: {
35
+ summary: string;
36
+ firstKeptEntryId: string;
37
+ tokensBefore: number;
38
+ estimatedTokensAfter: number;
39
+ };
40
40
  }
41
41
 
42
42
  /**
@@ -46,60 +46,61 @@ export interface NativeCompactionResult {
46
46
  * own native compaction, or skip). Never throws for "empty" — best-effort.
47
47
  */
48
48
  export function driveNativeCompaction(
49
- event: SessionBeforeCompactEvent,
50
- runtime: MegaRuntime,
51
- config: MegaConfig,
49
+ event: SessionBeforeCompactEvent,
50
+ runtime: MegaRuntime,
51
+ config: MegaConfig,
52
52
  ): NativeCompactionResult | undefined {
53
- const prep = event.preparation;
54
- if (!prep) return undefined;
53
+ const prep = event.preparation;
54
+ if (!prep) return undefined;
55
55
 
56
- const sid = runtime.rt.sessionId;
57
- const messagesToSummarize: AgentMessage[] = prep.messagesToSummarize ?? [];
58
- if (messagesToSummarize.length === 0) return undefined;
56
+ const sid = runtime.rt.sessionId;
57
+ const messagesToSummarize: AgentMessage[] = prep.messagesToSummarize ?? [];
58
+ if (messagesToSummarize.length === 0) return undefined;
59
59
 
60
- const engineView = toEngineMessages(messagesToSummarize);
61
- // We don't drop anything here — pi keeps from prep.firstKeptEntryId. We only
62
- // summarize the region pi is about to discard.
63
- const keepFrom = engineView.length;
60
+ const engineView = toEngineMessages(messagesToSummarize);
61
+ // We don't drop anything here — pi keeps from prep.firstKeptEntryId. We only
62
+ // summarize the region pi is about to discard.
63
+ const keepFrom = engineView.length;
64
64
 
65
- const result = compactSession(
66
- {
67
- sessionId: sid,
68
- messages: engineView,
69
- keepFrom,
70
- timestamp: Date.now(),
71
- useExtractiveSummary: true,
72
- },
73
- runtime.store,
74
- );
75
- if (result.skipped) return undefined;
65
+ const result = compactSession(
66
+ {
67
+ sessionId: sid,
68
+ messages: engineView,
69
+ keepFrom,
70
+ timestamp: Date.now(),
71
+ useExtractiveSummary: true,
72
+ },
73
+ runtime.store,
74
+ );
75
+ if (result.skipped) return undefined;
76
76
 
77
- // Prefer the RAPTOR root summary when the tree is built + enabled (Fix D):
78
- // it is a session-level compressed summary, broader than one slice's. Fall
79
- // back to the extractive topicSummary of this slice.
80
- let summary = result.summary;
81
- if (config.raptorEnabled) {
82
- const root = recallRaptorRootSummary(sid, runtime.currentStateDir);
83
- if (root) summary = root;
84
- }
77
+ // Prefer the RAPTOR root summary when the tree is built + enabled (Fix D):
78
+ // it is a session-level compressed summary, broader than one slice's. Fall
79
+ // back to the extractive topicSummary of this slice.
80
+ let summary = result.summary;
81
+ if (config.raptorEnabled) {
82
+ const root = recallRaptorRootSummary(sid, runtime.currentStateDir);
83
+ if (root) summary = root;
84
+ }
85
85
 
86
- const tokensBefore = prep.tokensBefore ?? estimateSessionTokens(engineView);
87
- const summaryTokens = estimateBlockTokens(summary);
88
- // pi keeps the tail from firstKeptEntryId; our summary replaces the discarded
89
- // region. Honest saved = discarded-region tokens − our summary tokens.
90
- const savedTokens = Math.max(0, tokensBefore - summaryTokens);
86
+ const tokensBefore = prep.tokensBefore ?? estimateSessionTokens(engineView);
87
+ const summaryTokens = estimateBlockTokens(summary);
88
+ // pi keeps the tail from firstKeptEntryId; our summary replaces the discarded
89
+ // region. Honest saved = discarded-region tokens − our summary tokens.
90
+ const savedTokens = Math.max(0, tokensBefore - summaryTokens);
91
91
 
92
- runtime.rt.lastCompactedFrom = keepFrom;
93
- runtime.rt.lastCompactedTokens = tokensBefore;
94
- runtime.rt.tokensSaved += savedTokens;
95
- runtime.rt.persistedThisSession = true;
92
+ runtime.rt.lastCompactedFrom = keepFrom;
93
+ runtime.rt.lastCompactedTokens = tokensBefore;
94
+ runtime.rt.tokensSaved += savedTokens;
95
+ runtime.rt.lastCompactAt = Date.now();
96
+ runtime.rt.persistedThisSession = true;
96
97
 
97
- return {
98
- compaction: {
99
- summary,
100
- firstKeptEntryId: prep.firstKeptEntryId,
101
- tokensBefore,
102
- estimatedTokensAfter: summaryTokens,
103
- },
104
- };
98
+ return {
99
+ compaction: {
100
+ summary,
101
+ firstKeptEntryId: prep.firstKeptEntryId,
102
+ tokensBefore,
103
+ estimatedTokensAfter: summaryTokens,
104
+ },
105
+ };
105
106
  }