@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monotykamary/pi-vcc",
3
- "version": "0.6.0",
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-ai": ">=0.74.0 <1.0.0",
19
- "@earendil-works/pi-agent-core": ">=0.74.0 <1.0.0",
20
- "@earendil-works/pi-coding-agent": ">=0.74.0 <1.0.0",
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
- "typescript": "6.0.3",
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
+ }
@@ -0,0 +1,3 @@
1
+ allowBuilds:
2
+ '@google/genai': false
3
+ protobufjs: false
@@ -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("Compacted with pi-vcc", "info");
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 {}