pi-ui-extend 1.0.41 → 1.0.45

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.
Files changed (236) hide show
  1. package/README.md +50 -13
  2. package/dist/app/app.d.ts +13 -0
  3. package/dist/app/app.js +158 -8
  4. package/dist/app/cli/install.js +2 -2
  5. package/dist/app/commands/command-controller.d.ts +4 -0
  6. package/dist/app/commands/command-controller.js +11 -0
  7. package/dist/app/commands/command-git-actions.d.ts +25 -0
  8. package/dist/app/commands/command-git-actions.js +381 -0
  9. package/dist/app/commands/command-host.d.ts +4 -0
  10. package/dist/app/commands/command-host.js +5 -2
  11. package/dist/app/commands/command-model-actions.d.ts +1 -0
  12. package/dist/app/commands/command-model-actions.js +57 -35
  13. package/dist/app/commands/command-navigation-actions.d.ts +1 -0
  14. package/dist/app/commands/command-navigation-actions.js +16 -3
  15. package/dist/app/commands/command-registry.d.ts +2 -0
  16. package/dist/app/commands/command-registry.js +15 -1
  17. package/dist/app/commands/command-session-actions.js +9 -3
  18. package/dist/app/commands/reload-context-inventory.d.ts +11 -0
  19. package/dist/app/commands/reload-context-inventory.js +70 -0
  20. package/dist/app/extensions/extension-actions-controller.d.ts +1 -0
  21. package/dist/app/extensions/extension-actions-controller.js +6 -0
  22. package/dist/app/extensions/subagent-catalog-state.d.ts +9 -0
  23. package/dist/app/extensions/subagent-catalog-state.js +23 -0
  24. package/dist/app/input/autocomplete-controller.js +61 -34
  25. package/dist/app/input/input-action-controller.d.ts +2 -0
  26. package/dist/app/input/input-action-controller.js +8 -1
  27. package/dist/app/input/input-controller.d.ts +2 -1
  28. package/dist/app/input/input-controller.js +7 -2
  29. package/dist/app/input/prompt-enhancer-controller.js +53 -35
  30. package/dist/app/input/voice-controller.d.ts +41 -45
  31. package/dist/app/input/voice-controller.js +351 -419
  32. package/dist/app/model/model-usage-controller.js +17 -7
  33. package/dist/app/model/model-usage-status.d.ts +4 -1
  34. package/dist/app/model/model-usage-status.js +270 -46
  35. package/dist/app/popup/menu-items-controller.d.ts +13 -3
  36. package/dist/app/popup/menu-items-controller.js +37 -21
  37. package/dist/app/popup/popup-action-controller.d.ts +12 -2
  38. package/dist/app/popup/popup-action-controller.js +77 -24
  39. package/dist/app/popup/popup-menu-controller.d.ts +36 -14
  40. package/dist/app/popup/popup-menu-controller.js +239 -69
  41. package/dist/app/rendering/dcp-stats.d.ts +9 -4
  42. package/dist/app/rendering/dcp-stats.js +40 -425
  43. package/dist/app/rendering/editor-panels.js +10 -4
  44. package/dist/app/rendering/popup-menu-renderer.d.ts +3 -5
  45. package/dist/app/rendering/popup-menu-renderer.js +42 -37
  46. package/dist/app/rendering/render-controller.js +23 -2
  47. package/dist/app/rendering/status-line-renderer.d.ts +5 -0
  48. package/dist/app/rendering/status-line-renderer.js +41 -5
  49. package/dist/app/rendering/tab-line-renderer.js +26 -20
  50. package/dist/app/runtime.d.ts +12 -1
  51. package/dist/app/runtime.js +120 -12
  52. package/dist/app/screen/mouse-controller.d.ts +2 -0
  53. package/dist/app/screen/mouse-controller.js +17 -7
  54. package/dist/app/screen/status-controller.d.ts +4 -0
  55. package/dist/app/screen/status-controller.js +5 -0
  56. package/dist/app/session/lazy-session-manager.js +34 -0
  57. package/dist/app/session/session-event-controller.d.ts +1 -0
  58. package/dist/app/session/session-event-controller.js +10 -1
  59. package/dist/app/session/session-history.d.ts +1 -0
  60. package/dist/app/session/session-history.js +12 -1
  61. package/dist/app/session/session-lifecycle-controller.d.ts +7 -1
  62. package/dist/app/session/session-lifecycle-controller.js +16 -1
  63. package/dist/app/session/tabs-controller.d.ts +26 -1
  64. package/dist/app/session/tabs-controller.js +454 -147
  65. package/dist/app/subagents/subagents-files.js +60 -1
  66. package/dist/app/subagents/subagents-model.d.ts +1 -0
  67. package/dist/app/subagents/subagents-model.js +18 -2
  68. package/dist/app/subagents/subagents-widget-controller.d.ts +1 -0
  69. package/dist/app/subagents/subagents-widget-controller.js +6 -0
  70. package/dist/app/types.d.ts +16 -1
  71. package/dist/app/workspace/workspace-actions-controller.js +10 -2
  72. package/dist/app/workspace/workspace-undo.d.ts +1 -0
  73. package/dist/app/workspace/workspace-undo.js +1 -0
  74. package/dist/bundled-extensions/question/index.js +9 -1
  75. package/dist/bundled-extensions/question/remote.d.ts +4 -0
  76. package/dist/bundled-extensions/question/remote.js +33 -0
  77. package/dist/bundled-extensions/telegram-connector/bot.d.ts +43 -0
  78. package/dist/bundled-extensions/telegram-connector/bot.js +166 -0
  79. package/dist/bundled-extensions/telegram-connector/config.d.ts +8 -0
  80. package/dist/bundled-extensions/telegram-connector/config.js +87 -0
  81. package/dist/bundled-extensions/telegram-connector/coordinator.d.ts +66 -0
  82. package/dist/bundled-extensions/telegram-connector/coordinator.js +413 -0
  83. package/dist/bundled-extensions/telegram-connector/index.d.ts +3 -0
  84. package/dist/bundled-extensions/telegram-connector/index.js +195 -0
  85. package/dist/bundled-extensions/terminal-bell/index.d.ts +0 -8
  86. package/dist/bundled-extensions/terminal-bell/index.js +0 -76
  87. package/dist/bundled-extensions/workspace-undo/index.d.ts +26 -0
  88. package/dist/bundled-extensions/workspace-undo/index.js +191 -0
  89. package/dist/config.d.ts +21 -2
  90. package/dist/config.js +159 -32
  91. package/dist/default-pix-config.js +25 -5
  92. package/dist/schemas/index.d.ts +1 -0
  93. package/dist/schemas/index.js +1 -0
  94. package/dist/schemas/pi-tools-suite-schema.d.ts +88 -62
  95. package/dist/schemas/pi-tools-suite-schema.js +54 -83
  96. package/dist/schemas/pix-schema.d.ts +19 -2
  97. package/dist/schemas/pix-schema.js +47 -5
  98. package/dist/schemas/tasks-schema.d.ts +18 -0
  99. package/dist/schemas/tasks-schema.js +41 -0
  100. package/docs/concurrency.md +9 -1
  101. package/docs/desktop-mvp.md +22 -6
  102. package/docs/desktop-task-manager.md +148 -84
  103. package/docs/release.md +30 -6
  104. package/external/pi-tools-suite/README.md +197 -84
  105. package/external/pi-tools-suite/docs/evals.md +1 -1
  106. package/external/pi-tools-suite/docs/session-recovery.md +47 -14
  107. package/external/pi-tools-suite/docs/subagent-model-pools.md +48 -30
  108. package/external/pi-tools-suite/docs/ui-qa-subagent.md +440 -0
  109. package/external/pi-tools-suite/package.json +6 -1
  110. package/external/pi-tools-suite/src/antigravity-auth/auth-store.ts +2 -1
  111. package/external/pi-tools-suite/src/antigravity-auth/constants.ts +9 -3
  112. package/external/pi-tools-suite/src/antigravity-auth/headers.ts +41 -3
  113. package/external/pi-tools-suite/src/antigravity-auth/models.ts +94 -21
  114. package/external/pi-tools-suite/src/antigravity-auth/oauth.ts +5 -17
  115. package/external/pi-tools-suite/src/antigravity-auth/payload.ts +72 -7
  116. package/external/pi-tools-suite/src/antigravity-auth/stream.ts +13 -1
  117. package/external/pi-tools-suite/src/async-subagents/agents/frontier-review.md +23 -0
  118. package/external/pi-tools-suite/src/async-subagents/agents/implement.md +1 -1
  119. package/external/pi-tools-suite/src/async-subagents/agents/presets.jsonc +16 -0
  120. package/external/pi-tools-suite/src/async-subagents/agents/research.md +5 -3
  121. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/backends/browser.mjs +346 -0
  122. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/backends/desktop.mjs +1038 -0
  123. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/backends/tui.mjs +759 -0
  124. package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/scripts/browser-qa-runner.mjs +32 -23
  125. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/chrome-devtools/chrome-devtools-provider.mjs +895 -0
  126. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/linux/linux-atspi.py +494 -0
  127. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/macos/macos-accessibility.swift +1085 -0
  128. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/native-terminal/bridge-client.mjs +50 -0
  129. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/native-terminal/native-terminal-host.mjs +501 -0
  130. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/windows/windows-uia.ps1 +454 -0
  131. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser-auth.md +114 -0
  132. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser-chrome-devtools.md +91 -0
  133. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser-playwright.md +145 -0
  134. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser.md +82 -0
  135. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop-linux.md +26 -0
  136. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop-macos.md +29 -0
  137. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop-windows.md +23 -0
  138. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop.md +54 -0
  139. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/tui-native-terminal.md +59 -0
  140. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/tui-pty.md +37 -0
  141. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/tui.md +60 -0
  142. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/scripts/ui-qa-runner.mjs +535 -0
  143. package/external/pi-tools-suite/src/async-subagents/agents/ui-qa.md +75 -0
  144. package/external/pi-tools-suite/src/async-subagents/commands.ts +15 -71
  145. package/external/pi-tools-suite/src/async-subagents/core/activity.ts +33 -0
  146. package/external/pi-tools-suite/src/async-subagents/core/agent-catalog.ts +5 -4
  147. package/external/pi-tools-suite/src/async-subagents/core/agent-strategy.ts +1 -1
  148. package/external/pi-tools-suite/src/async-subagents/core/agents-dir.ts +8 -5
  149. package/external/pi-tools-suite/src/async-subagents/core/browser-qa.ts +16 -2
  150. package/external/pi-tools-suite/src/async-subagents/core/config.ts +160 -327
  151. package/external/pi-tools-suite/src/async-subagents/core/model-selection.ts +2 -1
  152. package/external/pi-tools-suite/src/async-subagents/core/registry.ts +158 -33
  153. package/external/pi-tools-suite/src/async-subagents/core/routing.ts +21 -5
  154. package/external/pi-tools-suite/src/async-subagents/core/spawn.ts +40 -26
  155. package/external/pi-tools-suite/src/async-subagents/core/state.ts +40 -0
  156. package/external/pi-tools-suite/src/async-subagents/core/types.ts +7 -0
  157. package/external/pi-tools-suite/src/async-subagents/core/ultrawork-auto.ts +51 -45
  158. package/external/pi-tools-suite/src/async-subagents/index.ts +69 -5
  159. package/external/pi-tools-suite/src/async-subagents/lib.ts +16 -9
  160. package/external/pi-tools-suite/src/async-subagents/tools/spawn.ts +8 -5
  161. package/external/pi-tools-suite/src/async-subagents/tools/subagents.ts +5 -4
  162. package/external/pi-tools-suite/src/async-subagents/types.ts +1 -0
  163. package/external/pi-tools-suite/src/coding-discipline/index.ts +90 -59
  164. package/external/pi-tools-suite/src/config.ts +55 -1
  165. package/external/pi-tools-suite/src/context-gateway/accounting-log.ts +282 -0
  166. package/external/pi-tools-suite/src/context-gateway/config.ts +77 -3
  167. package/external/pi-tools-suite/src/context-gateway/efficiency.ts +414 -0
  168. package/external/pi-tools-suite/src/context-gateway/enforcement.ts +222 -0
  169. package/external/pi-tools-suite/src/context-gateway/index.ts +206 -19
  170. package/external/pi-tools-suite/src/context-gateway/storeless-capabilities.ts +7 -7
  171. package/external/pi-tools-suite/src/context-gateway/telemetry.ts +101 -28
  172. package/external/pi-tools-suite/src/context-gateway/types.ts +16 -3
  173. package/external/pi-tools-suite/src/context-inventory.ts +99 -0
  174. package/external/pi-tools-suite/src/dcp/auto-compress-budget.ts +39 -4
  175. package/external/pi-tools-suite/src/dcp/auto-compress.ts +128 -49
  176. package/external/pi-tools-suite/src/dcp/commands.ts +32 -156
  177. package/external/pi-tools-suite/src/dcp/compress-tool.ts +177 -46
  178. package/external/pi-tools-suite/src/dcp/compression-blocks.ts +6 -58
  179. package/external/pi-tools-suite/src/dcp/compression-preview.ts +9 -0
  180. package/external/pi-tools-suite/src/dcp/compression-progress.ts +22 -0
  181. package/external/pi-tools-suite/src/dcp/config.ts +114 -17
  182. package/external/pi-tools-suite/src/dcp/conversation-index.ts +36 -9
  183. package/external/pi-tools-suite/src/dcp/diagnostics.ts +41 -0
  184. package/external/pi-tools-suite/src/dcp/fresh-tool-results.ts +38 -0
  185. package/external/pi-tools-suite/src/dcp/index.ts +338 -66
  186. package/external/pi-tools-suite/src/dcp/journal.ts +126 -4
  187. package/external/pi-tools-suite/src/dcp/progress-controller.ts +2 -1
  188. package/external/pi-tools-suite/src/dcp/prompts.ts +83 -192
  189. package/external/pi-tools-suite/src/dcp/protected-continuity.ts +175 -0
  190. package/external/pi-tools-suite/src/dcp/pruner-candidates.ts +93 -3
  191. package/external/pi-tools-suite/src/dcp/pruner-message-ids.ts +6 -10
  192. package/external/pi-tools-suite/src/dcp/pruner-nudge.ts +36 -33
  193. package/external/pi-tools-suite/src/dcp/pruner-tools.ts +6 -3
  194. package/external/pi-tools-suite/src/dcp/pruner.ts +1 -0
  195. package/external/pi-tools-suite/src/dcp/routine-pressure.ts +86 -0
  196. package/external/pi-tools-suite/src/dcp/state.ts +9 -0
  197. package/external/pi-tools-suite/src/dcp/statistics.d.ts +8 -0
  198. package/external/pi-tools-suite/src/dcp/statistics.js +156 -0
  199. package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +78 -22
  200. package/external/pi-tools-suite/src/index.ts +7 -1
  201. package/external/pi-tools-suite/src/lib/project.ts +36 -1
  202. package/external/pi-tools-suite/src/model-tools/index.ts +10 -7
  203. package/external/pi-tools-suite/src/repo-discovery/index.ts +304 -4
  204. package/external/pi-tools-suite/src/resource-registry/index.ts +2551 -0
  205. package/external/pi-tools-suite/src/session-recovery/index.ts +17 -0
  206. package/external/pi-tools-suite/src/shell-command-policy.ts +219 -0
  207. package/external/pi-tools-suite/src/todo/index.ts +21 -0
  208. package/external/pi-tools-suite/src/todo/todo.ts +19 -1
  209. package/external/pi-tools-suite/src/tool-descriptions.ts +47 -19
  210. package/package.json +10 -9
  211. package/schemas/pi-tools-suite.json +466 -287
  212. package/schemas/pix.json +129 -11
  213. package/schemas/tasks.json +131 -0
  214. package/skills/simplify/SKILL.md +33 -5
  215. package/docs/desktop-markdown-media.md +0 -77
  216. package/external/pi-tools-suite/docs/browser-qa-subagent.md +0 -177
  217. package/external/pi-tools-suite/docs/dcp-emergency-current-turn.md +0 -102
  218. package/external/pi-tools-suite/src/async-subagents/agents/browser-qa.md +0 -598
  219. package/external/pi-tools-suite/src/async-subagents/async-subagents.sample.jsonc +0 -54
  220. package/external/pi-tools-suite/src/skill-installer/index.ts +0 -333
  221. package/skills/playwright-cli/SKILL.md +0 -420
  222. package/skills/playwright-cli/references/element-attributes.md +0 -23
  223. package/skills/playwright-cli/references/playwright-tests.md +0 -50
  224. package/skills/playwright-cli/references/request-mocking.md +0 -87
  225. package/skills/playwright-cli/references/running-code.md +0 -241
  226. package/skills/playwright-cli/references/session-management.md +0 -273
  227. package/skills/playwright-cli/references/spec-driven-testing.md +0 -311
  228. package/skills/playwright-cli/references/storage-state.md +0 -290
  229. package/skills/playwright-cli/references/test-generation.md +0 -142
  230. package/skills/playwright-cli/references/tracing.md +0 -154
  231. package/skills/playwright-cli/references/video-recording.md +0 -147
  232. package/skills/spec-lite/SKILL.md +0 -140
  233. /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/examples/qa-auth.example.jsonc +0 -0
  234. /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/examples/qa-flow.example.jsonc +0 -0
  235. /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/vendor/fflate.LICENSE +0 -0
  236. /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/vendor/fflate.mjs +0 -0
