pi-mega-compact 0.4.6 → 0.4.8
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-compact.js +46 -7
- package/dist/src/engine.js +2 -0
- package/extensions/mega-compact.ts +47 -11
- package/package.json +1 -1
- package/src/engine.ts +5 -0
|
@@ -229,7 +229,7 @@ export default function (pi) {
|
|
|
229
229
|
const tokStr = lastCtxTokens != null ? `${Math.round(lastCtxTokens / 1000)}k` : "?";
|
|
230
230
|
const maxStr = lastCtxWindow > 0 ? `${Math.round(lastCtxWindow / 1000)}k` : "?";
|
|
231
231
|
const pctStr = lastCtxPercent != null ? `${Math.round(lastCtxPercent * 10) / 10}%` : "?%";
|
|
232
|
-
const triggerLabel = ready ?
|
|
232
|
+
const triggerLabel = ready ? `${C.green}● ready${C.reset}` : armed ? `${C.amber}◐ armed${C.reset}` : `${C.gray}○ idle${C.reset}`;
|
|
233
233
|
// Storage dedup rate is cumulative (store-wide, per-repo) and survives
|
|
234
234
|
// session resets. Always show a number: 0% before any compaction, a
|
|
235
235
|
// decimal for sub-10% rates so small-but-real dedup isn't rounded away.
|
|
@@ -244,14 +244,21 @@ export default function (pi) {
|
|
|
244
244
|
// vs st.totalTokenEstimate). Use "k" only at/above 1000 so small-but-real
|
|
245
245
|
// numbers stay visible (previously Math.round(x/1000) zeroed <1000).
|
|
246
246
|
const fmt = (x) => (x >= 1000 ? `${(x / 1000).toFixed(1)}k` : `${x}`);
|
|
247
|
-
const savedStr = `${fmt(rt.tokensSaved)} sess / ${fmt(repo.tokensSaved)} repo`;
|
|
248
|
-
const usedStr = `${fmt(st.totalTokenEstimate)} sess / ${fmt(repo.totalTokenEstimate)} repo`;
|
|
247
|
+
const savedStr = `${C.green}${fmt(rt.tokensSaved)} sess${C.reset} / ${C.blue}${fmt(repo.tokensSaved)} repo${C.reset}`;
|
|
248
|
+
const usedStr = `${C.cyan}${fmt(st.totalTokenEstimate)} sess${C.reset} / ${C.blue}${fmt(repo.totalTokenEstimate)} repo${C.reset}`;
|
|
249
249
|
const agentStr = activeAgents > 0 ? ` │ 🤖 ${activeAgents} agent${activeAgents === 1 ? "" : "s"}` : "";
|
|
250
250
|
const turnStr = currentTurn > 0 ? ` │ turn ${currentTurn}` : "";
|
|
251
|
-
|
|
252
|
-
` ⚡ ${config.tier} │ ${tokStr}/${maxStr} tokens (${pctStr}) │ ${st.checkpointCount} chkpt${st.checkpointCount === 1 ? "" : "s"}${agentStr}${turnStr}`,
|
|
253
|
-
` ${triggerLabel} │ dedup: ${dedupStr} │ used
|
|
254
|
-
]
|
|
251
|
+
const lines = [
|
|
252
|
+
` ${C.amber}⚡ ${config.tier}${C.reset} │ ${tokStr}/${maxStr} tokens (${C.bold}${pctStr}${C.reset}) │ ${st.checkpointCount} chkpt${st.checkpointCount === 1 ? "" : "s"}${agentStr}${turnStr}`,
|
|
253
|
+
` ${triggerLabel} │ ${C.magenta}dedup: ${dedupStr}${C.reset} │ ${C.gray}used:${C.reset} ${usedStr} │ ${C.gray}saved:${C.reset} ${savedStr}`,
|
|
254
|
+
];
|
|
255
|
+
// Live "now processing" line — teal while fresh (≤4s), then the last-seen
|
|
256
|
+
// action keeps the widget lively. Cleared on session reset.
|
|
257
|
+
if (currentActivity) {
|
|
258
|
+
const fresh = Date.now() - lastActivityAt < 4000;
|
|
259
|
+
lines.push(` ${fresh ? C.teal : C.dim}${currentActivity}${C.reset}`);
|
|
260
|
+
}
|
|
261
|
+
ctx.ui.setWidget(WIDGET_KEY, lines, { placement: "aboveEditor" });
|
|
255
262
|
}
|
|
256
263
|
}
|
|
257
264
|
// The only mutable per-session state. Reset on session_start / session_tree.
|
|
@@ -273,6 +280,26 @@ export default function (pi) {
|
|
|
273
280
|
// before_agent_start should prepend to the system prompt. Unset after use.
|
|
274
281
|
let pendingRecallBlock;
|
|
275
282
|
let statusKey; // current status text for dashboard
|
|
283
|
+
// Live "what it's doing right now" line for the toolbar. Set on each
|
|
284
|
+
// compaction; shown in teal while recent, then kept as the last-seen action so
|
|
285
|
+
// the widget is never blank. Cleared on session reset.
|
|
286
|
+
let currentActivity;
|
|
287
|
+
let lastActivityAt = 0;
|
|
288
|
+
// ANSI palette for the toolbar. The pi TUI's Text component preserves ANSI
|
|
289
|
+
// escape codes (see wrapTextWithAnsi), so raw escapes render as colors. No
|
|
290
|
+
// chalk dependency needed — these are just strings.
|
|
291
|
+
const C = {
|
|
292
|
+
reset: "\x1b[0m",
|
|
293
|
+
dim: "\x1b[2m",
|
|
294
|
+
bold: "\x1b[1m",
|
|
295
|
+
amber: "\x1b[38;5;214m", // tier / ready
|
|
296
|
+
green: "\x1b[38;5;120m", // saved
|
|
297
|
+
cyan: "\x1b[38;5;51m", // used / live activity
|
|
298
|
+
teal: "\x1b[38;5;37m", // processing (compress/dedup)
|
|
299
|
+
magenta: "\x1b[38;5;201m", // dedup rate
|
|
300
|
+
blue: "\x1b[38;5;75m", // repo totals
|
|
301
|
+
gray: "\x1b[38;5;245m", // labels
|
|
302
|
+
};
|
|
276
303
|
function setStatus(ctx, text) {
|
|
277
304
|
statusKey = text;
|
|
278
305
|
ctx.ui.setStatus(STATUS_KEY, text);
|
|
@@ -294,6 +321,8 @@ export default function (pi) {
|
|
|
294
321
|
statusKey = undefined;
|
|
295
322
|
activeAgents = 0;
|
|
296
323
|
currentTurn = 0;
|
|
324
|
+
currentActivity = undefined;
|
|
325
|
+
lastActivityAt = 0;
|
|
297
326
|
}
|
|
298
327
|
/** Run the full compaction pipeline and persist a checkpoint. Returns the result. */
|
|
299
328
|
function runCompact(ctx, messages, opts = {}) {
|
|
@@ -332,6 +361,16 @@ export default function (pi) {
|
|
|
332
361
|
rt.tokensSaved += saved;
|
|
333
362
|
if (result.deduped)
|
|
334
363
|
rt.dedupSkips++;
|
|
364
|
+
// Live toolbar "now processing" line: what file/region just got compacted or
|
|
365
|
+
// deduped. Reset to the last-seen action after a few seconds (see snapshot).
|
|
366
|
+
const files = result.filesModified ?? [];
|
|
367
|
+
const fileLabel = files.length
|
|
368
|
+
? files.map((f) => f.split("/").pop() ?? f).slice(0, 2).join(", ")
|
|
369
|
+
: result.regionHash.slice(0, 8);
|
|
370
|
+
currentActivity = result.deduped
|
|
371
|
+
? `♻ deduped ${fileLabel}`
|
|
372
|
+
: `🗜 compacted ${result.checkpointId} · ${fileLabel}`;
|
|
373
|
+
lastActivityAt = Date.now();
|
|
335
374
|
// Record session activity + a daily-log entry in the per-repo SQLite store
|
|
336
375
|
// (foundation for resume-sessions / daily-log features). Best-effort — never
|
|
337
376
|
// block a compaction on bookkeeping.
|
package/dist/src/engine.js
CHANGED
|
@@ -46,6 +46,7 @@ export function compactSession(input, store = getDefaultStore()) {
|
|
|
46
46
|
summary: "",
|
|
47
47
|
regionHash: "",
|
|
48
48
|
tokenEstimate: 0,
|
|
49
|
+
filesModified: [],
|
|
49
50
|
originalTokenEstimate: 0,
|
|
50
51
|
compactedFrom,
|
|
51
52
|
};
|
|
@@ -111,6 +112,7 @@ export function compactSession(input, store = getDefaultStore()) {
|
|
|
111
112
|
summary,
|
|
112
113
|
regionHash,
|
|
113
114
|
tokenEstimate: storedTokens,
|
|
115
|
+
filesModified,
|
|
114
116
|
originalTokenEstimate,
|
|
115
117
|
compactedFrom,
|
|
116
118
|
};
|
|
@@ -325,7 +325,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
325
325
|
const tokStr = lastCtxTokens != null ? `${Math.round(lastCtxTokens / 1000)}k` : "?";
|
|
326
326
|
const maxStr = lastCtxWindow > 0 ? `${Math.round(lastCtxWindow / 1000)}k` : "?";
|
|
327
327
|
const pctStr = lastCtxPercent != null ? `${Math.round(lastCtxPercent * 10) / 10}%` : "?%";
|
|
328
|
-
const triggerLabel = ready ?
|
|
328
|
+
const triggerLabel = ready ? `${C.green}● ready${C.reset}` : armed ? `${C.amber}◐ armed${C.reset}` : `${C.gray}○ idle${C.reset}`;
|
|
329
329
|
// Storage dedup rate is cumulative (store-wide, per-repo) and survives
|
|
330
330
|
// session resets. Always show a number: 0% before any compaction, a
|
|
331
331
|
// decimal for sub-10% rates so small-but-real dedup isn't rounded away.
|
|
@@ -340,18 +340,21 @@ export default function (pi: ExtensionAPI) {
|
|
|
340
340
|
// vs st.totalTokenEstimate). Use "k" only at/above 1000 so small-but-real
|
|
341
341
|
// numbers stay visible (previously Math.round(x/1000) zeroed <1000).
|
|
342
342
|
const fmt = (x: number) => (x >= 1000 ? `${(x / 1000).toFixed(1)}k` : `${x}`);
|
|
343
|
-
const savedStr = `${fmt(rt.tokensSaved)} sess / ${fmt(repo.tokensSaved)} repo`;
|
|
344
|
-
const usedStr = `${fmt(st.totalTokenEstimate)} sess / ${fmt(repo.totalTokenEstimate)} repo`;
|
|
343
|
+
const savedStr = `${C.green}${fmt(rt.tokensSaved)} sess${C.reset} / ${C.blue}${fmt(repo.tokensSaved)} repo${C.reset}`;
|
|
344
|
+
const usedStr = `${C.cyan}${fmt(st.totalTokenEstimate)} sess${C.reset} / ${C.blue}${fmt(repo.totalTokenEstimate)} repo${C.reset}`;
|
|
345
345
|
const agentStr = activeAgents > 0 ? ` │ 🤖 ${activeAgents} agent${activeAgents === 1 ? "" : "s"}` : "";
|
|
346
346
|
const turnStr = currentTurn > 0 ? ` │ turn ${currentTurn}` : "";
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
347
|
+
const lines = [
|
|
348
|
+
` ${C.amber}⚡ ${config.tier}${C.reset} │ ${tokStr}/${maxStr} tokens (${C.bold}${pctStr}${C.reset}) │ ${st.checkpointCount} chkpt${st.checkpointCount === 1 ? "" : "s"}${agentStr}${turnStr}`,
|
|
349
|
+
` ${triggerLabel} │ ${C.magenta}dedup: ${dedupStr}${C.reset} │ ${C.gray}used:${C.reset} ${usedStr} │ ${C.gray}saved:${C.reset} ${savedStr}`,
|
|
350
|
+
];
|
|
351
|
+
// Live "now processing" line — teal while fresh (≤4s), then the last-seen
|
|
352
|
+
// action keeps the widget lively. Cleared on session reset.
|
|
353
|
+
if (currentActivity) {
|
|
354
|
+
const fresh = Date.now() - lastActivityAt < 4000;
|
|
355
|
+
lines.push(` ${fresh ? C.teal : C.dim}${currentActivity}${C.reset}`);
|
|
356
|
+
}
|
|
357
|
+
ctx.ui.setWidget(WIDGET_KEY, lines, { placement: "aboveEditor" });
|
|
355
358
|
}
|
|
356
359
|
}
|
|
357
360
|
|
|
@@ -374,6 +377,26 @@ export default function (pi: ExtensionAPI) {
|
|
|
374
377
|
// before_agent_start should prepend to the system prompt. Unset after use.
|
|
375
378
|
let pendingRecallBlock: string | undefined;
|
|
376
379
|
let statusKey: string | undefined; // current status text for dashboard
|
|
380
|
+
// Live "what it's doing right now" line for the toolbar. Set on each
|
|
381
|
+
// compaction; shown in teal while recent, then kept as the last-seen action so
|
|
382
|
+
// the widget is never blank. Cleared on session reset.
|
|
383
|
+
let currentActivity: string | undefined;
|
|
384
|
+
let lastActivityAt = 0;
|
|
385
|
+
// ANSI palette for the toolbar. The pi TUI's Text component preserves ANSI
|
|
386
|
+
// escape codes (see wrapTextWithAnsi), so raw escapes render as colors. No
|
|
387
|
+
// chalk dependency needed — these are just strings.
|
|
388
|
+
const C = {
|
|
389
|
+
reset: "\x1b[0m",
|
|
390
|
+
dim: "\x1b[2m",
|
|
391
|
+
bold: "\x1b[1m",
|
|
392
|
+
amber: "\x1b[38;5;214m", // tier / ready
|
|
393
|
+
green: "\x1b[38;5;120m", // saved
|
|
394
|
+
cyan: "\x1b[38;5;51m", // used / live activity
|
|
395
|
+
teal: "\x1b[38;5;37m", // processing (compress/dedup)
|
|
396
|
+
magenta: "\x1b[38;5;201m", // dedup rate
|
|
397
|
+
blue: "\x1b[38;5;75m", // repo totals
|
|
398
|
+
gray: "\x1b[38;5;245m", // labels
|
|
399
|
+
};
|
|
377
400
|
|
|
378
401
|
function setStatus(ctx: ExtensionContext, text: string | undefined) {
|
|
379
402
|
statusKey = text;
|
|
@@ -396,6 +419,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
396
419
|
statusKey = undefined;
|
|
397
420
|
activeAgents = 0;
|
|
398
421
|
currentTurn = 0;
|
|
422
|
+
currentActivity = undefined;
|
|
423
|
+
lastActivityAt = 0;
|
|
399
424
|
}
|
|
400
425
|
|
|
401
426
|
/** Run the full compaction pipeline and persist a checkpoint. Returns the result. */
|
|
@@ -443,6 +468,17 @@ export default function (pi: ExtensionAPI) {
|
|
|
443
468
|
rt.tokensSaved += saved;
|
|
444
469
|
if (result.deduped) rt.dedupSkips++;
|
|
445
470
|
|
|
471
|
+
// Live toolbar "now processing" line: what file/region just got compacted or
|
|
472
|
+
// deduped. Reset to the last-seen action after a few seconds (see snapshot).
|
|
473
|
+
const files = result.filesModified ?? [];
|
|
474
|
+
const fileLabel = files.length
|
|
475
|
+
? files.map((f) => f.split("/").pop() ?? f).slice(0, 2).join(", ")
|
|
476
|
+
: result.regionHash.slice(0, 8);
|
|
477
|
+
currentActivity = result.deduped
|
|
478
|
+
? `♻ deduped ${fileLabel}`
|
|
479
|
+
: `🗜 compacted ${result.checkpointId} · ${fileLabel}`;
|
|
480
|
+
lastActivityAt = Date.now();
|
|
481
|
+
|
|
446
482
|
// Record session activity + a daily-log entry in the per-repo SQLite store
|
|
447
483
|
// (foundation for resume-sessions / daily-log features). Best-effort — never
|
|
448
484
|
// block a compaction on bookkeeping.
|
package/package.json
CHANGED
package/src/engine.ts
CHANGED
|
@@ -51,6 +51,9 @@ export interface CompactResult {
|
|
|
51
51
|
summary: string;
|
|
52
52
|
regionHash: string;
|
|
53
53
|
tokenEstimate: number;
|
|
54
|
+
/** Files touched by the compacted region (surfaced to the UI for a live
|
|
55
|
+
* "compressing <file>" activity line). May be empty if not captured. */
|
|
56
|
+
filesModified: string[];
|
|
54
57
|
/** Token count of the original dropped region (before compaction). The honest
|
|
55
58
|
* "tokens saved" base = originalTokenEstimate − tokenEstimate (stored), or the
|
|
56
59
|
* full originalTokenEstimate when the region deduped onto an existing
|
|
@@ -92,6 +95,7 @@ export function compactSession(input: CompactInput, store: VectorStore = getDefa
|
|
|
92
95
|
summary: "",
|
|
93
96
|
regionHash: "",
|
|
94
97
|
tokenEstimate: 0,
|
|
98
|
+
filesModified: [],
|
|
95
99
|
originalTokenEstimate: 0,
|
|
96
100
|
compactedFrom,
|
|
97
101
|
};
|
|
@@ -163,6 +167,7 @@ export function compactSession(input: CompactInput, store: VectorStore = getDefa
|
|
|
163
167
|
summary,
|
|
164
168
|
regionHash,
|
|
165
169
|
tokenEstimate: storedTokens,
|
|
170
|
+
filesModified,
|
|
166
171
|
originalTokenEstimate,
|
|
167
172
|
compactedFrom,
|
|
168
173
|
};
|