pi-subagents 0.76.0 → 0.77.0

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 (347) hide show
  1. package/CHANGELOG.md +92 -0
  2. package/README.md +1 -1
  3. package/agents/oracle.md +8 -19
  4. package/agents/researcher.md +0 -3
  5. package/agents/reviewer.md +17 -61
  6. package/agents/scout.md +1 -4
  7. package/agents/worker.md +8 -25
  8. package/docs/agents.md +70 -3
  9. package/docs/configuration.md +55 -6
  10. package/docs/extension-api.md +36 -11
  11. package/docs/missions.md +24 -17
  12. package/docs/models.md +1 -1
  13. package/docs/observability.md +10 -5
  14. package/docs/tool-reference.md +101 -83
  15. package/docs/watchdog.md +8 -6
  16. package/docs/workflows.md +15 -6
  17. package/index.d.ts.map +1 -1
  18. package/index.js +5 -0
  19. package/index.js.map +1 -1
  20. package/package.json +2 -1
  21. package/prompts/council.md +1 -1
  22. package/skills/pi-subagents/SKILL.md +1 -1
  23. package/skills/pi-subagents/references/constraints-and-recipes.md +1 -1
  24. package/skills/pi-subagents/references/execution-controls.md +16 -16
  25. package/skills/pi-subagents/references/management-authoring-rpc.md +16 -12
  26. package/skills/pi-subagents/references/prompting-and-roles.md +3 -3
  27. package/src/agents/advertised-agent-prompt.d.ts +5 -1
  28. package/src/agents/advertised-agent-prompt.d.ts.map +1 -1
  29. package/src/agents/advertised-agent-prompt.js +8 -2
  30. package/src/agents/advertised-agent-prompt.js.map +1 -1
  31. package/src/agents/agent-management.d.ts.map +1 -1
  32. package/src/agents/agent-management.js +5 -0
  33. package/src/agents/agent-management.js.map +1 -1
  34. package/src/agents/agent-scope.d.ts +1 -0
  35. package/src/agents/agent-scope.d.ts.map +1 -1
  36. package/src/agents/agent-scope.js +3 -0
  37. package/src/agents/agent-scope.js.map +1 -1
  38. package/src/agents/agent-serializer.d.ts.map +1 -1
  39. package/src/agents/agent-serializer.js +3 -0
  40. package/src/agents/agent-serializer.js.map +1 -1
  41. package/src/agents/agents.d.ts +14 -2
  42. package/src/agents/agents.d.ts.map +1 -1
  43. package/src/agents/agents.js +94 -36
  44. package/src/agents/agents.js.map +1 -1
  45. package/src/api/preflight.d.ts +2 -0
  46. package/src/api/preflight.d.ts.map +1 -1
  47. package/src/api/preflight.js +6 -2
  48. package/src/api/preflight.js.map +1 -1
  49. package/src/extension/config.d.ts.map +1 -1
  50. package/src/extension/config.js +23 -2
  51. package/src/extension/config.js.map +1 -1
  52. package/src/extension/control-notices.d.ts +0 -2
  53. package/src/extension/control-notices.d.ts.map +1 -1
  54. package/src/extension/control-notices.js +1 -7
  55. package/src/extension/control-notices.js.map +1 -1
  56. package/src/extension/declaration-pinning.d.ts +14 -0
  57. package/src/extension/declaration-pinning.d.ts.map +1 -0
  58. package/src/extension/declaration-pinning.js +147 -0
  59. package/src/extension/declaration-pinning.js.map +1 -0
  60. package/src/extension/doctor.d.ts +3 -1
  61. package/src/extension/doctor.d.ts.map +1 -1
  62. package/src/extension/doctor.js +3 -9
  63. package/src/extension/doctor.js.map +1 -1
  64. package/src/extension/fanout-child.d.ts.map +1 -1
  65. package/src/extension/fanout-child.js +6 -8
  66. package/src/extension/fanout-child.js.map +1 -1
  67. package/src/extension/index.d.ts +1 -1
  68. package/src/extension/index.d.ts.map +1 -1
  69. package/src/extension/index.js +68 -116
  70. package/src/extension/index.js.map +1 -1
  71. package/src/extension/rpc.d.ts.map +1 -1
  72. package/src/extension/rpc.js +12 -6
  73. package/src/extension/rpc.js.map +1 -1
  74. package/src/extension/schemas.d.ts +137 -1
  75. package/src/extension/schemas.d.ts.map +1 -1
  76. package/src/extension/schemas.js +22 -22
  77. package/src/extension/schemas.js.map +1 -1
  78. package/src/extension/subagent-guide.d.ts +1 -0
  79. package/src/extension/subagent-guide.d.ts.map +1 -1
  80. package/src/extension/subagent-guide.js +80 -6
  81. package/src/extension/subagent-guide.js.map +1 -1
  82. package/src/extension/subagent-options.d.ts +8 -0
  83. package/src/extension/subagent-options.d.ts.map +1 -0
  84. package/src/extension/subagent-options.js +52 -0
  85. package/src/extension/subagent-options.js.map +1 -0
  86. package/src/extension/tool-activation.d.ts.map +1 -1
  87. package/src/extension/tool-activation.js +3 -2
  88. package/src/extension/tool-activation.js.map +1 -1
  89. package/src/extension/tool-description.d.ts +4 -7
  90. package/src/extension/tool-description.d.ts.map +1 -1
  91. package/src/extension/tool-description.js +45 -59
  92. package/src/extension/tool-description.js.map +1 -1
  93. package/src/inspectors/actions.d.ts +2 -0
  94. package/src/inspectors/actions.d.ts.map +1 -1
  95. package/src/inspectors/actions.js +41 -13
  96. package/src/inspectors/actions.js.map +1 -1
  97. package/src/inspectors/plugins.d.ts.map +1 -1
  98. package/src/inspectors/plugins.js +3 -2
  99. package/src/inspectors/plugins.js.map +1 -1
  100. package/src/inspectors/tmux/actions.d.ts +26 -0
  101. package/src/inspectors/tmux/actions.d.ts.map +1 -0
  102. package/src/inspectors/tmux/actions.js +182 -0
  103. package/src/inspectors/tmux/actions.js.map +1 -0
  104. package/src/inspectors/tmux/client.d.ts +28 -0
  105. package/src/inspectors/tmux/client.d.ts.map +1 -0
  106. package/src/inspectors/tmux/client.js +65 -0
  107. package/src/inspectors/tmux/client.js.map +1 -0
  108. package/src/inspectors/tmux/plugin.d.ts +8 -0
  109. package/src/inspectors/tmux/plugin.d.ts.map +1 -0
  110. package/src/inspectors/tmux/plugin.js +15 -0
  111. package/src/inspectors/tmux/plugin.js.map +1 -0
  112. package/src/integrations/herdr-status.d.ts +0 -1
  113. package/src/integrations/herdr-status.d.ts.map +1 -1
  114. package/src/integrations/herdr-status.js +18 -52
  115. package/src/integrations/herdr-status.js.map +1 -1
  116. package/src/integrations/program-status.d.ts +31 -0
  117. package/src/integrations/program-status.d.ts.map +1 -0
  118. package/src/integrations/program-status.js +189 -0
  119. package/src/integrations/program-status.js.map +1 -0
  120. package/src/intercom/native-supervisor-channel.d.ts +1 -0
  121. package/src/intercom/native-supervisor-channel.d.ts.map +1 -1
  122. package/src/intercom/native-supervisor-channel.js +77 -3
  123. package/src/intercom/native-supervisor-channel.js.map +1 -1
  124. package/src/intercom/result-intercom.js +1 -1
  125. package/src/intercom/result-intercom.js.map +1 -1
  126. package/src/intercom/supervisor-ui.d.ts +2 -12
  127. package/src/intercom/supervisor-ui.d.ts.map +1 -1
  128. package/src/intercom/supervisor-ui.js +2 -154
  129. package/src/intercom/supervisor-ui.js.map +1 -1
  130. package/src/missions/store.d.ts.map +1 -1
  131. package/src/missions/store.js +27 -5
  132. package/src/missions/store.js.map +1 -1
  133. package/src/runs/background/async-execution.d.ts +9 -1
  134. package/src/runs/background/async-execution.d.ts.map +1 -1
  135. package/src/runs/background/async-execution.js +250 -141
  136. package/src/runs/background/async-execution.js.map +1 -1
  137. package/src/runs/background/async-job-tracker.d.ts +4 -1
  138. package/src/runs/background/async-job-tracker.d.ts.map +1 -1
  139. package/src/runs/background/async-job-tracker.js +3 -2
  140. package/src/runs/background/async-job-tracker.js.map +1 -1
  141. package/src/runs/background/async-resume.d.ts.map +1 -1
  142. package/src/runs/background/async-resume.js +6 -2
  143. package/src/runs/background/async-resume.js.map +1 -1
  144. package/src/runs/background/await-async-run.d.ts +8 -4
  145. package/src/runs/background/await-async-run.d.ts.map +1 -1
  146. package/src/runs/background/await-async-run.js +14 -8
  147. package/src/runs/background/await-async-run.js.map +1 -1
  148. package/src/runs/background/binary-bootstrap.d.ts.map +1 -1
  149. package/src/runs/background/binary-bootstrap.js +2 -1
  150. package/src/runs/background/binary-bootstrap.js.map +1 -1
  151. package/src/runs/background/chain-root-attachment.d.ts +2 -0
  152. package/src/runs/background/chain-root-attachment.d.ts.map +1 -1
  153. package/src/runs/background/chain-root-attachment.js +5 -2
  154. package/src/runs/background/chain-root-attachment.js.map +1 -1
  155. package/src/runs/background/fleet-view.js +5 -5
  156. package/src/runs/background/fleet-view.js.map +1 -1
  157. package/src/runs/background/notify.d.ts +12 -2
  158. package/src/runs/background/notify.d.ts.map +1 -1
  159. package/src/runs/background/notify.js +148 -13
  160. package/src/runs/background/notify.js.map +1 -1
  161. package/src/runs/background/result-files.d.ts +29 -0
  162. package/src/runs/background/result-files.d.ts.map +1 -1
  163. package/src/runs/background/result-files.js +104 -6
  164. package/src/runs/background/result-files.js.map +1 -1
  165. package/src/runs/background/result-watcher.d.ts.map +1 -1
  166. package/src/runs/background/result-watcher.js +60 -64
  167. package/src/runs/background/result-watcher.js.map +1 -1
  168. package/src/runs/background/resume-guidance.js +2 -2
  169. package/src/runs/background/resume-guidance.js.map +1 -1
  170. package/src/runs/background/run-child-session.d.ts.map +1 -1
  171. package/src/runs/background/run-child-session.js +2 -1
  172. package/src/runs/background/run-child-session.js.map +1 -1
  173. package/src/runs/background/run-id-resolver.d.ts.map +1 -1
  174. package/src/runs/background/run-id-resolver.js +9 -6
  175. package/src/runs/background/run-id-resolver.js.map +1 -1
  176. package/src/runs/background/run-status.d.ts.map +1 -1
  177. package/src/runs/background/run-status.js +19 -15
  178. package/src/runs/background/run-status.js.map +1 -1
  179. package/src/runs/background/runner-child-launch.d.ts.map +1 -1
  180. package/src/runs/background/runner-child-launch.js +1 -0
  181. package/src/runs/background/runner-child-launch.js.map +1 -1
  182. package/src/runs/background/runner-http-dispatcher.d.ts +3 -0
  183. package/src/runs/background/runner-http-dispatcher.d.ts.map +1 -1
  184. package/src/runs/background/runner-http-dispatcher.js +2 -0
  185. package/src/runs/background/runner-http-dispatcher.js.map +1 -1
  186. package/src/runs/background/scheduled-runs.d.ts +9 -0
  187. package/src/runs/background/scheduled-runs.d.ts.map +1 -1
  188. package/src/runs/background/scheduled-runs.js +124 -36
  189. package/src/runs/background/scheduled-runs.js.map +1 -1
  190. package/src/runs/background/subagent-runner-bootstrap.d.ts.map +1 -1
  191. package/src/runs/background/subagent-runner-bootstrap.js +5 -1
  192. package/src/runs/background/subagent-runner-bootstrap.js.map +1 -1
  193. package/src/runs/background/subagent-runner.d.ts +3 -1
  194. package/src/runs/background/subagent-runner.d.ts.map +1 -1
  195. package/src/runs/background/subagent-runner.js +15 -6
  196. package/src/runs/background/subagent-runner.js.map +1 -1
  197. package/src/runs/background/subagent-wait.d.ts +2 -0
  198. package/src/runs/background/subagent-wait.d.ts.map +1 -1
  199. package/src/runs/background/subagent-wait.js +34 -20
  200. package/src/runs/background/subagent-wait.js.map +1 -1
  201. package/src/runs/background/terminal-run-index.d.ts +1 -0
  202. package/src/runs/background/terminal-run-index.d.ts.map +1 -1
  203. package/src/runs/background/terminal-run-index.js +47 -1
  204. package/src/runs/background/terminal-run-index.js.map +1 -1
  205. package/src/runs/background/wait-tool.d.ts.map +1 -1
  206. package/src/runs/background/wait-tool.js +36 -23
  207. package/src/runs/background/wait-tool.js.map +1 -1
  208. package/src/runs/foreground/async-stop-action.d.ts +7 -1
  209. package/src/runs/foreground/async-stop-action.d.ts.map +1 -1
  210. package/src/runs/foreground/async-stop-action.js +49 -25
  211. package/src/runs/foreground/async-stop-action.js.map +1 -1
  212. package/src/runs/foreground/execution.d.ts.map +1 -1
  213. package/src/runs/foreground/execution.js +50 -24
  214. package/src/runs/foreground/execution.js.map +1 -1
  215. package/src/runs/foreground/subagent-executor.d.ts +5 -1
  216. package/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  217. package/src/runs/foreground/subagent-executor.js +174 -65
  218. package/src/runs/foreground/subagent-executor.js.map +1 -1
  219. package/src/runs/shared/child-hooks.js +6 -5
  220. package/src/runs/shared/child-hooks.js.map +1 -1
  221. package/src/runs/shared/child-launch.d.ts +2 -0
  222. package/src/runs/shared/child-launch.d.ts.map +1 -1
  223. package/src/runs/shared/child-launch.js +1 -0
  224. package/src/runs/shared/child-launch.js.map +1 -1
  225. package/src/runs/shared/child-session.d.ts +4 -0
  226. package/src/runs/shared/child-session.d.ts.map +1 -1
  227. package/src/runs/shared/child-session.js +28 -23
  228. package/src/runs/shared/child-session.js.map +1 -1
  229. package/src/runs/shared/child-tool-plan.d.ts.map +1 -1
  230. package/src/runs/shared/child-tool-plan.js +11 -10
  231. package/src/runs/shared/child-tool-plan.js.map +1 -1
  232. package/src/runs/shared/dynamic-fanout.js +1 -1
  233. package/src/runs/shared/dynamic-fanout.js.map +1 -1
  234. package/src/runs/shared/herdr-placed-run.d.ts +1 -0
  235. package/src/runs/shared/herdr-placed-run.d.ts.map +1 -1
  236. package/src/runs/shared/herdr-placed-run.js +10 -6
  237. package/src/runs/shared/herdr-placed-run.js.map +1 -1
  238. package/src/runs/shared/model-resolution-diagnostic.d.ts +10 -0
  239. package/src/runs/shared/model-resolution-diagnostic.d.ts.map +1 -1
  240. package/src/runs/shared/model-resolution-diagnostic.js +24 -0
  241. package/src/runs/shared/model-resolution-diagnostic.js.map +1 -1
  242. package/src/runs/shared/model-resolution.d.ts.map +1 -1
  243. package/src/runs/shared/model-resolution.js +29 -1
  244. package/src/runs/shared/model-resolution.js.map +1 -1
  245. package/src/runs/shared/nested-events.d.ts +2 -0
  246. package/src/runs/shared/nested-events.d.ts.map +1 -1
  247. package/src/runs/shared/nested-events.js +4 -0
  248. package/src/runs/shared/nested-events.js.map +1 -1
  249. package/src/runs/shared/parallel-handoff.js +2 -2
  250. package/src/runs/shared/parallel-handoff.js.map +1 -1
  251. package/src/runs/shared/parallel-utils.d.ts +2 -0
  252. package/src/runs/shared/parallel-utils.d.ts.map +1 -1
  253. package/src/runs/shared/parallel-utils.js.map +1 -1
  254. package/src/runs/shared/runner-launcher.d.ts +12 -0
  255. package/src/runs/shared/runner-launcher.d.ts.map +1 -0
  256. package/src/runs/shared/runner-launcher.js +25 -0
  257. package/src/runs/shared/runner-launcher.js.map +1 -0
  258. package/src/runs/shared/single-output.d.ts +20 -0
  259. package/src/runs/shared/single-output.d.ts.map +1 -1
  260. package/src/runs/shared/single-output.js +57 -0
  261. package/src/runs/shared/single-output.js.map +1 -1
  262. package/src/runs/shared/structured-output.d.ts.map +1 -1
  263. package/src/runs/shared/structured-output.js +17 -8
  264. package/src/runs/shared/structured-output.js.map +1 -1
  265. package/src/runs/shared/subagent-control.js +3 -3
  266. package/src/runs/shared/subagent-control.js.map +1 -1
  267. package/src/runs/shared/subagent-prompt-runtime.d.ts +8 -2
  268. package/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
  269. package/src/runs/shared/subagent-prompt-runtime.js +43 -20
  270. package/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
  271. package/src/runs/shared/workflow-async-child-guidance.js +1 -1
  272. package/src/runs/shared/workflow-async-child-guidance.js.map +1 -1
  273. package/src/runs/shared/worktree-cleanup-plan.js +1 -1
  274. package/src/runs/shared/worktree-cleanup-plan.js.map +1 -1
  275. package/src/shared/atomic-json.d.ts +4 -3
  276. package/src/shared/atomic-json.d.ts.map +1 -1
  277. package/src/shared/atomic-json.js +3 -1
  278. package/src/shared/atomic-json.js.map +1 -1
  279. package/src/shared/edit-distance.d.ts +5 -0
  280. package/src/shared/edit-distance.d.ts.map +1 -0
  281. package/src/shared/edit-distance.js +33 -0
  282. package/src/shared/edit-distance.js.map +1 -0
  283. package/src/shared/formatters.d.ts.map +1 -1
  284. package/src/shared/formatters.js +1 -6
  285. package/src/shared/formatters.js.map +1 -1
  286. package/src/shared/model-info.d.ts +8 -0
  287. package/src/shared/model-info.d.ts.map +1 -1
  288. package/src/shared/model-info.js +22 -0
  289. package/src/shared/model-info.js.map +1 -1
  290. package/src/shared/package-version.d.ts +3 -0
  291. package/src/shared/package-version.d.ts.map +1 -0
  292. package/src/shared/package-version.js +15 -0
  293. package/src/shared/package-version.js.map +1 -0
  294. package/src/shared/parent-wake.d.ts +18 -0
  295. package/src/shared/parent-wake.d.ts.map +1 -0
  296. package/src/shared/parent-wake.js +60 -0
  297. package/src/shared/parent-wake.js.map +1 -0
  298. package/src/shared/pruned-fork.d.ts +1 -1
  299. package/src/shared/pruned-fork.d.ts.map +1 -1
  300. package/src/shared/pruned-fork.js +6 -0
  301. package/src/shared/pruned-fork.js.map +1 -1
  302. package/src/shared/runtime-module-path.d.ts +11 -0
  303. package/src/shared/runtime-module-path.d.ts.map +1 -0
  304. package/src/shared/runtime-module-path.js +17 -0
  305. package/src/shared/runtime-module-path.js.map +1 -0
  306. package/src/shared/types.d.ts +26 -2
  307. package/src/shared/types.d.ts.map +1 -1
  308. package/src/shared/types.js +3 -0
  309. package/src/shared/types.js.map +1 -1
  310. package/src/shared/utils.d.ts.map +1 -1
  311. package/src/shared/utils.js +8 -7
  312. package/src/shared/utils.js.map +1 -1
  313. package/src/slash/slash-commands.js +3 -3
  314. package/src/slash/slash-commands.js.map +1 -1
  315. package/src/slash/subagents-admin.d.ts.map +1 -1
  316. package/src/slash/subagents-admin.js +2 -1
  317. package/src/slash/subagents-admin.js.map +1 -1
  318. package/src/tui/fleet-transcript.d.ts +2 -0
  319. package/src/tui/fleet-transcript.d.ts.map +1 -1
  320. package/src/tui/fleet-transcript.js +7 -2
  321. package/src/tui/fleet-transcript.js.map +1 -1
  322. package/src/tui/fleet.d.ts.map +1 -1
  323. package/src/tui/fleet.js +9 -4
  324. package/src/tui/fleet.js.map +1 -1
  325. package/src/tui/render.d.ts +2 -2
  326. package/src/tui/render.d.ts.map +1 -1
  327. package/src/tui/render.js +19 -17
  328. package/src/tui/render.js.map +1 -1
  329. package/src/tui/subagent-messages.d.ts +23 -0
  330. package/src/tui/subagent-messages.d.ts.map +1 -0
  331. package/src/tui/subagent-messages.js +270 -0
  332. package/src/tui/subagent-messages.js.map +1 -0
  333. package/src/watchdog/register-main.d.ts.map +1 -1
  334. package/src/watchdog/register-main.js +1 -19
  335. package/src/watchdog/register-main.js.map +1 -1
  336. package/src/watchdog/render.d.ts +2 -10
  337. package/src/watchdog/render.d.ts.map +1 -1
  338. package/src/watchdog/render.js +1 -19
  339. package/src/watchdog/render.js.map +1 -1
  340. package/src/watchdog/tool-actions.js +2 -2
  341. package/src/watchdog/tool-actions.js.map +1 -1
  342. package/src/workflows/scripted-workflow.d.ts.map +1 -1
  343. package/src/workflows/scripted-workflow.js +20 -6
  344. package/src/workflows/scripted-workflow.js.map +1 -1
  345. package/src/workflows/workflow-resources.d.ts.map +1 -1
  346. package/src/workflows/workflow-resources.js +12 -0
  347. package/src/workflows/workflow-resources.js.map +1 -1
