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
@@ -26,19 +26,23 @@ const ToolRendererConfig = Type.Object({
26
26
  // ---------------------------------------------------------------------------
27
27
  // Terminal bell
28
28
  // ---------------------------------------------------------------------------
29
- const TerminalBellTelegramConfig = Type.Object({
30
- botToken: Type.Optional(Type.String({ description: "Telegram bot token (from @BotFather) used to send completion/error/question notifications." })),
31
- chatId: Type.Optional(Type.String({ description: "Telegram chat id that receives the notifications. Message @userinfobot to look yours up." })),
32
- }, { description: "Forward terminal-bell notifications to a Telegram chat. Independent of the bundled desktop sound gate." });
33
29
  const TerminalBellConfig = Type.Object({
34
30
  sound: Type.Optional(Type.Boolean({ description: "Play terminal bell sound on completion/error." })),
35
- telegram: Type.Optional(TerminalBellTelegramConfig),
36
31
  }, { description: "Terminal bell configuration." });
32
+ const TelegramConnectorConfig = Type.Object({
33
+ enabled: Type.Optional(Type.Boolean({ description: "Enable the Telegram task connector. Defaults to enabled when botToken and chatId are present." })),
34
+ botToken: Type.Optional(Type.String({ description: "Telegram Bot API token from @BotFather." })),
35
+ chatId: Type.Optional(Type.Union([
36
+ Type.String(),
37
+ Type.Integer(),
38
+ ], { description: "Private Telegram chat id allowed to control Pix." })),
39
+ }, { description: "Receive completion/question notifications and send follow-up or new-session tasks from Telegram." });
37
40
  // ---------------------------------------------------------------------------
38
41
  // DCP (Dynamic Context Pruning)
39
42
  // ---------------------------------------------------------------------------
40
43
  const DcpManualModeConfig = Type.Object({
41
44
  enabled: Type.Optional(Type.Boolean({ description: "Enable manual DCP mode." })),
45
+ automaticStrategies: Type.Optional(Type.Never({ description: "Removed legacy key. Manual mode now has only the explicit enabled flag." })),
42
46
  }, { description: "Manual mode configuration." });
43
47
  const DcpAutoCandidatesConfig = Type.Object({
44
48
  enabled: Type.Optional(Type.Boolean({ description: "Enable auto candidate selection for compression." })),
@@ -56,16 +60,17 @@ const DcpMessageModeConfig = Type.Object({
56
60
  maxSuggestions: Type.Optional(Type.Number({ description: "Maximum compression suggestions.", minimum: 0 })),
57
61
  }, { description: "Message-mode compression configuration." });
58
62
  const DcpAutoCompressConfig = Type.Object({
59
- enabled: Type.Optional(Type.Boolean({ description: "Allow bounded automatic summary creation after pressure/opportunity gates." })),
63
+ enabled: Type.Optional(Type.Boolean({ description: "Allow autonomous compression after pressure/opportunity gates. Explicit compress calls can still use summarizerModel when summary is omitted." })),
60
64
  patience: Type.Optional(Type.Number({ description: "Completed actionable opportunities allowed before automatic compression.", minimum: 0 })),
61
- summarizerModel: Type.Optional(Type.Array(Type.String(), { description: "Ordered summarizer model refs; empty uses the deterministic extractive summary." })),
62
- timeoutMs: Type.Optional(Type.Number({ description: "Per-summarizer deadline in milliseconds.", minimum: 1 })),
65
+ summarizerModel: Type.Optional(Type.Array(Type.String(), { description: "Ordered model refs used by auto-compress and explicit compress when summary is omitted; empty uses the deterministic extractive summary." })),
66
+ summarizerFallbackModels: Type.Optional(Type.Array(Type.String(), { description: "Ordered fallback model refs tried after summarizerModel." })),
67
+ timeoutMs: Type.Optional(Type.Number({ description: "Per-summarizer deadline in milliseconds for automatic and explicit generated summaries.", minimum: 1 })),
63
68
  }, { description: "Bounded automatic compression fallback." });
64
69
  const DcpCompressConfig = Type.Object({
65
70
  maxContextPercent: Type.Optional(Type.Union([Type.Number(), Type.String()], { description: "Maximum context percent (0–1 or '80%') before compression triggers." })),
66
71
  minContextPercent: Type.Optional(Type.Union([Type.Number(), Type.String()], { description: "Target context percent after compression." })),
67
- modelMaxContextPercent: Type.Optional(Type.Record(Type.String(), Type.Number(), { description: "Per-model max context percent overrides." })),
68
- modelMinContextPercent: Type.Optional(Type.Record(Type.String(), Type.Number(), { description: "Per-model min context percent overrides." })),
72
+ modelMaxContextPercent: Type.Optional(Type.Record(Type.String(), Type.Union([Type.Number(), Type.String()]), { description: "Per-model max context overrides using the same fraction/token/percent formats." })),
73
+ modelMinContextPercent: Type.Optional(Type.Record(Type.String(), Type.Union([Type.Number(), Type.String()]), { description: "Per-model min context overrides using the same fraction/token/percent formats." })),
69
74
  maxContextLimit: Type.Optional(Type.Union([Type.Number(), Type.String()], { description: "Absolute max context tokens or '200k'." })),
70
75
  minContextLimit: Type.Optional(Type.Union([Type.Number(), Type.String()], { description: "Absolute min context tokens." })),
71
76
  modelMaxContextLimits: Type.Optional(Type.Record(Type.String(), Type.Union([Type.Number(), Type.String()]), { description: "Per-model max context limit overrides." })),
@@ -93,7 +98,23 @@ const DcpEmergencyCurrentTurnPruningConfig = Type.Object({
93
98
  }, { description: "Single bounded emergency cleanup strategy." });
94
99
  const DcpStrategiesConfig = Type.Object({
95
100
  emergencyCurrentTurnPruning: Type.Optional(DcpEmergencyCurrentTurnPruningConfig),
101
+ deduplication: Type.Optional(Type.Never({ description: "Removed legacy key; no automatic replacement policy maps to it." })),
102
+ purgeErrors: Type.Optional(Type.Never({ description: "Removed legacy key; no automatic replacement policy maps to it." })),
103
+ autoToolPruning: Type.Optional(Type.Never({ description: "Removed legacy key. Use explicit /dcp sweep or DCP compression/emergency policies instead." })),
96
104
  }, { description: "Bounded DCP emergency strategy." });
105
+ const DcpConfigOverride = Type.Object({
106
+ enabled: Type.Optional(Type.Boolean()),
107
+ debug: Type.Optional(Type.Boolean()),
108
+ debugLog: Type.Optional(Type.Object({
109
+ maxBytes: Type.Optional(Type.Number({ minimum: 1024 })),
110
+ maxBackups: Type.Optional(Type.Number({ minimum: 1 })),
111
+ })),
112
+ manualMode: Type.Optional(DcpManualModeConfig),
113
+ compress: Type.Optional(DcpCompressConfig),
114
+ strategies: Type.Optional(DcpStrategiesConfig),
115
+ protectedFilePatterns: Type.Optional(Type.Array(Type.String())),
116
+ pruneNotification: Type.Optional(Type.Never({ description: "Removed legacy key; pruning notifications are no longer configurable." })),
117
+ }, { description: "Partial DCP override applied to a matching provider/model or bare-model key. Keys support * and ? wildcards." });
97
118
  const DcpConfig = Type.Object({
98
119
  enabled: Type.Optional(Type.Boolean({ description: "Enable DCP (Dynamic Context Pruning)." })),
99
120
  debug: Type.Optional(Type.Boolean({ description: "Enable DCP debug logging." })),
@@ -105,73 +126,10 @@ const DcpConfig = Type.Object({
105
126
  compress: Type.Optional(DcpCompressConfig),
106
127
  strategies: Type.Optional(DcpStrategiesConfig),
107
128
  protectedFilePatterns: Type.Optional(Type.Array(Type.String(), { description: "File path glob patterns whose content is protected from pruning." })),
129
+ modelOverrides: Type.Optional(Type.Record(Type.String(), DcpConfigOverride, { description: "Per-model partial DCP overrides. Exact keys take precedence over matching wildcards." })),
130
+ pruneNotification: Type.Optional(Type.Never({ description: "Removed legacy key; pruning notifications are no longer configurable." })),
108
131
  }, { description: "DCP (Dynamic Context Pruning) configuration." });
109
132
  // ---------------------------------------------------------------------------
110
- // Async subagents
111
- // ---------------------------------------------------------------------------
112
- const RetryConfig = Type.Object({
113
- maxRetries: Type.Optional(Type.Number({ description: "Maximum retry attempts.", minimum: 0 })),
114
- backoffMs: Type.Optional(Type.Number({ description: "Base delay in ms before first retry.", minimum: 0 })),
115
- retryableExitCodes: Type.Optional(Type.Array(Type.Number(), { description: "Exit codes eligible for retry. Empty array disables retry." })),
116
- }, { description: "Retry configuration for sub-agents." });
117
- const SubagentRoutingConfig = Type.Object({
118
- enabled: Type.Optional(Type.Boolean({ description: "Enable fallback LLM selection for omitted subagentType values. Explicit valid types bypass the router; when disabled, every spawn task must specify a valid type." })),
119
- model: Type.Optional(Type.String({ description: "Router model in provider/model form." })),
120
- fallbackModels: Type.Optional(Type.Array(Type.String(), { uniqueItems: true, description: "Ordered router model fallbacks tried when the primary routing model is unavailable or fails. The current parent model is always tried last." })),
121
- maxTaskChars: Type.Optional(Type.Number({ description: "Max task/scope characters sent to router.", minimum: 100 })),
122
- maxTokens: Type.Optional(Type.Number({ description: "Max router response tokens.", minimum: 8 })),
123
- maxRetries: Type.Optional(Type.Number({ description: "Router request retries.", minimum: 0 })),
124
- timeoutMs: Type.Optional(Type.Number({ description: "Router request timeout in ms.", minimum: 1000 })),
125
- debug: Type.Optional(Type.Boolean({ description: "Show routing debug warnings." })),
126
- }, { description: "Fallback role routing for omitted types. Unknown explicit types or failed/incomplete routing reject the entire batch before any agents launch." });
127
- const SubagentVisionConfig = Type.Object({
128
- blindModelPatterns: Type.Optional(Type.Array(Type.String(), { description: "Glob-like model refs treated as unable to inspect images." })),
129
- }, { description: "Vision capability overrides." });
130
- const SubagentPresetTypeOverride = Type.Object({
131
- model: Type.Optional(Type.String({ description: "Model override for this type within the preset." })),
132
- fallbackModels: Type.Optional(Type.Array(Type.String(), { description: "Per-role fallback models." })),
133
- thinking: Type.Optional(Type.String({ description: "Thinking level override." })),
134
- extraArgs: Type.Optional(Type.Array(Type.String(), { description: "Extra CLI arguments." })),
135
- timeoutMs: Type.Optional(Type.Number({ description: "Per-agent wall-clock timeout in ms.", minimum: 1 })),
136
- }, { description: "Per-type override within a preset." });
137
- const SubagentPreset = Type.Object({
138
- description: Type.Optional(Type.String({ description: "Preset description." })),
139
- models: Type.Optional(Type.Array(Type.String({ pattern: "^[^\\s/*]+/[^\\s*]+$" }), { uniqueItems: true, description: "Available model pool. Filter the agent's ordered models by membership; pool order is ignored. Empty intersection rejects spawn. Oracle also respects this pool." })),
140
- model: Type.Optional(Type.String({ description: "Legacy default model. Ignored when models is set.", deprecated: true })),
141
- fallbackModels: Type.Optional(Type.Array(Type.String(), { description: "Legacy fallback list. Ignored when models is set.", deprecated: true })),
142
- thinking: Type.Optional(Type.String({ description: "Default thinking level." })),
143
- extraArgs: Type.Optional(Type.Array(Type.String(), { description: "Extra CLI arguments." })),
144
- timeoutMs: Type.Optional(Type.Number({ description: "Per-agent wall-clock timeout in ms.", minimum: 1 })),
145
- types: Type.Optional(Type.Record(Type.String(), SubagentPresetTypeOverride, { description: "Per-type overrides." })),
146
- }, { description: "Named available-model pool. Legacy model/types overrides remain supported; prefer models for new presets." });
147
- const SubagentTypeConfig = Type.Object({
148
- description: Type.Optional(Type.String({ description: "Role description for routing." })),
149
- icon: Type.Optional(Type.String({ description: "Agent icon name rendered by UIs (pix TUI icon themes and Pix Desktop lucide icons): agent, search, code, flask, globe, sparkles, brain, wrench, terminal, bug, book, eye, zap, rocket. Unknown names render as the neutral agent icon." })),
150
- models: Type.Optional(Type.Array(Type.String({ pattern: "^[^\\s/*]+/[^\\s*]+$" }), { uniqueItems: true, description: "Ordered model candidates. First usable member of the preset pool runs; only remaining compatible members can be used on quota failure. Replaces legacy model/fallbackModels/modelByParent selection." })),
151
- model: Type.Optional(Type.String({ description: "Legacy primary model; use models for new profiles.", deprecated: true })),
152
- fallbackModels: Type.Optional(Type.Array(Type.String(), { description: "Legacy candidates after model; use models for a complete ranked list.", deprecated: true })),
153
- thinking: Type.Optional(Type.String({ description: "Thinking level." })),
154
- tools: Type.Optional(Type.Array(Type.String(), { description: "Enabled tools for this type." })),
155
- isolatedSkills: Type.Optional(Type.Array(Type.String(), { description: "Explicit skill files loaded after disabling normal skill discovery for this type." })),
156
- extraArgs: Type.Optional(Type.Array(Type.String(), { description: "Extra CLI arguments." })),
157
- promptAppend: Type.Optional(Type.String({ description: "Extra prompt text appended after generated prompt." })),
158
- promptOverride: Type.Optional(Type.String({ description: "Full prompt replacement." })),
159
- retry: Type.Optional(RetryConfig),
160
- maxResultBytes: Type.Optional(Type.Number({ description: "Max bytes in result summary.", minimum: 0 })),
161
- timeoutMs: Type.Optional(Type.Number({ description: "Per-agent wall-clock timeout in ms.", minimum: 1 })),
162
- }, { description: "Configuration for a sub-agent type/role." });
163
- const AsyncSubagentsConfig = Type.Object({
164
- defaultType: Type.Optional(Type.String({ description: "Preferred role for genuinely ambiguous router tasks and legacy resolver default. Not used as a spawn fallback for missing/invalid routes." })),
165
- routing: Type.Optional(SubagentRoutingConfig),
166
- vision: Type.Optional(SubagentVisionConfig),
167
- presets: Type.Optional(Type.Record(Type.String(), SubagentPreset, { description: "Named spawn presets." })),
168
- types: Type.Optional(Type.Record(Type.String(), SubagentTypeConfig, { description: "Sub-agent type definitions." })),
169
- maxConcurrent: Type.Optional(Type.Number({ description: "Max concurrent agents per spawn batch (0 = unlimited).", minimum: 0 })),
170
- retry: Type.Optional(RetryConfig),
171
- maxResultBytes: Type.Optional(Type.Number({ description: "Global max bytes in result summary.", minimum: 0 })),
172
- timeoutMs: Type.Optional(Type.Number({ description: "Global per-agent wall-clock timeout in ms.", minimum: 1 })),
173
- }, { description: "Async sub-agent configuration." });
174
- // ---------------------------------------------------------------------------
175
133
  // Prompt commands
176
134
  // ---------------------------------------------------------------------------
177
135
  const PromptCommand = Type.Object({
@@ -185,20 +143,29 @@ const SecretFirewallConfig = Type.Object({
185
143
  sessionHygiene: Type.Optional(Type.Boolean({ description: "Redact detected secret material from tool results and completed messages before it remains in session history." })),
186
144
  notify: Type.Optional(Type.Boolean({ description: "Show a warning when one or more secrets are redacted. Secret values are never included in notifications." })),
187
145
  }, { description: "Settings for the opt-in credential-firewall module." });
146
+ const CommentCheckerConfig = Type.Object({
147
+ enabled: Type.Optional(Type.Boolean({ description: "Enable or disable comment-checker without disabling the whole module." })),
148
+ strictness: Type.Optional(Type.Union([Type.Literal("conservative"), Type.Literal("balanced"), Type.Literal("aggressive")], { description: "Comment classification strictness. Defaults to balanced." })),
149
+ }, { description: "Settings for the comment-checker module." });
188
150
  const ContextGatewayBudgetsConfig = Type.Object({
189
- maxInlineBytes: Type.Optional(Type.Integer({ minimum: 1, maximum: 67108864, description: "Initial inline byte budget used by Context Gateway policy experiments. Default 8192." })),
190
- maxResultBytes: Type.Optional(Type.Integer({ minimum: 1, maximum: 67108864, description: "Experimental delivered-result byte budget. P01 observe measures the available tool-result content boundary; later shaping must account for the final provider-visible serialization. Default 8192." })),
191
- maxExactReadBytes: Type.Optional(Type.Integer({ minimum: 1, maximum: 67108864, description: "Future exact-read byte budget. Default 32768." })),
192
- maxSearchBytes: Type.Optional(Type.Integer({ minimum: 1, maximum: 67108864, description: "Future search-delivery byte budget. Default 8192." })),
193
- maxSearchMatches: Type.Optional(Type.Integer({ minimum: 1, maximum: 1000, description: "Future search match budget. Default 12." })),
194
- }, { description: "Context Gateway delivery budgets. In P01 only maxResultBytes is used for passive observe accounting." });
151
+ maxInlineBytes: Type.Optional(Type.Integer({ minimum: 1, maximum: 67108864, description: "Maximum inline size for a proven compact representation. Default 8192." })),
152
+ maxResultBytes: Type.Optional(Type.Integer({ minimum: 1, maximum: 67108864, description: "Budget for shell/other result classes. Selective enforce currently compacts only recognised complete simple test/build output. Default 8192." })),
153
+ maxExactReadBytes: Type.Optional(Type.Integer({ minimum: 1, maximum: 67108864, description: "Read-class observation budget. Reads remain passthrough because snapshot-safe recovery is not available. Default 32768." })),
154
+ maxSearchBytes: Type.Optional(Type.Integer({ minimum: 1, maximum: 67108864, description: "Repo-search/AST/structure observation budget. Gateway does not post-hoc truncate producer output. Default 8192." })),
155
+ maxSearchMatches: Type.Optional(Type.Integer({ minimum: 1, maximum: 1000, description: "Reserved search-match policy budget. Default 12." })),
156
+ }, { description: "Context Gateway class-specific observation and selective-enforcement budgets." });
195
157
  const ContextGatewayConfig = Type.Object({
196
- mode: Type.Optional(Type.Union([Type.Literal("off"), Type.Literal("observe"), Type.Literal("enforce")], { description: "Context Gateway mode. P01 implements off/observe; enforce is parsed but explicitly refused until later integration gates." })),
158
+ mode: Type.Optional(Type.Union([Type.Literal("off"), Type.Literal("observe"), Type.Literal("enforce")], { description: "Context Gateway mode. observe is passive; enforce only compacts proven complete simple test/build output and otherwise passes results through." })),
197
159
  budgets: Type.Optional(ContextGatewayBudgetsConfig),
198
160
  }, { description: "Context Gateway configuration. Default mode is off." });
199
161
  const RepoDiscoveryConfig = Type.Object({
200
162
  profile: Type.Optional(Type.Union([Type.Literal("baseline"), Type.Literal("native-compact")], { description: "repo_* runtime profile. baseline preserves historical argv/defaults; native-compact enables bounded native flags, cursors, validation, and an explicit per-call full override." })),
201
163
  }, { description: "Repository discovery runtime policy. Default profile is baseline." });
164
+ const ResourceRegistryConfig = Type.Object({
165
+ remote: Type.Optional(Type.String({ description: "Git remote URL for the private registry. The repository contains reusable top-level skills/ and agents/ plus project-scoped state under projects/." })),
166
+ branch: Type.Optional(Type.String({ description: "Registry branch used for install/update/push/pull. Defaults to main." })),
167
+ projectKey: Type.Optional(Type.String({ description: "Optional explicit key for this project's projects/<key>/tasks.jsonc, plans/, and TODO.md state. Normally derived from the current Git origin." })),
168
+ }, { description: "Private Git-backed registry for reusable skills/agents and project-scoped tasks/plans state." });
202
169
  // ---------------------------------------------------------------------------
203
170
  // LSP
204
171
  // ---------------------------------------------------------------------------
@@ -246,15 +213,19 @@ export const PiToolsSuiteConfigSchema = Type.Object({
246
213
  Type.Null(),
247
214
  ]), { description: "Force per-todo thinking for matching provider/model or bare-model keys. Keys support * and ? wildcards; null removes an inherited override." })),
248
215
  lookupModel: Type.Optional(Type.Union([Type.String(), Type.Null()], { description: "Vision-capable provider/model used by GLM's lookup tool; unset or null disables lookup." })),
216
+ lookupFallbackModels: Type.Optional(Type.Array(Type.String(), { description: "Ordered lookup model fallbacks tried after lookupModel." })),
249
217
  terminalBell: Type.Optional(TerminalBellConfig),
218
+ telegramConnector: Type.Optional(TelegramConnectorConfig),
219
+ commentChecker: Type.Optional(CommentCheckerConfig),
250
220
  dcp: Type.Optional(DcpConfig),
251
- asyncSubagents: Type.Optional(AsyncSubagentsConfig),
252
221
  toolRenderer: Type.Optional(ToolRendererConfig),
253
222
  promptCommands: Type.Optional(PromptCommandsConfig),
254
223
  secretFirewall: Type.Optional(SecretFirewallConfig),
255
224
  contextGateway: Type.Optional(ContextGatewayConfig),
256
225
  repoDiscovery: Type.Optional(RepoDiscoveryConfig),
226
+ resourceRegistry: Type.Optional(ResourceRegistryConfig),
257
227
  lsp: Type.Optional(LspConfig),
228
+ asyncSubagents: Type.Optional(Type.Never({ description: "Removed legacy key. Configure sub-agents in .pi/agents/*.md and model pools in .pi/agents/presets.jsonc." })),
258
229
  }, {
259
230
  $id: "https://unpkg.com/pi-ui-extend/schemas/pi-tools-suite.json",
260
231
  $schema: "https://json-schema.org/draft-07/schema#",
@@ -12,8 +12,11 @@ export declare const PixConfigSchema: Type.TObject<{
12
12
  maxProjectSessions: Type.TOptional<Type.TNumber>;
13
13
  defaultModel: Type.TOptional<Type.TObject<{
14
14
  modelRef: Type.TOptional<Type.TString>;
15
+ fallbackModels: Type.TOptional<Type.TArray<Type.TString>>;
15
16
  thinking: Type.TOptional<Type.TUnion<Type.TLiteral<string>[]>>;
16
17
  }>>;
18
+ visibleModels: Type.TOptional<Type.TArray<Type.TString>>;
19
+ thinkingByModel: Type.TOptional<Type.TRecord<"^.*$", Type.TUnion<[Type.TLiteral<"off">, Type.TLiteral<"minimal">, Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">, Type.TLiteral<"xhigh">, Type.TLiteral<"max">]>>>;
17
20
  toolRenderer: Type.TOptional<Type.TObject<{
18
21
  default: Type.TOptional<Type.TObject<{
19
22
  previewLines: Type.TOptional<Type.TNumber>;
@@ -37,9 +40,11 @@ export declare const PixConfigSchema: Type.TObject<{
37
40
  }>>;
38
41
  promptEnhancer: Type.TOptional<Type.TObject<{
39
42
  modelRef: Type.TOptional<Type.TString>;
43
+ fallbackModels: Type.TOptional<Type.TArray<Type.TString>>;
40
44
  }>>;
41
45
  autocomplete: Type.TOptional<Type.TObject<{
42
46
  modelRef: Type.TOptional<Type.TString>;
47
+ fallbackModels: Type.TOptional<Type.TArray<Type.TString>>;
43
48
  debounceMs: Type.TOptional<Type.TNumber>;
44
49
  timeoutMs: Type.TOptional<Type.TNumber>;
45
50
  maxTokens: Type.TOptional<Type.TNumber>;
@@ -57,12 +62,24 @@ export declare const PixConfigSchema: Type.TObject<{
57
62
  name: Type.TOptional<Type.TString>;
58
63
  }>>;
59
64
  dictation: Type.TOptional<Type.TObject<{
65
+ apiKey: Type.TOptional<Type.TString>;
60
66
  language: Type.TOptional<Type.TString>;
67
+ model: Type.TOptional<Type.TString>;
61
68
  languages: Type.TOptional<Type.TRecord<"^.*$", Type.TObject<{
62
- dirName: Type.TString;
63
- url: Type.TString;
64
69
  label: Type.TString;
70
+ deepgramLanguage: Type.TOptional<Type.TString>;
71
+ dirName: Type.TOptional<Type.TString>;
72
+ url: Type.TOptional<Type.TString>;
65
73
  }>>>;
66
74
  }>>;
75
+ desktop: Type.TOptional<Type.TObject<{
76
+ externalEditor: Type.TOptional<Type.TString>;
77
+ git: Type.TOptional<Type.TObject<{
78
+ reviewModelRef: Type.TOptional<Type.TString>;
79
+ reviewFallbackModels: Type.TOptional<Type.TArray<Type.TString>>;
80
+ commitMessageModelRef: Type.TOptional<Type.TString>;
81
+ commitMessageFallbackModels: Type.TOptional<Type.TArray<Type.TString>>;
82
+ }>>;
83
+ }>>;
67
84
  }>;
68
85
  export type PixConfigSchemaType = Static<typeof PixConfigSchema>;
@@ -33,10 +33,12 @@ const OutputFiltersConfig = Type.Object({
33
33
  }, { description: "Output filter patterns." });
34
34
  const DefaultModelConfig = Type.Object({
35
35
  modelRef: Type.Optional(Type.String({ description: "Provider/model identifier, e.g. 'openai-codex/gpt-5.4'." })),
36
+ fallbackModels: Type.Optional(Type.Array(Type.String({ description: "Fallback provider/model identifier." }), { description: "Ordered default-model fallbacks tried after modelRef." })),
36
37
  thinking: Type.Optional(DefaultThinkingSelection),
37
38
  }, { description: "Default model selection for new sessions." });
38
39
  const PromptEnhancerConfig = Type.Object({
39
40
  modelRef: Type.Optional(Type.String({ description: "Model used for prompt enhancement." })),
41
+ fallbackModels: Type.Optional(Type.Array(Type.String({ description: "Fallback provider/model identifier." }), { description: "Ordered prompt-enhancer fallbacks tried after modelRef." })),
40
42
  }, { description: "Prompt enhancer configuration." });
41
43
  const SessionTitleConfig = Type.Object({
42
44
  modelRef: Type.Optional(Type.String({ description: "Model used to generate compact session titles." })),
@@ -44,6 +46,7 @@ const SessionTitleConfig = Type.Object({
44
46
  }, { description: "Automatic session title generation configuration." });
45
47
  const AutocompleteConfig = Type.Object({
46
48
  modelRef: Type.Optional(Type.String({ description: "Model for inline autocomplete. Empty string disables LLM autocomplete." })),
49
+ fallbackModels: Type.Optional(Type.Array(Type.String({ description: "Fallback provider/model identifier." }), { description: "Ordered autocomplete fallbacks tried after modelRef." })),
47
50
  debounceMs: Type.Optional(Type.Number({ description: "Delay after typing before requesting completion.", minimum: 100, maximum: 2000 })),
48
51
  timeoutMs: Type.Optional(Type.Number({ description: "Hard timeout for completion request.", minimum: 250, maximum: 10000 })),
49
52
  maxTokens: Type.Optional(Type.Number({ description: "Maximum output tokens.", minimum: 8, maximum: 256 })),
@@ -61,14 +64,36 @@ const IconThemeConfig = Type.Object({
61
64
  name: Type.Optional(Type.String({ description: "Icon theme name, e.g. 'nerdFont' or 'fallback'." })),
62
65
  }, { description: "Icon theme configuration." });
63
66
  const DictationLanguageModelConfig = Type.Object({
64
- dirName: Type.String({ description: "Vosk model directory name." }),
65
- url: Type.String({ description: "Download URL for the Vosk model zip." }),
66
67
  label: Type.String({ description: "Human-readable language label." }),
67
- }, { description: "Vosk voice dictation model definition." });
68
+ deepgramLanguage: Type.Optional(Type.String({ description: "Deepgram language code. Defaults to the language map key." })),
69
+ dirName: Type.Optional(Type.String({ description: "Deprecated legacy Vosk model directory name; ignored by Deepgram dictation." })),
70
+ url: Type.Optional(Type.String({ description: "Deprecated legacy Vosk model URL; ignored by Deepgram dictation." })),
71
+ }, { description: "Deepgram voice dictation language definition." });
68
72
  const DictationConfig = Type.Object({
73
+ apiKey: Type.Optional(Type.String({ description: "Deepgram API key used by terminal and desktop voice input. Store it in the user config (~/.config/pi/pix.jsonc); project-level .pi/pix.jsonc does not override this secret." })),
69
74
  language: Type.Optional(Type.String({ description: "Selected language code, e.g. 'en' or 'ru'." })),
70
- languages: Type.Optional(Type.Record(Type.String(), DictationLanguageModelConfig, { description: "Available language models keyed by language code." })),
71
- }, { description: "Voice dictation (Vosk) configuration." });
75
+ model: Type.Optional(Type.String({ description: "Deepgram speech-to-text model. Defaults to 'nova-3'." })),
76
+ languages: Type.Optional(Type.Record(Type.String(), DictationLanguageModelConfig, { description: "Available dictation languages keyed by local language code." })),
77
+ }, { description: "Voice dictation (Deepgram) configuration. Uses dictation.apiKey from the user pix config, with DEEPGRAM_API_KEY as a compatibility fallback." });
78
+ const DesktopConfig = Type.Object({
79
+ externalEditor: Type.Optional(Type.String({
80
+ description: "External editor used by Pix Desktop project explorer. Known aliases include zed, code/vscode, cursor, subl/sublime, idea/intellij, and webstorm; an executable path/name is also accepted.",
81
+ })),
82
+ git: Type.Optional(Type.Object({
83
+ reviewModelRef: Type.Optional(Type.String({
84
+ description: "Model reference used by Pix Desktop and TUI for LLM review of Git diffs, optionally with a :thinking suffix.",
85
+ })),
86
+ reviewFallbackModels: Type.Optional(Type.Array(Type.String(), {
87
+ description: "Ordered fallback model references used for Git diff review.",
88
+ })),
89
+ commitMessageModelRef: Type.Optional(Type.String({
90
+ description: "Model reference used by Pix Desktop and TUI to generate Git commit messages, optionally with a :thinking suffix.",
91
+ })),
92
+ commitMessageFallbackModels: Type.Optional(Type.Array(Type.String(), {
93
+ description: "Ordered fallback model references used for Git commit-message generation.",
94
+ })),
95
+ }, { description: "Pix Git/Source Control LLM preferences shared by Desktop and TUI." })),
96
+ }, { description: "Pix Desktop preferences; the nested git model settings are also consumed by TUI Git helpers for compatibility." });
72
97
  // ---------------------------------------------------------------------------
73
98
  // Top-level schema
74
99
  // ---------------------------------------------------------------------------
@@ -77,6 +102,22 @@ export const PixConfigSchema = Type.Object({
77
102
  ignoreContextFiles: Type.Optional(Type.Boolean({ description: "Disable AGENTS.md / CLAUDE.md discovery for sessions started in this project, equivalent to pi --no-context-files." })),
78
103
  maxProjectSessions: Type.Optional(Type.Number({ description: "Maximum number of pi session JSONL files to retain per project. Set to 0 to disable automatic session deletion.", minimum: 0 })),
79
104
  defaultModel: Type.Optional(DefaultModelConfig),
105
+ visibleModels: Type.Optional(Type.Array(Type.String({
106
+ description: "Provider/model identifier shown in Pix model pickers.",
107
+ }), {
108
+ description: "User-level whitelist shared by Pix TUI and Desktop model pickers. Omit to show every available model.",
109
+ })),
110
+ thinkingByModel: Type.Optional(Type.Record(Type.String(), Type.Union([
111
+ Type.Literal("off"),
112
+ Type.Literal("minimal"),
113
+ Type.Literal("low"),
114
+ Type.Literal("medium"),
115
+ Type.Literal("high"),
116
+ Type.Literal("xhigh"),
117
+ Type.Literal("max"),
118
+ ]), {
119
+ description: "User-level last-applied thinking level per provider/model, shared by Pix TUI and Desktop model pickers.",
120
+ })),
80
121
  toolRenderer: Type.Optional(ToolRendererConfig),
81
122
  outputFilters: Type.Optional(OutputFiltersConfig),
82
123
  promptEnhancer: Type.Optional(PromptEnhancerConfig),
@@ -85,6 +126,7 @@ export const PixConfigSchema = Type.Object({
85
126
  modelColors: Type.Optional(ModelColorsConfig),
86
127
  iconTheme: Type.Optional(IconThemeConfig),
87
128
  dictation: Type.Optional(DictationConfig),
129
+ desktop: Type.Optional(DesktopConfig),
88
130
  }, {
89
131
  $id: "https://unpkg.com/pi-ui-extend/schemas/pix.json",
90
132
  $schema: "https://json-schema.org/draft-07/schema#",
@@ -0,0 +1,18 @@
1
+ /** JSON Schema for project-scoped Desktop tasks stored in <cwd>/.pi/tasks.jsonc. */
2
+ import { Static, Type } from "typebox";
3
+ export declare const ProjectTasksSchema: Type.TObject<{
4
+ $schema: Type.TOptional<Type.TString>;
5
+ version: Type.TLiteral<1>;
6
+ tasks: Type.TArray<Type.TObject<{
7
+ id: Type.TString;
8
+ title: Type.TString;
9
+ description: Type.TOptional<Type.TString>;
10
+ type: Type.TUnion<[Type.TLiteral<"bug">, Type.TLiteral<"feature">, Type.TLiteral<"improvement">]>;
11
+ status: Type.TUnion<[Type.TLiteral<"backlog">, Type.TLiteral<"todo">, Type.TLiteral<"in-progress">, Type.TLiteral<"done">]>;
12
+ priority: Type.TUnion<[Type.TLiteral<"low">, Type.TLiteral<"medium">, Type.TLiteral<"high">, Type.TLiteral<"urgent">]>;
13
+ sessionId: Type.TOptional<Type.TString>;
14
+ createdAt: Type.TString;
15
+ updatedAt: Type.TString;
16
+ }>>;
17
+ }>;
18
+ export type ProjectTasksSchemaType = Static<typeof ProjectTasksSchema>;
@@ -0,0 +1,41 @@
1
+ /** JSON Schema for project-scoped Desktop tasks stored in <cwd>/.pi/tasks.jsonc. */
2
+ import { Type } from "typebox";
3
+ const TaskType = Type.Union([
4
+ Type.Literal("bug"),
5
+ Type.Literal("feature"),
6
+ Type.Literal("improvement"),
7
+ ]);
8
+ const TaskStatus = Type.Union([
9
+ Type.Literal("backlog"),
10
+ Type.Literal("todo"),
11
+ Type.Literal("in-progress"),
12
+ Type.Literal("done"),
13
+ ]);
14
+ const TaskPriority = Type.Union([
15
+ Type.Literal("low"),
16
+ Type.Literal("medium"),
17
+ Type.Literal("high"),
18
+ Type.Literal("urgent"),
19
+ ]);
20
+ const ProjectTask = Type.Object({
21
+ id: Type.String({ minLength: 1, maxLength: 128, description: "Stable unique task id." }),
22
+ title: Type.String({ maxLength: 200, description: "Short task title. May be empty when the task has description content." }),
23
+ description: Type.Optional(Type.String({ maxLength: 10_000, description: "Optional detailed task description." })),
24
+ type: TaskType,
25
+ status: TaskStatus,
26
+ priority: TaskPriority,
27
+ sessionId: Type.Optional(Type.String({ minLength: 1, maxLength: 512, description: "Optional Pi session associated with this task." })),
28
+ createdAt: Type.String({ format: "date-time", description: "RFC 3339 creation timestamp." }),
29
+ updatedAt: Type.String({ format: "date-time", description: "RFC 3339 last-update timestamp." }),
30
+ }, { additionalProperties: false });
31
+ export const ProjectTasksSchema = Type.Object({
32
+ $schema: Type.Optional(Type.String({ description: "JSON Schema URL used by editors for validation and autocomplete." })),
33
+ version: Type.Literal(1, { description: "Task document format version." }),
34
+ tasks: Type.Array(ProjectTask, { maxItems: 10_000, description: "Project tasks. Task ids must be unique." }),
35
+ }, {
36
+ $id: "https://unpkg.com/pi-ui-extend/schemas/tasks.json",
37
+ $schema: "https://json-schema.org/draft-07/schema#",
38
+ title: "Pix Project Tasks",
39
+ description: "Project-scoped task document stored in <cwd>/.pi/tasks.jsonc.",
40
+ additionalProperties: false,
41
+ });
@@ -1,9 +1,15 @@
1
1
  # Spec: Application concurrency and lifecycle safety
2
2
 
3
+ <!-- markdownlint-disable MD013 -->
4
+
3
5
  ## Type
4
6
 
5
7
  Change
6
8
 
9
+ ## Lifecycle
10
+
11
+ Active implemented contract.
12
+
7
13
  ## Goal
8
14
 
9
15
  Keep tab, session, editor, extension UI, persistence, and shutdown work bound to
@@ -67,7 +73,9 @@ the state that started it, without blocking normal terminal interaction.
67
73
  ## Risks / unknowns
68
74
 
69
75
  - SDK session hydration and append APIs are synchronous; eliminating those stalls may require an upstream SDK API or worker/process boundary.
70
- - Voice model inference may require a dedicated worker to become fully non-blocking.
76
+ - Deepgram voice finalization must stay bounded, and shutdown must use the
77
+ immediate voice-dispose path rather than spend the global cleanup deadline
78
+ waiting for speech-to-text final results.
71
79
 
72
80
  ## Evidence
73
81
 
@@ -4,6 +4,13 @@
4
4
 
5
5
  Change
6
6
 
7
+ ## Lifecycle
8
+
9
+ Historical baseline. This document records the first Desktop vertical slice and
10
+ still contains useful process-host/ACP transport contracts, but it is no longer
11
+ the current feature-scope inventory. Later implemented Desktop behavior is
12
+ specified by the `specs/desktop-*.md` family.
13
+
7
14
  ## Goal
8
15
 
9
16
  Provide a lightweight desktop client for Pix using Tauri 2 and Svelte 5 +
@@ -21,7 +28,11 @@ updates, cancel a running turn, and answer extension elicitations.
21
28
  elicitations.
22
29
  - Development commands and a documented local setup path.
23
30
 
24
- ## Non-goals
31
+ ## MVP-era non-goals
32
+
33
+ The items below were intentionally out of scope for the first slice. Several
34
+ were implemented later and are governed by newer feature specs; they are not
35
+ current product non-goals.
25
36
 
26
37
  - Feature parity with `PiUiExtendApp`.
27
38
  - Voice input, an embedded terminal, custom widgets, image attachments,
@@ -33,8 +44,10 @@ updates, cancel a running turn, and answer extension elicitations.
33
44
 
34
45
  ## Behavior
35
46
 
36
- 1. Tauri starts one isolated `pix-acp` child and exposes only start, line-send,
37
- and stop commands to the webview. Arbitrary shell execution is not exposed.
47
+ 1. Tauri starts one isolated `pix-acp` child for the ACP protocol. The host's
48
+ command surface has since grown beyond start/line-send/stop (e.g. package and
49
+ shell terminals via portable-pty); those additions are governed by the later
50
+ `specs/desktop-*.md` family, not by this historical baseline.
38
51
  2. The client initializes ACP with form-elicitation support before creating or
39
52
  loading a session.
40
53
  3. Selecting a workspace lists its persisted sessions. The user can create a
@@ -64,10 +77,13 @@ updates, cancel a running turn, and answer extension elicitations.
64
77
  object and the generation must still own the child
65
78
  - `acp_stop(generation)`; stale generations cannot stop a replacement child
66
79
  - Rust → webview events:
67
- - `acp://stdout` with `{ generation, line }` for one complete stdout line
68
- - `acp://stderr` with `{ generation, line }` for one diagnostic line
80
+ - `acp://stdout` with `{ windowLabel, generation, lines: string[] }` batches
81
+ of complete stdout lines (stdout stays protocol-only)
82
+ - `acp://stderr` with `{ windowLabel, generation, lines: string[] }` batches
83
+ of diagnostic lines
69
84
  - `acp://exit` with the generation and child exit status
70
- - Rust starts `node ../../acp/dist/main.js` by default. `PIX_ACP_NODE_BINARY`
85
+ - Rust starts Node with the generated `<repo>/acp/dist/main.js` entry by
86
+ default. `PIX_ACP_NODE_BINARY`
71
87
  and `PIX_ACP_ENTRY` may override executable and entry path for development.
72
88
  - Webview ↔ adapter payloads follow `@agentclientprotocol/sdk` 1.4.0 types.
73
89