pi-mega-compact 0.6.7 → 0.7.0
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 +10 -8
- package/dist/extensions/dashboard-server.js +112 -14
- package/dist/extensions/mega-commands.js +12 -1
- package/dist/extensions/mega-compact.test.js +286 -51
- package/dist/extensions/mega-config.js +67 -5
- package/dist/extensions/mega-events.js +151 -27
- package/dist/extensions/mega-runtime.js +163 -32
- package/dist/extensions/openclaw-mega-compact.js +291 -0
- package/dist/src/compact.js +5 -1
- package/dist/src/dedup-engine.test.js +63 -38
- package/dist/src/minilm.js +92 -0
- package/dist/src/supersede.js +8 -5
- package/dist/src/wordpiece.js +129 -0
- package/extensions/dashboard-server.ts +125 -14
- package/extensions/mega-commands.ts +12 -1
- package/extensions/mega-compact.test.ts +947 -516
- package/extensions/mega-config.ts +84 -6
- package/extensions/mega-dashboard.ts +11 -0
- package/extensions/mega-events.ts +558 -360
- package/extensions/mega-runtime.ts +168 -32
- package/package.json +1 -1
- package/src/compact.ts +5 -1
- package/src/dedup-engine.test.ts +103 -42
- package/src/supersede.ts +8 -5
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ sessions into a **local SQLite store** and offers **deduped inline recall** —
|
|
|
6
6
|
running **locally inside the extension**, with **no remote MCP server** and
|
|
7
7
|
**zero network calls at runtime** (PREVENT-PI-004).
|
|
8
8
|
|
|
9
|
-
> **Current version:** `v0.6.
|
|
9
|
+
> **Current version:** `v0.6.9` — storage backend is **`node:sqlite`**
|
|
10
10
|
> (`DatabaseSync`, a Node ≥22.13 built-in), replacing the old `better-sqlite3`
|
|
11
11
|
> native addon and the per-session gzipped JSON checkpoint files. **Zero native
|
|
12
12
|
> build step, fully local, zero network at runtime.** Legacy
|
|
@@ -23,10 +23,12 @@ running **locally inside the extension**, with **no remote MCP server** and
|
|
|
23
23
|
pi's context window is finite. When a session gets long — especially a team run
|
|
24
24
|
with sub-agents — pi-mega-compact keeps it going without overflowing:
|
|
25
25
|
|
|
26
|
-
1. **Watches one signal.** A single live `pressure = currentTokens /
|
|
26
|
+
1. **Watches one signal.** A single live `pressure = currentTokens / effectiveThreshold`
|
|
27
27
|
drives everything — the tier label, how aggressively the live trim drops
|
|
28
|
-
context, and how often durable memory is reviewed.
|
|
29
|
-
|
|
28
|
+
context, and how often durable memory is reviewed. `effectiveThreshold` is
|
|
29
|
+
`tierPct × contextWindow` (a **% of the model's context window**), so the
|
|
30
|
+
trim fires below pi's native ~80% auto-compaction for any model size. As
|
|
31
|
+
context fills, the whole system reacts together; as it's relieved, it backs off.
|
|
30
32
|
2. **Compacts in two layers.** On every LLM call it returns a **live, compacted
|
|
31
33
|
view** (the model sees a summary + recent anchor, non-destructively). And it
|
|
32
34
|
persists a durable **checkpoint** — and, at each agent settle during a team
|
|
@@ -233,7 +235,7 @@ The commands (slash commands inside pi):
|
|
|
233
235
|
| `/mega-help` | Explain the toolbar widget terms (live tier, gate, dedup, tokens saved). |
|
|
234
236
|
| `/mega-compat-check` | Detect extension conflicts (duplicate commands / overlapping handlers) across installed pi extensions. |
|
|
235
237
|
|
|
236
|
-
The **tier** you see in the toolbar and dashboard is a *live pressure band* (`low` → `medium` → `high` → `ultra` → `mega`) that climbs automatically as your context window fills and falls back as it's relieved — it is driven by `currentTokens /
|
|
238
|
+
The **tier** you see in the toolbar and dashboard is a *live pressure band* (`low` → `medium` → `high` → `ultra` → `mega`) that climbs automatically as your context window fills and falls back as it's relieved — it is driven by `currentTokens / effectiveThreshold`, not a manual setting. The base compaction *threshold* is set by `MEGACOMPACT_TIER` at startup as a **% of the model context window** (`low` 50% · `medium` 60% · `high` 70% · `ultra` 70% · `mega` 75%; default `low`) — the fire point is `tierPct × contextWindow`, so it always lands below pi's native ~80% auto-compaction (any model size). The old static token amounts (50k/100k/200k/1M/10M) are now only the boot fallback used before the first context event reports a window. `/mega-tier` was removed in v0.6.0. Higher pressure also deepens the live trim and reviews durable memory more often — the whole system reacts as one.
|
|
237
239
|
| `/mega-dashboard` | Start the **localhost-only** live dashboard and open it in a browser (token gauge, store stats, live event stream, per-repo + cross-repo drift). |
|
|
238
240
|
| `/mega-dashboard-status` | Report dashboard server status. |
|
|
239
241
|
| `/mega-dashboard-stop` | Stop the dashboard server. |
|
|
@@ -266,9 +268,9 @@ before starting pi.
|
|
|
266
268
|
|
|
267
269
|
| Variable | Default | Meaning |
|
|
268
270
|
|---|---|---|
|
|
269
|
-
| `MEGACOMPACT_FAST_GATE_PCT` | `70` | Context-usage % that arms the auto-trigger. |
|
|
270
|
-
| `MEGACOMPACT_TIER` | `low` | Named trigger preset — sets the
|
|
271
|
-
| `MEGACOMPACT_THRESHOLD_TOKENS` | _(tier default)_ | Explicit token budget
|
|
271
|
+
| `MEGACOMPACT_FAST_GATE_PCT` | `70` | Context-usage % that arms the auto-trigger. Defaults to the tier's % of window (`tierPct*100`): low 50 · med 60 · high 70 · ultra 70 · mega 75. Override raises the arming floor. |
|
|
272
|
+
| `MEGACOMPACT_TIER` | `low` | Named trigger preset — sets the compaction threshold as a **% of the model context window**: `low`(50%) `medium`(60%) `high`(70%) `ultra`(70%) `mega`(75%). Fire point = `tierPct × contextWindow`, so it always fires below pi's native ~80% auto-compaction (any model size). The old static token amounts (50k/100k/200k/1M/10M) are now only the **boot fallback** used before the first context event reports a window. Default `low`. |
|
|
273
|
+
| `MEGACOMPACT_THRESHOLD_TOKENS` | _(tier default)_ | Explicit **absolute** token budget (the `custom` tier). Overrides `MEGACOMPACT_TIER` when set and is **never percent-scaled** — use this to pin an exact token fire point regardless of model window. |
|
|
272
274
|
| `MEGACOMPACT_ANCHOR_USER_MESSAGES` | `3` | Never drop the most recent N user messages (anchor floor). |
|
|
273
275
|
| `MEGACOMPACT_PRESERVE_RECENT` | `4` | Preserve the most recent N messages verbatim. |
|
|
274
276
|
| `MEGACOMPACT_AUTO` | `true` | Enable the auto-trigger. |
|
|
@@ -83,7 +83,52 @@ function readIndex() {
|
|
|
83
83
|
inputRate: r.input_rate ?? null,
|
|
84
84
|
outputRate: r.output_rate ?? null,
|
|
85
85
|
lastSeen: Number(r.last_seen ?? 0),
|
|
86
|
+
// Defaults — enriched below from each repo's own store.
|
|
87
|
+
tokensKept: 0,
|
|
88
|
+
tokensDropped: 0,
|
|
89
|
+
sessions: 0,
|
|
90
|
+
contextWindow: null,
|
|
91
|
+
maxTokens: null,
|
|
92
|
+
reasoning: null,
|
|
86
93
|
}));
|
|
94
|
+
// Enrich each repo with per-store token + model detail read directly via
|
|
95
|
+
// node:sqlite (same zero-dependency invariant as readIndex; no store graph
|
|
96
|
+
// import). Best-effort: a missing/corrupt store degrades to the defaults
|
|
97
|
+
// above so the dashboard never fails to render.
|
|
98
|
+
for (const repo of mapped) {
|
|
99
|
+
try {
|
|
100
|
+
const storePath = join(repo.stateDir, "sqlite.db");
|
|
101
|
+
if (existsSync(storePath)) {
|
|
102
|
+
const sdb = new DatabaseSync(storePath, { readOnly: true });
|
|
103
|
+
try {
|
|
104
|
+
const tok = sdb
|
|
105
|
+
.prepare(`SELECT COALESCE(SUM(token_estimate),0) AS kept,
|
|
106
|
+
COALESCE(SUM(original_token_estimate),0) AS dropped,
|
|
107
|
+
COUNT(DISTINCT session_id) AS sess
|
|
108
|
+
FROM context_chunks WHERE dedup_status != 'removed'`)
|
|
109
|
+
.get();
|
|
110
|
+
repo.tokensKept = Number(tok.kept ?? 0);
|
|
111
|
+
repo.tokensDropped = Number(tok.dropped ?? 0);
|
|
112
|
+
repo.sessions = Number(tok.sess ?? 0);
|
|
113
|
+
const mrow = sdb
|
|
114
|
+
.prepare(`SELECT context_window, max_tokens, reasoning
|
|
115
|
+
FROM model_snapshots ORDER BY captured_at DESC LIMIT 1`)
|
|
116
|
+
.get();
|
|
117
|
+
if (mrow) {
|
|
118
|
+
repo.contextWindow = Number(mrow.context_window ?? 0) || null;
|
|
119
|
+
repo.maxTokens = Number(mrow.max_tokens ?? 0) || null;
|
|
120
|
+
repo.reasoning = Number(mrow.reasoning ?? 0) === 1;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
finally {
|
|
124
|
+
sdb.close();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
/* best-effort — keep the defaults */
|
|
130
|
+
}
|
|
131
|
+
}
|
|
87
132
|
// Defensive display hygiene (belt-and-suspenders — the real fix is that
|
|
88
133
|
// tests now isolate via MEGACOMPACT_INDEX_DIR): drop transient test/temp
|
|
89
134
|
// paths that should never have been real repos, and collapse duplicate
|
|
@@ -139,14 +184,15 @@ function readSnapshot(snapshotPath) {
|
|
|
139
184
|
tier: "unknown",
|
|
140
185
|
presetTier: "unknown",
|
|
141
186
|
pressure: 0,
|
|
142
|
-
config: { fastGatePct: 80, thresholdTokens: 100_000, anchorUserMessages: 1, preserveRecent: 2, auto: true, autoInlineK: 3 },
|
|
187
|
+
config: { fastGatePct: 80, thresholdTokens: 100_000, tierPct: null, effectiveThresholdPct: null, anchorUserMessages: 1, preserveRecent: 2, auto: true, autoInlineK: 3 },
|
|
143
188
|
session: { id: null, state: null, persistedThisSession: false, lastCheckpointId: null, lastCompactedFrom: 0 },
|
|
144
189
|
context: { tokens: null, percent: null, contextWindow: 0 },
|
|
145
|
-
trigger: { armed: false, ready: false, currentTokens: null, thresholdTokens: 100_000, fastGatePct: 80 },
|
|
190
|
+
trigger: { armed: false, ready: false, currentTokens: null, thresholdTokens: 100_000, fastGatePct: 80, tierPct: null, effectiveThresholdPct: null },
|
|
146
191
|
store: { checkpointCount: 0, totalTokenEstimate: 0, originalTokens: 0, tokensSaved: 0, injectedCount: 0, dedupHitRate: 0, storageDedupRate: 0, dedupCollapsed: 0 },
|
|
147
192
|
crew: { activeAgents: 0, currentTurn: 0 },
|
|
148
193
|
repo: { checkpointCount: 0, totalTokenEstimate: 0, originalTokens: 0, tokensSaved: 0, sessionCount: 0, dedupAttempts: 0, dedupCollapsed: 0, storageDedupRate: 0 },
|
|
149
194
|
integrity: { regionsRetained: 0, compressedOriginalBytes: 0, duplicatesCollapsed: 0, bytesPermanentlyDeleted: 0 },
|
|
195
|
+
compression: { session: { tokensIn: 0, tokensOut: 0, tokensFreed: 0, compressionPct: 0, dedupPct: 0 }, repo: { tokensIn: 0, tokensOut: 0, tokensFreed: 0, compressionPct: 0, dedupPct: 0 } },
|
|
150
196
|
model: undefined,
|
|
151
197
|
};
|
|
152
198
|
}
|
|
@@ -332,9 +378,9 @@ function dashboardHtml(tierName) {
|
|
|
332
378
|
<div class="conf-grid">
|
|
333
379
|
<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>
|
|
334
380
|
<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>
|
|
335
|
-
<span class="label" title="Live pressure = currentTokens /
|
|
336
|
-
<span class="label">Threshold</span><span class="value" id="cf-threshold">—</span>
|
|
337
|
-
<span class="label">Fast Gate</span><span class="value" id="cf-gate">—</span>
|
|
381
|
+
<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>
|
|
382
|
+
<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>
|
|
383
|
+
<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>
|
|
338
384
|
<span class="label">Auto</span><span class="value" id="cf-auto">—</span>
|
|
339
385
|
<span class="label">Anchor</span><span class="value" id="cf-anchor">—</span>
|
|
340
386
|
</div>
|
|
@@ -443,15 +489,23 @@ function dashboardHtml(tierName) {
|
|
|
443
489
|
<thead>
|
|
444
490
|
<tr>
|
|
445
491
|
<th>Model</th><th>Provider</th>
|
|
446
|
-
<th style="text-align:right">
|
|
492
|
+
<th style="text-align:right" title="Tokens dropped from context by compaction (the input reclaimed)">Tokens In</th>
|
|
493
|
+
<th style="text-align:right" title="Tokens kept as compacted summaries still in context (the output retained)">Tokens Out</th>
|
|
494
|
+
<th style="text-align:right">Freed</th>
|
|
495
|
+
<th style="text-align:right" title="Model context window (max input tokens the model accepts)">Ctx Window</th>
|
|
496
|
+
<th style="text-align:right" title="Model max output tokens per turn">Max Out</th>
|
|
497
|
+
<th style="text-align:right" title="Reasoning-capable model">Reas.</th>
|
|
498
|
+
<th style="text-align:right" title="Distinct sessions with at least one checkpoint">Sessions</th>
|
|
447
499
|
<th style="text-align:right">Checkpoints</th>
|
|
448
|
-
<th style="text-align:right">
|
|
500
|
+
<th style="text-align:right" title="USD per input token">In $/tok</th>
|
|
501
|
+
<th style="text-align:right" title="USD per output token">Out $/tok</th>
|
|
449
502
|
<th style="text-align:right">$ Saved</th>
|
|
450
503
|
<th style="text-align:right">Last Used</th>
|
|
451
504
|
</tr>
|
|
452
505
|
</thead>
|
|
453
|
-
<tbody id="bm-rows"><tr><td colspan="
|
|
506
|
+
<tbody id="bm-rows"><tr><td colspan="14" class="repo-none">loading…</td></tr></tbody>
|
|
454
507
|
</table>
|
|
508
|
+
<p class="legend-note" style="margin-top:8px">Tokens In = Σ original region tokens dropped by compaction. Tokens Out = Σ compacted summary tokens still retained in context. Freed = Tokens In − Tokens Out (net context reclaimed). Ctx Window / Max Out / Reas. come from the latest captured model snapshot for each repo.</p>
|
|
455
509
|
|
|
456
510
|
<div class="updated" id="sm-updated"></div>
|
|
457
511
|
</div>
|
|
@@ -547,7 +601,17 @@ function dashboardHtml(tierName) {
|
|
|
547
601
|
document.getElementById('cf-tier').textContent = d.tier + ' (live)';
|
|
548
602
|
document.getElementById('cf-preset').textContent = d.presetTier;
|
|
549
603
|
document.getElementById('cf-pressure').textContent = Math.round((d.pressure || 0) * 100) + '%';
|
|
550
|
-
|
|
604
|
+
// (b) Threshold: show the effective token threshold AND the % of the model
|
|
605
|
+
// context window it represents (percentage-based tiers). d.config.tierPct
|
|
606
|
+
// is present on the live snapshot written by the runtime (Phase-1/2a).
|
|
607
|
+
var cfgPct = d.config.tierPct;
|
|
608
|
+
var cw = d.context.contextWindow || 0;
|
|
609
|
+
var thresholdTxt = d.config.thresholdTokens.toLocaleString();
|
|
610
|
+
if (cfgPct != null && cw > 0) {
|
|
611
|
+
thresholdTxt += ' (' + Math.round(cfgPct * 100) + '% of ' + cw.toLocaleString() + ')';
|
|
612
|
+
}
|
|
613
|
+
document.getElementById('cf-threshold').textContent = thresholdTxt;
|
|
614
|
+
// (c) Fast Gate: arming floor — live trim arms once context passes this %.
|
|
551
615
|
document.getElementById('cf-gate').textContent = d.config.fastGatePct + '%';
|
|
552
616
|
document.getElementById('cf-auto').textContent = d.config.auto ? 'enabled' : 'disabled';
|
|
553
617
|
document.getElementById('cf-anchor').textContent = d.config.anchorUserMessages;
|
|
@@ -673,33 +737,67 @@ function dashboardHtml(tierName) {
|
|
|
673
737
|
var rows = document.getElementById('bm-rows');
|
|
674
738
|
if (!rows) return;
|
|
675
739
|
if (!repos || !repos.length) {
|
|
676
|
-
rows.innerHTML = '<tr><td colspan="
|
|
740
|
+
rows.innerHTML = '<tr><td colspan="14" class="repo-none">No repositories registered yet.</td></tr>';
|
|
677
741
|
return;
|
|
678
742
|
}
|
|
679
743
|
var groups = {};
|
|
680
744
|
for (var i = 0; i < repos.length; i++) {
|
|
681
745
|
var r = repos[i];
|
|
682
746
|
var key = (r.modelName && String(r.modelName).trim()) || '(unknown)';
|
|
683
|
-
if (!groups[key]) groups[key] = {
|
|
747
|
+
if (!groups[key]) groups[key] = {
|
|
748
|
+
model: key, provider: r.providerName || r.provider || '—', repos: 0, checkpoints: 0,
|
|
749
|
+
tokensSaved: 0, tokensIn: 0, tokensOut: 0, sessions: 0, usd: 0, lastAt: 0,
|
|
750
|
+
inRates: [], outRates: [], ctxWindows: [], maxTokens: [], reasoning: null,
|
|
751
|
+
};
|
|
684
752
|
var g = groups[key];
|
|
685
753
|
g.repos++;
|
|
686
754
|
g.checkpoints += (r.checkpointCount || 0);
|
|
687
755
|
g.tokensSaved += (r.tokensSaved || 0);
|
|
688
|
-
|
|
756
|
+
g.tokensIn += (r.tokensDropped || 0);
|
|
757
|
+
g.tokensOut += (r.tokensKept || 0);
|
|
758
|
+
g.sessions += (r.sessions || 0);
|
|
759
|
+
if (r.inputRate) { g.usd += (r.tokensSaved || 0) * r.inputRate; g.inRates.push(r.inputRate); }
|
|
760
|
+
if (r.outputRate) g.outRates.push(r.outputRate);
|
|
761
|
+
if (r.contextWindow) g.ctxWindows.push(r.contextWindow);
|
|
762
|
+
if (r.maxTokens) g.maxTokens.push(r.maxTokens);
|
|
763
|
+
if (r.reasoning != null) g.reasoning = r.reasoning;
|
|
689
764
|
if (r.lastCompactedAt && r.lastCompactedAt > g.lastAt) g.lastAt = r.lastCompactedAt;
|
|
690
765
|
}
|
|
691
766
|
var arr = [];
|
|
692
767
|
for (var k in groups) { if (Object.prototype.hasOwnProperty.call(groups, k)) arr.push(groups[k]); }
|
|
693
768
|
arr.sort(function(a, b) { return b.tokensSaved - a.tokensSaved; });
|
|
769
|
+
// Helper: a set of numeric samples collapses to a single value when all
|
|
770
|
+
// repos in the group agree, otherwise shows the range (min–max) so the
|
|
771
|
+
// user can see mixed-config model groups at a glance.
|
|
772
|
+
function collapseNum(samples) {
|
|
773
|
+
if (!samples || !samples.length) return '—';
|
|
774
|
+
var lo = Math.min.apply(null, samples), hi = Math.max.apply(null, samples);
|
|
775
|
+
return lo === hi ? lo.toLocaleString() : lo.toLocaleString() + '–' + hi.toLocaleString();
|
|
776
|
+
}
|
|
777
|
+
function collapseRate(samples) {
|
|
778
|
+
if (!samples || !samples.length) return '—';
|
|
779
|
+
var lo = Math.min.apply(null, samples), hi = Math.max.apply(null, samples);
|
|
780
|
+
var fmt = function(v) { return '$' + v.toFixed(6); };
|
|
781
|
+
return lo === hi ? fmt(lo) : fmt(lo) + '–' + fmt(hi);
|
|
782
|
+
}
|
|
694
783
|
rows.innerHTML = arr.map(function(g) {
|
|
784
|
+
var freed = (g.tokensIn || 0) - (g.tokensOut || 0);
|
|
695
785
|
var usd = g.usd > 0 ? '$' + g.usd.toFixed(4) : '—';
|
|
696
786
|
var when = g.lastAt ? new Date(g.lastAt).toLocaleString() : '—';
|
|
787
|
+
var reas = g.reasoning == null ? '—' : (g.reasoning ? 'yes' : 'no');
|
|
697
788
|
return '<tr>' +
|
|
698
789
|
'<td><span class="repo-model">' + sanitize(g.model) + '</span></td>' +
|
|
699
790
|
'<td>' + sanitize(g.provider) + '</td>' +
|
|
700
|
-
'<td class="num">' + g.
|
|
791
|
+
'<td class="num">' + (g.tokensIn || 0).toLocaleString() + '</td>' +
|
|
792
|
+
'<td class="num">' + (g.tokensOut || 0).toLocaleString() + '</td>' +
|
|
793
|
+
'<td class="num">' + freed.toLocaleString() + '</td>' +
|
|
794
|
+
'<td class="num">' + collapseNum(g.ctxWindows) + '</td>' +
|
|
795
|
+
'<td class="num">' + collapseNum(g.maxTokens) + '</td>' +
|
|
796
|
+
'<td class="num">' + reas + '</td>' +
|
|
797
|
+
'<td class="num">' + g.sessions.toLocaleString() + '</td>' +
|
|
701
798
|
'<td class="num">' + g.checkpoints.toLocaleString() + '</td>' +
|
|
702
|
-
'<td class="num">' + g.
|
|
799
|
+
'<td class="num">' + collapseRate(g.inRates) + '</td>' +
|
|
800
|
+
'<td class="num">' + collapseRate(g.outRates) + '</td>' +
|
|
703
801
|
'<td class="num">' + sanitize(usd) + '</td>' +
|
|
704
802
|
'<td class="num">' + sanitize(when) + '</td>' +
|
|
705
803
|
'</tr>';
|
|
@@ -116,9 +116,20 @@ export function registerCommands(pi, runtime, config) {
|
|
|
116
116
|
}
|
|
117
117
|
catch { /* non-fatal */ }
|
|
118
118
|
const crossRepoStr = `${crossRepoInjections} cross-repo injections recorded · ${repoCount} repos indexed`;
|
|
119
|
+
// Effective compaction threshold = tierPct × model context window (kept
|
|
120
|
+
// BELOW pi's native ~80% auto-compact for any model size). Falls back to
|
|
121
|
+
// the boot token value when the window is unknown (custom tier / pre-
|
|
122
|
+
// model-select). Display matches the dashboard's percentage-based view.
|
|
123
|
+
const effThreshold = config.tierPct != null && ctxWindow > 0
|
|
124
|
+
? Math.round(config.tierPct * ctxWindow)
|
|
125
|
+
: config.thresholdTokens;
|
|
126
|
+
const winStr = ctxWindow > 0
|
|
127
|
+
? (ctxWindow >= 1_000_000 ? `${Math.round(ctxWindow / 1_000_000)}M` : `${Math.round(ctxWindow / 1_000)}k`)
|
|
128
|
+
: "?";
|
|
129
|
+
const tierPctStr = config.tierPct != null ? `${Math.round(config.tierPct * 100)}%` : "n/a";
|
|
119
130
|
ctx.ui.notify(`[mega-compact] pct=${pct} tokens=${tokens} tier=${runtime.pressureBand} (live) preset=${config.tier} ` +
|
|
120
131
|
`pressure=${Math.round(runtime.pressure * 100)}% fastGate=${config.fastGatePct}% ` +
|
|
121
|
-
`threshold=${config.
|
|
132
|
+
`threshold=${effThreshold.toLocaleString()} (${tierPctStr} of ${winStr} window) tierPct=${config.tierPct != null ? config.tierPct.toFixed(2) : "n/a"} auto=${config.auto} autoInline=${config.autoInline}\n` +
|
|
122
133
|
`[mega-compact] store: ${st.checkpointCount} chkpt · ` +
|
|
123
134
|
`${st.totalTokenEstimate} tok · last=${st.lastCheckpointId ?? "—"} · ` +
|
|
124
135
|
`injected=${st.injectedCount} · dedup=${(st.dedupHitRate * 100).toFixed(0)}%\n` +
|