@@ -9,6 +9,7 @@ import * as path from "node:path";
9
9
  import { fileURLToPath } from "node:url";
10
10
  import { createAtomicJsonWriter } from "../shared/atomic-json.js";
11
11
  import { resolveSettingsWriteTarget, withSettingsFileLease } from "../shared/settings-file-lease.js";
12
+ import { RUNNER_LAUNCHER_NAME_PATTERN, RUNNER_LAUNCHER_NAME_RULE } from "../shared/types.js";
12
13
  import { CODE_OWNED_EXTERNAL_CLI_ADAPTER_LABEL, isCodeOwnedExternalCliAdapterId, parseExternalCliCapabilityNarrowing, validateCodeOwnedProfileRunner } from "../runs/shared/external-cli-contract.js";
13
14
  import { isClaudeCodeAdapterId } from "../runs/shared/claude-code-adapter.js";
14
15
  import { getAgentDir, getProjectConfigDir } from "../shared/utils.js";
@@ -16,6 +17,8 @@ import { expandHomePath } from "../shared/settings.js";
16
17
  import { KNOWN_FIELDS } from "./agent-serializer.js";
17
18
  import { parseChain, parseJsonChain } from "./chain-serializer.js";
18
19
  import { mergeAgentsForScope } from "./agent-selection.js";
