pi-magi-theme 0.1.0 → 0.1.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 CHANGED
@@ -4,6 +4,10 @@ A three-mind council theme + extension for [pi](https://pi.dev): a detailed Tree
4
4
 
5
5
  All artwork is original. The symbolism (the three Magi, the Tree of Life, the golem, the seven seals) is public domain.
6
6
 
7
+ ![pi with the MAGI theme: Tree of Life header, side panel with the MAGI triangle and llama-swap telemetry](https://raw.githubusercontent.com/b-iurea/pi-magi-theme/main/docs/screenshot.png)
8
+
9
+ ![The MAGI deliberating while the model thinks](https://raw.githubusercontent.com/b-iurea/pi-magi-theme/main/docs/deliberation.png)
10
+
7
11
  ## Install
8
12
 
9
13
  ```bash
@@ -48,6 +52,16 @@ Every symbol stands for something real the agent is doing.
48
52
  | the seven seals | the end of an age | **context window usage**, one seal per seventh | panel |
49
53
  | breaking the seals → seventh seal opened | apocalypse and renewal | **context compaction** running → done | panel + footer |
50
54
 
55
+ ## The seventh seal: smart compaction
56
+
57
+ The theme does not compact anything itself: it shows who does. For better compaction install [pi-smart-compact](https://www.npmjs.com/package/pi-smart-compact):
58
+
59
+ ```bash
60
+ pi install npm:pi-smart-compact
61
+ ```
62
+
63
+ It extracts files, errors, decisions and open loops locally (no LLM calls), then synthesizes and verifies the summary. Point its `summaryModel` at a local model to keep compaction free. When it is installed, the seals name it while they break (`✶ BREAKING THE SEALS · smart-compact · 4s`) and the seventh seal reports who actually produced the summary: `smart-compact`, or `pi native` if it fell back to pi's own compactor.
64
+
51
65
  ## The council
52
66
 
53
67
  `/magi <question>` asks three models in parallel, each with its own nature, then shows the votes and a majority verdict:
@@ -200,7 +200,6 @@ const state = {
200
200
  phaseSince: Date.now(),
201
201
  toolName: "",
202
202
  turns: 0,
203
- tools: 0,
204
203
  toolOk: 0, // CHESED
205
204
  toolFail: 0, // GEBURAH
206
205
  lastFailAt: 0,
@@ -209,6 +208,7 @@ const state = {
209
208
  lastRunMs: 0,
210
209
  compacting: false,
211
210
  compactSince: 0,
211
+ compactBy: "", // who opens the seals: "smart-compact" (pi-smart-compact package) or "pi native"
212
212
  rebornAt: 0,
213
213
  };
214
214
 
@@ -646,7 +646,9 @@ class MagiPanel implements Component {
646
646
  if (state.compacting || now - state.rebornAt < REBIRTH_MS) {
647
647
  // the seals break while the context is compacted; then the world is remade
648
648
  const reborn = !state.compacting;
649
- title = reborn ? "SEVENTH SEAL OPENED · REBORN" : `BREAKING THE SEALS ${secsSince(state.compactSince, now)}s`;
649
+ title = reborn
650
+ ? "SEVENTH SEAL OPENED · REBORN"
651
+ : `SEALS · ${state.compactBy || "compacting"} ${secsSince(state.compactSince, now)}s`;
650
652
  link = reborn ? "success" : f % 4 < 2 ? "warning" : "error";
651
653
  hub = reborn ? "═MAGI═" : ["─SEAL─", "━SEAL━"][f % 2]!;
652
654
  units = names.map((name, i) =>
@@ -748,7 +750,7 @@ class MagiPanel implements Component {
748
750
  const stats = tokenStats();
749
751
  out.push(
750
752
  this.frameLine(
751
- ` ${th.fg("dim", "TURNS".padEnd(9))}${th.fg("text", String(state.turns).padEnd(6))}${th.fg("dim", "TOOLS ")}${th.fg("text", String(state.tools))}`,
753
+ ` ${th.fg("dim", "TURNS".padEnd(9))}${th.fg("text", String(state.turns))}`,
752
754
  inner,
753
755
  ),
754
756
  );
@@ -771,14 +773,13 @@ class MagiPanel implements Component {
771
773
  inner,
772
774
  ),
773
775
  );
774
- if (state.toolOk + state.toolFail) {
775
- out.push(
776
- this.frameLine(
777
- ` ${th.fg("dim", "CHESED".padEnd(9))}${th.fg("success", `✓${state.toolOk}`.padEnd(6))}${th.fg("dim", "GEBURAH ")}${th.fg(state.toolFail ? "error" : "dim", `✗${state.toolFail}`)}`,
778
- inner,
779
- ),
780
- );
781
- }
776
+ // TOOLS: CHESED (mercy) = succeeded, GEBURAH (severity) = failed
777
+ out.push(
778
+ this.frameLine(
779
+ ` ${th.fg("dim", "TOOLS".padEnd(7))}${th.fg("success", `✓${state.toolOk}`)}${th.fg("dim", " CHESED ")}${th.fg(state.toolFail ? "error" : "dim", `✗${state.toolFail}`)}${th.fg("dim", " GEBURAH")}`,
780
+ inner,
781
+ ),
782
+ );
782
783
 
783
784
  // SEALS: the context window, one seal per seventh
784
785
  const usage = liveCtx?.getContextUsage?.();
@@ -800,9 +801,11 @@ class MagiPanel implements Component {
800
801
  ),
801
802
  );
802
803
  if (swap.srvPps) out.push(this.field("PROMPT/S", swap.srvPps.toFixed(1), inner, "muted"));
803
- if (swap.inputTokens) {
804
- const hit = Math.round((swap.cacheTokens / swap.inputTokens) * 100);
805
- out.push(this.field("KV CACHE", `${fmtTokens(swap.cacheTokens)}/${fmtTokens(swap.inputTokens)} hit ${hit}%`, inner, "muted"));
804
+ // llama-swap's input_tokens are the prompt tokens processed outside the cache
805
+ const promptTotal = swap.cacheTokens + swap.inputTokens;
806
+ if (promptTotal) {
807
+ const hit = Math.round((swap.cacheTokens / promptTotal) * 100);
808
+ out.push(this.field("KV CACHE", `${fmtTokens(swap.cacheTokens)}/${fmtTokens(promptTotal)} hit ${hit}%`, inner, "muted"));
806
809
  }
807
810
  out.push(this.field("PEAK", perf.peakTps ? `${perf.peakTps.toFixed(1)} tok/s` : "—", inner, "muted"));
808
811
  out.push(this.field("TTFT", perf.ttft ? fmtMs(perf.ttft) : "—", inner, "muted"));
@@ -1119,7 +1122,9 @@ function footerLeft(th: Theme, now = Date.now()): string {
1119
1122
  th.fg("warning", "◉".repeat(broken)) +
1120
1123
  dim("○".repeat(7 - broken)) +
1121
1124
  th.fg("warning", " BREAKING THE SEALS") +
1122
- dim(` · compacting context ${secsSince(state.compactSince, now)}s`)
1125
+ dim(" · ") +
1126
+ th.fg("text", state.compactBy || "compacting") +
1127
+ dim(` · ${secsSince(state.compactSince, now)}s`)
1123
1128
  );
1124
1129
  }
1125
1130
  if (now - state.rebornAt < REBIRTH_MS) {
@@ -1127,7 +1132,7 @@ function footerLeft(th: Theme, now = Date.now()): string {
1127
1132
  th.fg("success", "✶ ") +
1128
1133
  renderPath(th, lights(() => (step % 2 ? "on" : "hot"))) +
1129
1134
  th.fg("success", " SEVENTH SEAL OPENED") +
1130
- dim(" · context compacted, the world is remade")
1135
+ dim(` · context compacted by ${state.compactBy || "pi"}, the world is remade`)
1131
1136
  );
1132
1137
  }
1133
1138
  if (state.phase === "tool" || now - state.lastFailAt < FAIL_FLASH_MS) {
@@ -1395,7 +1400,6 @@ export default function (pi: ExtensionAPI) {
1395
1400
  liveCtx = ctx;
1396
1401
  setPhase("tool");
1397
1402
  state.toolName = event.toolName ?? "";
1398
- state.tools++;
1399
1403
  repaint();
1400
1404
  });
1401
1405
 
@@ -1422,15 +1426,21 @@ export default function (pi: ExtensionAPI) {
1422
1426
  });
1423
1427
 
1424
1428
  // The seven seals: compaction breaks them, and the context is reborn.
1429
+ // When pi-smart-compact is installed it owns the compaction; this theme only watches and names it.
1430
+ const hasSmartCompact = () => pi.getCommands().some((c) => c.name.replace(/^\//, "") === "smart-compact");
1431
+
1425
1432
  pi.on("session_before_compact", async () => {
1426
1433
  state.compacting = true;
1427
1434
  state.compactSince = Date.now();
1435
+ state.compactBy = hasSmartCompact() ? "smart-compact" : "pi native";
1428
1436
  repaint();
1429
1437
  });
1430
1438
 
1431
- pi.on("session_compact", async () => {
1439
+ pi.on("session_compact", async (event) => {
1432
1440
  state.compacting = false;
1433
1441
  state.rebornAt = Date.now();
1442
+ // fromExtension: an extension supplied the summary; otherwise pi's own compactor did (e.g. smart-compact fell back)
1443
+ state.compactBy = event.fromExtension ? (hasSmartCompact() ? "smart-compact" : "extension") : "pi native";
1434
1444
  repaint();
1435
1445
  });
1436
1446
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-magi-theme",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "MAGI theme + extension for pi: Tree of Life header, three-model /magi council, golem tool animations, seven-seal context gauge, llama-swap telemetry",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -29,6 +29,7 @@
29
29
  "LICENSE"
30
30
  ],
31
31
  "pi": {
32
+ "image": "https://raw.githubusercontent.com/b-iurea/pi-magi-theme/main/docs/screenshot.png",
32
33
  "extensions": [
33
34
  "./extensions/magi/index.ts"
34
35
  ],