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
@@ -3,15 +3,12 @@ import * as fs from "node:fs";
3
3
  import * as path from "node:path";
4
4
  import { ignoreStaleExtensionContextError } from "../context-usage.js";
5
5
  import {
6
- copySubagentConfigSample,
7
6
  ensureSessionFileLink,
8
- existingSubagentConfigFiles,
9
7
  findSubagentSessionByFile,
10
8
  getActiveSubagentPresetName,
11
- getDefaultSubagentConfigPath,
9
+ getBuiltinSubagentPresetsPath,
10
+ getProjectSubagentPresetsPath,
12
11
  getSessionSubagentPresetOverride,
13
- getSubagentConfigInitTargetPath,
14
- getSubagentConfigSamplePath,
15
12
  getSubagentPresetSelectionPath,
16
13
  getRunState,
17
14
  listRunDirs,
@@ -49,11 +46,10 @@ type MessageSender = ExtensionAPI & {
49
46
  };
50
47
 
51
48
  const CLEAR_ACTIVE_PRESET_LABEL = "Use no active preset";
52
- const COPY_SAMPLE_CONFIG_LABEL = "Copy sample asyncSubagents config";
53
49
 
54
50
  export const ULTRAWORK_PROMPT = `Run ultrawork mode for the current objective.
55
51
 
56
- Use subagents when a lower-cost worker or isolation of noisy evidence helps, including one bounded sequential task. Pick subagentType from the effective catalog: research for reading/review, implement for code/docs/tests/UI changes, verify for running checks, browser-qa for real-browser testing, and oracle only for a deliberate strong independent opinion. Prefer an appropriate project-local specialist. Keep decisions and integration in the parent; do not create agents just to assign a discipline.
52
+ Use subagents when a lower-cost worker or isolation of noisy evidence helps, including one bounded sequential task. Pick subagentType from the effective catalog: research for reading/review, implement for code/docs/tests/UI changes, verify for running checks, ui-qa for real UI testing across browsers, TUIs, and desktop GUIs, and oracle only for a deliberate strong independent opinion. Prefer an appropriate project-local specialist. Keep decisions and integration in the parent; do not create agents just to assign a discipline.
57
53
 
58
54
  Keep parent context lean: spawn for broad parallel work, read results only when needed, and finish unless genuinely blocked.`;
59
55
 
@@ -192,12 +188,10 @@ async function triggerOrchestrationPrompt(
192
188
 
193
189
  function registerPresetCommands(pi: ExtensionAPI): void {
194
190
  pi.registerCommand("subagent-preset", {
195
- description: "Select a sub-agent preset defined in asyncSubagents config, run session <name> for a process override, or init to copy the sample config",
191
+ description: "Select a sub-agent model-pool preset, or run session <name> for a process-only override",
196
192
  getArgumentCompletions: (prefix: string) => {
197
- const names = existingSubagentConfigFiles(process.cwd()).length > 0
198
- ? sortedPresetNames(loadSubagentConfig(process.cwd()).presets ?? {}, getActiveSubagentPresetName())
199
- : [];
200
- return [...names, ...names.map((name) => `session ${name}`), "list", "path", "config", "init", "clear", "session", "session-clear"]
193
+ const names = sortedPresetNames(loadSubagentConfig(process.cwd()).presets ?? {}, getActiveSubagentPresetName());
194
+ return [...names, ...names.map((name) => `session ${name}`), "list", "path", "clear", "session", "session-clear"]
201
195
  .filter((name) => name.startsWith(prefix))
202
196
  .map((name) => ({ value: name, label: name }));
203
197
  },
@@ -209,28 +203,19 @@ function registerPresetCommands(pi: ExtensionAPI): void {
209
203
  if (name === "session-clear") return clearSessionActiveSubagentPreset(ctx);
210
204
  if (name === "list") return listSubagentPresets(ctx);
211
205
  if (name === "path") return showSubagentPresetPaths(ctx);
212
- if (name === "config") return showSubagentPresetConfigurator(ctx);
213
- if (name === "init") return initSubagentConfigSample(ctx);
214
206
  if (name === "clear") return clearActiveSubagentPreset(ctx);
215
- if (existingSubagentConfigFiles(ctx.cwd).length === 0) return ctx.ui.notify(missingSubagentConfigMessage(ctx), "warning");
216
207
 
217
208
  const config = loadSubagentConfig(ctx.cwd);
218
209
  const preset = config.presets?.[name];
219
- if (!preset) return ctx.ui.notify(`Unknown sub-agent preset "${name}". Define it in asyncSubagents config or run /subagent-preset list.`, "error");
210
+ if (!preset) return ctx.ui.notify(`Unknown sub-agent preset "${name}". Run /subagent-preset list to see available pools.`, "error");
220
211
  setActiveSubagentPreset(name);
221
212
  notifyActiveSubagentPreset(ctx, name, preset);
222
213
  },
223
214
  });
224
-
225
- pi.registerCommand("subagent-preset-config", {
226
- description: "Select sub-agent presets defined in asyncSubagents config",
227
- handler: async (_args: string, ctx: CommandContext) => showSubagentPresetConfigurator(ctx),
228
- });
229
215
  }
230
216
 
231
217
  async function showSubagentPresetSelector(ctx: CommandContext): Promise<void> {
232
218
  if (!ctx.hasUI) return ctx.ui.notify("Sub-agent preset selector requires interactive UI. Use /subagent-preset <name>.", "warning");
233
- if (existingSubagentConfigFiles(ctx.cwd).length === 0) return showMissingSubagentConfigSelector(ctx);
234
219
 
235
220
  const config = loadSubagentConfig(ctx.cwd);
236
221
  const activePreset = getActiveSubagentPresetName();
@@ -240,12 +225,12 @@ async function showSubagentPresetSelector(ctx: CommandContext): Promise<void> {
240
225
  const labels = [...presetLabels];
241
226
  if (activePreset) labels.push(CLEAR_ACTIVE_PRESET_LABEL);
242
227
  if (labels.length === 0) {
243
- ctx.ui.notify("No sub-agent presets are defined in asyncSubagents config.", "warning");
228
+ ctx.ui.notify("No sub-agent model-pool presets are available.", "warning");
244
229
  showSubagentPresetPaths(ctx);
245
230
  return;
246
231
  }
247
232
  const labelToName = new Map(presetLabels.map((label, index) => [label, names[index]]));
248
- const selected = await ctx.ui.select(names.length > 0 ? "Select active sub-agent preset" : "No sub-agent presets in asyncSubagents config", labels);
233
+ const selected = await ctx.ui.select("Select active sub-agent preset", labels);
249
234
  if (!selected) return;
250
235
  if (selected === CLEAR_ACTIVE_PRESET_LABEL) return clearActiveSubagentPreset(ctx);
251
236
 
@@ -254,69 +239,29 @@ async function showSubagentPresetSelector(ctx: CommandContext): Promise<void> {
254
239
  setActiveSubagentPreset(name);
255
240
  notifyActiveSubagentPreset(ctx, name, presets[name]);
256
241
  }
257
-
258
- async function showSubagentPresetConfigurator(ctx: CommandContext): Promise<void> {
259
- if (!ctx.hasUI) return ctx.ui.notify("Sub-agent preset selector requires interactive UI.", "warning");
260
- return showSubagentPresetSelector(ctx);
261
- }
262
-
263
- async function showMissingSubagentConfigSelector(ctx: CommandContext): Promise<void> {
264
- const selected = await ctx.ui.select("No asyncSubagents config found", [COPY_SAMPLE_CONFIG_LABEL]);
265
- if (selected === COPY_SAMPLE_CONFIG_LABEL) initSubagentConfigSample(ctx);
266
- }
267
-
268
242
  function listSubagentPresets(ctx: CommandContext): void {
269
- if (existingSubagentConfigFiles(ctx.cwd).length === 0) {
270
- ctx.ui.notify(missingSubagentConfigMessage(ctx), "warning");
271
- return;
272
- }
273
243
  const config = loadSubagentConfig(ctx.cwd);
274
244
  const activePreset = getActiveSubagentPresetName();
275
245
  const presets = config.presets ?? {};
276
246
  const names = sortedPresetNames(presets, activePreset);
277
- if (names.length === 0) return ctx.ui.notify("No sub-agent presets are defined in asyncSubagents config.", "warning");
247
+ if (names.length === 0) return ctx.ui.notify("No sub-agent model-pool presets are available.", "warning");
278
248
  ctx.ui.notify([
279
- "Sub-agent presets from asyncSubagents config:",
249
+ "Sub-agent model-pool presets:",
280
250
  ...names.map((name) => `- ${subagentPresetLabel(name, presets[name], activePreset)}`),
281
251
  ].join("\n"), "info");
282
252
  }
283
253
 
284
254
  function showSubagentPresetPaths(ctx: CommandContext): void {
285
255
  ctx.ui.notify([
286
- "Preset definitions: asyncSubagents in ~/.config/pi/pi-tools-suite.jsonc, $PI_CONFIG_DIR/pi-tools-suite.jsonc, or project .pi/pi-tools-suite.jsonc",
287
- "Explicit override files are still supported via ASYNC_SUBAGENTS_CONFIG / PI_SUBAGENTS_CONFIG.",
288
- `Default config target: ${getDefaultSubagentConfigPath()}`,
289
- `Sample config: ${getSubagentConfigSamplePath()}`,
290
- `Copy sample target: ${getSubagentConfigInitTargetPath(ctx.cwd)}`,
256
+ `Bundled presets: ${getBuiltinSubagentPresetsPath()}`,
257
+ `Project preset override: ${getProjectSubagentPresetsPath(ctx.cwd)}`,
258
+ "Project presets are defined as model pools in .pi/agents/presets.jsonc; agent behavior stays in .pi/agents/*.md.",
291
259
  `Active selection state: ${getSubagentPresetSelectionPath()}`,
292
260
  `Session override: ${formatSessionPresetOverride()}`,
293
261
  "Use /subagent-preset session <name> to override only the current Pi process; use /subagent-preset session-clear to clear that runtime override.",
294
- "Run /subagent-preset init to copy the bundled sample only when no config exists.",
295
262
  ].join("\n"), "info");
296
263
  }
297
264
 
298
- function initSubagentConfigSample(ctx: CommandContext): void {
299
- try {
300
- const result = copySubagentConfigSample(ctx.cwd);
301
- if (result.copied) {
302
- ctx.ui.notify(`Copied sample asyncSubagents config:\n${result.samplePath}\n→ ${result.targetPath}`, "info");
303
- return;
304
- }
305
- ctx.ui.notify(`AsyncSubagents config already exists; not overwriting:\n${result.existingFiles.join("\n") || result.targetPath}`, "warning");
306
- } catch (error) {
307
- ctx.ui.notify(error instanceof Error ? error.message : String(error), "error");
308
- }
309
- }
310
-
311
- function missingSubagentConfigMessage(ctx: CommandContext): string {
312
- return [
313
- "No asyncSubagents config found in pi-tools-suite config.",
314
- `Sample config: ${getSubagentConfigSamplePath()}`,
315
- `Copy target: ${getSubagentConfigInitTargetPath(ctx.cwd)}`,
316
- "Run /subagent-preset init to copy the bundled sample into the shared config.",
317
- ].join("\n");
318
- }
319
-
320
265
  function clearActiveSubagentPreset(ctx: CommandContext): void {
321
266
  setActiveSubagentPreset(undefined);
322
267
  const override = getSessionSubagentPresetOverride();
@@ -327,10 +272,9 @@ function clearActiveSubagentPreset(ctx: CommandContext): void {
327
272
 
328
273
  function setSessionActiveSubagentPreset(ctx: CommandContext, name: string): void {
329
274
  if (!name) return ctx.ui.notify("Usage: /subagent-preset session <name>", "warning");
330
- if (existingSubagentConfigFiles(ctx.cwd).length === 0) return ctx.ui.notify(missingSubagentConfigMessage(ctx), "warning");
331
275
  const config = loadSubagentConfig(ctx.cwd);
332
276
  const preset = config.presets?.[name];
333
- if (!preset) return ctx.ui.notify(`Unknown sub-agent preset "${name}". Define it in asyncSubagents config or run /subagent-preset list.`, "error");
277
+ if (!preset) return ctx.ui.notify(`Unknown sub-agent preset "${name}". Run /subagent-preset list to see available pools.`, "error");
334
278
  setSessionSubagentPresetOverride(name);
335
279
  ctx.ui.notify(`Session-only sub-agent preset "${name}": ${subagentPresetDescription(preset)}\nApplies to future sub-agent spawns only until this Pi process exits or /subagent-preset session-clear is run. Saved preset selection is unchanged.`, "info");
336
280
  }
@@ -0,0 +1,33 @@
1
+ import type { AgentActivity, RpcEventRecord } from "./types.js";
2
+ import { isRecord, isoNow } from "./utils.js";
3
+
4
+ export function activityFromRpcEvent(event: RpcEventRecord, at = isoNow()): AgentActivity | undefined {
5
+ if (event.type === "tool_execution_start") {
6
+ const toolName = nonEmptyString(event.toolName);
7
+ return toolName ? { label: toolName, at } : undefined;
8
+ }
9
+ if ((event.type === "message_start" || event.type === "message_end") && rpcMessageRole(event) === "assistant") {
10
+ return { label: "Thinking", at };
11
+ }
12
+ return undefined;
13
+ }
14
+
15
+ export function activityFromProgressRecord(value: unknown): AgentActivity | undefined {
16
+ if (!isRecord(value) || value.stage !== "rpc_event") return undefined;
17
+ const at = nonEmptyString(value.at);
18
+ if (!at) return undefined;
19
+ const toolName = nonEmptyString(value.toolName);
20
+ if (toolName) return { label: toolName, at };
21
+ if (value.type === "message_start" || value.type === "message_end") return { label: "Thinking", at };
22
+ return undefined;
23
+ }
24
+
25
+ function rpcMessageRole(event: RpcEventRecord): string | undefined {
26
+ const directRole = nonEmptyString(event.role);
27
+ if (directRole) return directRole;
28
+ return isRecord(event.message) ? nonEmptyString(event.message.role) : undefined;
29
+ }
30
+
31
+ function nonEmptyString(value: unknown): string | undefined {
32
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
33
+ }
@@ -1,7 +1,7 @@
1
- import type { SubagentConfig } from "./config.js";
1
+ import { filterSubagentConfigForParentModel, type SubagentConfig } from "./config.js";
2
2
  import { SUBAGENT_DELEGATION_GUIDANCE } from "./agent-strategy.js";
3
3
 
4
- export const SUBAGENT_TYPE_SELECTION_GUIDANCE = "Choose and set subagentType from the available catalog when a role clearly matches, preferring a matching project-local specialist. Preserve a user-requested role. Omit subagentType only when unsure or when the user explicitly requests automatic routing; the LLM router handles omissions only. Model/thinking overrides are not substitutes for choosing a role.";
4
+ export const SUBAGENT_TYPE_SELECTION_GUIDANCE = "Choose and set subagentType from the available catalog when a role clearly matches, preferring a matching project-local specialist. Preserve a user-requested role when it is available in the current catalog. Omit subagentType only when unsure or when the user explicitly requests automatic routing; the LLM router handles omissions only. Model/thinking overrides are not substitutes for choosing a role.";
5
5
 
6
6
  const MAX_DESCRIPTION_CHARS = 500;
7
7
 
@@ -10,8 +10,9 @@ const MAX_DESCRIPTION_CHARS = 500;
10
10
  * The config has already merged built-ins, config files, and project-local
11
11
  * `.pi/agents/*.md`, so this stays aligned with what spawn/routing can use.
12
12
  */
13
- export function buildSubagentCatalogPrompt(config: SubagentConfig): string | undefined {
14
- const entries = Object.entries(config.types).sort(([left], [right]) => left.localeCompare(right));
13
+ export function buildSubagentCatalogPrompt(config: SubagentConfig, parentModelRef?: string): string | undefined {
14
+ const effectiveConfig = filterSubagentConfigForParentModel(config, parentModelRef);
15
+ const entries = Object.entries(effectiveConfig.types).sort(([left], [right]) => left.localeCompare(right));
15
16
  if (entries.length === 0) return undefined;
16
17
 
17
18
  return [
@@ -7,7 +7,7 @@ export interface AgentStrategyOptions {
7
7
  }
8
8
 
9
9
  /** Shared by the strategy, tool description and role catalog. */
10
- export const SUBAGENT_DELEGATION_GUIDANCE = "Delegate bounded work when a lower-cost worker can do it or noisy intermediate evidence should stay out of the parent context; one sequential task can qualify. Keep planning, decisions, integration and the final answer in the parent. Use research for evidence/review, implement for code/docs/tests/UI changes, verify for running checks, browser-qa for browser testing. Reserve oracle for a deliberate strong independent opinion, not automatic escalation. Do trivial lookups/edits directly; redirect a noisy command to a log instead of spawning an LLM when no interpretation is needed.";
10
+ export const SUBAGENT_DELEGATION_GUIDANCE = "Delegate bounded work when a lower-cost worker can do it or noisy intermediate evidence should stay out of the parent context; one sequential task can qualify. Keep planning, decisions, integration and the final answer in the parent. Use research for evidence/focused review questions, implement for code/docs/tests/UI changes, verify for running checks, ui-qa for real user-interface testing across browsers, TUIs, and desktop GUIs. When frontier-review is present in the current role catalog and substantive code changed, use it as the independent post-implementation review gate before finalizing; it is intentionally hidden for parent models excluded by its profile. Reserve oracle for a deliberate strong second opinion, not routine code review. Do trivial lookups/edits directly; redirect a noisy command to a log instead of spawning an LLM when no interpretation is needed.";
11
11
 
12
12
  export function agentStrategyPrompt(options: AgentStrategyOptions = {}): string | undefined {
13
13
  const env = options.env ?? process.env;
@@ -46,9 +46,10 @@ const KNOWN_FRONTMATTER_KEYS = new Set([
46
46
  "model",
47
47
  "fallbackModels",
48
48
  "modelByParent",
49
+ "forParentModels",
50
+ "notForParentModels",
49
51
  "thinking",
50
52
  "tools",
51
- "isolatedSkills",
52
53
  "extraArgs",
53
54
  "promptAppend",
54
55
  "promptOverride",
@@ -62,7 +63,8 @@ const COMMA_SEPARATED_ARRAY_KEYS = new Set([
62
63
  "tools",
63
64
  "models",
64
65
  "fallbackModels",
65
- "isolatedSkills",
66
+ "forParentModels",
67
+ "notForParentModels",
66
68
  "extraArgs",
67
69
  "retryableExitCodes",
68
70
  ]);
@@ -72,7 +74,7 @@ const NUMERIC_PATTERN = /^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/;
72
74
 
73
75
  /** Discover and parse `.pi/agents/*.md` for the project containing `cwd`. */
74
76
  export function readProjectAgentDefinitions(cwd: string): Record<string, ProjectAgentDefinition> {
75
- const dir = findProjectAgentsDir(cwd);
77
+ const dir = projectAgentsDir(cwd);
76
78
  return dir ? readAgentDefinitionsFromDir(dir) : {};
77
79
  }
78
80
 
@@ -94,7 +96,7 @@ export function readAgentDefinitionsFromDir(dir: string): Record<string, AgentDe
94
96
  * deterministic merge order.
95
97
  */
96
98
  export function projectAgentDefinitionFiles(cwd: string): string[] {
97
- const dir = findProjectAgentsDir(cwd);
99
+ const dir = projectAgentsDir(cwd);
98
100
  return dir ? agentDefinitionFiles(dir) : [];
99
101
  }
100
102
 
@@ -108,7 +110,8 @@ export function agentDefinitionFiles(dir: string): string[] {
108
110
  .sort();
109
111
  }
110
112
 
111
- function findProjectAgentsDir(startDir: string): string | undefined {
113
+ /** First project `.pi/agents` directory found walking up from cwd. */
114
+ export function projectAgentsDir(startDir: string): string | undefined {
112
115
  let dir = path.resolve(startDir);
113
116
  const root = path.parse(dir).root;
114
117
  while (true) {
@@ -1,9 +1,23 @@
1
1
  import { fileURLToPath } from "node:url";
2
2
 
3
- /** Non-secret, launcher-owned path supplied only to browser-qa children. */
3
+ /** Canonical UI-QA role plus the pre-rename compatibility alias. */
4
+ export const UI_QA_TYPE = "ui-qa";
5
+ export const LEGACY_BROWSER_QA_TYPE = "browser-qa";
6
+
7
+ export function isUiQaType(value: string | undefined): boolean {
8
+ return value === UI_QA_TYPE || value === LEGACY_BROWSER_QA_TYPE;
9
+ }
10
+
11
+ /** Non-secret, launcher-owned path supplied only to UI-QA children. */
4
12
  export const BROWSER_QA_RUNNER_ENV = "PI_BROWSER_QA_RUNNER";
13
+ export const UI_QA_RUNNER_ENV = "PI_UI_QA_RUNNER";
5
14
 
6
15
  /** Resolve against the installed package, never the delegated project's cwd. */
7
16
  export function getBrowserQaRunnerPath(): string {
8
- return fileURLToPath(new URL("../agents/browser-qa/scripts/browser-qa-runner.mjs", import.meta.url));
17
+ return fileURLToPath(new URL("../agents/ui-qa/browser/scripts/browser-qa-runner.mjs", import.meta.url));
18
+ }
19
+
20
+ /** Resolve the capability-first UI-QA runner against the installed package. */
21
+ export function getUiQaRunnerPath(): string {
22
+ return fileURLToPath(new URL("../agents/ui-qa/scripts/ui-qa-runner.mjs", import.meta.url));
9
23
  }