20
+ import { projectScopeRequiresTrustMessage } from "./agent-scope.js";
21
+ import { closestMatch } from "../shared/edit-distance.js";
19
22
  import { parseFrontmatter, parseFrontmatterList } from "./frontmatter.js";
20
23
  import { buildRuntimeName, parsePackageName } from "./identity.js";
21
24
  import { parseModelScopeConfig } from "../runs/shared/model-scope.js";
@@ -72,8 +75,27 @@ export function unknownAgentDiagnosticContext(discovered) {
72
75
  scope: discovered.scope,
73
76
  directories: discovered.directories,
74
77
  agents: discovered.agents,
78
+ ...(discovered.disabledAgents?.length ? { disabledAgents: discovered.disabledAgents } : {}),
75
79
  };
76
80
  }
81
+ const MAX_LISTED_AGENTS = 30;
82
+ const MAX_LISTED_DESCRIPTION_CHARS = 80;
83
+ /** One line per agent the caller can launch instead, so a wrong name needs no separate list call. */
84
+ export function formatAvailableAgentLines(agents) {
85
+ const sorted = [...agents].sort((left, right) => left.name.localeCompare(right.name) || left.source.localeCompare(right.source));
86
+ const lines = sorted.slice(0, MAX_LISTED_AGENTS).map((agent) => {
87
+ const description = agent.description.replace(/\s+/gu, " ").trim();
88
+ const short = description.length > MAX_LISTED_DESCRIPTION_CHARS ? `${description.slice(0, MAX_LISTED_DESCRIPTION_CHARS - 1).trimEnd()}…` : description;
89
+ return `- ${agent.name} (${agent.source})${short ? ` — ${short}` : ""}`;
90
+ });
91
+ if (sorted.length > MAX_LISTED_AGENTS)
92
+ lines.push(`+${sorted.length - MAX_LISTED_AGENTS} more; {action:"list"}`);
93
+ return lines.length ? lines : ["- (none)"];
94
+ }
95
+ /** The closest agent name or alias when `name` looks like a typo of one. */
96
+ export function suggestAgentName(name, agents) {
97
+ return closestMatch(name.trim(), new Set(agents.flatMap((agent) => [agent.name, ...(agent.localName ? [agent.localName] : []), ...(agent.aliases ?? [])])));
98
+ }
77
99
  /** Render local discovery evidence without exposing filesystem error details. */
