@monotykamary/pi-vcc 0.6.0 → 0.6.2
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 +1 -0
- package/npm-shrinkwrap.json +3270 -1806
- package/package.json +12 -11
- package/pnpm-workspace.yaml +3 -0
- package/src/commands/pi-vcc.ts +7 -2
- package/src/core/compaction-count.ts +52 -0
- package/src/core/invisible-continue.ts +4 -0
- package/src/hooks/before-compact.ts +6 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monotykamary/pi-vcc",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "Algorithmic conversation compactor for pi - transcript-preserving structured summaries, no LLM calls",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"keywords": [
|
|
@@ -15,22 +15,23 @@
|
|
|
15
15
|
"url": "git+https://github.com/monotykamary/pi-vcc.git"
|
|
16
16
|
},
|
|
17
17
|
"peerDependencies": {
|
|
18
|
-
"@earendil-works/pi-
|
|
19
|
-
"@earendil-works/pi-
|
|
20
|
-
"@earendil-works/pi-coding-agent": "
|
|
18
|
+
"@earendil-works/pi-agent-core": "^0.79.8",
|
|
19
|
+
"@earendil-works/pi-ai": "^0.79.8",
|
|
20
|
+
"@earendil-works/pi-coding-agent": "^0.79.8",
|
|
21
21
|
"typebox": ">=1.1.24 <2.0.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"
|
|
25
|
-
"knip": "6.14.1"
|
|
26
|
-
|
|
27
|
-
"scripts": {
|
|
28
|
-
"typecheck": "tsc --noEmit",
|
|
29
|
-
"lint:dead": "knip"
|
|
24
|
+
"@types/node": "^26.0.0",
|
|
25
|
+
"knip": "6.14.1",
|
|
26
|
+
"typescript": "6.0.3"
|
|
30
27
|
},
|
|
31
28
|
"pi": {
|
|
32
29
|
"extensions": [
|
|
33
30
|
"./index.ts"
|
|
34
31
|
]
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"typecheck": "tsc --noEmit",
|
|
35
|
+
"lint:dead": "knip"
|
|
35
36
|
}
|
|
36
|
-
}
|
|
37
|
+
}
|
package/src/commands/pi-vcc.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { getLastCompactionStats, PI_VCC_COMPACT_INSTRUCTION } from "../hooks/before-compact";
|
|
3
|
+
import { countPiVccCompactionsFromSession, ordinalSuffix } from "../core/compaction-count";
|
|
3
4
|
|
|
4
5
|
const formatTokens = (n: number): string => {
|
|
5
6
|
if (n >= 1000) return `${(n / 1000).toFixed(1)}k`;
|
|
@@ -14,13 +15,17 @@ export const registerPiVccCommand = (pi: ExtensionAPI) => {
|
|
|
14
15
|
customInstructions: PI_VCC_COMPACT_INSTRUCTION,
|
|
15
16
|
onComplete: () => {
|
|
16
17
|
const stats = getLastCompactionStats();
|
|
18
|
+
const { total, latestOrdinal } = countPiVccCompactionsFromSession(ctx.sessionManager);
|
|
19
|
+
const compactionLabel = total > 0
|
|
20
|
+
? ` (${latestOrdinal}${ordinalSuffix(latestOrdinal)} compaction; ${total} total)`
|
|
21
|
+
: "";
|
|
17
22
|
if (stats) {
|
|
18
23
|
ctx.ui.notify(
|
|
19
|
-
`pi-vcc: ${stats.summarized} source entries processed; tail kept ${stats.kept} (~${formatTokens(stats.keptTokensEst)} tok)
|
|
24
|
+
`pi-vcc: ${stats.summarized} source entries processed; tail kept ${stats.kept} (~${formatTokens(stats.keptTokensEst)} tok).${compactionLabel}`,
|
|
20
25
|
"info",
|
|
21
26
|
);
|
|
22
27
|
} else {
|
|
23
|
-
ctx.ui.notify(
|
|
28
|
+
ctx.ui.notify(`Compacted with pi-vcc${compactionLabel}`, "info");
|
|
24
29
|
}
|
|
25
30
|
},
|
|
26
31
|
onError: (err) => {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Count pi-vcc compactions in the session.
|
|
3
|
+
*
|
|
4
|
+
* Compaction entries are persisted to the session file as
|
|
5
|
+
* `{ type: "compaction", details: { compactor: "pi-vcc", ... } }`.
|
|
6
|
+
* `session_compact` fires after the new compaction entry has been appended,
|
|
7
|
+
* so counting entries at that point includes the just-completed compaction.
|
|
8
|
+
*
|
|
9
|
+
* `getEntries()` returns the full append-only session (all lineages), which
|
|
10
|
+
* matches the `compaction:N` indexing scheme used by vcc_recall — so the
|
|
11
|
+
* ordinal shown in the notification lines up with `scope:"compaction:N"`.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export const ordinalSuffix = (n: number): string => {
|
|
15
|
+
const last = n % 10;
|
|
16
|
+
const lastTwo = n % 100;
|
|
17
|
+
if (lastTwo >= 11 && lastTwo <= 13) return "th";
|
|
18
|
+
if (last === 1) return "st";
|
|
19
|
+
if (last === 2) return "nd";
|
|
20
|
+
if (last === 3) return "rd";
|
|
21
|
+
return "th";
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
interface SessionManagerLike {
|
|
25
|
+
getEntries?: () => any[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface CompactionCount {
|
|
29
|
+
/** Total pi-vcc compactions in the session (includes the just-completed one). */
|
|
30
|
+
total: number;
|
|
31
|
+
/** 1-based ordinal of the latest compaction (== total, or 0 when none). */
|
|
32
|
+
latestOrdinal: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const countPiVccCompactions = (entries: any[]): CompactionCount => {
|
|
36
|
+
let total = 0;
|
|
37
|
+
for (const e of entries) {
|
|
38
|
+
if (e?.type === "compaction" && e?.details?.compactor === "pi-vcc") total++;
|
|
39
|
+
}
|
|
40
|
+
return { total, latestOrdinal: total };
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const countPiVccCompactionsFromSession = (
|
|
44
|
+
sessionManager: SessionManagerLike | undefined,
|
|
45
|
+
): CompactionCount => {
|
|
46
|
+
try {
|
|
47
|
+
const entries = sessionManager?.getEntries?.() ?? [];
|
|
48
|
+
return countPiVccCompactions(entries);
|
|
49
|
+
} catch {
|
|
50
|
+
return { total: 0, latestOrdinal: 0 };
|
|
51
|
+
}
|
|
52
|
+
};
|
|
@@ -40,6 +40,10 @@ Agent.prototype.subscribe = function (this: Agent, ...args: any[]) {
|
|
|
40
40
|
// "Cannot continue from message role: assistant" and the agent loop
|
|
41
41
|
// exits — leaving mid-task work unfinished.
|
|
42
42
|
//
|
|
43
|
+
// Note (pi 0.79+): Agent.continue() now drains queued steering/follow-up
|
|
44
|
+
// messages before throwing, so this throw path only fires when there are
|
|
45
|
+
// genuinely no queued messages — the prompt([]) fallback is still correct.
|
|
46
|
+
//
|
|
43
47
|
// The fix: when continue() would throw because the last message is an
|
|
44
48
|
// assistant, fall back to prompt([]) instead. prompt([]) doesn't check
|
|
45
49
|
// the last message role — it starts a fresh agent loop with the current
|
|
@@ -3,6 +3,7 @@ import { writeFileSync } from "fs";
|
|
|
3
3
|
import { compile, type CompileInput } from "../core/summarize";
|
|
4
4
|
import { loadSettings, type PiVccSettings } from "../core/settings";
|
|
5
5
|
import { triggerInvisibleContinue } from "../core/invisible-continue";
|
|
6
|
+
import { countPiVccCompactionsFromSession, ordinalSuffix } from "../core/compaction-count";
|
|
6
7
|
import type { PiVccCompactionDetails } from "../details";
|
|
7
8
|
|
|
8
9
|
export const PI_VCC_COMPACT_INSTRUCTION = "__pi_vcc__";
|
|
@@ -489,11 +490,15 @@ export const registerBeforeCompactHook = (pi: ExtensionAPI) => {
|
|
|
489
490
|
// /pi-vcc path uses its own onComplete callback in the command handler.
|
|
490
491
|
if (!lastCompactWasPiVcc) {
|
|
491
492
|
const stats = lastStats;
|
|
493
|
+
const { total, latestOrdinal } = countPiVccCompactionsFromSession(ctx?.sessionManager as any);
|
|
494
|
+
const compactionLabel = total > 0
|
|
495
|
+
? ` (${latestOrdinal}${ordinalSuffix(latestOrdinal)} compaction; ${total} total)`
|
|
496
|
+
: "";
|
|
492
497
|
if (stats) {
|
|
493
498
|
setTimeout(() => {
|
|
494
499
|
try {
|
|
495
500
|
ctx?.ui?.notify?.(
|
|
496
|
-
`pi-vcc: ${stats.summarized} source entries processed; tail kept ${stats.kept} (~${formatTokens(stats.keptTokensEst)} tok)
|
|
501
|
+
`pi-vcc: ${stats.summarized} source entries processed; tail kept ${stats.kept} (~${formatTokens(stats.keptTokensEst)} tok).${compactionLabel}`,
|
|
497
502
|
"info",
|
|
498
503
|
);
|
|
499
504
|
} catch {}
|