@@ -0,0 +1,156 @@
1
+ // Shared, dependency-free presentation for the extension, TUI and ACP. Plain
2
+ // ESM is intentional: the compiled host can import the shipped extension source
3
+ // without loading TypeScript or bringing the extension runtime into the host.
4
+
5
+ /** @param {any} v */
6
+ const finite = (v) => typeof v === "number" && Number.isFinite(v);
7
+ /** @param {any} v */
8
+ const num = (v) => finite(v) ? Math.round(v).toLocaleString("en-US") : "unknown";
9
+ /** @param {any} n @param {any} d */
10
+ const percent = (n, d) => finite(n) && finite(d) && d > 0 ? `${(100 * n / d).toFixed(1)}%` : "unknown";
11
+ /** @param {any} v */
12
+ const mode = (v) => typeof v === "boolean" ? (v ? "on" : "off") : "unknown";
13
+ /** @param {any} m */
14
+ const modelRef = (m) => m?.provider && m?.id ? `${m.provider}/${m.id}` : undefined;
15
+ /** @param {any} v */
16
+ const record = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
17
+
18
+ /** Read-only diagnostic reducer. Never runs the pruner, a model, or a mutation.
19
+ * @param {import('./statistics.js').DcpStatisticsInput} input */
20
+ export function collectDcpStatistics(input) {
21
+ const entries = input.branch ?? [];
22
+ const blocks = new Map(), pruned = new Map(), operations = new Map(), measured = new Map();
23
+ let journal = "absent", previous = null, anchors = [], manualMode;
24
+ let epoch, snapshot, lastReminder, ignored, evidenceEpoch = false;
25
+ let projections = 0, attempts = 0, completed = 0, rejected = 0;
26
+ const publishedIds = new Set();
27
+ const attemptIds = new Set(), completionIds = new Set(), manualFailures = new Set();
28
+ const diagnostics = [];
29
+ for (const entry of entries) {
30
+ if (entry?.type === "custom" && entry.customType === "dcp-journal") {
31
+ const op = entry.data;
32
+ if (!record(op) || op.schemaVersion !== 1 || !["init", "delta"].includes(op.kind) || typeof op.operationId !== "string") {
33
+ journal = "invalid/unsupported"; break;
34
+ }
35
+ if (operations.has(op.operationId)) {
36
+ if (operations.get(op.operationId) !== JSON.stringify(op)) { journal = "conflicting operations"; break; }
37
+ continue;
38
+ }
39
+ if ((op.kind === "init" && (previous !== null || op.previousOperationId !== null)) ||
40
+ (op.kind === "delta" && (previous === null || op.previousOperationId !== previous))) {
41
+ journal = "incomplete/broken chain"; break;
42
+ }
43
+ previous = op.operationId;
44
+ operations.set(previous, JSON.stringify(op));
45
+ journal = "chain verified";
46
+ for (const b of op.blocks ?? []) {
47
+ if (!record(b) || !finite(b.id) || typeof b.active !== "boolean" || blocks.has(b.id)) { journal = "invalid blocks"; break; }
48
+ blocks.set(b.id, { ...b });
49
+ const m = b.commitMetrics;
50
+ if (record(m) && typeof m.operationId === "string" && finite(m.netGainTokens) && m.netGainTokens > 0 &&
51
+ finite(m.beforeTokens) && finite(m.afterTokens) && m.beforeTokens - m.afterTokens === m.netGainTokens) measured.set(m.operationId, m);
52
+ }
53
+ if (journal !== "chain verified") break;
54
+ for (const update of op.blockStates ?? []) {
55
+ const b = blocks.get(update.id);
56
+ if (!b || typeof update.active !== "boolean" || (!b.active && update.active)) { journal = "invalid block states"; break; }
57
+ b.active = update.active;
58
+ }
59
+ if (journal !== "chain verified") break;
60
+ for (const p of op.prunedTools ?? []) if (typeof p?.toolCallId === "string") pruned.set(p.toolCallId, p);
61
+ if (Array.isArray(op.nudgeAnchors)) {
62
+ anchors = op.nudgeAnchors;
63
+ for (const anchor of anchors) publishedIds.add(anchor.id);
64
+ }
65
+ if (typeof op.manualMode === "boolean") manualMode = op.manualMode;
66
+ }
67
+ if (entry?.type === "custom" && entry.customType === "dcp-nudge") {
68
+ const e = entry.data;
69
+ if (["emitted", "reapplied", "upgraded"].includes(e?.event)) { projections++; lastReminder = e; }
70
+ }
71
+ if (entry?.type === "custom" && entry.customType === "dcp-diagnostic" && entry.data?.version === 1) diagnostics.push(entry.data);
72
+ if (entry?.type === "message" && entry.message?.role === "toolResult" && entry.message.toolName === "compress" && entry.message.isError) {
73
+ manualFailures.add(entry.message.toolCallId ?? entry.id);
74
+ }
75
+ }
76
+ // Epoch markers invalidate live measurements/evidence, not durable history.
77
+ for (const d of diagnostics) {
78
+ if (d.event === "epoch") { epoch = d.epoch; snapshot = undefined; ignored = 0; evidenceEpoch = true; }
79
+ if (d.event === "request" && d.epoch === epoch) {
80
+ snapshot = d.snapshot;
81
+ if (finite(snapshot?.ignored)) ignored = snapshot.ignored;
82
+ if (d.reminder && !attemptIds.has(d.id)) { attempts++; attemptIds.add(d.id); }
83
+ }
84
+ if (d.event === "completion" && d.epoch === epoch && !completionIds.has(d.id) && (!d.reminder || attemptIds.has(d.id))) {
85
+ if (d.reminder) completed++;
86
+ completionIds.add(d.id); ignored = d.ignored;
87
+ }
88
+ if (d.event === "auto-rejected") rejected++;
89
+ }
90
+ const valid = journal === "chain verified" && input.historyStatus !== "unavailable";
91
+ const all = valid ? [...blocks.values()] : [];
92
+ const active = all.filter((b) => b.active);
93
+ const activity = { manual: new Set(), auto: new Set(), consolidation: new Set(), unknownBlocks: 0 };
94
+ for (const b of all) {
95
+ const kind = b.commitMetrics?.kind ?? (b.createdByToolCallId ? "manual" : b.autoSummaryRepresentation
96
+ ? ((b.coveredBlockIds?.length ?? 0) >= 2 && b.sourceCoverage?.itemCount === b.coveredBlockIds.length ? "consolidation" : "auto") : undefined);
97
+ const bucket = kind === "manual" ? activity.manual : kind === "auto" ? activity.auto : kind === "consolidation" ? activity.consolidation : undefined;
98
+ if (bucket) bucket.add(b.commitMetrics?.operationId ?? (kind === "manual" ? `manual:${b.createdByToolCallId}` : `auto:${b.id}`));
99
+ else activity.unknownBlocks++;
100
+ }
101
+ const currentWindow = input.model?.contextWindow;
102
+ const snapshotMatchesModel = snapshot && modelRef(input.model) === snapshot.model &&
103
+ (!finite(currentWindow) || currentWindow === snapshot.contextWindow);
104
+ return { valid, journal, operations: operations.size, all, active, pruned: valid ? pruned.size : undefined,
105
+ summaryTokens: valid && active.every((b) => finite(b.summaryTokenEstimate)) ? active.reduce((s,b) => s + b.summaryTokenEstimate, 0) : undefined,
106
+ manualMode, activity, measured: valid ? measured.size : undefined,
107
+ measuredGain: valid && measured.size ? [...measured.values()].reduce((s,m) => s + m.netGainTokens, 0) : valid && all.length === 0 ? 0 : undefined,
108
+ snapshot: snapshotMatchesModel ? snapshot : undefined, snapshotStale: Boolean(snapshot && !snapshotMatchesModel),
109
+ published: publishedIds.size, projections, attempts: evidenceEpoch ? attempts : undefined, completed: evidenceEpoch ? completed : undefined,
110
+ ignored: snapshotMatchesModel ? ignored : undefined, anchors: valid ? anchors : [], lastReminder,
111
+ rejected: evidenceEpoch ? rejected : undefined, manualFailures: manualFailures.size };
112
+ }
113
+
114
+ /** @param {import('./statistics.js').DcpStatisticsInput} input */
115
+ export function formatDcpStatistics(input) {
116
+ let s;
117
+ try { s = collectDcpStatistics(input); }
118
+ catch { return "DCP Session Statistics\n\nHistory unavailable: malformed diagnostic/journal records. No zero statistics inferred."; }
119
+ const usage = input.usage ?? {}, m = input.model, snap = s.snapshot;
120
+ const window = finite(m?.contextWindow) && m.contextWindow > 0 ? m.contextWindow : usage.contextWindow;
121
+ const lines = ["DCP Session Statistics:", "Context",
122
+ ` Model: ${modelRef(m) ?? "unknown"}`,
123
+ ` SDK usage: ${num(usage.tokens)} / ${num(window)} (${percent(usage.tokens, window)}; may lag)`,
124
+ ];
125
+ if (snap) {
126
+ lines.push(` Last DCP request: ~${num(snap.projectedTokens)} tokens; ${snap.pressure} (${snap.reason})`,
127
+ ` Input capacity: ${num(snap.inputCapacityTokens)}; reserved output: ${num(snap.reservedOutputTokens)}`,
128
+ ` Resolved thresholds: routine ${percent(snap.routineTokens, snap.contextWindow)} / strong ${percent(snap.strongTokens, snap.contextWindow)} / hard ${percent(snap.hardTokens, snap.contextWindow)}`,
129
+ ` Modes (last request): DCP ${mode(snap.enabled)}, manual ${mode(snap.manualMode)}, auto ${mode(snap.autoEnabled)}`,
130
+ ` Snapshot: ${finite(snap.createdAt) && Math.abs(snap.createdAt) < 8.64e15 ? new Date(snap.createdAt).toISOString() : "unknown time"} (last request)`);
131
+ } else lines.push(` DCP budget/thresholds: ${s.snapshotStale ? "stale (model/window changed); awaiting projection" : "not recorded; awaiting projection"}`);
132
+ lines.push("History projection (active branch)");
133
+ if (!s.valid) {
134
+ lines.push(` Unavailable: ${input.historyStatus === "unavailable" ? "full history could not be read" : s.journal}`,
135
+ " Blocks, gains and reminders: unknown (not zero)");
136
+ return lines.join("\n");
137
+ }
138
+ lines.push(` Blocks: ${s.active.length} active / ${s.all.length - s.active.length} retired / ${s.all.length} total`,
139
+ ` Active summaries: ~${num(s.summaryTokens)} tokens; result bodies pruned: ${num(s.pruned)}`);
140
+ if (snap) lines.push(` Input/projection: ~${num(snap.rawTokens)} -> ~${num(snap.projectedTokens)} (reduction ~${num(snap.rawTokens - snap.projectedTokens)})`);
141
+ lines.push("Compression activity",
142
+ ` Commits: ${s.activity.manual.size} model/tool, ${s.activity.auto.size} auto, ${s.activity.consolidation.size} consolidations`);
143
+ if (s.activity.unknownBlocks) lines.push(` Provenance unknown: ${s.activity.unknownBlocks} blocks`);
144
+ lines.push(` Measured commit gain: ${num(s.measuredGain)} tokens (${num(s.measured)} measured commits)`,
145
+ ` Rejections recorded: ${num(s.rejected)} auto; ${num(s.manualFailures)} failed compress results`,
146
+ "Reminder delivery",
147
+ ` Anchors journaled: ${s.published}; projection events: ${s.projections} (not sends)`,
148
+ ` Recorded provider attempts with reminder: ${num(s.attempts)}`,
149
+ ` confirmed completed opportunities: ${num(s.completed)}`,
150
+ ` Outstanding consecutive opportunities (last sample): ${num(s.ignored)}`,
151
+ ` Active anchors: ${s.anchors.length}${s.anchors.length ? " (" + s.anchors.map((/** @type {any} */ a) => `${a.type}/${a.anchorRole ?? "unknown carrier"}`).join(", ") + ")" : ""}`,
152
+ ` Last published/reapplied: ${s.lastReminder ? `${s.lastReminder.type} / ${s.lastReminder.anchorRole ?? "unknown carrier"}` : "none recorded"}`,
153
+ `Journal: ${s.journal} (${s.operations} records); full active branch`,
154
+ "Estimates, not billing. Old unmeasured gains/deliveries excluded.");
155
+ return lines.join("\n");
156
+ }
@@ -1,8 +1,3 @@
1
- import { readFileSync } from "node:fs";
2
-
3
- // Reuse the shipped sample instead of copying role descriptions/model defaults.
4
- const subagentDefaults = readFileSync(new URL("./async-subagents/async-subagents.sample.jsonc", import.meta.url), "utf8").trim();
5
-
6
1
  // Default user config written when pi-tools-suite.jsonc is missing.