78
100
  export function formatUnknownAgentError(name, context, prefix = "Unknown agent") {
79
101
  const directories = context.directories.map((directory) => {
@@ -84,16 +106,15 @@ export function formatUnknownAgentError(name, context, prefix = "Unknown agent")
84
106
  : directory.state;
85
107
  return `- ${directory.source}: ${directory.path} (${state})`;
86
108
  });
87
- const agents = [...context.agents]
88
- .sort((left, right) => left.name.localeCompare(right.name) || left.source.localeCompare(right.source))
89
- .map((agent) => `- ${agent.name} (${agent.source})`);
109
+ const disabled = context.disabledAgents?.includes(name.trim()) === true;
110
+ const suggestion = disabled ? undefined : suggestAgentName(name, context.agents);
90
111
  return [
91
- `${prefix}: ${name}`,
112
+ disabled ? `${prefix}: ${name} is disabled by a settings override.` : `${prefix}: ${name}${suggestion ? `. Did you mean '${suggestion}'?` : ""}`,
92
113
  `Effective cwd: ${path.resolve(context.cwd)}`,
93
114
  "Consulted agent-definition directories:",
94
115
  ...(directories.length ? directories : ["- (none)"]),
95
- "Discovered agents:",
96
- ...(agents.length ? agents : ["- (none)"]),
116
+ "Available agents:",
117
+ ...formatAvailableAgentLines(context.agents),
97
118
  ].join("\n");
98
119
  }
