pi-mega-compact 0.7.2 → 0.7.3
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/dist/extensions/mega-runtime.js +222 -97
- package/extensions/mega-runtime.ts +937 -737
- package/package.json +1 -1
|
@@ -16,9 +16,9 @@ import { VectorStore } from "../src/vectorStore.js";
|
|
|
16
16
|
import { toEngineMessages } from "../src/adapt.js";
|
|
17
17
|
import { normalizeSessionId } from "../src/store.js";
|
|
18
18
|
import { Logger } from "../src/log.js";
|
|
19
|
-
import { recordModelSnapshot, latestModelSnapshot, upsertRepoRegistry, recordRepoModel } from "../src/store/sqlite.js";
|
|
19
|
+
import { recordModelSnapshot, latestModelSnapshot, upsertRepoRegistry, recordRepoModel, } from "../src/store/sqlite.js";
|
|
20
20
|
import { detectCrossRepoDrift } from "../src/driftDetection.js";
|
|
21
|
-
import { repoStateDir, resolveRepoRoot, pressureRatio, pressureFromPct, pressureBand, effectiveThresholdTokens } from "./mega-config.js";
|
|
21
|
+
import { repoStateDir, resolveRepoRoot, pressureRatio, pressureFromPct, pressureBand, effectiveThresholdTokens, } from "./mega-config.js";
|
|
22
22
|
import { Dashboard } from "./mega-dashboard.js";
|
|
23
23
|
export const STATUS_KEY = "mega-compact";
|
|
24
24
|
export const WIDGET_KEY = "mega-compact-stats";
|
|
@@ -74,39 +74,51 @@ function visibleWidth(s) {
|
|
|
74
74
|
let w = 0;
|
|
75
75
|
for (const ch of stripped) {
|
|
76
76
|
const cp = ch.codePointAt(0) ?? 0;
|
|
77
|
-
const wide = cp >= 0x1100 &&
|
|
78
|
-
(cp
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
77
|
+
const wide = cp >= 0x1100 &&
|
|
78
|
+
(cp <= 0x115f ||
|
|
79
|
+
(cp >= 0x2e80 && cp <= 0x303e) ||
|
|
80
|
+
(cp >= 0x3041 && cp <= 0x33ff) ||
|
|
81
|
+
(cp >= 0x3400 && cp <= 0x4dbf) ||
|
|
82
|
+
(cp >= 0x4e00 && cp <= 0x9fff) ||
|
|
83
|
+
(cp >= 0xa000 && cp <= 0xa4cf) ||
|
|
84
|
+
(cp >= 0xac00 && cp <= 0xd7a3) ||
|
|
85
|
+
(cp >= 0xf900 && cp <= 0xfaff) ||
|
|
86
|
+
(cp >= 0xfe30 && cp <= 0xfe4f) ||
|
|
87
|
+
(cp >= 0xff00 && cp <= 0xff60) ||
|
|
88
|
+
(cp >= 0xffe0 && cp <= 0xffe6) ||
|
|
89
|
+
(cp >= 0x1f300 && cp <= 0x1faff) ||
|
|
90
|
+
(cp >= 0x20000 && cp <= 0x3fffd));
|
|
84
91
|
w += wide ? 2 : 1;
|
|
85
92
|
}
|
|
86
93
|
return w;
|
|
87
94
|
}
|
|
88
95
|
/** Pad a content string (with ANSI colors) to `width` cells using panel bg. */
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
96
|
+
/** Wrap a string (with ANSI codes) to fit within `maxWidth` visible chars.
|
|
97
|
+
* Splits at │ separators or whitespace when possible. */
|
|
98
|
+
function wrapLine(text, maxWidth) {
|
|
99
|
+
if (maxWidth <= 0)
|
|
100
|
+
return [text];
|
|
101
|
+
const result = [];
|
|
102
|
+
let current = "";
|
|
103
|
+
let currentW = 0;
|
|
104
|
+
// Split at │ boundaries first
|
|
105
|
+
const segments = text.split("│");
|
|
106
|
+
for (let i = 0; i < segments.length; i++) {
|
|
107
|
+
const seg = (i > 0 ? "│" : "") + segments[i];
|
|
108
|
+
const segW = visibleWidth(PANEL_BG + seg.replace(/\x1b\[0m/g, PANEL_RST));
|
|
109
|
+
if (currentW + segW <= maxWidth || currentW === 0) {
|
|
110
|
+
current += seg;
|
|
111
|
+
currentW += segW;
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
result.push(current);
|
|
115
|
+
current = seg;
|
|
116
|
+
currentW = segW;
|
|
107
117
|
}
|
|
108
118
|
}
|
|
109
|
-
|
|
119
|
+
if (current)
|
|
120
|
+
result.push(current);
|
|
121
|
+
return result;
|
|
110
122
|
}
|
|
111
123
|
function panelLine(content, width) {
|
|
112
124
|
const withBg = PANEL_BG + content.replace(/\x1b\[0m/g, PANEL_RST);
|
|
@@ -120,8 +132,10 @@ function panelBar(width, ch = "─") {
|
|
|
120
132
|
/** Token-count formatter: M at/above 1e6, k at/above 1e3, raw below.
|
|
121
133
|
* 5,472,700 → "5.5mil", 24,100 → "24.1k", 142 → "142". */
|
|
122
134
|
function fmtTokens(x) {
|
|
123
|
-
return x >= 1_000_000
|
|
124
|
-
|
|
135
|
+
return x >= 1_000_000
|
|
136
|
+
? `${(x / 1_000_000).toFixed(1)}mil`
|
|
137
|
+
: x >= 1000
|
|
138
|
+
? `${(x / 1000).toFixed(1)}k`
|
|
125
139
|
: `${Math.round(x)}`;
|
|
126
140
|
}
|
|
127
141
|
/** Retro gradient bar — `w` cells shaded by fill position (green→amber→red).
|
|
@@ -136,8 +150,10 @@ function ramp(pct, w = 12) {
|
|
|
136
150
|
for (let i = 0; i < full; i++)
|
|
137
151
|
out += (i / w < 0.6 ? C.green : i / w < 0.85 ? C.amber : C.red) + "█";
|
|
138
152
|
if (fracCell)
|
|
139
|
-
out +=
|
|
140
|
-
|
|
153
|
+
out +=
|
|
154
|
+
(full / w < 0.6 ? C.green : full / w < 0.85 ? C.amber : C.red) + fracCell;
|
|
155
|
+
out +=
|
|
156
|
+
C.dim + "░".repeat(Math.max(0, w - full - (fracCell ? 1 : 0))) + C.reset;
|
|
141
157
|
return out;
|
|
142
158
|
}
|
|
143
159
|
/** Human "time since" string from a millisecond delta (or null → "never"). */
|
|
@@ -268,7 +284,9 @@ export class MegaRuntime {
|
|
|
268
284
|
* context event, or a `custom` tier with no tierPct). Always finite + in [0,1].
|
|
269
285
|
*/
|
|
270
286
|
get pressure() {
|
|
271
|
-
if (this.lastCtxWindow > 0 &&
|
|
287
|
+
if (this.lastCtxWindow > 0 &&
|
|
288
|
+
this.config.tierPct != null &&
|
|
289
|
+
this.lastCtxPercent != null) {
|
|
272
290
|
// pressureFromPct(x) = x/100, and x = lastCtxPercent/tierPct, so this is
|
|
273
291
|
// exactly the intended lastCtxPercent/(tierPct*100) 0–1 ratio: at the
|
|
274
292
|
// fire point (lastCtxPercent == tierPct*100) pressure == 1.0, matching the
|
|
@@ -276,7 +294,9 @@ export class MegaRuntime {
|
|
|
276
294
|
// the band doesn't jump when a token-count vs percent-only event arrives.
|
|
277
295
|
return pressureFromPct(this.lastCtxPercent / this.config.tierPct);
|
|
278
296
|
}
|
|
279
|
-
if (this.lastCtxTokens != null &&
|
|
297
|
+
if (this.lastCtxTokens != null &&
|
|
298
|
+
this.lastCtxTokens > 0 &&
|
|
299
|
+
this.config.thresholdTokens > 0) {
|
|
280
300
|
return pressureRatio(this.lastCtxTokens, this.config.thresholdTokens);
|
|
281
301
|
}
|
|
282
302
|
return pressureFromPct(this.lastCtxPercent);
|
|
@@ -302,8 +322,14 @@ export class MegaRuntime {
|
|
|
302
322
|
}
|
|
303
323
|
constructor(config) {
|
|
304
324
|
this.config = config;
|
|
305
|
-
this.store = new VectorStore({
|
|
306
|
-
|
|
325
|
+
this.store = new VectorStore({
|
|
326
|
+
dedupSim: config.dedupSim,
|
|
327
|
+
stateDir: config.stateDir,
|
|
328
|
+
});
|
|
329
|
+
this.logger = new Logger({
|
|
330
|
+
enabled: config.debug,
|
|
331
|
+
path: join(config.stateDir, "mega-compact.log"),
|
|
332
|
+
});
|
|
307
333
|
this.dashboard = new Dashboard(config.stateDir);
|
|
308
334
|
this.currentStateDir = config.stateDir;
|
|
309
335
|
}
|
|
@@ -314,14 +340,22 @@ export class MegaRuntime {
|
|
|
314
340
|
* and events are fully isolated. Falls back to the global default outside git.
|
|
315
341
|
*/
|
|
316
342
|
bindRepo(cwd) {
|
|
317
|
-
const dir = cwd
|
|
318
|
-
|
|
343
|
+
const dir = cwd
|
|
344
|
+
? repoStateDir(cwd, this.config.stateDir)
|
|
345
|
+
: this.config.stateDir;
|
|
346
|
+
const key = cwd ? (resolveRepoRoot(cwd) ?? dir) : dir;
|
|
319
347
|
if (key === this.activeRepoRoot)
|
|
320
348
|
return dir;
|
|
321
349
|
this.activeRepoRoot = key;
|
|
322
350
|
this.currentStateDir = dir;
|
|
323
|
-
this.store = new VectorStore({
|
|
324
|
-
|
|
351
|
+
this.store = new VectorStore({
|
|
352
|
+
dedupSim: this.config.dedupSim,
|
|
353
|
+
stateDir: dir,
|
|
354
|
+
});
|
|
355
|
+
this.logger = new Logger({
|
|
356
|
+
enabled: this.config.debug,
|
|
357
|
+
path: join(dir, "mega-compact.log"),
|
|
358
|
+
});
|
|
325
359
|
this.dashboard = new Dashboard(dir);
|
|
326
360
|
// Aggregate this repo into the machine-wide index so the multi-repo
|
|
327
361
|
// dashboard (Summary / All-repos tabs) can show it alongside every other
|
|
@@ -331,7 +365,7 @@ export class MegaRuntime {
|
|
|
331
365
|
try {
|
|
332
366
|
const repo = this.store.repoStats();
|
|
333
367
|
const di = this.store.dataInvariant();
|
|
334
|
-
const root = key !== dir ? key : resolveRepoRoot(cwd ?? dir) ?? dir;
|
|
368
|
+
const root = key !== dir ? key : (resolveRepoRoot(cwd ?? dir) ?? dir);
|
|
335
369
|
upsertRepoRegistry({
|
|
336
370
|
repoRoot: root,
|
|
337
371
|
displayName: root.split(/[\\/]/).filter(Boolean).pop() ?? root,
|
|
@@ -371,7 +405,9 @@ export class MegaRuntime {
|
|
|
371
405
|
// armed lights at/above the REAL fire point: max(effectiveThresholdPct,
|
|
372
406
|
// fastGatePct). fastGatePct already equals tierPct*100 by default, but a
|
|
373
407
|
// MEGACOMPACT_FAST_GATE_PCT override can raise it, so we take the max.
|
|
374
|
-
const armed = this.lastCtxPercent != null &&
|
|
408
|
+
const armed = this.lastCtxPercent != null &&
|
|
409
|
+
this.lastCtxPercent >=
|
|
410
|
+
Math.max(effectiveThresholdPct ?? 0, this.config.fastGatePct);
|
|
375
411
|
const ready = armed && (this.lastCtxTokens ?? 0) >= this.effectiveThreshold;
|
|
376
412
|
this.dashboard.snapshot({
|
|
377
413
|
version: 1,
|
|
@@ -401,10 +437,32 @@ export class MegaRuntime {
|
|
|
401
437
|
dedupSkips: this.rt.dedupSkips,
|
|
402
438
|
dedupAttempts: this.rt.dedupAttempts,
|
|
403
439
|
},
|
|
404
|
-
context: {
|
|
405
|
-
|
|
440
|
+
context: {
|
|
441
|
+
tokens: this.lastCtxTokens,
|
|
442
|
+
percent: this.lastCtxPercent,
|
|
443
|
+
contextWindow: this.lastCtxWindow,
|
|
444
|
+
},
|
|
445
|
+
trigger: {
|
|
446
|
+
armed,
|
|
447
|
+
ready,
|
|
448
|
+
currentTokens: this.lastCtxTokens,
|
|
449
|
+
thresholdTokens: this.effectiveThreshold,
|
|
450
|
+
fastGatePct: this.config.fastGatePct,
|
|
451
|
+
tierPct: this.config.tierPct,
|
|
452
|
+
effectiveThresholdPct,
|
|
453
|
+
},
|
|
406
454
|
crew: { activeAgents: this.activeAgents, currentTurn: this.currentTurn },
|
|
407
|
-
store: {
|
|
455
|
+
store: {
|
|
456
|
+
checkpointCount: st.checkpointCount,
|
|
457
|
+
totalTokenEstimate: st.totalTokenEstimate,
|
|
458
|
+
originalTokens: st.originalTokens,
|
|
459
|
+
tokensSaved: this.rt.tokensSaved,
|
|
460
|
+
injectedCount: st.injectedCount,
|
|
461
|
+
dedupHitRate: st.dedupHitRate,
|
|
462
|
+
storageDedupRate: st.storageDedupRate,
|
|
463
|
+
dedupAttempts: st.dedupAttempts,
|
|
464
|
+
dedupCollapsed: st.dedupCollapsed,
|
|
465
|
+
},
|
|
408
466
|
// Reconciled token accounting (single canonical formula, session + repo).
|
|
409
467
|
// Freed = In − Out; In = Freed + Out. session.Freed = rt.tokensSaved (incl.
|
|
410
468
|
// deduped-away originals); repo.Freed = repo.tokensSaved meta counter.
|
|
@@ -413,14 +471,19 @@ export class MegaRuntime {
|
|
|
413
471
|
tokensIn: this.rt.tokensSaved + st.totalTokenEstimate,
|
|
414
472
|
tokensOut: st.totalTokenEstimate,
|
|
415
473
|
tokensFreed: this.rt.tokensSaved,
|
|
416
|
-
compressionPct:
|
|
474
|
+
compressionPct: this.rt.tokensSaved + st.totalTokenEstimate > 0
|
|
475
|
+
? this.rt.tokensSaved /
|
|
476
|
+
(this.rt.tokensSaved + st.totalTokenEstimate)
|
|
477
|
+
: 0,
|
|
417
478
|
dedupPct: st.storageDedupRate,
|
|
418
479
|
},
|
|
419
480
|
repo: {
|
|
420
481
|
tokensIn: repo.tokensSaved + repo.totalTokenEstimate,
|
|
421
482
|
tokensOut: repo.totalTokenEstimate,
|
|
422
483
|
tokensFreed: repo.tokensSaved,
|
|
423
|
-
compressionPct:
|
|
484
|
+
compressionPct: repo.tokensSaved + repo.totalTokenEstimate > 0
|
|
485
|
+
? repo.tokensSaved / (repo.tokensSaved + repo.totalTokenEstimate)
|
|
486
|
+
: 0,
|
|
424
487
|
dedupPct: repo.storageDedupRate,
|
|
425
488
|
},
|
|
426
489
|
},
|
|
@@ -445,14 +508,24 @@ export class MegaRuntime {
|
|
|
445
508
|
// Live stats widget above the editor
|
|
446
509
|
if (ctx) {
|
|
447
510
|
// ── gather widget data (computed per snapshot, rendered per frame) ────
|
|
448
|
-
const tokStr = this.lastCtxTokens != null
|
|
449
|
-
|
|
450
|
-
|
|
511
|
+
const tokStr = this.lastCtxTokens != null
|
|
512
|
+
? `${Math.round(this.lastCtxTokens / 1000)}k`
|
|
513
|
+
: "?";
|
|
514
|
+
const maxStr = this.lastCtxWindow > 0
|
|
515
|
+
? `${Math.round(this.lastCtxWindow / 1000)}k`
|
|
516
|
+
: "?";
|
|
517
|
+
const pctStr = this.lastCtxPercent != null
|
|
518
|
+
? `${Math.round(this.lastCtxPercent * 10) / 10}%`
|
|
519
|
+
: "?%";
|
|
451
520
|
// S24: the tier label is the LIVE pressure band (low/medium/high/ultra/
|
|
452
521
|
// mega), not the static env preset. It climbs as context fills.
|
|
453
522
|
const liveBand = this.pressureBand;
|
|
454
523
|
const tierLabel = `${C.bold}${liveBand}${C.reset}${C.gray}·${this.config.tier}${C.reset}`;
|
|
455
|
-
const triggerLabel = ready
|
|
524
|
+
const triggerLabel = ready
|
|
525
|
+
? `${C.green}● ready${C.reset}`
|
|
526
|
+
: armed
|
|
527
|
+
? `${C.amber}◐ armed${C.reset}`
|
|
528
|
+
: `${C.gray}○ idle${C.reset}`;
|
|
456
529
|
// Storage dedup rate is cumulative (store-wide, per-repo) and survives
|
|
457
530
|
// session resets. Always show a number (decimal for sub-10%).
|
|
458
531
|
const storageRate = st.storageDedupRate; // 0..1
|
|
@@ -477,27 +550,55 @@ export class MegaRuntime {
|
|
|
477
550
|
const ctxPct = this.lastCtxPercent != null ? this.lastCtxPercent / 100 : 0;
|
|
478
551
|
// Model + provider (S26 capture) for the header.
|
|
479
552
|
const modelName = modelSnap?.modelName ?? modelSnap?.modelId ?? "?";
|
|
480
|
-
const modelStr = modelSnap?.provider
|
|
553
|
+
const modelStr = modelSnap?.provider
|
|
554
|
+
? `${modelName}·${modelSnap.provider}`
|
|
555
|
+
: modelName;
|
|
481
556
|
// Since-last-compact (ms; null until first compaction this session).
|
|
482
|
-
const sinceCompact = this.rt.lastCompactAt != null
|
|
557
|
+
const sinceCompact = this.rt.lastCompactAt != null
|
|
558
|
+
? Date.now() - this.rt.lastCompactAt
|
|
559
|
+
: null;
|
|
483
560
|
// Memory store: embedder + compression ratio (original / stored).
|
|
484
561
|
const embedderName = this.embedderName();
|
|
485
562
|
const compRatio = st.originalTokens > 0 && st.totalTokenEstimate > 0
|
|
486
563
|
? st.originalTokens / st.totalTokenEstimate
|
|
487
|
-
:
|
|
564
|
+
: st.originalTokens > 0
|
|
565
|
+
? 1
|
|
566
|
+
: 0;
|
|
488
567
|
const compStr = compRatio >= 1 ? `${compRatio.toFixed(1)}x` : "—";
|
|
489
568
|
// Cross-repo drift status (cached, read-only).
|
|
490
569
|
const driftStatus = this.driftStatus();
|
|
491
570
|
const agentsActive = this.activeAgents > 0;
|
|
492
571
|
this.widgetData = {
|
|
493
572
|
version: ownVersion(),
|
|
494
|
-
tierLabel,
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
573
|
+
tierLabel,
|
|
574
|
+
triggerLabel,
|
|
575
|
+
pctStr,
|
|
576
|
+
tokStr,
|
|
577
|
+
maxStr,
|
|
578
|
+
ctxPct,
|
|
579
|
+
chk: st.checkpointCount,
|
|
580
|
+
agentStr,
|
|
581
|
+
turnStr,
|
|
582
|
+
dedupStr,
|
|
583
|
+
sessIn,
|
|
584
|
+
sessKept,
|
|
585
|
+
sTxt,
|
|
586
|
+
repoIn,
|
|
587
|
+
repoKept,
|
|
588
|
+
rTxt,
|
|
589
|
+
repoChk: repo.checkpointCount,
|
|
590
|
+
repoSess: repo.sessionCount,
|
|
591
|
+
modelStr,
|
|
592
|
+
sinceCompact,
|
|
593
|
+
embedderName,
|
|
594
|
+
compStr,
|
|
595
|
+
driftStatus,
|
|
596
|
+
agentsActive,
|
|
499
597
|
fresh: Date.now() - this.lastActivityAt < 4000,
|
|
500
|
-
ticker: this.ticker,
|
|
598
|
+
ticker: this.ticker,
|
|
599
|
+
lastWhy: this.lastWhy,
|
|
600
|
+
tierTrace: this.tierTrace,
|
|
601
|
+
pulsing: this.pulsing,
|
|
501
602
|
};
|
|
502
603
|
// Auto-fit: register a factory so pi re-renders the panel at the REAL
|
|
503
604
|
// terminal width every frame (tui.columns), instead of guessing with
|
|
@@ -520,31 +621,35 @@ export class MegaRuntime {
|
|
|
520
621
|
buildWidgetLines(width) {
|
|
521
622
|
const wd = this.widgetData;
|
|
522
623
|
if (!wd) {
|
|
523
|
-
return [
|
|
624
|
+
return [
|
|
625
|
+
panelBar(width, "─"),
|
|
626
|
+
panelLine(" mega-compact: warming up…", width),
|
|
627
|
+
panelBar(width, "─"),
|
|
628
|
+
];
|
|
524
629
|
}
|
|
525
|
-
const pulse = wd.pulsing
|
|
630
|
+
const pulse = wd.pulsing
|
|
631
|
+
? `${C.cyan}${PULSE[Math.floor(Date.now() / 250) % PULSE.length]}${C.reset} `
|
|
632
|
+
: "";
|
|
633
|
+
const sep = ` ${C.dim}│${C.reset} `;
|
|
634
|
+
// Build one long content line — let terminal wrap it naturally
|
|
635
|
+
const content = [
|
|
636
|
+
`${C.amber}⚡ ${wd.tierLabel}${C.reset} v${C.bold}${wd.version}${C.reset} ${ramp(wd.ctxPct, 20)} ${C.bold}${wd.pctStr}${C.reset} ${wd.tokStr}/${wd.maxStr}`,
|
|
637
|
+
wd.triggerLabel,
|
|
638
|
+
`${C.cyan}${wd.modelStr}${C.reset}`,
|
|
639
|
+
`${wd.chk} chk${wd.agentStr}${wd.turnStr}`,
|
|
640
|
+
`${C.magenta}dup ${wd.dedupStr}${C.reset}`,
|
|
641
|
+
`${C.gray}sess${C.reset} ${fmtTokens(wd.sessIn)}→${fmtTokens(wd.sessKept)} kept ${C.green}(${wd.sTxt}% freed)${C.reset}`,
|
|
642
|
+
`${C.gray}all-time${C.reset} ${fmtTokens(wd.repoIn)}→${fmtTokens(wd.repoKept)} kept ${C.blue}(${wd.rTxt}% freed)${C.reset}`,
|
|
643
|
+
`${wd.repoChk} chk/${wd.repoSess} sess`,
|
|
644
|
+
`${C.gray}mem${C.reset} ${wd.embedderName} · ${wd.chk} chunks · ${C.blue}comp ${wd.compStr}${C.reset}`,
|
|
645
|
+
`${C.gray}drift${C.reset} ${wd.driftStatus === "ok" ? C.green : C.amber}${wd.driftStatus}${C.reset}`,
|
|
646
|
+
`${C.gray}compact${C.reset} ${sinceCompactStr(wd.sinceCompact)}`,
|
|
647
|
+
].join(sep);
|
|
648
|
+
// Wrap to terminal width and pad each line
|
|
649
|
+
const wrapped = wrapLine(content, width - 2); // 2-char indent
|
|
526
650
|
const lines = [
|
|
527
|
-
// top border
|
|
528
651
|
panelBar(width, "─"),
|
|
529
|
-
|
|
530
|
-
spreadGroups(width, [
|
|
531
|
-
`${C.amber}⚡ ${wd.tierLabel}${C.reset} v${C.bold}${wd.version}${C.reset} ${ramp(wd.ctxPct, 20)} ${C.bold}${wd.pctStr}${C.reset} ${wd.tokStr}/${wd.maxStr}`,
|
|
532
|
-
wd.triggerLabel,
|
|
533
|
-
`${C.cyan}${wd.modelStr}${C.reset}`,
|
|
534
|
-
`${wd.chk} chk${wd.agentStr}${wd.turnStr}`,
|
|
535
|
-
]),
|
|
536
|
-
// L2 — savings reconciled (session + all-time)
|
|
537
|
-
spreadGroups(width, [
|
|
538
|
-
`${C.magenta}dup ${wd.dedupStr}${C.reset}`,
|
|
539
|
-
`${C.gray}sess${C.reset} ${fmtTokens(wd.sessIn)}→${fmtTokens(wd.sessKept)} kept ${C.green}(${wd.sTxt}% freed)${C.reset} · ${C.gray}all-time${C.reset} ${fmtTokens(wd.repoIn)}→${fmtTokens(wd.repoKept)} kept ${C.blue}(${wd.rTxt}% freed)${C.reset}`,
|
|
540
|
-
`${wd.repoChk} chk/${wd.repoSess} sess`,
|
|
541
|
-
]),
|
|
542
|
-
// L3 — memory store + compression + drift + since-compact (NEW)
|
|
543
|
-
spreadGroups(width, [
|
|
544
|
-
`${C.gray}mem${C.reset} ${wd.embedderName} · ${wd.chk} chunks · ${C.blue}comp ${wd.compStr}${C.reset}`,
|
|
545
|
-
`${C.gray}drift${C.reset} ${wd.driftStatus === "ok" ? C.green : C.amber}${wd.driftStatus}${C.reset}`,
|
|
546
|
-
`${C.gray}compact${C.reset} ${sinceCompactStr(wd.sinceCompact)}`,
|
|
547
|
-
]),
|
|
652
|
+
...wrapped.map((l) => panelLine(l, width)),
|
|
548
653
|
];
|
|
549
654
|
// L4 — agents block (S27, count + status; per-agent tokens gated on P0)
|
|
550
655
|
if (wd.agentsActive) {
|
|
@@ -559,7 +664,9 @@ export class MegaRuntime {
|
|
|
559
664
|
const idx = wd.ticker.length - 1 - (step % wd.ticker.length);
|
|
560
665
|
const head = wd.ticker[idx].text;
|
|
561
666
|
const why = wd.lastWhy ? ` ${C.gray}· ${wd.lastWhy}${C.reset}` : "";
|
|
562
|
-
const more = wd.ticker.length > 1
|
|
667
|
+
const more = wd.ticker.length > 1
|
|
668
|
+
? ` ${C.dim}(+${wd.ticker.length - 1} more)${C.reset}`
|
|
669
|
+
: "";
|
|
563
670
|
lines.push(panelLine(` ${wd.fresh ? C.teal : C.dim}${head}${why}${more}${C.reset}`, width));
|
|
564
671
|
}
|
|
565
672
|
else if (wd.pulsing) {
|
|
@@ -573,7 +680,8 @@ export class MegaRuntime {
|
|
|
573
680
|
embedderName() {
|
|
574
681
|
// MINILM_EMBEDDER flag lives in src/config/dedup.ts; read the same env var
|
|
575
682
|
// the embedder factory uses so the label matches what's actually running.
|
|
576
|
-
return process.env.MEGACOMPACT_MINILM === "true" ||
|
|
683
|
+
return process.env.MEGACOMPACT_MINILM === "true" ||
|
|
684
|
+
process.env.MEGACOMPACT_MINILM === "1"
|
|
577
685
|
? "MiniLM"
|
|
578
686
|
: "Trigram";
|
|
579
687
|
}
|
|
@@ -633,13 +741,18 @@ export class MegaRuntime {
|
|
|
633
741
|
this.appendEvent("captureModel:no-model", { cwd: ctx.cwd });
|
|
634
742
|
return;
|
|
635
743
|
}
|
|
636
|
-
if (this.currentModel &&
|
|
744
|
+
if (this.currentModel &&
|
|
745
|
+
this.currentModel.modelId === m.id &&
|
|
746
|
+
this.currentModel.provider === m.provider)
|
|
637
747
|
return;
|
|
638
748
|
let providerName = null;
|
|
639
749
|
try {
|
|
640
|
-
providerName =
|
|
750
|
+
providerName =
|
|
751
|
+
ctx.modelRegistry?.getProviderDisplayName(m.provider) ?? null;
|
|
752
|
+
}
|
|
753
|
+
catch {
|
|
754
|
+
/* optional */
|
|
641
755
|
}
|
|
642
|
-
catch { /* optional */ }
|
|
643
756
|
const snap = {
|
|
644
757
|
provider: m.provider,
|
|
645
758
|
providerName,
|
|
@@ -661,14 +774,18 @@ export class MegaRuntime {
|
|
|
661
774
|
try {
|
|
662
775
|
recordModelSnapshot(repo, snap, this.currentStateDir);
|
|
663
776
|
this.appendEvent("captureModel:recorded", {
|
|
664
|
-
repo,
|
|
665
|
-
|
|
777
|
+
repo,
|
|
778
|
+
modelId: snap.modelId,
|
|
779
|
+
provider: snap.provider,
|
|
780
|
+
inputRate: snap.inputRate,
|
|
781
|
+
outputRate: snap.outputRate,
|
|
666
782
|
});
|
|
667
783
|
}
|
|
668
784
|
catch (e) {
|
|
669
785
|
this.diagCaptureModelFails++;
|
|
670
786
|
this.appendEvent("captureModel:record-failed", {
|
|
671
|
-
repo,
|
|
787
|
+
repo,
|
|
788
|
+
modelId: snap.modelId,
|
|
672
789
|
error: e instanceof Error ? e.message : String(e),
|
|
673
790
|
stack: e instanceof Error ? e.stack : undefined,
|
|
674
791
|
});
|
|
@@ -689,7 +806,8 @@ export class MegaRuntime {
|
|
|
689
806
|
}
|
|
690
807
|
catch (e) {
|
|
691
808
|
this.appendEvent("captureModel:index-record-failed", {
|
|
692
|
-
repo,
|
|
809
|
+
repo,
|
|
810
|
+
modelId: snap.modelId,
|
|
693
811
|
error: e instanceof Error ? e.message : String(e),
|
|
694
812
|
});
|
|
695
813
|
}
|
|
@@ -705,7 +823,9 @@ export class MegaRuntime {
|
|
|
705
823
|
mkdirSync(this.currentStateDir, { recursive: true });
|
|
706
824
|
appendFileSync(join(this.currentStateDir, "events.log"), JSON.stringify({ ts: Date.now(), event, ...fields }) + "\n");
|
|
707
825
|
}
|
|
708
|
-
catch {
|
|
826
|
+
catch {
|
|
827
|
+
/* non-fatal */
|
|
828
|
+
}
|
|
709
829
|
}
|
|
710
830
|
/** S21: state dir of the currently bound repo (where memories live). */
|
|
711
831
|
getStateDir() {
|
|
@@ -715,10 +835,13 @@ export class MegaRuntime {
|
|
|
715
835
|
makeTierCallback(ctx) {
|
|
716
836
|
const order = ["L0", "L1", "L2", "new"];
|
|
717
837
|
const seen = new Map();
|
|
718
|
-
const glyph = (status) => status === "deduped"
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
838
|
+
const glyph = (status) => status === "deduped"
|
|
839
|
+
? `${C.green}✓${C.reset}`
|
|
840
|
+
: status === "passed"
|
|
841
|
+
? `${C.dim}○${C.reset}`
|
|
842
|
+
: status === "scanning"
|
|
843
|
+
? `${C.amber}…${C.reset}`
|
|
844
|
+
: `${C.cyan}●${C.reset}`;
|
|
722
845
|
return (ev) => {
|
|
723
846
|
const label = ev.tier === "new"
|
|
724
847
|
? `${C.cyan}stored${C.reset}`
|
|
@@ -735,7 +858,9 @@ export class MegaRuntime {
|
|
|
735
858
|
try {
|
|
736
859
|
this.snapshot(ctx);
|
|
737
860
|
}
|
|
738
|
-
catch {
|
|
861
|
+
catch {
|
|
862
|
+
/* non-fatal */
|
|
863
|
+
}
|
|
739
864
|
};
|
|
740
865
|
}
|
|
741
866
|
// Phase 3 — recall/activity ticker ring buffer.
|