7
2
  export const DEFAULT_PI_TOOLS_SUITE_CONFIG_JSONC = String.raw`{
8
3
  "$schema": "https://unpkg.com/pi-ui-extend/schemas/pi-tools-suite.json",
@@ -23,8 +18,11 @@ export const DEFAULT_PI_TOOLS_SUITE_CONFIG_JSONC = String.raw`{
23
18
  "sessionHygiene": true,
24
19
  "notify": true
25
20
  },
26
- // Context Gateway is passive/off by default. P01 supports off/observe only;
27
- // enforce is explicitly refused until capture/store/reader integration lands.
21
+ // Context Gateway is off by default. observe is passive telemetry; enforce
22
+ // compacts recognised complete simple test/build output and over-budget
23
+ // structured web_search/web_fetch results whose raw details remain recoverable
24
+ // from the append-only session. Reads/repo and unsupported result shapes stay
25
+ // producer-owned passthrough/native-compact.
28
26
  "contextGateway": {
29
27
  "mode": "off",
30
28
  "budgets": {
@@ -40,6 +38,15 @@ export const DEFAULT_PI_TOOLS_SUITE_CONFIG_JSONC = String.raw`{
40
38
  "repoDiscovery": {
41
39
  "profile": "baseline"
42
40
  },
41
+ // Private Git repository used as the reusable resource registry. Create the
42
+ // repo first, then set remote with /registry configure <git-url>.
43
+ "resourceRegistry": {
44
+ // "remote": "git@github.com:you/pix-resources.git",
45
+ "branch": "main"
46
+ // Optional per-project override. Normally the project key is derived from
47
+ // the current repository's Git origin and stored under registry/projects/.
48
+ // "projectKey": "github.com__you__my-project"
49
+ },
43
50
  // When true, todo items may carry a per-task thinking level and the todo
44
51
  // module will switch/restore Pi's thinking level as in-progress tasks change.
45
52
  "todoThinking": true,
@@ -52,6 +59,7 @@ export const DEFAULT_PI_TOOLS_SUITE_CONFIG_JSONC = String.raw`{
52
59
  // Vision-capable model used by the coding-discipline lookup tool for blind-model
53
60
  // screenshot/image questions. Remove or set to null to disable lookup.
54
61
  "lookupModel": "zai/glm-5.3-flash",
62
+ "lookupFallbackModels": [],
55
63
  "terminalBell": { "sound": true },
56
64
  // comment-checker: nudges the agent to remove AI-slop code comments it just
57
65
  // added via write/edit/apply_patch. Net-new comments are classified and a
@@ -89,29 +97,43 @@ export const DEFAULT_PI_TOOLS_SUITE_CONFIG_JSONC = String.raw`{
89
97
  }
90
98
  },
91
99
  "modelOverrides": {
100
+ // DCP policy reviewed 2026-09-14. Engineering starting points, not
101
+ // provider-certified optima. Keep candidate/message availability aligned
102
+ // with each model's routine compression threshold.
92
103
  "openai-codex/gpt-5*": {
93
104
  "compress": {
94
105
  "minContextPercent": "26%",
95
- "maxContextPercent": "46%"
106
+ "maxContextPercent": "46%",
107
+ "autoCandidates": { "minContextPercent": 0.26 },
108
+ "messageMode": { "minContextPercent": 0.26 }
96
109
  }
97
110
  },
98
111
  "openai-codex/gpt-5.4-mini": {
99
112
  "compress": {
100
113
  "minContextPercent": "20%",
101
- "maxContextPercent": "38%"
114
+ "maxContextPercent": "38%",
115
+ "autoCandidates": { "minContextPercent": 0.20 },
116
+ "messageMode": { "minContextPercent": 0.20 }
117
+ }
118
+ },
119
+ "openai-codex/gpt-6-astra": {
120
+ "compress": {
121
+ "minContextPercent": "26%",
122
+ "maxContextPercent": "46%",
123
+ "autoCandidates": { "minContextPercent": 0.26 },
124
+ "messageMode": { "minContextPercent": 0.26 }
102
125
  }
103
126
  },
104
127
  "zai/*": {
105
128
  "compress": {
106
129
  "minContextPercent": "16%",
107
- "maxContextPercent": "30%"
130
+ "maxContextPercent": "30%",
131
+ "autoCandidates": { "minContextPercent": 0.16 },
132
+ "messageMode": { "minContextPercent": 0.16 }
108
133
  }
109
134
  },
110
- // glm-5.3 reports a ~1M-token window. Even zai/* 16%/30% = 160K/300K is
111
- // above the ~15% (~150K) point where long sessions degrade, and an
112
- // observed 14h/273K-token session never crossed 16%. Lower ONLY glm-5.3
113
- // within the zai family: 8%/15% (~80K/150K) so nudging starts early and
114
- // auto-compress fires at the observed degradation point. Other zai/*
135
+ // GLM-5.3 and GLM-5.3-Flash expose ~1M-token windows. Use 8%/15%
136
+ // (~80K/~150K) as a conservative long-session policy while other zai/*
115
137
  // models keep 16%/30%.
116
138
  "zai/glm-5.3": {
117
139
  "compress": {
@@ -121,34 +143,68 @@ export const DEFAULT_PI_TOOLS_SUITE_CONFIG_JSONC = String.raw`{
121
143
  "messageMode": { "minContextPercent": 0.08 }
122
144
  }
123
145
  },
146
+ "zai/glm-5.3-flash": {
147
+ "compress": {
148
+ "minContextPercent": "8%",
149
+ "maxContextPercent": "15%",
150
+ "autoCandidates": { "minContextPercent": 0.08 },
151
+ "messageMode": { "minContextPercent": 0.08 }
152
+ }
153
+ },
124
154
  "antigravity/*sonnet*": {
125
155
  "compress": {
126
156
  "minContextPercent": "22%",
127
- "maxContextPercent": "40%"
157
+ "maxContextPercent": "40%",
158
+ "autoCandidates": { "minContextPercent": 0.22 },
159
+ "messageMode": { "minContextPercent": 0.22 }
128
160
  }
129
161
  },
130
162
  "antigravity/gemini-3.1-pro*": {
131
163
  "compress": {
132
164
  "minContextPercent": "24%",
133
- "maxContextPercent": "42%"
165
+ "maxContextPercent": "42%",
166
+ "autoCandidates": { "minContextPercent": 0.24 },
167
+ "messageMode": { "minContextPercent": 0.24 }
134
168
  }
135
169
  },
136
170
  "antigravity/gemini-3-flash*": {
137
171
  "compress": {
138
172
  "minContextPercent": "18%",
139
- "maxContextPercent": "34%"
173
+ "maxContextPercent": "34%",
174
+ "autoCandidates": { "minContextPercent": 0.18 },
175
+ "messageMode": { "minContextPercent": 0.18 }
140
176
  }
141
177
  },
142
178
  "antigravity/gemini-2.5-flash*": {
143
179
  "compress": {
144
180
  "minContextPercent": "18%",
145
- "maxContextPercent": "32%"
181
+ "maxContextPercent": "32%",
182
+ "autoCandidates": { "minContextPercent": 0.18 },
183
+ "messageMode": { "minContextPercent": 0.18 }
146
184
  }
147
185
  },
148
186
  "antigravity/antigravity-claude-opus-4-6-thinking": {
149
187
  "compress": {
150
188
  "minContextPercent": "26%",
151
- "maxContextPercent": "44%"
189
+ "maxContextPercent": "44%",
190
+ "autoCandidates": { "minContextPercent": 0.26 },
191
+ "messageMode": { "minContextPercent": 0.26 }
192
+ }
193
+ },
194
+ "antigravity/antigravity-gemini-3.1-pro": {
195
+ "compress": {
196
+ "minContextPercent": "24%",
197
+ "maxContextPercent": "42%",
198
+ "autoCandidates": { "minContextPercent": 0.24 },
199
+ "messageMode": { "minContextPercent": 0.24 }
200
+ }
201
+ },
202
+ "antigravity/antigravity-gemini-3.8-flash": {
203
+ "compress": {
204
+ "minContextPercent": "18%",
205
+ "maxContextPercent": "34%",
206
+ "autoCandidates": { "minContextPercent": 0.18 },
207
+ "messageMode": { "minContextPercent": 0.18 }
152
208
  }
153
209
  }
154
210
  },
@@ -163,12 +219,12 @@ export const DEFAULT_PI_TOOLS_SUITE_CONFIG_JSONC = String.raw`{
163
219
  "autoCompress": {
164
220
  "enabled": false,
165
221
  "patience": 2,
166
- "summarizerModel": ["zai/glm-5.3", "zai/glm-5-turbo"],
222
+ "summarizerModel": ["zai/glm-5-turbo"],
223
+ "summarizerFallbackModels": ["openai-codex/gpt-5.6-luna"],
167
224
  "timeoutMs": 20000
168
225
  }
169
226
  }
170
227
  },
171
- "asyncSubagents": ${subagentDefaults},
172
228
  "toolRenderer": {},
173
229
  "promptCommands": {
174
230
  "commands": {
@@ -1,4 +1,5 @@
1
1
  import { loadPiToolsSuiteConfig } from "./config";
2
+ import { publishContextInventoryState } from "./context-inventory";
2
3
  import { publishStartupModuleList } from "./startup-section";
3
4
 
4
5
  type ExtensionAPI = any;
@@ -35,7 +36,7 @@ export const MODULES: Array<{ name: string; load: () => Promise<ExtensionModule>
35
36
  { name: "truncation-metadata-normalizer", load: () => import("./truncation-metadata-normalizer/index") },
36
37
  { name: "dcp", load: () => import("./dcp/index") },
37
38
  { name: "prompt-commands", load: () => import("./prompt-commands/index") },
38
- { name: "skill-installer", load: () => import("./skill-installer/index") },
39
+ { name: "resource-registry", load: () => import("./resource-registry/index") },
39
40
  // Secret firewall is intentionally opt-in. Keep it after payload-shaping modules.
40
41
  { name: "credential-firewall", load: () => import("./credential-firewall/index") },
41
42
  // Keep this last: its before_provider_request handler is the final payload
@@ -61,5 +62,10 @@ export default async function piToolsSuite(pi: ExtensionAPI) {
61
62
  }
62
63
  }
63
64
 
65
+ // Register last so the snapshot observes model-specific tool selection after
66
+ // every module's session/model hooks have run.
67
+ pi.on("session_start", (event: any, ctx: any) => publishContextInventoryState(pi, ctx, event?.reason));
68
+ pi.on("model_select", (_event: unknown, ctx: any) => publishContextInventoryState(pi, ctx, "model_select"));
69
+
64
70
  await publishStartupModuleList(loadedModuleNames);
65
71
  }
@@ -1,4 +1,4 @@
1
- import { existsSync, statSync } from "node:fs";
1
+ import { accessSync, constants, existsSync, statSync } from "node:fs";
2
2
  import path from "node:path";
3
3
 
4
4
  export function directoryExists(file: string): boolean {
@@ -40,3 +40,38 @@ export function findIndexedProjectRoot(cwd: string): string | undefined {
40
40
  export function hasIndexedProjectRoot(cwd: string = process.cwd()): boolean {
41
41
  return findIndexedProjectRoot(cwd) !== undefined;
42
42
  }
43
+
44
+ export function commandAvailable(command: string, env: NodeJS.ProcessEnv = process.env): boolean {
45
+ const value = command.trim();
46
+ if (!value || value.includes("/") || value.includes("\\")) return false;
47
+ const pathValue = env.PATH ?? "";
48
+ const candidates = process.platform === "win32"
49
+ ? [
50
+ value,
51
+ ...(env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD")
52
+ .split(";")
53
+ .map((extension) => extension.trim())
54
+ .filter(Boolean)
55
+ .map((extension) => `${value}${extension.startsWith(".") ? extension : `.${extension}`}`),
56
+ ]
57
+ : [value];
58
+ for (const directory of pathValue.split(path.delimiter)) {
59
+ if (!directory) continue;
60
+ for (const candidate of candidates) {
61
+ try {
62
+ accessSync(path.join(directory, candidate), constants.X_OK);
63
+ return true;
64
+ } catch {
65
+ // Continue through PATH without spawning a process or blocking on shell lookup.
66
+ }
67
+ }
68
+ }
69
+ return false;
70
+ }
71
+
72
+ export function hasAvailableIndexedProjectRoot(
73
+ cwd: string = process.cwd(),
74
+ env: NodeJS.ProcessEnv = process.env,
75
+ ): boolean {
76
+ return hasIndexedProjectRoot(cwd) && commandAvailable("idx", env);
77
+ }
@@ -15,8 +15,8 @@ import {
15
15
  import { realpath } from "node:fs/promises";
16
16
  import { resolve } from "node:path";
17
17
  import { Type, type TSchema } from "typebox";
18
- import { CODEX_ALIAS_TOOL_DESCRIPTIONS, REPO_DISCOVERY_TOOL_NAMES, claudeAliasToolDescriptions } from "../tool-descriptions";
19
- import { hasIndexedProjectRoot } from "../lib/project.js";
18
+ import { REPO_DISCOVERY_TOOL_NAMES, claudeAliasToolDescriptions, codexAliasToolDescriptions } from "../tool-descriptions";
19
+ import { hasAvailableIndexedProjectRoot } from "../lib/project.js";
20
20
  import { applyPatch } from "./apply-patch";
21
21
  import { isPathInside } from "./path-utils";
22
22
  import {
@@ -32,6 +32,7 @@ import {
32
32
  } from "./tool-args";
33
33
 
34
34
  const CLAUDE_ALIAS_TOOL_DESCRIPTIONS = claudeAliasToolDescriptions(false);
35
+ const CODEX_ALIAS_TOOL_DESCRIPTIONS = codexAliasToolDescriptions(false);
35
36
  const CLAUDE_ALIAS_TOOLS = Object.values(CLAUDE_ALIAS_TOOL_DESCRIPTIONS).map((tool) => tool.name);
36
37
  const CODEX_ALIAS_TOOLS = ["read", ...Object.values(CODEX_ALIAS_TOOL_DESCRIPTIONS).map((tool) => tool.name)];
37
38
  const BUILTIN_TOOLS = ["read", "bash", "edit", "write", "grep", "find", "ls"] as const;
@@ -379,7 +380,8 @@ async function runShellAlias(
379
380
  return tool.execute(id, { command, timeout: timeoutSeconds(input) }, signal, onUpdate, ctx);
380
381
  }
381
382
 
382
- function registerCodexAliases(runtime: ModelToolsRuntime, pi: ExtensionAPI): void {
383
+ function registerCodexAliases(runtime: ModelToolsRuntime, pi: ExtensionAPI, repoDiscovery: boolean): void {
384
+ const descriptions = codexAliasToolDescriptions(repoDiscovery);
383
385
  const shellParameters = Type.Object({
384
386
  command: Type.String({ description: "The shell script to execute in the user's default shell" }),
385
387
  workdir: Type.Optional(Type.String({ description: "Working directory" })),
@@ -390,7 +392,7 @@ function registerCodexAliases(runtime: ModelToolsRuntime, pi: ExtensionAPI): voi
390
392
 
391
393
  pi.registerTool(
392
394
  defineTool({
393
- ...CODEX_ALIAS_TOOL_DESCRIPTIONS.shellCommand,
395
+ ...descriptions.shellCommand,
394
396
  parameters: shellParameters,
395
397
  renderCall: (args, theme, context) => renderShellAliasCall(runtime, args, theme, context),
396
398
  renderResult: (result, options, theme, context) => renderShellAliasResult(runtime, result, options, theme, context),
@@ -402,7 +404,7 @@ function registerCodexAliases(runtime: ModelToolsRuntime, pi: ExtensionAPI): voi
402
404
 
403
405
  pi.registerTool(
404
406
  defineTool({
405
- ...CODEX_ALIAS_TOOL_DESCRIPTIONS.applyPatch,
407
+ ...descriptions.applyPatch,
406
408
  parameters: Type.Object({
407
409
  input: Type.String({ description: "Complete patch text: either a unified diff or a Begin Patch block" }),
408
410
  }),
@@ -457,8 +459,9 @@ function shouldPreserveSelection(env: NodeJS.ProcessEnv = process.env): boolean
457
459
 
458
460
  export default function modelTools(pi: ExtensionAPI, dependencies: Partial<ModelToolsDependencies> = {}): void {
459
461
  const runtime = createModelToolsRuntime(dependencies);
460
- registerClaudeAliases(runtime, pi, hasIndexedProjectRoot());
461
- registerCodexAliases(runtime, pi);
462
+ const repoDiscovery = hasAvailableIndexedProjectRoot();
463
+ registerClaudeAliases(runtime, pi, repoDiscovery);
464
+ registerCodexAliases(runtime, pi, repoDiscovery);
462
465
 
463
466
  let baseTools: string[] = [];
464
467