99
120
  function getUserChainDir() {
@@ -323,13 +344,10 @@ function collectSettingsPackageRoots(settingsFile, baseDir) {
323
344
  }
324
345
  return roots;
325
346
  }
326
- function collectPackageSubagentPaths(cwd, options = { includeUser: true, includeProject: true }) {
347
+ function collectPackageSubagentPaths(cwd, options) {
327
348
  const agentDir = getAgentDir();
328
- const projectRoot = findConfiguredProjectRoot(cwd) ?? cwd;
329
- const packageRoots = [
330
- { root: projectRoot, scope: "root" },
331
- ];
332
- const watchPaths = [path.join(projectRoot, "package.json")];
349
+ const packageRoots = [];
350
+ const watchPaths = [];
333
351
  const settingsErrors = {};
334
352
  const collectScopedSettingsRoots = (scope, settingsFile, baseDir) => {
335
353
  try {
@@ -345,11 +363,17 @@ function collectPackageSubagentPaths(cwd, options = { includeUser: true, include
345
363
  return [];
346
364
  }
347
365
  };
348
- if (options.includeProject) {
349
- const projectConfigDir = getProjectConfigDir(projectRoot);
350
- const nodeModulesDir = path.join(projectConfigDir, "npm", "node_modules");
351
- packageRoots.push(...collectPackageRootsFromNodeModules(nodeModulesDir, watchPaths).map((root) => ({ root, scope: "project" })));
352
- packageRoots.push(...collectScopedSettingsRoots("project", path.join(projectConfigDir, "settings.json"), projectConfigDir).map((root) => ({ root, scope: "project" })));
366
+ // Resolving the project root reads project settings, which an untrusted project does not supply.
367
+ if (options.projectTrusted !== false) {
368
+ const projectRoot = findConfiguredProjectRoot(cwd) ?? cwd;
369
+ packageRoots.push({ root: projectRoot, scope: "root" });
370
+ watchPaths.push(path.join(projectRoot, "package.json"));
371
+ if (options.includeProject) {
372
+ const projectConfigDir = getProjectConfigDir(projectRoot);
373
+ const nodeModulesDir = path.join(projectConfigDir, "npm", "node_modules");
374
+ packageRoots.push(...collectPackageRootsFromNodeModules(nodeModulesDir, watchPaths).map((root) => ({ root, scope: "project" })));
375
+ packageRoots.push(...collectScopedSettingsRoots("project", path.join(projectConfigDir, "settings.json"), projectConfigDir).map((root) => ({ root, scope: "project" })));
376
+ }
353
377
  }
354
378
  if (options.includeUser) {
355
379
  const nodeModulesDir = path.join(agentDir, "npm", "node_modules");
@@ -736,6 +760,9 @@ function parseBuiltinOverrideEntry(name, value, filePath) {
736
760
  if (Object.hasOwn(input, "fallbackModels")) {
737
761
  throw new Error(`Builtin override '${name}' in '${filePath}' uses removed field 'fallbackModels'; configure one model instead.`);
738
762
  }
763
+ if (Object.hasOwn(input, "launcher")) {
764
+ throw new Error(`Builtin override '${name}' in '${filePath}' sets 'launcher', which settings overrides do not support; set 'launcher' in a user agent file instead.`);
765
+ }
739
766
  const override = {};
740
767
  if ("description" in input) {
741
768
  if (typeof input.description === "string" && input.description.trim()) {
@@ -1387,7 +1414,7 @@ function runtimeAgentOverrides(settings) {
1387
1414
  export function applyRuntimeAgentSettings(agents, context) {
1388
1415
  if (agents.length === 0)
1389
1416
  return agents;
1390
- const sources = getAgentDiscoverySources(context.cwd, context.preferredModelProvider);
1417
+ const sources = getAgentDiscoverySources(context.cwd, context.preferredModelProvider, false, undefined, context.projectTrusted !== false);
1391
1418
  const { user, project } = settingsForScope(sources, context.scope);
1392
1419
  const defaultProvider = resolveSubagentDefaultProvider(user, project, sources.projectSettingsPath);
1393
1420
  const defaultModel = resolveSubagentDefaultModel(user, project, sources.userSettingsPath, sources.projectSettingsPath, defaultProvider);
@@ -2023,6 +2050,13 @@ function loadAgentsFromDefinitionFiles(files, source, discoveryPriority, package
2023
2050
  : undefined;
2024
2051
  const memory = parseMemoryFrontmatter(frontmatter.memory);
2025
2052
  const machine = validateOptionalMachine(frontmatter.machine, `Agent '${runtimeName}' frontmatter 'machine'`);
2053
+ const launcher = frontmatter.launcher;
2054
+ if (launcher !== undefined && !RUNNER_LAUNCHER_NAME_PATTERN.test(launcher)) {
2055
+ throw new Error(`Agent '${runtimeName}' frontmatter 'launcher' ${JSON.stringify(launcher)} is invalid; launcher names ${RUNNER_LAUNCHER_NAME_RULE}.`);
2056
+ }
2057
+ if (launcher !== undefined && (runner?.type === "external-cli" || runner?.type === "external-job" || machine !== undefined)) {
2058
+ throw new Error(`Agent '${runtimeName}' sets 'launcher', which wraps the local Pi background runner, so it cannot be combined with ${machine !== undefined ? "'machine'" : `runner.type='${runner.type}'`}.`);
2059
+ }
2026
2060
  const agent = {
2027
2061
  name: runtimeName,
2028
2062
  ...(runner !== undefined ? { runner } : {}),
@@ -2062,6 +2096,7 @@ function loadAgentsFromDefinitionFiles(files, source, discoveryPriority, package
2062
2096
  ...(subagentOnlyExtensions !== undefined ? { subagentOnlyExtensions } : {}),
2063
2097
  ...(mutationTools?.length ? { mutationTools } : {}),
2064
2098
  ...(machine !== undefined ? { machine } : {}),
2099
+ ...(launcher !== undefined ? { launcher } : {}),
2065
2100
  ...(frontmatter.output !== undefined ? { output: frontmatter.output } : {}),
2066
2101
  ...(outputMode !== undefined ? { outputMode } : {}),
2067
2102
  ...(outputSchema !== undefined ? { outputSchema } : {}),
@@ -2314,11 +2349,12 @@ function discoveryFingerprint(sources) {
2314
2349
  .map((filePath) => `${filePath}:${watchPathSignature(filePath, sources.exclusionRoots.length && !unfilteredPaths.has(filePath) ? sources.isExcluded : undefined)}`)
2315
2350
  .join("\n");
2316
2351
  }
2317
- function discoveryCacheKey(cwd, preferredModelProvider, globalNpmRoot) {
2352
+ function discoveryCacheKey(cwd, preferredModelProvider, globalNpmRoot, projectTrusted) {
2318
2353
  return JSON.stringify([
2319
2354
  path.resolve(cwd),
2320
2355
  preferredModelProvider ?? null,
2321
2356
  globalNpmRoot === undefined ? ["default"] : ["override", globalNpmRoot],
2357
+ projectTrusted,
2322
2358
  getProjectConfigDir(path.resolve(cwd)),
2323
2359
  getAgentDir(),
2324
2360
  os.homedir(),
@@ -2346,16 +2382,19 @@ function packageEntryIncluded(scope, packageScopes) {
2346
2382
  return true;
2347
2383
  return packageScopes.has(scope);
2348
2384
  }
2349
- function buildAgentDiscoverySources(cwd, preferredModelProvider, globalNpmRoot) {
2385
+ function buildAgentDiscoverySources(cwd, preferredModelProvider, globalNpmRoot, projectTrusted) {
2350
2386
  const effectiveCwd = path.resolve(cwd);
2351
2387
  const userDirOld = path.join(getAgentDir(), "agents");
2352
2388
  const userDirNew = path.join(os.homedir(), ".agents");
2353
2389
  const userChainDir = getUserChainDir();
2354
- const { readDirs: projectAgentDirs, candidateDirs: projectCandidateDirs, preferredDir: projectAgentsDir } = resolveNearestProjectAgentDirs(effectiveCwd);
2355
- const { readDirs: projectChainDirs, preferredDir: projectChainDir } = resolveNearestProjectChainDirs(effectiveCwd);
2390
+ // The project's settings choose its root, so an untrusted project contributes no directories or settings at all.
2391
+ const { readDirs: projectAgentDirs, candidateDirs: projectCandidateDirs, preferredDir: projectAgentsDir } = projectTrusted
2392
+ ? resolveNearestProjectAgentDirs(effectiveCwd)
2393
+ : { readDirs: [], candidateDirs: [], preferredDir: null };
2394
+ const { readDirs: projectChainDirs, preferredDir: projectChainDir } = projectTrusted ? resolveNearestProjectChainDirs(effectiveCwd) : { readDirs: [], preferredDir: null };
2356
2395
  const userSettingsPath = getUserAgentSettingsPath();
2357
- const projectSettingsPath = getProjectAgentSettingsPath(effectiveCwd);
2358
- const packageSubagentPaths = collectPackageSubagentPaths(effectiveCwd, { includeUser: true, includeProject: true, globalNpmRoot });
2396
+ const projectSettingsPath = projectTrusted ? getProjectAgentSettingsPath(effectiveCwd) : null;
2397
+ const packageSubagentPaths = collectPackageSubagentPaths(effectiveCwd, { includeUser: true, includeProject: true, globalNpmRoot, projectTrusted });
2359
2398
  const exclusionRoots = agentExclusionRoots(userSettingsPath, projectSettingsPath);
2360
2399
  const isExcluded = agentExclusions(exclusionRoots);
2361
2400
  const userScanDirs = settingsAgentScanDirs(readConfiguredAgentScanDirs(userSettingsPath), isExcluded);
@@ -2442,8 +2481,8 @@ function ensureDiscoveryChains(sources) {
2442
2481
  sources.chainWatchPaths = watchPaths;
2443
2482
  sources.watchPaths = [...new Set([...sources.watchPaths, ...watchPaths])];
2444
2483
  }
2445
- function getAgentDiscoverySources(cwd, preferredModelProvider, includeChains = false, globalNpmRoot) {
2446
- const key = discoveryCacheKey(cwd, preferredModelProvider, globalNpmRoot);
2484
+ function getAgentDiscoverySources(cwd, preferredModelProvider, includeChains = false, globalNpmRoot, projectTrusted = true) {
2485
+ const key = discoveryCacheKey(cwd, preferredModelProvider, globalNpmRoot, projectTrusted);
2447
2486
  const cached = agentDiscoveryCache.get(key);
2448
2487
  if (cached && cached.fingerprint === discoveryFingerprint(cached.sources)) {
2449
2488
  if (includeChains) {
@@ -2452,7 +2491,7 @@ function getAgentDiscoverySources(cwd, preferredModelProvider, includeChains = f
2452
2491
  }
2453
2492
  return cached.sources;
2454
2493
  }
2455
- const sources = buildAgentDiscoverySources(cwd, preferredModelProvider, globalNpmRoot);
2494
+ const sources = buildAgentDiscoverySources(cwd, preferredModelProvider, globalNpmRoot, projectTrusted);
2456
2495
  const entry = { sources, fingerprint: discoveryFingerprint(sources) };
2457
2496
  agentDiscoveryCache.set(key, entry);
2458
2497
  if (includeChains) {
@@ -2558,9 +2597,12 @@ function discoveryDiagnostics(sources, scope) {
2558
2597
  }
2559
2598
  function buildEffectiveDiscovery(sources, scope) {
2560
2599
  const configured = configuredAgentsForScope(sources, scope);
2561
- const agents = applySubagentMaxThinking(mergeAgentsForScope(scope, configured.user, configured.project, configured.builtin, configured.package).filter((agent) => agent.disabled !== true), configured.maxThinking);
2600
+ const merged = mergeAgentsForScope(scope, configured.user, configured.project, configured.builtin, configured.package);
2601
+ const agents = applySubagentMaxThinking(merged.filter((agent) => agent.disabled !== true), configured.maxThinking);
2602
+ const disabledAgents = merged.filter((agent) => agent.disabled === true).map((agent) => agent.name);
2562
2603
  return {
2563
2604
  agents,
2605
+ ...(disabledAgents.length ? { disabledAgents } : {}),
2564
2606
  agentDiagnostics: discoveryDiagnostics(sources, scope),
2565
2607
  projectAgentsDir: sources.projectAgentsDir,
2566
2608
  cwd: sources.cwd,
@@ -2619,8 +2661,19 @@ function buildAllDiscovery(sources, includeChains, settingsScope) {
2619
2661
  }
2620
2662
  export function discoverAgentSnapshot(cwd, scope, preferredModelProvider, options = {}) {
2621
2663
  const includeChains = options.includeChains !== false;
2622
- const sources = getAgentDiscoverySources(cwd, preferredModelProvider, includeChains, options.globalNpmRoot);
2623
- return { effective: buildEffectiveDiscovery(sources, scope), all: buildAllDiscovery(sources, includeChains, scope) };
2664
+ const projectTrusted = options.projectTrusted !== false;
2665
+ const trustedScope = trustedDiscoveryScope(cwd, scope, projectTrusted);
2666
+ const sources = getAgentDiscoverySources(cwd, preferredModelProvider, includeChains, options.globalNpmRoot, projectTrusted);
2667
+ return { effective: buildEffectiveDiscovery(sources, trustedScope), all: buildAllDiscovery(sources, includeChains, trustedScope) };
2668
+ }
2669
+ // Pi loads nothing from an untrusted project's `.pi` directory, so declined trust leaves user scope.
2670
+ // A trusted lookup keeps its scope as given, including an omitted one from untyped callers.
2671
+ function trustedDiscoveryScope(cwd, scope, projectTrusted) {
2672
+ if (projectTrusted)
2673
+ return scope;
2674
+ if (scope === "project")
2675
+ throw new Error(projectScopeRequiresTrustMessage(path.resolve(cwd)));
2676
+ return "user";
2624
2677
  }
2625
2678
  function discoverAgentsUncached(cwd, scope, preferredModelProvider, options = {}) {
2626
2679
  const effectiveCwd = path.resolve(cwd);
@@ -2674,15 +2727,20 @@ function discoverAgentsUncached(cwd, scope, preferredModelProvider, options = {}
2674
2727
  if (!packageMap.has(agent.name))
2675
2728
  packageMap.set(agent.name, agent);
2676
2729
  const packageAgents = applyCustomAgentOverrides(applyDefaults(Array.from(packageMap.values())), userSettings, projectSettings, userSettingsPath, projectSettingsPath);
2677
- const agents = applySubagentMaxThinking(mergeAgentsForScope(scope, userAgents, projectAgents, builtinAgents, packageAgents).filter((agent) => agent.disabled !== true), maxThinking);
2730
+ const merged = mergeAgentsForScope(scope, userAgents, projectAgents, builtinAgents, packageAgents);
2731
+ const agents = applySubagentMaxThinking(merged.filter((agent) => agent.disabled !== true), maxThinking);
2732
+ const disabledAgents = merged.filter((agent) => agent.disabled === true).map((agent) => agent.name);
2678
2733
  const agentDiagnostics = [...builtinLoaded.diagnostics, ...userLoaded.flatMap((loaded) => loaded.diagnostics), ...projectLoaded.flatMap((loaded) => loaded.diagnostics), ...packageLoaded.flatMap((loaded) => loaded.diagnostics)];
2679
- return { agents, agentDiagnostics, projectAgentsDir, cwd: effectiveCwd, scope, directories, ...(modelScope !== undefined ? { modelScope } : {}), ...(maxThinking !== undefined ? { maxThinking } : {}) };
2734
+ return { agents, ...(disabledAgents.length ? { disabledAgents } : {}), agentDiagnostics, projectAgentsDir, cwd: effectiveCwd, scope, directories, ...(modelScope !== undefined ? { modelScope } : {}), ...(maxThinking !== undefined ? { maxThinking } : {}) };
2680
2735
  }
2681
2736
  export function discoverAgents(cwd, scope, preferredModelProvider, options = {}) {
2682
- if (scope !== "both")
2683
- return discoverAgentsUncached(cwd, scope, preferredModelProvider, options);
2684
- const sources = getAgentDiscoverySources(cwd, preferredModelProvider, false, options.globalNpmRoot);
2685
- return buildEffectiveDiscovery(sources, scope);
2737
+ const projectTrusted = options.projectTrusted !== false;
2738
+ const trustedScope = trustedDiscoveryScope(cwd, scope, projectTrusted);
2739
+ // The uncached path always loads the project's own package.json entries.
2740
+ if (projectTrusted && trustedScope !== "both")
2741
+ return discoverAgentsUncached(cwd, trustedScope, preferredModelProvider, options);
2742
+ const sources = getAgentDiscoverySources(cwd, preferredModelProvider, false, options.globalNpmRoot, projectTrusted);
2743
+ return buildEffectiveDiscovery(sources, trustedScope);
2686
2744
  }
2687
2745
  export function discoverAgentsAll(cwd, preferredModelProvider, options = {}) {
2688
2746
  return discoverAgentSnapshot(cwd, "both", preferredModelProvider, options).all;