@fitchmultz/pi-subagents 0.44.7 → 0.46.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 (955) hide show
  1. package/CHANGELOG.md +264 -7
  2. package/LICENSE +1 -0
  3. package/README.md +58 -1483
  4. package/agents/context-builder.md +19 -1
  5. package/agents/debugger.md +10 -3
  6. package/agents/delegate.md +1 -0
  7. package/agents/fixer.md +4 -1
  8. package/agents/oracle.md +13 -2
  9. package/agents/planner.md +14 -3
  10. package/agents/researcher.md +11 -2
  11. package/agents/reviewer-claude.md +11 -2
  12. package/agents/reviewer-gpt.md +12 -2
  13. package/agents/reviewer-ponytail.md +11 -1
  14. package/agents/reviewer-security.md +13 -2
  15. package/agents/reviewer.md +12 -3
  16. package/agents/scout.md +12 -1
  17. package/agents/ui-designer.md +10 -3
  18. package/agents/watcher.md +1 -0
  19. package/agents/worker.md +8 -2
  20. package/agents/writer.md +6 -3
  21. package/dist/agents/agent-defaults.js +9 -0
  22. package/dist/agents/agent-definition.js +196 -0
  23. package/dist/agents/agent-management.js +64 -905
  24. package/dist/agents/agent-scope.js +4 -2
  25. package/dist/agents/agent-selection.js +10 -5
  26. package/dist/agents/agent-serializer.js +55 -67
  27. package/dist/agents/agents.js +75 -716
  28. package/dist/agents/builtin-overrides.js +218 -0
  29. package/dist/agents/chain-serializer.js +3 -367
  30. package/dist/agents/config-values.js +52 -0
  31. package/dist/agents/discovery-paths.js +91 -0
  32. package/dist/agents/frontmatter.js +15 -5
  33. package/dist/agents/identity.js +25 -8
  34. package/dist/agents/json-chain.js +254 -0
  35. package/dist/agents/management-config.js +332 -0
  36. package/dist/agents/management-format.js +231 -0
  37. package/dist/agents/management-persistence.js +287 -0
  38. package/dist/agents/management-targets.js +136 -0
  39. package/dist/agents/management-warnings.js +81 -0
  40. package/dist/agents/markdown-chain.js +210 -0
  41. package/dist/agents/package-agents.js +154 -0
  42. package/dist/agents/skill-files.js +157 -0
  43. package/dist/agents/skill-search-paths.js +246 -0
  44. package/dist/agents/skill-types.js +1 -0
  45. package/dist/agents/skills.js +54 -499
  46. package/dist/extension/acceptance-schema.js +55 -0
  47. package/dist/extension/build-info.js +1 -1
  48. package/dist/extension/chain-schema.js +196 -0
  49. package/dist/extension/child-runtime.js +237 -0
  50. package/dist/extension/compact-tools.js +122 -51
  51. package/dist/extension/config-schema.js +29 -0
  52. package/dist/extension/config.js +27 -11
  53. package/dist/extension/control-notice-schema.js +37 -0
  54. package/dist/extension/control-notices.js +13 -6
  55. package/dist/extension/delegation-bridges.js +43 -0
  56. package/dist/extension/doctor.js +48 -25
  57. package/dist/extension/everyday-schemas.js +207 -0
  58. package/dist/extension/fanout-child.js +18 -319
  59. package/dist/extension/index.js +8 -563
  60. package/dist/extension/message-renderers.js +225 -0
  61. package/dist/extension/nested-control-inbox.js +154 -0
  62. package/dist/extension/parent-runtime.js +339 -0
  63. package/dist/extension/primary-tool.js +69 -0
  64. package/dist/extension/result-snapshot.js +22 -0
  65. package/dist/extension/runtime-reload.js +62 -0
  66. package/dist/extension/runtime-storage.js +43 -0
  67. package/dist/extension/schema-overrides.js +75 -0
  68. package/dist/extension/schemas.js +265 -336
  69. package/dist/extension/tool-input.js +27 -12
  70. package/dist/extension/tool-result.js +19 -4
  71. package/dist/history/answer-texts.js +57 -0
  72. package/dist/history/canonical-result.js +76 -43
  73. package/dist/history/canonical-selection.js +40 -0
  74. package/dist/history/database-generation.js +82 -0
  75. package/dist/history/database.js +57 -33
  76. package/dist/history/entry-ingestion.js +61 -0
  77. package/dist/history/index.js +242 -97
  78. package/dist/history/ingest.js +168 -331
  79. package/dist/history/output-digests.js +40 -0
  80. package/dist/history/preview.js +210 -0
  81. package/dist/history/prune.js +33 -0
  82. package/dist/history/queries.js +60 -349
  83. package/dist/history/query-scope.js +190 -0
  84. package/dist/history/rows.js +77 -0
  85. package/dist/history/run-projection.js +137 -0
  86. package/dist/history/run-queries.js +153 -0
  87. package/dist/history/schema.js +31 -0
  88. package/dist/history/search-queries.js +163 -0
  89. package/dist/history/selected-record.js +108 -0
  90. package/dist/history/source-file.js +45 -0
  91. package/dist/history/source-watches.js +141 -0
  92. package/dist/history/store.js +164 -153
  93. package/dist/history/text-chunks.js +169 -0
  94. package/dist/history/text.js +35 -0
  95. package/dist/history/transcript-queries.js +177 -0
  96. package/dist/history/types.js +5 -1
  97. package/dist/history/values.js +36 -0
  98. package/dist/history/wire-inputs.js +122 -0
  99. package/dist/history/wire-models.js +38 -0
  100. package/dist/history/worker-runtime.js +441 -0
  101. package/dist/history/worker.js +66 -462
  102. package/dist/intercom/intercom-bridge.js +48 -20
  103. package/dist/intercom/live-intercom.js +80 -23
  104. package/dist/intercom/nested-result-tree.js +163 -0
  105. package/dist/intercom/result-delivery.js +40 -0
  106. package/dist/intercom/result-intercom.js +178 -261
  107. package/dist/pi-intercom/agent-dir.js +7 -3
  108. package/dist/pi-intercom/async.js +27 -0
  109. package/dist/pi-intercom/bridge-ask.js +57 -0
  110. package/dist/pi-intercom/bridge-config.js +89 -0
  111. package/dist/pi-intercom/bridge-http.js +86 -0
  112. package/dist/pi-intercom/bridge-launch-policy.js +88 -0
  113. package/dist/pi-intercom/bridge-launch.js +217 -0
  114. package/dist/pi-intercom/bridge-protocol.js +106 -0
  115. package/dist/pi-intercom/bridge-routes.js +72 -0
  116. package/dist/pi-intercom/bridge-rpc-process.js +264 -0
  117. package/dist/pi-intercom/bridge-session.js +420 -0
  118. package/dist/pi-intercom/bridge.js +221 -606
  119. package/dist/pi-intercom/broker/broker.js +236 -244
  120. package/dist/pi-intercom/broker/client.js +189 -304
  121. package/dist/pi-intercom/broker/connection.js +165 -0
  122. package/dist/pi-intercom/broker/framing.js +5 -3
  123. package/dist/pi-intercom/broker/paths.js +4 -1
  124. package/dist/pi-intercom/broker/pid.js +53 -25
  125. package/dist/pi-intercom/broker/snapshot-reader.js +78 -0
  126. package/dist/pi-intercom/broker/snapshots.js +188 -0
  127. package/dist/pi-intercom/broker/spawn.js +36 -25
  128. package/dist/pi-intercom/config.js +85 -71
  129. package/dist/pi-intercom/connection.js +297 -0
  130. package/dist/pi-intercom/identity.js +58 -0
  131. package/dist/pi-intercom/inbound-delivery.js +356 -0
  132. package/dist/pi-intercom/inbound-journal.js +303 -0
  133. package/dist/pi-intercom/inbound-record.js +113 -0
  134. package/dist/pi-intercom/inbound.js +179 -0
  135. package/dist/pi-intercom/index.js +79 -2933
  136. package/dist/pi-intercom/inspection.js +62 -0
  137. package/dist/pi-intercom/interview.js +236 -0
  138. package/dist/pi-intercom/lifecycle.js +168 -0
  139. package/dist/pi-intercom/message-format.js +69 -0
  140. package/dist/pi-intercom/outbound.js +304 -0
  141. package/dist/pi-intercom/peer-awareness.js +66 -0
  142. package/dist/pi-intercom/reply-tracker.js +62 -43
  143. package/dist/pi-intercom/reply-wait.js +201 -0
  144. package/dist/pi-intercom/runtime-types.js +3 -0
  145. package/dist/pi-intercom/session-events.js +180 -0
  146. package/dist/pi-intercom/session-targets.js +42 -34
  147. package/dist/pi-intercom/subagent-events.js +238 -0
  148. package/dist/pi-intercom/subagent-live-events.js +129 -86
  149. package/dist/pi-intercom/supervisor.js +282 -0
  150. package/dist/pi-intercom/tool-arguments.js +74 -0
  151. package/dist/pi-intercom/tool-registration.js +95 -0
  152. package/dist/pi-intercom/tool-results.js +38 -0
  153. package/dist/pi-intercom/tool-schemas.js +82 -0
  154. package/dist/pi-intercom/tools.js +51 -0
  155. package/dist/pi-intercom/topic-actions.js +177 -0
  156. package/dist/pi-intercom/topics.js +177 -92
  157. package/dist/pi-intercom/transport.js +1 -0
  158. package/dist/pi-intercom/types.js +151 -114
  159. package/dist/pi-intercom/ui/compose-paste.js +93 -0
  160. package/dist/pi-intercom/ui/compose.js +121 -143
  161. package/dist/pi-intercom/ui/inline-message.js +59 -59
  162. package/dist/pi-intercom/ui/message-renderers.js +147 -0
  163. package/dist/pi-intercom/ui/overlay.js +181 -0
  164. package/dist/pi-intercom/ui/session-format.js +124 -0
  165. package/dist/pi-intercom/ui/session-list.js +76 -43
  166. package/dist/pi-intercom/ui/tool-renderers.js +110 -0
  167. package/dist/pi-intercom/ui/topic-view.js +88 -0
  168. package/dist/pi-intercom/validation.js +59 -0
  169. package/dist/runs/background/async-chain-plan.js +265 -0
  170. package/dist/runs/background/async-control.js +134 -58
  171. package/dist/runs/background/async-execution.js +136 -633
  172. package/dist/runs/background/async-job-admission.js +40 -0
  173. package/dist/runs/background/async-job-projection.js +169 -0
  174. package/dist/runs/background/async-job-tracker.js +297 -327
  175. package/dist/runs/background/async-launch.js +216 -0
  176. package/dist/runs/background/async-plan.js +116 -0
  177. package/dist/runs/background/async-result-file.js +47 -23
  178. package/dist/runs/background/async-resume.js +195 -253
  179. package/dist/runs/background/async-run-discovery.js +213 -0
  180. package/dist/runs/background/async-run-location.js +135 -0
  181. package/dist/runs/background/async-run-record.js +1 -0
  182. package/dist/runs/background/async-run-repair.js +223 -0
  183. package/dist/runs/background/async-run-summary.js +1 -0
  184. package/dist/runs/background/async-single-plan.js +105 -0
  185. package/dist/runs/background/async-status-projection.js +155 -0
  186. package/dist/runs/background/async-status-render.js +117 -0
  187. package/dist/runs/background/async-status-validation.js +181 -0
  188. package/dist/runs/background/async-status.js +3 -442
  189. package/dist/runs/background/async-value.js +21 -0
  190. package/dist/runs/background/completion-dedupe.js +36 -12
  191. package/dist/runs/background/completion-delivery.js +211 -205
  192. package/dist/runs/background/completion-receipts.js +237 -0
  193. package/dist/runs/background/legacy-status-acceptance.js +34 -0
  194. package/dist/runs/background/notify.js +96 -48
  195. package/dist/runs/background/parallel-groups.js +36 -19
  196. package/dist/runs/background/result-payload.js +178 -0
  197. package/dist/runs/background/result-watcher.js +348 -339
  198. package/dist/runs/background/run-id-resolver.js +53 -33
  199. package/dist/runs/background/run-schemas.js +189 -0
  200. package/dist/runs/background/run-status-contracts.js +14 -0
  201. package/dist/runs/background/run-status-render.js +270 -0
  202. package/dist/runs/background/run-status.js +231 -339
  203. package/dist/runs/background/runner-attempt-output.js +155 -0
  204. package/dist/runs/background/runner-attempt.js +263 -0
  205. package/dist/runs/background/runner-child-executor.js +166 -0
  206. package/dist/runs/background/runner-child-observer.js +192 -0
  207. package/dist/runs/background/runner-completion-summary.js +71 -0
  208. package/dist/runs/background/runner-completion.js +211 -0
  209. package/dist/runs/background/runner-config.js +1 -0
  210. package/dist/runs/background/runner-contract.js +1 -0
  211. package/dist/runs/background/runner-dynamic.js +121 -0
  212. package/dist/runs/background/runner-finalization.js +149 -0
  213. package/dist/runs/background/runner-graph.js +68 -0
  214. package/dist/runs/background/runner-initial-status.js +60 -0
  215. package/dist/runs/background/runner-lifecycle.js +142 -0
  216. package/dist/runs/background/runner-monitor.js +309 -0
  217. package/dist/runs/background/runner-parallel.js +204 -0
  218. package/dist/runs/background/runner-prepare-step.js +86 -0
  219. package/dist/runs/background/runner-reporting.js +153 -0
  220. package/dist/runs/background/runner-status.js +148 -0
  221. package/dist/runs/background/runner-step-output.js +92 -0
  222. package/dist/runs/background/runner-step-record.js +45 -0
  223. package/dist/runs/background/runner-step.js +112 -0
  224. package/dist/runs/background/runner-streaming.js +173 -0
  225. package/dist/runs/background/runner-workflow.js +213 -0
  226. package/dist/runs/background/stale-run-reconciler.js +155 -292
  227. package/dist/runs/background/subagent-runner-launcher.js +33 -13
  228. package/dist/runs/background/subagent-runner.js +51 -1842
  229. package/dist/runs/background/top-level-async.js +2 -1
  230. package/dist/runs/foreground/chain-clarify.js +293 -1017
  231. package/dist/runs/foreground/clarification-draft.js +87 -0
  232. package/dist/runs/foreground/clarify-contracts.js +1 -0
  233. package/dist/runs/foreground/clarify-invocation.js +129 -38
  234. package/dist/runs/foreground/clarify-text-editor.js +210 -0
  235. package/dist/runs/foreground/clarify-view.js +167 -0
  236. package/dist/runs/foreground/execution-input.js +226 -353
  237. package/dist/runs/foreground/execution-routing.js +33 -0
  238. package/dist/runs/foreground/execution-timeout.js +81 -0
  239. package/dist/runs/foreground/foreground-control.js +222 -763
  240. package/dist/runs/foreground/foreground-memory.js +99 -0
  241. package/dist/runs/foreground/invocation-context.js +55 -0
  242. package/dist/runs/foreground/invocation-execution.js +331 -0
  243. package/dist/runs/foreground/invocation-expansion.js +48 -0
  244. package/dist/runs/foreground/management-actions.js +295 -0
  245. package/dist/runs/foreground/nested-control.js +179 -0
  246. package/dist/runs/foreground/question-continuation.js +78 -0
  247. package/dist/runs/foreground/question-control.js +155 -50
  248. package/dist/runs/foreground/resume-target.js +221 -0
  249. package/dist/runs/foreground/revival-launch-policy.js +58 -0
  250. package/dist/runs/foreground/run-async-path.js +190 -178
  251. package/dist/runs/foreground/run-interrupt.js +164 -0
  252. package/dist/runs/foreground/run-nudge.js +278 -0
  253. package/dist/runs/foreground/saved-revival.js +251 -0
  254. package/dist/runs/foreground/subagent-executor.js +135 -424
  255. package/dist/runs/foreground/subagent-params.js +67 -30
  256. package/dist/runs/foreground/wait-observation.js +104 -0
  257. package/dist/runs/foreground/wait-registration.js +17 -0
  258. package/dist/runs/foreground/wait-run.js +283 -123
  259. package/dist/runs/shared/acceptance-contract.js +193 -99
  260. package/dist/runs/shared/acceptance-defaults.js +1 -0
  261. package/dist/runs/shared/acceptance-evaluation.js +201 -181
  262. package/dist/runs/shared/acceptance-finalization.js +256 -180
  263. package/dist/runs/shared/acceptance-outcome.js +53 -0
  264. package/dist/runs/shared/acceptance-reports.js +137 -72
  265. package/dist/runs/shared/acceptance-submission.js +167 -0
  266. package/dist/runs/shared/acceptance-verification.js +100 -0
  267. package/dist/runs/shared/chain-outputs.js +80 -52
  268. package/dist/runs/shared/child-attempt-types.js +1 -0
  269. package/dist/runs/shared/child-attempt.js +314 -667
  270. package/dist/runs/shared/child-boundaries.js +173 -0
  271. package/dist/runs/shared/child-context-filter.js +44 -0
  272. package/dist/runs/shared/child-event-observer.js +390 -0
  273. package/dist/runs/shared/child-execution-cwd.js +73 -43
  274. package/dist/runs/shared/child-execution-outcome.js +72 -0
  275. package/dist/runs/shared/child-invocation.js +54 -0
  276. package/dist/runs/shared/child-message-validation.js +215 -0
  277. package/dist/runs/shared/child-native-accounting.js +106 -0
  278. package/dist/runs/shared/child-native-observation.js +69 -0
  279. package/dist/runs/shared/child-observation-spool.js +164 -0
  280. package/dist/runs/shared/child-observations.js +157 -76
  281. package/dist/runs/shared/child-presence.js +3 -0
  282. package/dist/runs/shared/child-route-env.js +119 -0
  283. package/dist/runs/shared/child-stream-observer.js +221 -0
  284. package/dist/runs/shared/child-stream-projection.js +137 -0
  285. package/dist/runs/shared/child-structured-tool.js +27 -0
  286. package/dist/runs/shared/claude-code.js +121 -158
  287. package/dist/runs/shared/claude-model.js +42 -0
  288. package/dist/runs/shared/claude-session.js +83 -0
  289. package/dist/runs/shared/claude-types.js +1 -0
  290. package/dist/runs/shared/completion-guard.js +18 -18
  291. package/dist/runs/shared/control-event-policy.js +8 -0
  292. package/dist/runs/shared/control-notification-owner.js +13 -0
  293. package/dist/runs/shared/dynamic-fanout.js +188 -173
  294. package/dist/runs/shared/dynamic-item.js +102 -0
  295. package/dist/runs/shared/history-index.js +62 -36
  296. package/dist/runs/shared/legacy-async-recovery.js +114 -0
  297. package/dist/runs/shared/legacy-output-recovery.js +148 -0
  298. package/dist/runs/shared/mcp-config-schema.js +36 -0
  299. package/dist/runs/shared/mcp-direct-tool-allowlist.js +147 -116
  300. package/dist/runs/shared/model-fallback.js +97 -38
  301. package/dist/runs/shared/mutating-tool-guard.js +128 -88
  302. package/dist/runs/shared/native-finalization-types.js +1 -0
  303. package/dist/runs/shared/native-finalization.js +155 -76
  304. package/dist/runs/shared/native-usage.js +238 -98
  305. package/dist/runs/shared/nested-control-records.js +128 -0
  306. package/dist/runs/shared/nested-events.js +8 -700
  307. package/dist/runs/shared/nested-path.js +32 -28
  308. package/dist/runs/shared/nested-projection.js +155 -0
  309. package/dist/runs/shared/nested-protocol.js +18 -0
  310. package/dist/runs/shared/nested-registry.js +191 -0
  311. package/dist/runs/shared/nested-render.js +106 -58
  312. package/dist/runs/shared/nested-route.js +220 -0
  313. package/dist/runs/shared/nested-validation.js +216 -0
  314. package/dist/runs/shared/owned-child-evidence.js +125 -0
  315. package/dist/runs/shared/owned-run-list.js +146 -0
  316. package/dist/runs/shared/owned-run-observation.js +267 -0
  317. package/dist/runs/shared/owned-run-progress.js +109 -0
  318. package/dist/runs/shared/owned-run-read-state.js +1 -0
  319. package/dist/runs/shared/owned-run-results.js +202 -0
  320. package/dist/runs/shared/owned-run-status.js +180 -0
  321. package/dist/runs/shared/owned-run-view.js +51 -0
  322. package/dist/runs/shared/owned-workflow-details.js +17 -0
  323. package/dist/runs/shared/owner-output.js +43 -0
  324. package/dist/runs/shared/parallel-utils.js +36 -28
  325. package/dist/runs/shared/parent-receipts.js +90 -32
  326. package/dist/runs/shared/parent-usage.js +169 -57
  327. package/dist/runs/shared/pi-args.js +108 -201
  328. package/dist/runs/shared/pi-launch-input.js +1 -0
  329. package/dist/runs/shared/pi-session-launch.js +86 -0
  330. package/dist/runs/shared/pi-spawn.js +35 -21
  331. package/dist/runs/shared/run-history-queries.js +126 -35
  332. package/dist/runs/shared/run-history.js +101 -35
  333. package/dist/runs/shared/run-metadata-paths.js +14 -0
  334. package/dist/runs/shared/run-metadata.js +158 -0
  335. package/dist/runs/shared/run-persistence.js +131 -0
  336. package/dist/runs/shared/run-records.js +9 -679
  337. package/dist/runs/shared/run-restoration.js +338 -0
  338. package/dist/runs/shared/run-state-owner.js +26 -0
  339. package/dist/runs/shared/session-cwd-preload.js +27 -18
  340. package/dist/runs/shared/single-output.js +148 -70
  341. package/dist/runs/shared/stable-value.js +15 -0
  342. package/dist/runs/shared/streaming-text.js +23 -12
  343. package/dist/runs/shared/structured-output.js +25 -13
  344. package/dist/runs/shared/subagent-control.js +167 -100
  345. package/dist/runs/shared/subagent-prompt-runtime.js +27 -130
  346. package/dist/runs/shared/subagent-tool-loop-guard.js +81 -52
  347. package/dist/runs/shared/supervisor-question-state.js +145 -0
  348. package/dist/runs/shared/supervisor-questions.js +185 -254
  349. package/dist/runs/shared/workflow-graph.js +259 -167
  350. package/dist/runs/shared/workflow-policy.js +120 -48
  351. package/dist/runs/shared/worktree-contract.js +1 -0
  352. package/dist/runs/shared/worktree-hook.js +138 -0
  353. package/dist/runs/shared/worktree-location.js +47 -0
  354. package/dist/runs/shared/worktree-preservation.js +8 -0
  355. package/dist/runs/shared/worktree-process.js +107 -0
  356. package/dist/runs/shared/worktree.js +183 -322
  357. package/dist/shared/agent-context-policy.js +34 -44
  358. package/dist/shared/agent-dir.js +14 -0
  359. package/dist/shared/artifacts.js +30 -12
  360. package/dist/shared/atomic-json.js +4 -1
  361. package/dist/shared/chain-files.js +72 -0
  362. package/dist/shared/concurrency.js +18 -0
  363. package/dist/shared/content-preview.js +115 -0
  364. package/dist/shared/cooperative.js +5 -2
  365. package/dist/shared/execution-cwd.js +13 -5
  366. package/dist/shared/file-coalescer.js +2 -1
  367. package/dist/shared/fork-context.js +10 -12
  368. package/dist/shared/formatters.js +45 -19
  369. package/dist/shared/journal-frames.js +164 -0
  370. package/dist/shared/journal-projections.js +121 -0
  371. package/dist/shared/journal-reader.js +6 -407
  372. package/dist/shared/json-projection.js +191 -0
  373. package/dist/shared/lazy-tools.js +19 -8
  374. package/dist/shared/message-output.js +116 -0
  375. package/dist/shared/model-info.js +31 -14
  376. package/dist/shared/native-import.js +20 -0
  377. package/dist/shared/native-journal.js +140 -0
  378. package/dist/shared/native-session-loader.js +17 -0
  379. package/dist/shared/native-session.js +2 -13
  380. package/dist/shared/native-tui.js +7 -2
  381. package/dist/shared/native-typebox.js +15 -3
  382. package/dist/shared/output-page.js +63 -0
  383. package/dist/shared/post-exit-stdio-guard.js +128 -88
  384. package/dist/shared/prompt-sections.js +2 -0
  385. package/dist/shared/session-entries.js +70 -35
  386. package/dist/shared/session-identity.js +5 -3
  387. package/dist/shared/settings.js +62 -192
  388. package/dist/shared/status-format.js +97 -37
  389. package/dist/shared/task-file-policy.js +24 -0
  390. package/dist/shared/temp-root.js +44 -15
  391. package/dist/shared/types/acceptance.js +1 -0
  392. package/dist/shared/types/async.js +1 -0
  393. package/dist/shared/types/config.js +1 -0
  394. package/dist/shared/types/details.js +1 -0
  395. package/dist/shared/types/history.js +1 -0
  396. package/dist/shared/types/inputs.js +1 -0
  397. package/dist/shared/types/intercom.js +1 -0
  398. package/dist/shared/types/launch.js +1 -0
  399. package/dist/shared/types/messages.js +1 -0
  400. package/dist/shared/types/nested.js +1 -0
  401. package/dist/shared/types/owned-runs.js +1 -0
  402. package/dist/shared/types/progress.js +1 -0
  403. package/dist/shared/types/questions.js +1 -0
  404. package/dist/shared/types/results.js +1 -0
  405. package/dist/shared/types/state.js +1 -0
  406. package/dist/shared/types/usage.js +1 -0
  407. package/dist/shared/types/workflow.js +1 -0
  408. package/dist/shared/types.js +75 -30
  409. package/dist/shared/unknown.js +52 -0
  410. package/dist/shared/utils.js +54 -260
  411. package/dist/slash/command-discovery.js +82 -0
  412. package/dist/slash/command-input.js +190 -0
  413. package/dist/slash/prompt-template-bridge.js +94 -270
  414. package/dist/slash/prompt-template-contract.js +77 -0
  415. package/dist/slash/prompt-template-results.js +125 -0
  416. package/dist/slash/request-protocol.js +68 -0
  417. package/dist/slash/result-delivery.js +237 -0
  418. package/dist/slash/saved-chain.js +78 -0
  419. package/dist/slash/slash-bridge.js +123 -89
  420. package/dist/slash/slash-commands.js +101 -572
  421. package/dist/slash/slash-live-state.js +68 -47
  422. package/dist/tui/action-hints.js +50 -22
  423. package/dist/tui/activity-lines.js +32 -0
  424. package/dist/tui/agent-browser.js +290 -0
  425. package/dist/tui/agent-controls.js +289 -0
  426. package/dist/tui/agent-conversation.js +444 -0
  427. package/dist/tui/agent-dock.js +171 -0
  428. package/dist/tui/agent-history.js +50 -183
  429. package/dist/tui/agent-model.js +62 -0
  430. package/dist/tui/agent-picker.js +262 -0
  431. package/dist/tui/agent-view.js +232 -1564
  432. package/dist/tui/compact-results.js +193 -0
  433. package/dist/tui/conversation-details.js +190 -0
  434. package/dist/tui/conversation-frame.js +135 -0
  435. package/dist/tui/conversation-history.js +201 -0
  436. package/dist/tui/conversation-menu.js +78 -0
  437. package/dist/tui/conversation-notices.js +79 -0
  438. package/dist/tui/conversation-selection.js +58 -0
  439. package/dist/tui/conversation-viewport.js +129 -0
  440. package/dist/tui/direction-message.js +27 -0
  441. package/dist/tui/display.js +282 -0
  442. package/dist/tui/editor-viewport.js +18 -0
  443. package/dist/tui/expanded-content.js +87 -0
  444. package/dist/tui/expanded-multi.js +170 -0
  445. package/dist/tui/expanded-single.js +65 -0
  446. package/dist/tui/history-cards.js +216 -0
  447. package/dist/tui/history-display.js +238 -0
  448. package/dist/tui/history-json.js +16 -0
  449. package/dist/tui/history-metadata.js +152 -0
  450. package/dist/tui/history-record.js +251 -0
  451. package/dist/tui/history-text.js +34 -0
  452. package/dist/tui/indexed-history.js +116 -0
  453. package/dist/tui/nested-widget.js +120 -0
  454. package/dist/tui/picker-page.js +59 -0
  455. package/dist/tui/render.js +58 -1501
  456. package/dist/tui/result-facts.js +64 -0
  457. package/dist/tui/task-observation.js +59 -0
  458. package/dist/tui/task-store.js +366 -0
  459. package/dist/tui/text-values.js +16 -0
  460. package/dist/tui/view-connections.js +47 -0
  461. package/dist/tui/view-model.js +94 -0
  462. package/dist/tui/view-persistence.js +51 -0
  463. package/dist/tui/view-ports.js +1 -0
  464. package/dist/tui/view-session.js +37 -0
  465. package/dist/tui/widget-details.js +144 -0
  466. package/dist/tui/widget-status.js +245 -0
  467. package/dist/tui/widget.js +145 -0
  468. package/dist/tui/workflow-labels.js +223 -0
  469. package/dist/tui/workflow-outcomes.js +124 -0
  470. package/docs/code-quality.md +38 -0
  471. package/docs/development.md +99 -0
  472. package/docs/intercom-bridge.md +77 -22
  473. package/docs/intercom.md +132 -106
  474. package/docs/performance.md +19 -17
  475. package/docs/reference.md +1472 -0
  476. package/generated/RunValidators.d.ts +28 -0
  477. package/generated/RunValidators.js +2 -0
  478. package/package.json +27 -6
  479. package/prompts/parallel-cleanup.md +3 -0
  480. package/prompts/parallel-context-build.md +3 -0
  481. package/prompts/parallel-handoff-plan.md +6 -0
  482. package/prompts/parallel-research.md +4 -0
  483. package/prompts/parallel-review.md +2 -0
  484. package/prompts/review-loop.md +2 -0
  485. package/scripts/build.mjs +129 -85
  486. package/scripts/check-compat.mjs +48 -11
  487. package/scripts/compat-host.mjs +35 -7
  488. package/scripts/generate-run-schemas.mjs +210 -0
  489. package/scripts/intercom-bridge-credentials.mjs +158 -29
  490. package/scripts/intercom-remote.mjs +213 -52
  491. package/scripts/local-install-smoke.mjs +47 -37
  492. package/scripts/native-package-smoke.mjs +135 -25
  493. package/scripts/package-smoke.mjs +360 -140
  494. package/scripts/prepare.mjs +54 -34
  495. package/scripts/real-pi-processes.mjs +261 -0
  496. package/scripts/real-pi-smoke.mjs +432 -351
  497. package/scripts/run-tests.mjs +29 -15
  498. package/skills/pi-intercom/SKILL.md +11 -11
  499. package/skills/pi-intercom/references/peer-sessions.md +7 -2
  500. package/skills/pi-subagents/SKILL.md +1 -1
  501. package/skills/pi-subagents/references/full-orchestration-guide.md +254 -112
  502. package/src/agents/agent-defaults.ts +13 -0
  503. package/src/agents/agent-definition.ts +253 -0
  504. package/src/agents/agent-management.ts +111 -808
  505. package/src/agents/agent-scope.ts +7 -3
  506. package/src/agents/agent-selection.ts +26 -16
  507. package/src/agents/agent-serializer.ts +84 -93
  508. package/src/agents/agents.ts +199 -906
  509. package/src/agents/builtin-overrides.ts +297 -0
  510. package/src/agents/chain-serializer.ts +3 -329
  511. package/src/agents/config-values.ts +57 -0
  512. package/src/agents/discovery-paths.ts +134 -0
  513. package/src/agents/frontmatter.ts +35 -17
  514. package/src/agents/identity.ts +49 -18
  515. package/src/agents/json-chain.ts +305 -0
  516. package/src/agents/management-config.ts +342 -0
  517. package/src/agents/management-format.ts +243 -0
  518. package/src/agents/management-persistence.ts +408 -0
  519. package/src/agents/management-targets.ts +260 -0
  520. package/src/agents/management-warnings.ts +115 -0
  521. package/src/agents/markdown-chain.ts +237 -0
  522. package/src/agents/package-agents.ts +231 -0
  523. package/src/agents/skill-files.ts +182 -0
  524. package/src/agents/skill-search-paths.ts +289 -0
  525. package/src/agents/skill-types.ts +31 -0
  526. package/src/agents/skills.ts +152 -610
  527. package/src/extension/acceptance-schema.ts +88 -0
  528. package/src/extension/chain-schema.ts +276 -0
  529. package/src/extension/child-runtime.ts +302 -0
  530. package/src/extension/compact-tools.ts +259 -102
  531. package/src/extension/config-schema.ts +59 -0
  532. package/src/extension/config.ts +39 -17
  533. package/src/extension/control-notice-schema.ts +55 -0
  534. package/src/extension/control-notices.ts +57 -33
  535. package/src/extension/delegation-bridges.ts +59 -0
  536. package/src/extension/doctor.ts +171 -135
  537. package/src/extension/everyday-schemas.ts +252 -0
  538. package/src/extension/fanout-child.ts +29 -308
  539. package/src/extension/index.ts +17 -642
  540. package/src/extension/message-renderers.ts +334 -0
  541. package/src/extension/nested-control-inbox.ts +196 -0
  542. package/src/extension/parent-runtime.ts +405 -0
  543. package/src/extension/primary-tool.ts +130 -0
  544. package/src/extension/result-snapshot.ts +35 -0
  545. package/src/extension/runtime-reload.ts +72 -0
  546. package/src/extension/runtime-storage.ts +49 -0
  547. package/src/extension/schema-overrides.ts +114 -0
  548. package/src/extension/schemas.ts +451 -418
  549. package/src/extension/tool-input.ts +40 -13
  550. package/src/extension/tool-result.ts +45 -14
  551. package/src/history/answer-texts.ts +74 -0
  552. package/src/history/canonical-result.ts +127 -51
  553. package/src/history/canonical-selection.ts +54 -0
  554. package/src/history/database-generation.ts +86 -0
  555. package/src/history/database.ts +86 -48
  556. package/src/history/entry-ingestion.ts +129 -0
  557. package/src/history/index.ts +426 -148
  558. package/src/history/ingest.ts +372 -342
  559. package/src/history/output-digests.ts +41 -0
  560. package/src/history/preview.ts +235 -0
  561. package/src/history/prune.ts +48 -0
  562. package/src/history/queries.ts +122 -256
  563. package/src/history/query-scope.ts +278 -0
  564. package/src/history/rows.ts +118 -0
  565. package/src/history/run-projection.ts +164 -0
  566. package/src/history/run-queries.ts +199 -0
  567. package/src/history/schema.ts +34 -0
  568. package/src/history/search-queries.ts +216 -0
  569. package/src/history/selected-record.ts +140 -0
  570. package/src/history/source-file.ts +51 -0
  571. package/src/history/source-watches.ts +156 -0
  572. package/src/history/store.ts +310 -197
  573. package/src/history/text-chunks.ts +181 -0
  574. package/src/history/text.ts +43 -0
  575. package/src/history/transcript-queries.ts +251 -0
  576. package/src/history/types.ts +27 -164
  577. package/src/history/values.ts +36 -0
  578. package/src/history/wire-inputs.ts +141 -0
  579. package/src/history/wire-models.ts +51 -0
  580. package/src/history/worker-runtime.ts +502 -0
  581. package/src/history/worker.ts +94 -336
  582. package/src/intercom/intercom-bridge.ts +136 -69
  583. package/src/intercom/live-intercom.ts +197 -92
  584. package/src/intercom/nested-result-tree.ts +213 -0
  585. package/src/intercom/result-delivery.ts +56 -0
  586. package/src/intercom/result-intercom.ts +364 -382
  587. package/src/pi-intercom/agent-dir.ts +9 -3
  588. package/src/pi-intercom/async.ts +33 -0
  589. package/src/pi-intercom/bridge-ask.ts +64 -0
  590. package/src/pi-intercom/bridge-config.ts +120 -0
  591. package/src/pi-intercom/bridge-http.ts +97 -0
  592. package/src/pi-intercom/bridge-launch-policy.ts +109 -0
  593. package/src/pi-intercom/bridge-launch.ts +317 -0
  594. package/src/pi-intercom/bridge-protocol.ts +123 -0
  595. package/src/pi-intercom/bridge-routes.ts +105 -0
  596. package/src/pi-intercom/bridge-rpc-process.ts +293 -0
  597. package/src/pi-intercom/bridge-session.ts +510 -0
  598. package/src/pi-intercom/bridge.ts +305 -549
  599. package/src/pi-intercom/broker/broker.ts +326 -263
  600. package/src/pi-intercom/broker/client.ts +273 -354
  601. package/src/pi-intercom/broker/connection.ts +192 -0
  602. package/src/pi-intercom/broker/framing.ts +11 -6
  603. package/src/pi-intercom/broker/paths.ts +28 -25
  604. package/src/pi-intercom/broker/pid.ts +68 -24
  605. package/src/pi-intercom/broker/snapshot-reader.ts +91 -0
  606. package/src/pi-intercom/broker/snapshots.ts +241 -0
  607. package/src/pi-intercom/broker/spawn.ts +58 -34
  608. package/src/pi-intercom/config.ts +113 -108
  609. package/src/pi-intercom/connection.ts +346 -0
  610. package/src/pi-intercom/identity.ts +71 -0
  611. package/src/pi-intercom/inbound-delivery.ts +450 -0
  612. package/src/pi-intercom/inbound-journal.ts +350 -0
  613. package/src/pi-intercom/inbound-record.ts +141 -0
  614. package/src/pi-intercom/inbound.ts +237 -0
  615. package/src/pi-intercom/index.ts +86 -2923
  616. package/src/pi-intercom/inspection.ts +82 -0
  617. package/src/pi-intercom/interview.ts +295 -0
  618. package/src/pi-intercom/lifecycle.ts +183 -0
  619. package/src/pi-intercom/message-format.ts +77 -0
  620. package/src/pi-intercom/outbound.ts +418 -0
  621. package/src/pi-intercom/peer-awareness.ts +84 -0
  622. package/src/pi-intercom/reply-tracker.ts +121 -59
  623. package/src/pi-intercom/reply-wait.ts +247 -0
  624. package/src/pi-intercom/runtime-types.ts +97 -0
  625. package/src/pi-intercom/session-events.ts +247 -0
  626. package/src/pi-intercom/session-targets.ts +124 -72
  627. package/src/pi-intercom/subagent-events.ts +299 -0
  628. package/src/pi-intercom/subagent-live-events.ts +212 -109
  629. package/src/pi-intercom/supervisor.ts +362 -0
  630. package/src/pi-intercom/tool-arguments.ts +120 -0
  631. package/src/pi-intercom/tool-registration.ts +121 -0
  632. package/src/pi-intercom/tool-results.ts +54 -0
  633. package/src/pi-intercom/tool-schemas.ts +134 -0
  634. package/src/pi-intercom/tools.ts +80 -0
  635. package/src/pi-intercom/topic-actions.ts +243 -0
  636. package/src/pi-intercom/topics.ts +267 -121
  637. package/src/pi-intercom/transport.ts +14 -0
  638. package/src/pi-intercom/types.ts +288 -190
  639. package/src/pi-intercom/ui/compose-paste.ts +109 -0
  640. package/src/pi-intercom/ui/compose.ts +173 -157
  641. package/src/pi-intercom/ui/inline-message.ts +80 -62
  642. package/src/pi-intercom/ui/message-renderers.ts +182 -0
  643. package/src/pi-intercom/ui/overlay.ts +238 -0
  644. package/src/pi-intercom/ui/session-format.ts +146 -0
  645. package/src/pi-intercom/ui/session-list.ts +145 -62
  646. package/src/pi-intercom/ui/tool-renderers.ts +148 -0
  647. package/src/pi-intercom/ui/topic-view.ts +107 -0
  648. package/src/pi-intercom/validation.ts +69 -0
  649. package/src/runs/background/async-chain-plan.ts +451 -0
  650. package/src/runs/background/async-control.ts +201 -71
  651. package/src/runs/background/async-execution.ts +206 -829
  652. package/src/runs/background/async-job-admission.ts +54 -0
  653. package/src/runs/background/async-job-projection.ts +225 -0
  654. package/src/runs/background/async-job-tracker.ts +416 -360
  655. package/src/runs/background/async-launch.ts +319 -0
  656. package/src/runs/background/async-plan.ts +285 -0
  657. package/src/runs/background/async-result-file.ts +79 -37
  658. package/src/runs/background/async-resume.ts +338 -285
  659. package/src/runs/background/async-run-discovery.ts +270 -0
  660. package/src/runs/background/async-run-location.ts +194 -0
  661. package/src/runs/background/async-run-record.ts +14 -0
  662. package/src/runs/background/async-run-repair.ts +307 -0
  663. package/src/runs/background/async-run-summary.ts +71 -0
  664. package/src/runs/background/async-single-plan.ts +168 -0
  665. package/src/runs/background/async-status-projection.ts +188 -0
  666. package/src/runs/background/async-status-render.ts +164 -0
  667. package/src/runs/background/async-status-validation.ts +238 -0
  668. package/src/runs/background/async-status.ts +9 -481
  669. package/src/runs/background/async-value.ts +29 -0
  670. package/src/runs/background/completion-dedupe.ts +103 -54
  671. package/src/runs/background/completion-delivery.ts +313 -187
  672. package/src/runs/background/completion-receipts.ts +309 -0
  673. package/src/runs/background/legacy-status-acceptance.ts +38 -0
  674. package/src/runs/background/notify.ts +167 -106
  675. package/src/runs/background/parallel-groups.ts +95 -46
  676. package/src/runs/background/result-payload.ts +268 -0
  677. package/src/runs/background/result-watcher.ts +484 -387
  678. package/src/runs/background/run-id-resolver.ts +126 -57
  679. package/src/runs/background/run-schemas.ts +240 -0
  680. package/src/runs/background/run-status-contracts.ts +46 -0
  681. package/src/runs/background/run-status-render.ts +364 -0
  682. package/src/runs/background/run-status.ts +338 -356
  683. package/src/runs/background/runner-attempt-output.ts +281 -0
  684. package/src/runs/background/runner-attempt.ts +354 -0
  685. package/src/runs/background/runner-child-executor.ts +232 -0
  686. package/src/runs/background/runner-child-observer.ts +270 -0
  687. package/src/runs/background/runner-completion-summary.ts +106 -0
  688. package/src/runs/background/runner-completion.ts +274 -0
  689. package/src/runs/background/runner-config.ts +52 -0
  690. package/src/runs/background/runner-contract.ts +51 -0
  691. package/src/runs/background/runner-dynamic.ts +185 -0
  692. package/src/runs/background/runner-finalization.ts +203 -0
  693. package/src/runs/background/runner-graph.ts +91 -0
  694. package/src/runs/background/runner-initial-status.ts +72 -0
  695. package/src/runs/background/runner-lifecycle.ts +159 -0
  696. package/src/runs/background/runner-monitor.ts +399 -0
  697. package/src/runs/background/runner-parallel.ts +280 -0
  698. package/src/runs/background/runner-prepare-step.ts +128 -0
  699. package/src/runs/background/runner-reporting.ts +192 -0
  700. package/src/runs/background/runner-status.ts +220 -0
  701. package/src/runs/background/runner-step-output.ts +158 -0
  702. package/src/runs/background/runner-step-record.ts +76 -0
  703. package/src/runs/background/runner-step.ts +150 -0
  704. package/src/runs/background/runner-streaming.ts +220 -0
  705. package/src/runs/background/runner-workflow.ts +284 -0
  706. package/src/runs/background/stale-run-reconciler.ts +279 -336
  707. package/src/runs/background/subagent-runner-launcher.ts +67 -35
  708. package/src/runs/background/subagent-runner.ts +80 -2048
  709. package/src/runs/background/top-level-async.ts +9 -7
  710. package/src/runs/foreground/chain-clarify.ts +499 -1334
  711. package/src/runs/foreground/clarification-draft.ts +92 -0
  712. package/src/runs/foreground/clarify-contracts.ts +33 -0
  713. package/src/runs/foreground/clarify-invocation.ts +192 -65
  714. package/src/runs/foreground/clarify-text-editor.ts +229 -0
  715. package/src/runs/foreground/clarify-view.ts +222 -0
  716. package/src/runs/foreground/execution-input.ts +358 -424
  717. package/src/runs/foreground/execution-routing.ts +41 -0
  718. package/src/runs/foreground/execution-timeout.ts +92 -0
  719. package/src/runs/foreground/foreground-control.ts +333 -812
  720. package/src/runs/foreground/foreground-memory.ts +132 -0
  721. package/src/runs/foreground/invocation-context.ts +88 -0
  722. package/src/runs/foreground/invocation-execution.ts +465 -0
  723. package/src/runs/foreground/invocation-expansion.ts +58 -0
  724. package/src/runs/foreground/management-actions.ts +360 -0
  725. package/src/runs/foreground/nested-control.ts +248 -0
  726. package/src/runs/foreground/question-continuation.ts +112 -0
  727. package/src/runs/foreground/question-control.ts +297 -70
  728. package/src/runs/foreground/resume-target.ts +330 -0
  729. package/src/runs/foreground/revival-launch-policy.ts +112 -0
  730. package/src/runs/foreground/run-async-path.ts +307 -223
  731. package/src/runs/foreground/run-interrupt.ts +202 -0
  732. package/src/runs/foreground/run-nudge.ts +355 -0
  733. package/src/runs/foreground/saved-revival.ts +356 -0
  734. package/src/runs/foreground/subagent-executor.ts +195 -493
  735. package/src/runs/foreground/subagent-params.ts +314 -242
  736. package/src/runs/foreground/wait-observation.ts +160 -0
  737. package/src/runs/foreground/wait-registration.ts +18 -0
  738. package/src/runs/foreground/wait-run.ts +361 -119
  739. package/src/runs/shared/acceptance-contract.ts +410 -209
  740. package/src/runs/shared/acceptance-defaults.ts +1 -0
  741. package/src/runs/shared/acceptance-evaluation.ts +314 -240
  742. package/src/runs/shared/acceptance-finalization.ts +447 -305
  743. package/src/runs/shared/acceptance-outcome.ts +69 -0
  744. package/src/runs/shared/acceptance-reports.ts +220 -126
  745. package/src/runs/shared/acceptance-submission.ts +251 -0
  746. package/src/runs/shared/acceptance-verification.ts +118 -0
  747. package/src/runs/shared/acceptance.ts +25 -25
  748. package/src/runs/shared/chain-outputs.ts +190 -98
  749. package/src/runs/shared/child-attempt-types.ts +118 -0
  750. package/src/runs/shared/child-attempt.ts +372 -608
  751. package/src/runs/shared/child-boundaries.ts +217 -0
  752. package/src/runs/shared/child-context-filter.ts +53 -0
  753. package/src/runs/shared/child-event-observer.ts +496 -0
  754. package/src/runs/shared/child-execution-cwd.ts +139 -68
  755. package/src/runs/shared/child-execution-outcome.ts +103 -0
  756. package/src/runs/shared/child-invocation.ts +74 -0
  757. package/src/runs/shared/child-message-validation.ts +233 -0
  758. package/src/runs/shared/child-native-accounting.ts +154 -0
  759. package/src/runs/shared/child-native-observation.ts +79 -0
  760. package/src/runs/shared/child-observation-spool.ts +188 -0
  761. package/src/runs/shared/child-observations.ts +219 -89
  762. package/src/runs/shared/child-presence.ts +6 -0
  763. package/src/runs/shared/child-route-env.ts +142 -0
  764. package/src/runs/shared/child-stream-observer.ts +302 -0
  765. package/src/runs/shared/child-stream-projection.ts +160 -0
  766. package/src/runs/shared/child-structured-tool.ts +38 -0
  767. package/src/runs/shared/claude-code.ts +201 -228
  768. package/src/runs/shared/claude-model.ts +67 -0
  769. package/src/runs/shared/claude-session.ts +124 -0
  770. package/src/runs/shared/claude-types.ts +31 -0
  771. package/src/runs/shared/completion-guard.ts +35 -26
  772. package/src/runs/shared/control-event-policy.ts +15 -0
  773. package/src/runs/shared/control-notification-owner.ts +20 -0
  774. package/src/runs/shared/dynamic-fanout.ts +402 -238
  775. package/src/runs/shared/dynamic-item.ts +114 -0
  776. package/src/runs/shared/history-index.ts +112 -51
  777. package/src/runs/shared/legacy-async-recovery.ts +153 -0
  778. package/src/runs/shared/legacy-output-recovery.ts +214 -0
  779. package/src/runs/shared/mcp-config-schema.ts +46 -0
  780. package/src/runs/shared/mcp-direct-tool-allowlist.ts +396 -307
  781. package/src/runs/shared/model-fallback.ts +302 -180
  782. package/src/runs/shared/mutating-tool-guard.ts +259 -158
  783. package/src/runs/shared/native-finalization-types.ts +29 -0
  784. package/src/runs/shared/native-finalization.ts +233 -109
  785. package/src/runs/shared/native-usage.ts +379 -96
  786. package/src/runs/shared/nested-control-records.ts +178 -0
  787. package/src/runs/shared/nested-events.ts +45 -752
  788. package/src/runs/shared/nested-path.ts +47 -34
  789. package/src/runs/shared/nested-projection.ts +230 -0
  790. package/src/runs/shared/nested-protocol.ts +67 -0
  791. package/src/runs/shared/nested-registry.ts +273 -0
  792. package/src/runs/shared/nested-render.ts +198 -100
  793. package/src/runs/shared/nested-route.ts +292 -0
  794. package/src/runs/shared/nested-validation.ts +291 -0
  795. package/src/runs/shared/owned-child-evidence.ts +184 -0
  796. package/src/runs/shared/owned-run-list.ts +187 -0
  797. package/src/runs/shared/owned-run-observation.ts +368 -0
  798. package/src/runs/shared/owned-run-progress.ts +172 -0
  799. package/src/runs/shared/owned-run-read-state.ts +7 -0
  800. package/src/runs/shared/owned-run-results.ts +289 -0
  801. package/src/runs/shared/owned-run-status.ts +239 -0
  802. package/src/runs/shared/owned-run-view.ts +65 -0
  803. package/src/runs/shared/owned-workflow-details.ts +24 -0
  804. package/src/runs/shared/owner-output.ts +73 -0
  805. package/src/runs/shared/parallel-utils.ts +93 -129
  806. package/src/runs/shared/parent-receipts.ts +177 -50
  807. package/src/runs/shared/parent-usage.ts +314 -91
  808. package/src/runs/shared/pi-args.ts +241 -311
  809. package/src/runs/shared/pi-launch-input.ts +48 -0
  810. package/src/runs/shared/pi-session-launch.ts +94 -0
  811. package/src/runs/shared/pi-spawn.ts +57 -33
  812. package/src/runs/shared/run-history-queries.ts +189 -38
  813. package/src/runs/shared/run-history.ts +197 -76
  814. package/src/runs/shared/run-id-ambiguity.ts +7 -3
  815. package/src/runs/shared/run-metadata-paths.ts +17 -0
  816. package/src/runs/shared/run-metadata.ts +240 -0
  817. package/src/runs/shared/run-persistence.ts +181 -0
  818. package/src/runs/shared/run-records.ts +19 -607
  819. package/src/runs/shared/run-restoration.ts +455 -0
  820. package/src/runs/shared/run-state-owner.ts +31 -0
  821. package/src/runs/shared/session-cwd-preload.ts +39 -19
  822. package/src/runs/shared/single-output.ts +358 -205
  823. package/src/runs/shared/stable-value.ts +15 -0
  824. package/src/runs/shared/streaming-text.ts +39 -12
  825. package/src/runs/shared/structured-output.ts +76 -46
  826. package/src/runs/shared/subagent-control.ts +330 -197
  827. package/src/runs/shared/subagent-prompt-runtime.ts +92 -174
  828. package/src/runs/shared/subagent-tool-loop-guard.ts +118 -68
  829. package/src/runs/shared/supervisor-question-state.ts +221 -0
  830. package/src/runs/shared/supervisor-questions.ts +396 -401
  831. package/src/runs/shared/workflow-graph.ts +400 -198
  832. package/src/runs/shared/workflow-policy.ts +245 -110
  833. package/src/runs/shared/worktree-contract.ts +29 -0
  834. package/src/runs/shared/worktree-hook.ts +181 -0
  835. package/src/runs/shared/worktree-location.ts +61 -0
  836. package/src/runs/shared/worktree-preservation.ts +10 -0
  837. package/src/runs/shared/worktree-process.ts +132 -0
  838. package/src/runs/shared/worktree.ts +459 -587
  839. package/src/shared/agent-context-policy.ts +176 -145
  840. package/src/shared/agent-dir.ts +15 -0
  841. package/src/shared/artifacts.ts +99 -68
  842. package/src/shared/atomic-json.ts +14 -11
  843. package/src/shared/chain-files.ts +72 -0
  844. package/src/shared/concurrency.ts +27 -0
  845. package/src/shared/content-preview.ts +117 -0
  846. package/src/shared/cooperative.ts +17 -13
  847. package/src/shared/execution-cwd.ts +34 -9
  848. package/src/shared/file-coalescer.ts +24 -22
  849. package/src/shared/fork-context.ts +52 -48
  850. package/src/shared/formatters.ts +88 -47
  851. package/src/shared/journal-frames.ts +197 -0
  852. package/src/shared/journal-projections.ts +133 -0
  853. package/src/shared/journal-reader.ts +18 -333
  854. package/src/shared/json-projection.ts +224 -0
  855. package/src/shared/lazy-tools.ts +76 -27
  856. package/src/shared/message-output.ts +146 -0
  857. package/src/shared/model-info.ts +94 -58
  858. package/src/shared/native-import.ts +25 -0
  859. package/src/shared/native-journal.ts +172 -0
  860. package/src/shared/native-session-loader.ts +13 -0
  861. package/src/shared/native-session.ts +3 -5
  862. package/src/shared/native-tui.ts +13 -3
  863. package/src/shared/native-typebox.ts +18 -3
  864. package/src/shared/output-page.ts +76 -0
  865. package/src/shared/post-exit-stdio-guard.ts +232 -172
  866. package/src/shared/prompt-sections.ts +13 -7
  867. package/src/shared/session-entries.ts +103 -44
  868. package/src/shared/session-identity.ts +17 -10
  869. package/src/shared/settings.ts +182 -367
  870. package/src/shared/status-format.ts +207 -98
  871. package/src/shared/stream-json.d.ts +10 -0
  872. package/src/shared/task-file-policy.ts +35 -0
  873. package/src/shared/temp-root.ts +122 -71
  874. package/src/shared/types/acceptance.ts +149 -0
  875. package/src/shared/types/async.ts +247 -0
  876. package/src/shared/types/config.ts +139 -0
  877. package/src/shared/types/details.ts +104 -0
  878. package/src/shared/types/history.ts +217 -0
  879. package/src/shared/types/inputs.ts +4 -0
  880. package/src/shared/types/intercom.ts +57 -0
  881. package/src/shared/types/launch.ts +39 -0
  882. package/src/shared/types/messages.ts +104 -0
  883. package/src/shared/types/nested.ts +153 -0
  884. package/src/shared/types/owned-runs.ts +148 -0
  885. package/src/shared/types/progress.ts +106 -0
  886. package/src/shared/types/questions.ts +103 -0
  887. package/src/shared/types/results.ts +119 -0
  888. package/src/shared/types/state.ts +56 -0
  889. package/src/shared/types/usage.ts +36 -0
  890. package/src/shared/types/workflow.ts +187 -0
  891. package/src/shared/types.ts +222 -1161
  892. package/src/shared/ui-mode.ts +1 -1
  893. package/src/shared/unknown.ts +59 -0
  894. package/src/shared/utils.ts +111 -305
  895. package/src/slash/command-discovery.ts +109 -0
  896. package/src/slash/command-input.ts +232 -0
  897. package/src/slash/prompt-template-bridge.ts +153 -400
  898. package/src/slash/prompt-template-contract.ts +152 -0
  899. package/src/slash/prompt-template-results.ts +189 -0
  900. package/src/slash/request-protocol.ts +87 -0
  901. package/src/slash/result-delivery.ts +312 -0
  902. package/src/slash/saved-chain.ts +115 -0
  903. package/src/slash/slash-bridge.ts +202 -156
  904. package/src/slash/slash-commands.ts +176 -598
  905. package/src/slash/slash-live-state.ts +287 -229
  906. package/src/tui/action-hints.ts +147 -61
  907. package/src/tui/activity-lines.ts +40 -0
  908. package/src/tui/agent-browser.ts +354 -0
  909. package/src/tui/agent-controls.ts +355 -0
  910. package/src/tui/agent-conversation.ts +514 -0
  911. package/src/tui/agent-dock.ts +250 -0
  912. package/src/tui/agent-history.ts +78 -203
  913. package/src/tui/agent-model.ts +78 -0
  914. package/src/tui/agent-picker.ts +325 -0
  915. package/src/tui/agent-view.ts +391 -1333
  916. package/src/tui/compact-results.ts +342 -0
  917. package/src/tui/conversation-details.ts +206 -0
  918. package/src/tui/conversation-frame.ts +184 -0
  919. package/src/tui/conversation-history.ts +246 -0
  920. package/src/tui/conversation-menu.ts +119 -0
  921. package/src/tui/conversation-notices.ts +116 -0
  922. package/src/tui/conversation-selection.ts +66 -0
  923. package/src/tui/conversation-viewport.ts +169 -0
  924. package/src/tui/direction-message.ts +35 -0
  925. package/src/tui/display.ts +409 -0
  926. package/src/tui/editor-viewport.ts +19 -0
  927. package/src/tui/expanded-content.ts +134 -0
  928. package/src/tui/expanded-multi.ts +264 -0
  929. package/src/tui/expanded-single.ts +92 -0
  930. package/src/tui/history-cards.ts +316 -0
  931. package/src/tui/history-display.ts +334 -0
  932. package/src/tui/history-json.ts +17 -0
  933. package/src/tui/history-metadata.ts +177 -0
  934. package/src/tui/history-record.ts +321 -0
  935. package/src/tui/history-text.ts +34 -0
  936. package/src/tui/indexed-history.ts +149 -0
  937. package/src/tui/nested-widget.ts +192 -0
  938. package/src/tui/picker-page.ts +80 -0
  939. package/src/tui/render.ts +100 -1546
  940. package/src/tui/result-facts.ts +99 -0
  941. package/src/tui/task-observation.ts +96 -0
  942. package/src/tui/task-store.ts +432 -0
  943. package/src/tui/text-values.ts +20 -0
  944. package/src/tui/view-connections.ts +64 -0
  945. package/src/tui/view-model.ts +181 -0
  946. package/src/tui/view-persistence.ts +57 -0
  947. package/src/tui/view-ports.ts +55 -0
  948. package/src/tui/view-session.ts +42 -0
  949. package/src/tui/widget-details.ts +220 -0
  950. package/src/tui/widget-status.ts +331 -0
  951. package/src/tui/widget.ts +208 -0
  952. package/src/tui/workflow-labels.ts +340 -0
  953. package/src/tui/workflow-outcomes.ts +150 -0
  954. package/tsconfig.build.json +11 -10
  955. package/tsconfig.json +30 -17
@@ -1,813 +1,116 @@
1
- import * as fs from "node:fs";
2
- import * as path from "node:path";
3
- import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
1
+ import { discoverAgents, discoverAgentsAll } from "./agents.ts";
2
+ import { formatAgentGroups, formatAgentDetail, formatChainDetail } from "./management-format.ts";
3
+ import { handleCreate, handleUpdate, handleDelete } from "./management-persistence.ts";
4
4
  import {
5
- type AgentConfig,
6
- type AgentScope,
7
- type AgentSource,
8
- type ChainConfig,
9
- type ChainStepConfig,
10
- defaultInheritProjectContext,
11
- defaultInheritSkills,
12
- defaultSystemPromptMode,
13
- discoverAgents,
14
- discoverAgentsAll,
15
- buildRuntimeName,
16
- frontmatterNameForConfig,
17
- parsePackageName,
18
- } from "./agents.ts";
19
- import { serializeAgent } from "./agent-serializer.ts";
20
- import { serializeChain, serializeJsonChain } from "./chain-serializer.ts";
21
- import { discoverAvailableSkills } from "./skills.ts";
22
- import { isClaudeCodeModel } from "../runs/shared/claude-code.ts";
5
+ result,
6
+ normalizeListScope,
7
+ discoveryOptions,
8
+ findEffectiveAgents,
9
+ findChains,
10
+ availableNamesText,
11
+ type ManagementContext,
12
+ type ManagementParams,
13
+ } from "./management-targets.ts";
14
+ import type { AgentScope } from "../shared/types/config.ts";
23
15
  import type { SubagentExecutionResult } from "../shared/types.ts";
24
- import { resolveEffectiveThinking } from "../shared/model-info.ts";
25
-
26
- type ManagementAction = "list" | "get" | "create" | "update" | "delete";
27
- type ManagementScope = "user" | "project";
28
- type ManagementContext = Pick<ExtensionContext, "cwd" | "modelRegistry" | "isProjectTrusted">;
29
-
30
- interface ManagementParams {
31
- action?: string;
32
- agent?: string;
33
- chainName?: string;
34
- agentScope?: string;
35
- config?: unknown;
36
- }
37
-
38
- function result(text: string, isError = false): SubagentExecutionResult {
39
- return { content: [{ type: "text", text }], isError, details: { mode: "management", results: [] } };
40
- }
41
-
42
- function parseCsv(value: string): string[] {
43
- return [...new Set(value.split(",").map((v) => v.trim()).filter(Boolean))];
44
- }
45
-
46
- function configObject(config: unknown): { value?: Record<string, unknown>; error?: string } {
47
- let val = config;
48
- if (typeof val === "string") {
49
- try {
50
- val = JSON.parse(val);
51
- } catch (error) {
52
- const message = error instanceof Error ? error.message : String(error);
53
- return { error: `config must be valid JSON: ${message}` };
54
- }
55
- }
56
- if (!val || typeof val !== "object" || Array.isArray(val)) return {};
57
- return { value: val as Record<string, unknown> };
58
- }
59
-
60
- function hasKey(obj: Record<string, unknown>, key: string): boolean {
61
- return Object.prototype.hasOwnProperty.call(obj, key);
62
- }
63
-
64
- function asDisambiguationScope(scope: unknown): ManagementScope | undefined {
65
- if (scope === "user" || scope === "project") return scope;
66
- return undefined;
67
- }
68
-
69
- function normalizeListScope(scope: unknown): AgentScope | undefined {
70
- if (scope === undefined) return "both";
71
- if (scope === "user" || scope === "project" || scope === "both") return scope;
72
- return undefined;
73
- }
74
-
75
- function sanitizeName(name: string): string {
76
- return name.toLowerCase().trim().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
77
- }
78
-
79
- function parsePackageConfig(value: unknown): { packageName?: string; error?: string } {
80
- return parsePackageName(value, "config.package");
81
- }
82
-
83
- function allAgents(d: { builtin: AgentConfig[]; package: AgentConfig[]; user: AgentConfig[]; project: AgentConfig[] }): AgentConfig[] {
84
- return [...d.builtin, ...d.package, ...d.user, ...d.project];
85
- }
86
-
87
- function discoveryOptions(ctx: ManagementContext): { projectTrusted: boolean } {
88
- return { projectTrusted: ctx.isProjectTrusted() };
16
+ export { handleCreate, handleUpdate } from "./management-persistence.ts";
17
+
18
+ export function handleList(
19
+ params: ManagementParams,
20
+ ctx: ManagementContext,
21
+ ): SubagentExecutionResult {
22
+ const scope = normalizeListScope(params.agentScope);
23
+ if (scope === undefined) {
24
+ return result("agentScope must be 'user', 'project', or 'both'.", true);
25
+ }
26
+ const discovery = discoverAgentsAll(ctx.cwd, discoveryOptions(ctx), scope);
27
+ const agents = discoverAgents(ctx.cwd, scope, discoveryOptions(ctx)).agents.sort((a, b) =>
28
+ a.name.localeCompare(b.name),
29
+ );
30
+ const chains = discovery.chains
31
+ .filter((chain) => scope === "both" || chain.source === scope)
32
+ .sort((a, b) => a.name.localeCompare(b.name));
33
+ const diagnostics = [...discovery.agentDiagnostics, ...discovery.chainDiagnostics];
34
+ return result(
35
+ [
36
+ ...formatAgentGroups(agents),
37
+ "",
38
+ "Chains:",
39
+ ...(chains.length > 0
40
+ ? chains.map((chain) => `- ${chain.name} (${chain.source}): ${chain.description}`)
41
+ : ["- (none)"]),
42
+ ...(diagnostics.length > 0
43
+ ? [
44
+ "",
45
+ "Discovery diagnostics:",
46
+ ...diagnostics.map((entry) => `- ${entry.filePath}: ${entry.error}`),
47
+ ]
48
+ : []),
49
+ ].join("\n"),
50
+ );
51
+ }
52
+ function getBlocks(
53
+ kind: "agent" | "chain",
54
+ name: string,
55
+ ctx: ManagementContext,
56
+ scope: AgentScope,
57
+ ): { found: boolean; blocks: string[] } {
58
+ const matches =
59
+ kind === "agent" ? findEffectiveAgents(name, ctx, scope) : findChains(name, ctx, scope);
60
+ if (matches.length === 0) {
61
+ return {
62
+ found: false,
63
+ blocks: [
64
+ `${kind === "agent" ? "Agent" : "Chain"} '${name}' not found. Available: ${availableNamesText(ctx, kind, scope)}.`,
65
+ ],
66
+ };
67
+ }
68
+ return {
69
+ found: true,
70
+ blocks: matches.map((match) =>
71
+ "steps" in match ? formatChainDetail(match) : formatAgentDetail(match),
72
+ ),
73
+ };
89
74
  }
90
-
91
- function availableNames(ctx: ManagementContext, kind: "agent" | "chain", scope: AgentScope = "both"): string[] {
92
- const d = discoverAgentsAll(ctx.cwd, discoveryOptions(ctx), scope);
93
- const items = kind === "agent" ? allAgents(d) : d.chains;
94
- return [...new Set(items.map((x) => x.name))].sort((a, b) => a.localeCompare(b));
95
- }
96
-
97
- function findAgents(name: string, ctx: ManagementContext, scope: AgentScope = "both"): AgentConfig[] {
98
- const d = discoverAgentsAll(ctx.cwd, discoveryOptions(ctx), scope);
99
- const raw = name.trim();
100
- const sanitized = sanitizeName(raw);
101
- return allAgents(d)
102
- .filter((a) => (scope === "both" || a.source === scope) && (a.name === raw || a.name === sanitized))
103
- .sort((a, b) => a.source.localeCompare(b.source));
104
- }
105
-
106
- function findChains(name: string, ctx: ManagementContext, scope: AgentScope = "both"): ChainConfig[] {
107
- const raw = name.trim();
108
- const sanitized = sanitizeName(raw);
109
- return discoverAgentsAll(ctx.cwd, discoveryOptions(ctx), scope).chains
110
- .filter((c) => (scope === "both" || c.source === scope) && (c.name === raw || c.name === sanitized))
111
- .sort((a, b) => a.source.localeCompare(b.source));
112
- }
113
-
114
- function findEffectiveAgents(name: string, ctx: ManagementContext, scope: AgentScope = "both"): AgentConfig[] {
115
- const raw = name.trim();
116
- const sanitized = sanitizeName(raw);
117
- return discoverAgents(ctx.cwd, scope, discoveryOptions(ctx)).agents
118
- .filter((a) => a.name === raw || a.name === sanitized);
119
- }
120
-
121
- function nameExistsInScope(ctx: ManagementContext, scope: ManagementScope, name: string, excludePath?: string): boolean {
122
- const d = discoverAgentsAll(ctx.cwd, discoveryOptions(ctx), scope);
123
- for (const a of scope === "user" ? d.user : d.project) {
124
- if (a.name === name && a.filePath !== excludePath) return true;
125
- }
126
- for (const c of d.chains) {
127
- if (c.source === scope && c.name === name && c.filePath !== excludePath) return true;
128
- }
129
- return false;
130
- }
131
-
132
- function unknownChainAgents(ctx: ManagementContext, steps: ChainStepConfig[]): string[] {
133
- const d = discoverAgentsAll(ctx.cwd, discoveryOptions(ctx));
134
- const known = new Set(allAgents(d).map((a) => a.name));
135
- return [...new Set(steps.map((s) => s.agent).filter((agent): agent is string => typeof agent === "string" && !known.has(agent)))].sort((a, b) => a.localeCompare(b));
136
- }
137
-
138
- function chainStepWarnings(ctx: ManagementContext, steps: ChainStepConfig[]): string[] {
139
- const warnings: string[] = [];
140
- const available = new Set(discoverAvailableSkills(ctx.cwd, discoveryOptions(ctx)).map((s) => s.name));
141
- for (let i = 0; i < steps.length; i++) {
142
- const s = steps[i]!;
143
- if (s.model && !isClaudeCodeModel(s.model)) {
144
- const found = ctx.modelRegistry.getAvailable().some((m) => `${m.provider}/${m.id}` === s.model || m.id === s.model);
145
- if (!found) warnings.push(`Warning: step ${i + 1} (${s.agent}): model '${s.model}' is not in the current model registry.`);
146
- }
147
- if (Array.isArray(s.skills) && s.skills.length > 0) {
148
- const missing = s.skills.filter((sk) => !available.has(sk));
149
- if (missing.length) warnings.push(`Warning: step ${i + 1} (${s.agent}): skills not found: ${missing.join(", ")}.`);
150
- }
151
- }
152
- return warnings;
153
- }
154
-
155
- function modelWarning(ctx: ManagementContext, model: string | undefined): string | undefined {
156
- if (!model || isClaudeCodeModel(model)) return undefined;
157
- const found = ctx.modelRegistry.getAvailable().some((m) => `${m.provider}/${m.id}` === model || m.id === model);
158
- return found ? undefined : `Warning: model '${model}' is not in the current model registry.`;
159
- }
160
-
161
- function fallbackModelsWarning(ctx: ManagementContext, fallbackModels: string[] | undefined): string | undefined {
162
- if (!fallbackModels || fallbackModels.length === 0) return undefined;
163
- const available = new Set(ctx.modelRegistry.getAvailable().flatMap((m) => [`${m.provider}/${m.id}`, m.id]));
164
- const missing = fallbackModels.filter((model) => !isClaudeCodeModel(model) && !available.has(model));
165
- return missing.length ? `Warning: fallback models not in the current model registry: ${missing.join(", ")}.` : undefined;
166
- }
167
-
168
- function skillsWarning(ctx: ManagementContext, skills: string[] | undefined): string | undefined {
169
- if (!skills || skills.length === 0) return undefined;
170
- const available = new Set(discoverAvailableSkills(ctx.cwd, discoveryOptions(ctx)).map((s) => s.name));
171
- const missing = skills.filter((s) => !available.has(s));
172
- return missing.length ? `Warning: skills not found: ${missing.join(", ")}.` : undefined;
173
- }
174
-
175
- const SAVED_CHAIN_STEP_KEYS = new Set(["agent", "task", "phase", "label", "as", "outputSchema", "output", "outputMode", "reads", "model", "skills", "progress"]);
176
-
177
- function parseStepList(raw: unknown): { steps?: ChainStepConfig[]; error?: string } {
178
- if (!Array.isArray(raw)) return { error: "config.steps must be an array." };
179
- if (raw.length === 0) return { error: "config.steps must include at least one step." };
180
- const steps: ChainStepConfig[] = [];
181
- for (let i = 0; i < raw.length; i++) {
182
- const item = raw[i];
183
- if (!item || typeof item !== "object" || Array.isArray(item)) return { error: `config.steps[${i}] must be an object.` };
184
- const s = item as Record<string, unknown>;
185
- if (hasKey(s, "skill")) return { error: `config.steps[${i}].skill is not supported; use skills.` };
186
- const unknownKeys = Object.keys(s).filter((key) => !SAVED_CHAIN_STEP_KEYS.has(key));
187
- if (unknownKeys.length) return { error: `config.steps[${i}] has unknown field${unknownKeys.length === 1 ? "" : "s"}: ${unknownKeys.join(", ")}.` };
188
- if (typeof s.agent !== "string" || !s.agent.trim()) return { error: `config.steps[${i}].agent must be a non-empty string.` };
189
- const step: ChainStepConfig = { agent: s.agent.trim(), task: typeof s.task === "string" ? s.task : "" };
190
- if (hasKey(s, "phase")) {
191
- if (typeof s.phase === "string") step.phase = s.phase;
192
- else return { error: `config.steps[${i}].phase must be a string.` };
193
- }
194
- if (hasKey(s, "label")) {
195
- if (typeof s.label === "string") step.label = s.label;
196
- else return { error: `config.steps[${i}].label must be a string.` };
197
- }
198
- if (hasKey(s, "as")) {
199
- if (typeof s.as === "string") step.as = s.as;
200
- else return { error: `config.steps[${i}].as must be a string.` };
201
- }
202
- if (hasKey(s, "outputSchema")) {
203
- if (typeof s.outputSchema === "string") step.outputSchema = s.outputSchema;
204
- else return { error: `config.steps[${i}].outputSchema must be a schema file path string for saved chains.` };
205
- }
206
- if (hasKey(s, "output")) {
207
- if (s.output === false) step.output = false;
208
- else if (typeof s.output === "string") step.output = s.output;
209
- else return { error: `config.steps[${i}].output must be a string or false.` };
210
- }
211
- if (hasKey(s, "outputMode")) {
212
- if (s.outputMode === "inline" || s.outputMode === "file-only") step.outputMode = s.outputMode;
213
- else return { error: `config.steps[${i}].outputMode must be 'inline' or 'file-only'.` };
214
- }
215
- if (hasKey(s, "reads")) {
216
- if (s.reads === false) step.reads = false;
217
- else if (Array.isArray(s.reads) && s.reads.every((value) => typeof value === "string")) step.reads = s.reads.map((value) => value.trim()).filter(Boolean);
218
- else return { error: `config.steps[${i}].reads must be a string array or false.` };
219
- }
220
- if (hasKey(s, "model")) {
221
- if (typeof s.model === "string") step.model = s.model;
222
- else return { error: `config.steps[${i}].model must be a string.` };
223
- }
224
- if (hasKey(s, "skill")) {
225
- return { error: `config.steps[${i}].skill is not supported for saved chains; use skills (array or false).` };
226
- }
227
- if (hasKey(s, "skills")) {
228
- if (s.skills === false) step.skills = false;
229
- else if (Array.isArray(s.skills) && s.skills.every((value) => typeof value === "string")) step.skills = s.skills.map((value) => value.trim()).filter(Boolean);
230
- else return { error: `config.steps[${i}].skills must be a string array or false.` };
231
- }
232
- if (hasKey(s, "progress")) {
233
- if (typeof s.progress === "boolean") step.progress = s.progress;
234
- else return { error: `config.steps[${i}].progress must be a boolean.` };
235
- }
236
- steps.push(step);
237
- }
238
- return { steps };
239
- }
240
-
241
- function parseTools(raw: string): { tools?: string[]; mcpDirectTools?: string[] } {
242
- const tools: string[] = [];
243
- const mcpDirectTools: string[] = [];
244
- for (const item of parseCsv(raw)) {
245
- if (item.startsWith("mcp:")) {
246
- const direct = item.slice(4).trim();
247
- if (direct) mcpDirectTools.push(direct);
248
- } else tools.push(item);
249
- }
250
- return { tools: tools.length ? tools : undefined, mcpDirectTools: mcpDirectTools.length ? mcpDirectTools : undefined };
251
- }
252
-
253
- const CHAIN_CONFIG_KEYS = new Set(["name", "package", "description", "scope", "steps"]);
254
-
255
- function validateChainConfigKeys(cfg: Record<string, unknown>): string | undefined {
256
- const unknownKeys = Object.keys(cfg).filter((key) => !CHAIN_CONFIG_KEYS.has(key));
257
- return unknownKeys.length ? `config has unknown field${unknownKeys.length === 1 ? "" : "s"}: ${unknownKeys.join(", ")}.` : undefined;
258
- }
259
-
260
- const AGENT_CONFIG_KEYS = new Set([
261
- "name", "package", "description", "scope", "systemPrompt", "model", "fallbackModels", "tools", "skills", "extensions", "thinking",
262
- "systemPromptMode", "inheritProjectContext", "inheritSkills", "defaultContext", "output", "reads", "progress", "allowSubagents",
263
- "maxSubagentDepth", "maxExecutionTimeMs", "maxTokens", "completionGuard",
264
- ]);
265
-
266
- function applyAgentConfig(target: AgentConfig, cfg: Record<string, unknown>): string | undefined {
267
- const unknownKeys = Object.keys(cfg).filter((key) => !AGENT_CONFIG_KEYS.has(key));
268
- if (unknownKeys.length) return `config has unknown field${unknownKeys.length === 1 ? "" : "s"}: ${unknownKeys.join(", ")}.`;
269
- if (hasKey(cfg, "systemPrompt")) {
270
- if (cfg.systemPrompt === false || cfg.systemPrompt === "") target.systemPrompt = "";
271
- else if (typeof cfg.systemPrompt === "string") target.systemPrompt = cfg.systemPrompt;
272
- else return "config.systemPrompt must be a string or false when provided.";
273
- }
274
- if (hasKey(cfg, "model")) {
275
- if (cfg.model === false || cfg.model === "") target.model = undefined;
276
- else if (typeof cfg.model === "string") target.model = cfg.model.trim() || undefined;
277
- else return "config.model must be a string or false when provided.";
278
- }
279
- if (hasKey(cfg, "fallbackModels")) {
280
- if (cfg.fallbackModels === false || cfg.fallbackModels === "") target.fallbackModels = undefined;
281
- else if (typeof cfg.fallbackModels === "string") {
282
- const models = parseCsv(cfg.fallbackModels);
283
- target.fallbackModels = models.length ? models : undefined;
284
- } else if (Array.isArray(cfg.fallbackModels)) {
285
- const models = cfg.fallbackModels
286
- .filter((value): value is string => typeof value === "string")
287
- .map((value) => value.trim())
288
- .filter(Boolean);
289
- target.fallbackModels = models.length ? [...new Set(models)] : undefined;
290
- } else return "config.fallbackModels must be a comma-separated string, string array, or false when provided.";
291
- }
292
- if (hasKey(cfg, "tools")) {
293
- if (cfg.tools === false || cfg.tools === "") { target.tools = undefined; target.mcpDirectTools = undefined; }
294
- else if (typeof cfg.tools === "string") { const parsed = parseTools(cfg.tools); target.tools = parsed.tools; target.mcpDirectTools = parsed.mcpDirectTools; }
295
- else return "config.tools must be a comma-separated string or false when provided.";
296
- }
297
- if (hasKey(cfg, "skills")) {
298
- if (cfg.skills === false || cfg.skills === "") target.skills = undefined;
299
- else if (typeof cfg.skills === "string") { const skills = parseCsv(cfg.skills); target.skills = skills.length ? skills : undefined; }
300
- else return "config.skills must be a comma-separated string or false when provided.";
301
- }
302
- if (hasKey(cfg, "extensions")) {
303
- if (cfg.extensions === false) target.extensions = undefined;
304
- else if (cfg.extensions === "") target.extensions = [];
305
- else if (typeof cfg.extensions === "string") target.extensions = parseCsv(cfg.extensions);
306
- else return "config.extensions must be a comma-separated string, empty string, or false when provided.";
307
- }
308
- if (hasKey(cfg, "thinking")) {
309
- if (cfg.thinking === false || cfg.thinking === "") target.thinking = undefined;
310
- else if (typeof cfg.thinking === "string") target.thinking = cfg.thinking.trim() || undefined;
311
- else return "config.thinking must be a string or false when provided.";
312
- }
313
- if (hasKey(cfg, "systemPromptMode")) {
314
- if (cfg.systemPromptMode === "append" || cfg.systemPromptMode === "replace") target.systemPromptMode = cfg.systemPromptMode;
315
- else return "config.systemPromptMode must be 'append' or 'replace' when provided.";
316
- }
317
- if (hasKey(cfg, "inheritProjectContext")) {
318
- if (typeof cfg.inheritProjectContext !== "boolean") return "config.inheritProjectContext must be a boolean when provided.";
319
- target.inheritProjectContext = cfg.inheritProjectContext;
320
- }
321
- if (hasKey(cfg, "inheritSkills")) {
322
- if (typeof cfg.inheritSkills !== "boolean") return "config.inheritSkills must be a boolean when provided.";
323
- target.inheritSkills = cfg.inheritSkills;
324
- }
325
- if (hasKey(cfg, "defaultContext")) {
326
- if (cfg.defaultContext === false || cfg.defaultContext === "") target.defaultContext = undefined;
327
- else if (cfg.defaultContext === "fresh" || cfg.defaultContext === "fork") target.defaultContext = cfg.defaultContext;
328
- else return "config.defaultContext must be 'fresh', 'fork', or false when provided.";
329
- }
330
- if (hasKey(cfg, "output")) {
331
- if (cfg.output === false || cfg.output === "") target.output = undefined;
332
- else if (typeof cfg.output === "string") target.output = cfg.output;
333
- else return "config.output must be a string or false when provided.";
334
- }
335
- if (hasKey(cfg, "reads")) {
336
- if (cfg.reads === false || cfg.reads === "") target.defaultReads = undefined;
337
- else if (typeof cfg.reads === "string") {
338
- const reads = parseCsv(cfg.reads);
339
- target.defaultReads = reads.length ? reads : undefined;
340
- } else return "config.reads must be a comma-separated string or false when provided.";
341
- }
342
- if (hasKey(cfg, "progress")) {
343
- if (typeof cfg.progress !== "boolean") return "config.progress must be a boolean when provided.";
344
- target.defaultProgress = cfg.progress;
345
- }
346
- if (hasKey(cfg, "allowSubagents")) {
347
- if (typeof cfg.allowSubagents !== "boolean") return "config.allowSubagents must be a boolean when provided.";
348
- target.allowSubagents = cfg.allowSubagents;
349
- }
350
- if (hasKey(cfg, "maxSubagentDepth")) {
351
- if (cfg.maxSubagentDepth === false || cfg.maxSubagentDepth === "") target.maxSubagentDepth = undefined;
352
- else if (typeof cfg.maxSubagentDepth === "number" && Number.isInteger(cfg.maxSubagentDepth) && cfg.maxSubagentDepth >= 0) {
353
- target.maxSubagentDepth = cfg.maxSubagentDepth;
354
- } else return "config.maxSubagentDepth must be an integer >= 0 or false when provided.";
355
- }
356
- if (hasKey(cfg, "maxExecutionTimeMs")) {
357
- if (cfg.maxExecutionTimeMs === false || cfg.maxExecutionTimeMs === "") target.maxExecutionTimeMs = undefined;
358
- else if (typeof cfg.maxExecutionTimeMs === "number" && Number.isInteger(cfg.maxExecutionTimeMs) && cfg.maxExecutionTimeMs >= 1) {
359
- target.maxExecutionTimeMs = cfg.maxExecutionTimeMs;
360
- } else return "config.maxExecutionTimeMs must be an integer >= 1 or false when provided.";
361
- }
362
- if (hasKey(cfg, "maxTokens")) {
363
- if (cfg.maxTokens === false || cfg.maxTokens === "") target.maxTokens = undefined;
364
- else if (typeof cfg.maxTokens === "number" && Number.isInteger(cfg.maxTokens) && cfg.maxTokens >= 1) {
365
- target.maxTokens = cfg.maxTokens;
366
- } else return "config.maxTokens must be an integer >= 1 or false when provided.";
367
- }
368
- if (hasKey(cfg, "completionGuard")) {
369
- if (typeof cfg.completionGuard !== "boolean") return "config.completionGuard must be a boolean when provided.";
370
- target.completionGuard = cfg.completionGuard;
371
- }
372
- return undefined;
373
- }
374
-
375
- type MutableTarget<T extends { source: AgentSource }> = T & { source: ManagementScope };
376
-
377
- function isMutableTarget<T extends { source: AgentSource }>(target: T): target is MutableTarget<T> {
378
- return target.source === "user" || target.source === "project";
379
- }
380
-
381
- function resolveTarget<T extends { source: AgentSource; filePath: string }>(
382
- kind: "agent" | "chain",
383
- name: string,
384
- matches: T[],
385
- ctx: ManagementContext,
386
- scopeHint?: string,
387
- ): MutableTarget<T> | SubagentExecutionResult {
388
- const mutable = matches.filter(isMutableTarget);
389
- if (mutable.length === 0) {
390
- if (matches.length > 0) {
391
- return result(`${kind === "agent" ? "Agent" : "Chain"} '${name}' is ${matches[0]!.source} and cannot be modified. Create a same-named ${kind} in user or project scope to override it.`, true);
392
- }
393
- const available = availableNames(ctx, kind);
394
- return result(`${kind === "agent" ? "Agent" : "Chain"} '${name}' not found. Available: ${available.join(", ") || "none"}.`, true);
395
- }
396
- if (mutable.length === 1) return mutable[0]!;
397
- const scope = asDisambiguationScope(scopeHint);
398
- if (!scope) {
399
- const paths = mutable.map((m) => `${m.source}: ${m.filePath}`).join("\n");
400
- const sources = new Set(mutable.map((entry) => entry.source));
401
- return sources.size === 1
402
- ? result(`${kind === "agent" ? "Agent" : "Chain"} '${name}' has multiple definitions in ${mutable[0]!.source} scope and cannot be modified safely. Remove or rename one definition first.\n${paths}`, true)
403
- : result(`${kind === "agent" ? "Agent" : "Chain"} '${name}' exists in both scopes. Specify agentScope: 'user' or 'project'.\n${paths}`, true);
404
- }
405
- const scoped = mutable.filter((m) => m.source === scope);
406
- if (scoped.length === 0) return result(`${kind === "agent" ? "Agent" : "Chain"} '${name}' not found in scope '${scope}'.`, true);
407
- if (scoped.length > 1) {
408
- return result(`${kind === "agent" ? "Agent" : "Chain"} '${name}' has multiple definitions in scope '${scope}' and cannot be modified safely. Remove or rename one definition first:\n${scoped.map((entry) => entry.filePath).join("\n")}`, true);
409
- }
410
- return scoped[0]!;
411
- }
412
-
413
- function renamePath(
414
- kind: "agent" | "chain",
415
- currentPath: string,
416
- newName: string,
417
- scope: ManagementScope,
418
- ctx: ManagementContext,
419
- ): { filePath?: string; error?: string } {
420
- if (nameExistsInScope(ctx, scope, newName, currentPath)) return { error: `Name '${newName}' already exists in ${scope} scope.` };
421
- const ext = kind === "agent" ? ".md" : currentPath.endsWith(".chain.json") ? ".chain.json" : ".chain.md";
422
- const filePath = path.join(path.dirname(currentPath), `${newName}${ext}`);
423
- if (fs.existsSync(filePath) && filePath !== currentPath) {
424
- return { error: `File already exists at ${filePath} but is not a valid ${kind} definition. Remove or rename it first.` };
425
- }
426
- fs.renameSync(currentPath, filePath);
427
- return { filePath };
428
- }
429
-
430
- function formatModelDefaults(agent: AgentConfig): string[] {
431
- const thinking = resolveEffectiveThinking(agent.model, agent.thinking) ?? agent.thinking;
432
- const inherited = "inherited runtime default (unset)";
433
- const fallbacks = agent.fallbackModels?.map((model) =>
434
- `${model} (thinking: ${resolveEffectiveThinking(model, agent.thinking ?? thinking) ?? inherited})`);
435
- return [
436
- `Model: ${agent.model ?? "inherited from parent (resolved at launch)"}`,
437
- `Thinking: ${thinking ?? inherited}`,
438
- `Fallback models: ${fallbacks?.length ? fallbacks.join(", ") : "none configured"}`,
439
- ];
440
- }
441
-
442
- function formatAgentDetail(agent: AgentConfig): string {
443
- const tools = [...(agent.tools ?? []), ...(agent.mcpDirectTools ?? []).map((t) => `mcp:${t}`)];
444
- const lines: string[] = [`Agent: ${agent.name} (${agent.source})`, `Path: ${agent.filePath}`, `Description: ${agent.description}`];
445
- if (agent.packageName) {
446
- lines.push(`Local name: ${frontmatterNameForConfig(agent)}`);
447
- lines.push(`Package: ${agent.packageName}`);
448
- }
449
- lines.push(...formatModelDefaults(agent));
450
- if (tools.length) lines.push(`Tools: ${tools.join(", ")}`);
451
- if (agent.skills?.length) lines.push(`Skills: ${agent.skills.join(", ")}`);
452
- lines.push(`System prompt mode: ${agent.systemPromptMode}`);
453
- lines.push(`Inherit project context: ${agent.inheritProjectContext ? "true" : "false"}`);
454
- lines.push(`Inherit skills: ${agent.inheritSkills ? "true" : "false"}`);
455
- if (agent.defaultContext) lines.push(`Default context: ${agent.defaultContext}`);
456
- if (agent.source === "builtin") lines.push(`Disabled: ${agent.disabled ? "true" : "false"}`);
457
- if (agent.extensions !== undefined) lines.push(`Extensions: ${agent.extensions.length ? agent.extensions.join(", ") : "(none)"}`);
458
- if (agent.output) lines.push(`Output: ${agent.output}`);
459
- if (agent.defaultReads?.length) lines.push(`Reads: ${agent.defaultReads.join(", ")}`);
460
- if (agent.defaultProgress) lines.push("Progress: true");
461
- if (agent.allowSubagents) lines.push("Allow subagents: true");
462
- if (agent.maxSubagentDepth !== undefined) lines.push(`Max subagent depth: ${agent.maxSubagentDepth}`);
463
- if (agent.maxExecutionTimeMs !== undefined) lines.push(`Max execution time: ${agent.maxExecutionTimeMs}ms`);
464
- if (agent.maxTokens !== undefined) lines.push(`Max tokens: ${agent.maxTokens}`);
465
- if (agent.completionGuard !== undefined) lines.push(`Completion guard: ${agent.completionGuard}`);
466
- if (agent.systemPrompt.trim()) lines.push("", "System Prompt:", agent.systemPrompt);
467
- return lines.join("\n");
468
- }
469
-
470
- function formatChainStepDetail(step: ChainStepConfig, index: number): string[] {
471
- const lines: string[] = [];
472
- if (step.expand || step.collect) {
473
- const parallel = step.parallel && !Array.isArray(step.parallel) && typeof step.parallel === "object" ? step.parallel as { agent?: unknown; task?: unknown; label?: unknown; outputSchema?: unknown } : undefined;
474
- const expand = step.expand && typeof step.expand === "object" ? step.expand as { from?: { output?: unknown; path?: unknown }; item?: unknown; key?: unknown; maxItems?: unknown; onEmpty?: unknown } : undefined;
475
- const collect = step.collect && typeof step.collect === "object" ? step.collect as { as?: unknown; outputSchema?: unknown } : undefined;
476
- lines.push(`${index + 1}. Dynamic fanout${typeof collect?.as === "string" ? ` -> ${collect.as}` : ""}`);
477
- if (expand?.from) lines.push(` Expand: ${String(expand.from.output ?? "?")}${String(expand.from.path ?? "")}`);
478
- if (typeof expand?.item === "string") lines.push(` Item variable: ${expand.item}`);
479
- if (typeof expand?.key === "string") lines.push(` Key: ${expand.key}`);
480
- if (typeof expand?.maxItems === "number") lines.push(` Max items: ${expand.maxItems}`);
481
- if (typeof expand?.onEmpty === "string") lines.push(` On empty: ${expand.onEmpty}`);
482
- if (parallel?.agent) lines.push(` Agent: ${String(parallel.agent)}`);
483
- if (typeof parallel?.label === "string") lines.push(` Label: ${parallel.label}`);
484
- if (typeof parallel?.task === "string" && parallel.task.trim()) lines.push(` Task: ${parallel.task}`);
485
- if (parallel?.outputSchema) lines.push(" Structured output: true");
486
- if (collect?.outputSchema) lines.push(" Collect schema: true");
487
- if (step.concurrency !== undefined) lines.push(` Concurrency: ${step.concurrency}`);
488
- if (step.failFast !== undefined) lines.push(` Fail fast: ${step.failFast ? "true" : "false"}`);
489
- return lines;
490
- }
491
- lines.push(`${index + 1}. ${step.agent}`);
492
- if (step.task?.trim()) lines.push(` Task: ${step.task}`);
493
- if (step.output === false) lines.push(" Output: false");
494
- else if (step.output) lines.push(` Output: ${step.output}`);
495
- if (step.outputMode) lines.push(` Output mode: ${step.outputMode}`);
496
- if (step.reads === false) lines.push(" Reads: false");
497
- else if (Array.isArray(step.reads) && step.reads.length > 0) lines.push(` Reads: ${step.reads.join(", ")}`);
498
- if (step.model) lines.push(` Model: ${step.model}`);
499
- if (step.skills === false) lines.push(" Skills: false");
500
- else if (Array.isArray(step.skills) && step.skills.length > 0) lines.push(` Skills: ${step.skills.join(", ")}`);
501
- if (step.progress !== undefined) lines.push(` Progress: ${step.progress ? "true" : "false"}`);
502
- return lines;
503
- }
504
-
505
- function formatChainDetail(chain: ChainConfig): string {
506
- const lines: string[] = [`Chain: ${chain.name} (${chain.source})`, `Path: ${chain.filePath}`, `Description: ${chain.description}`];
507
- if (chain.packageName) {
508
- lines.push(`Local name: ${frontmatterNameForConfig(chain)}`);
509
- lines.push(`Package: ${chain.packageName}`);
510
- }
511
- lines.push("", "Steps:");
512
- for (let i = 0; i < chain.steps.length; i++) {
513
- lines.push(...formatChainStepDetail(chain.steps[i]!, i));
514
- }
515
- return lines.join("\n");
516
- }
517
-
518
- type AgentListRole = "Recon" | "Planning" | "Implementation" | "Review" | "Coordination" | "Specialized" | "Custom/other";
519
-
520
- const AGENT_ROLE_HINTS: Record<AgentListRole, string> = {
521
- Recon: "Use for read-only codebase mapping, grep/delta sweeps, and external facts.",
522
- Planning: "Use when decomposition or an implementation handoff matters.",
523
- Implementation: "Use for bounded code/doc changes after scope is clear.",
524
- Review: "Use for independent validation, regressions, and drift checks.",
525
- Coordination: "Use for generic delegation or high-context decision checks.",
526
- Specialized: "Use only when the task matches the skill description.",
527
- "Custom/other": "Project/user agents not classified by the builtins.",
528
- };
529
-
530
- function agentListRole(agent: AgentConfig): AgentListRole {
531
- const name = agent.name.split(".").at(-1) ?? agent.name;
532
- if (["scout", "context-builder", "researcher"].includes(name)) return "Recon";
533
- if (name === "planner") return "Planning";
534
- if (["worker", "fixer"].includes(name)) return "Implementation";
535
- if (name === "reviewer" || name.includes("review")) return "Review";
536
- if (["delegate", "oracle"].includes(name)) return "Coordination";
537
- if (agent.source === "builtin") return "Specialized";
538
- return "Custom/other";
539
- }
540
-
541
- function formatAgentListLine(a: AgentConfig): string {
542
- return `- ${a.name} (${a.source}${a.defaultContext ? `, context: ${a.defaultContext}` : ""}): ${a.description}\n ${formatModelDefaults(a).join("; ")}`;
543
- }
544
-
545
- export function handleList(params: ManagementParams, ctx: ManagementContext): SubagentExecutionResult {
546
- const scope = normalizeListScope(params.agentScope);
547
- if (!scope) return result("agentScope must be 'user', 'project', or 'both'.", true);
548
- const d = discoverAgentsAll(ctx.cwd, discoveryOptions(ctx), scope);
549
- const agents = discoverAgents(ctx.cwd, scope, discoveryOptions(ctx)).agents
550
- .sort((a, b) => a.name.localeCompare(b.name));
551
- const chains = d.chains.filter((c) => scope === "both" || c.source === scope).sort((a, b) => a.name.localeCompare(b.name));
552
- const diagnostics = [...d.agentDiagnostics, ...d.chainDiagnostics];
553
- const roleOrder: AgentListRole[] = ["Recon", "Planning", "Implementation", "Review", "Coordination", "Specialized", "Custom/other"];
554
- const lines: string[] = ["Executable agents (grouped by role):"];
555
- if (!agents.length) {
556
- lines.push("- (none)");
557
- } else {
558
- for (const role of roleOrder) {
559
- const group = agents.filter((agent) => agentListRole(agent) === role);
560
- if (!group.length) continue;
561
- lines.push(``, `**${role}** — ${AGENT_ROLE_HINTS[role]}`, ...group.map(formatAgentListLine));
562
- }
563
- }
564
- lines.push(
565
- "",
566
- "Chains:",
567
- ...(chains.length ? chains.map((c) => `- ${c.name} (${c.source}): ${c.description}`) : ["- (none)"]),
568
- ...(diagnostics.length ? ["", "Discovery diagnostics:", ...diagnostics.map((entry) => `- ${entry.filePath}: ${entry.error}`)] : []),
569
- );
570
- return result(lines.join("\n"));
571
- }
572
-
573
75
  function handleGet(params: ManagementParams, ctx: ManagementContext): SubagentExecutionResult {
574
- if (!params.agent && !params.chainName) return result("Specify 'agent' or 'chainName' for get.", true);
575
- const hasBoth = Boolean(params.agent && params.chainName);
576
- const blocks: string[] = [];
577
- let anyFound = false;
578
- const scope = normalizeListScope(params.agentScope);
579
- if (!scope) return result("agentScope must be 'user', 'project', or 'both'.", true);
580
- if (params.agent) {
581
- const matches = findEffectiveAgents(params.agent, ctx, scope);
582
- if (!matches.length) {
583
- const msg = `Agent '${params.agent}' not found. Available: ${availableNames(ctx, "agent", scope).join(", ") || "none"}.`;
584
- if (!hasBoth) return result(msg, true);
585
- blocks.push(msg);
586
- } else {
587
- anyFound = true;
588
- blocks.push(...matches.map(formatAgentDetail));
589
- }
590
- }
591
- if (params.chainName) {
592
- const matches = findChains(params.chainName, ctx, scope);
593
- if (!matches.length) {
594
- const msg = `Chain '${params.chainName}' not found. Available: ${availableNames(ctx, "chain", scope).join(", ") || "none"}.`;
595
- if (!hasBoth) return result(msg, true);
596
- blocks.push(msg);
597
- } else {
598
- anyFound = true;
599
- blocks.push(...matches.map(formatChainDetail));
600
- }
601
- }
602
- return result(blocks.join("\n\n"), !anyFound);
603
- }
604
-
605
- export function handleCreate(params: ManagementParams, ctx: ManagementContext): SubagentExecutionResult {
606
- const parsedConfig = configObject(params.config);
607
- if (parsedConfig.error) return result(parsedConfig.error, true);
608
- const cfg = parsedConfig.value;
609
- if (!cfg) return result("config required for create.", true);
610
- if (typeof cfg.name !== "string" || !cfg.name.trim()) return result("config.name is required and must be a non-empty string.", true);
611
- if (typeof cfg.description !== "string" || !cfg.description.trim()) return result("config.description is required and must be a non-empty string.", true);
612
- const name = sanitizeName(cfg.name);
613
- if (!name) return result("config.name is invalid after sanitization. Use letters, numbers, spaces, or hyphens.", true);
614
- const parsedPackage = parsePackageConfig(cfg.package);
615
- if (parsedPackage.error) return result(parsedPackage.error, true);
616
- const runtimeName = buildRuntimeName(name, parsedPackage.packageName);
617
- const scopeRaw = cfg.scope ?? "user";
618
- if (scopeRaw !== "user" && scopeRaw !== "project") return result("config.scope must be 'user' or 'project'.", true);
619
- const scope = scopeRaw as ManagementScope;
620
- const isChain = hasKey(cfg, "steps");
621
- const options = discoveryOptions(ctx);
622
- if (scope === "project" && options.projectTrusted === false) return result("Project scope is not available because this project is untrusted. Run from a trusted project or use scope: 'user'.", true);
623
- const d = discoverAgentsAll(ctx.cwd, options);
624
- const targetDir = isChain
625
- ? scope === "user" ? d.userChainDir : d.projectChainDir ?? path.join(ctx.cwd, ".pi", "chains")
626
- : scope === "user" ? d.userDir : d.projectDir ?? path.join(ctx.cwd, ".pi", "agents");
627
- fs.mkdirSync(targetDir, { recursive: true });
628
- if (nameExistsInScope(ctx, scope, runtimeName)) return result(`Name '${runtimeName}' already exists in ${scope} scope. Use update instead.`, true);
629
- const targetPath = path.join(targetDir, isChain ? `${runtimeName}.chain.md` : `${runtimeName}.md`);
630
- if (fs.existsSync(targetPath)) return result(`File already exists at ${targetPath} but is not a valid ${isChain ? "chain" : "agent"} definition. Remove or rename it first.`, true);
631
- const warnings: string[] = [];
632
- if (!isChain && d.builtin.some((a) => a.name === runtimeName)) warnings.push(`Note: this shadows the builtin agent '${runtimeName}'.`);
633
- if (isChain) {
634
- const keyError = validateChainConfigKeys(cfg);
635
- if (keyError) return result(keyError, true);
636
- const parsed = parseStepList(cfg.steps);
637
- if (parsed.error) return result(parsed.error, true);
638
- const chain: ChainConfig = { name: runtimeName, localName: name, packageName: parsedPackage.packageName, description: cfg.description.trim(), source: scope, filePath: targetPath, steps: parsed.steps! };
639
- fs.writeFileSync(targetPath, serializeChain(chain), "utf-8");
640
- const missing = unknownChainAgents(ctx, chain.steps);
641
- if (missing.length) warnings.push(`Warning: chain steps reference unknown agents: ${missing.join(", ")}.`);
642
- warnings.push(...chainStepWarnings(ctx, chain.steps));
643
- return result([`Created chain '${runtimeName}' at ${targetPath}.`, ...warnings].join("\n"));
644
- }
645
- const agent: AgentConfig = {
646
- name: runtimeName,
647
- localName: name,
648
- packageName: parsedPackage.packageName,
649
- description: cfg.description.trim(),
650
- source: scope,
651
- filePath: targetPath,
652
- systemPrompt: "",
653
- systemPromptMode: defaultSystemPromptMode(name),
654
- inheritProjectContext: defaultInheritProjectContext(name),
655
- inheritSkills: defaultInheritSkills(),
656
- maxSubagentDepth: 0,
657
- };
658
- const applyError = applyAgentConfig(agent, cfg);
659
- if (applyError) return result(applyError, true);
660
- const mw = modelWarning(ctx, agent.model);
661
- if (mw) warnings.push(mw);
662
- const fmw = fallbackModelsWarning(ctx, agent.fallbackModels);
663
- if (fmw) warnings.push(fmw);
664
- const sw = skillsWarning(ctx, agent.skills);
665
- if (sw) warnings.push(sw);
666
- fs.writeFileSync(targetPath, serializeAgent(agent), "utf-8");
667
- return result([`Created agent '${runtimeName}' at ${targetPath}.`, ...warnings].join("\n"));
668
- }
669
-
670
- export function handleUpdate(params: ManagementParams, ctx: ManagementContext): SubagentExecutionResult {
671
- if (!params.agent && !params.chainName) return result("Specify 'agent' or 'chainName' for update.", true);
672
- if (params.agent && params.chainName) return result("Specify either 'agent' or 'chainName', not both.", true);
673
- const parsedConfig = configObject(params.config);
674
- if (parsedConfig.error) return result(parsedConfig.error, true);
675
- const cfg = parsedConfig.value;
676
- if (!cfg) return result("config required for update.", true);
677
- const warnings: string[] = [];
678
- if (params.agent) {
679
- const scopeHint = asDisambiguationScope(params.agentScope);
680
- const targetOrError = resolveTarget("agent", params.agent, findAgents(params.agent, ctx, scopeHint ?? "both"), ctx, params.agentScope);
681
- if ("content" in targetOrError) return targetOrError;
682
- const target = targetOrError;
683
- const updated: AgentConfig = { ...target };
684
- const oldName = target.name;
685
- if (hasKey(cfg, "name") && (typeof cfg.name !== "string" || !cfg.name.trim())) return result("config.name must be a non-empty string when provided.", true);
686
- if (hasKey(cfg, "description") && (typeof cfg.description !== "string" || !cfg.description.trim())) return result("config.description must be a non-empty string when provided.", true);
687
- let newLocalName = target.localName ?? frontmatterNameForConfig(target);
688
- if (hasKey(cfg, "name")) {
689
- newLocalName = sanitizeName(cfg.name as string);
690
- if (!newLocalName) return result("config.name is invalid after sanitization.", true);
691
- }
692
- let newPackageName = target.packageName;
693
- if (hasKey(cfg, "package")) {
694
- const parsedPackage = parsePackageConfig(cfg.package);
695
- if (parsedPackage.error) return result(parsedPackage.error, true);
696
- newPackageName = parsedPackage.packageName;
697
- }
698
- const applyError = applyAgentConfig(updated, cfg);
699
- if (applyError) return result(applyError, true);
700
- updated.localName = newLocalName;
701
- updated.packageName = newPackageName;
702
- updated.name = buildRuntimeName(newLocalName, newPackageName);
703
- if (hasKey(cfg, "description")) updated.description = (cfg.description as string).trim();
704
- if (hasKey(cfg, "model")) {
705
- const mw = modelWarning(ctx, updated.model);
706
- if (mw) warnings.push(mw);
707
- }
708
- if (hasKey(cfg, "fallbackModels")) {
709
- const fmw = fallbackModelsWarning(ctx, updated.fallbackModels);
710
- if (fmw) warnings.push(fmw);
711
- }
712
- if (hasKey(cfg, "skills")) {
713
- const sw = skillsWarning(ctx, updated.skills);
714
- if (sw) warnings.push(sw);
715
- }
716
- if (updated.name !== oldName) {
717
- const renamed = renamePath("agent", target.filePath, updated.name, target.source, ctx);
718
- if (renamed.error) return result(renamed.error, true);
719
- updated.filePath = renamed.filePath!;
720
- }
721
- fs.writeFileSync(updated.filePath, serializeAgent(updated), "utf-8");
722
- if (updated.name !== oldName) {
723
- const refs = discoverAgentsAll(ctx.cwd, discoveryOptions(ctx)).chains.filter((c) => c.steps.some((s) => s.agent === oldName)).map((c) => `${c.name} (${c.source})`);
724
- if (refs.length) warnings.push(`Warning: chains still reference '${oldName}': ${refs.join(", ")}.`);
725
- }
726
- const headline = updated.name === oldName
727
- ? `Updated agent '${updated.name}' at ${updated.filePath}.`
728
- : `Updated agent '${oldName}' to '${updated.name}' at ${updated.filePath}.`;
729
- return result([headline, ...warnings].join("\n"));
730
- }
731
- const scopeHint = asDisambiguationScope(params.agentScope);
732
- const targetOrError = resolveTarget("chain", params.chainName!, findChains(params.chainName!, ctx, scopeHint ?? "both"), ctx, params.agentScope);
733
- if ("content" in targetOrError) return targetOrError;
734
- const target = targetOrError;
735
- const keyError = validateChainConfigKeys(cfg);
736
- if (keyError) return result(keyError, true);
737
- const updated: ChainConfig = { ...target, steps: [...target.steps] };
738
- const oldName = target.name;
739
- if (hasKey(cfg, "name") && (typeof cfg.name !== "string" || !cfg.name.trim())) return result("config.name must be a non-empty string when provided.", true);
740
- if (hasKey(cfg, "description") && (typeof cfg.description !== "string" || !cfg.description.trim())) return result("config.description must be a non-empty string when provided.", true);
741
- let newLocalName = target.localName ?? frontmatterNameForConfig(target);
742
- if (hasKey(cfg, "name")) {
743
- newLocalName = sanitizeName(cfg.name as string);
744
- if (!newLocalName) return result("config.name is invalid after sanitization.", true);
745
- }
746
- let newPackageName = target.packageName;
747
- if (hasKey(cfg, "package")) {
748
- const parsedPackage = parsePackageConfig(cfg.package);
749
- if (parsedPackage.error) return result(parsedPackage.error, true);
750
- newPackageName = parsedPackage.packageName;
751
- }
752
- let parsedSteps: ChainStepConfig[] | undefined;
753
- if (hasKey(cfg, "steps")) {
754
- const parsed = parseStepList(cfg.steps);
755
- if (parsed.error) return result(parsed.error, true);
756
- parsedSteps = parsed.steps!;
757
- }
758
- updated.localName = newLocalName;
759
- updated.packageName = newPackageName;
760
- updated.name = buildRuntimeName(newLocalName, newPackageName);
761
- if (hasKey(cfg, "description")) updated.description = (cfg.description as string).trim();
762
- if (parsedSteps) {
763
- updated.steps = parsedSteps;
764
- const missing = unknownChainAgents(ctx, updated.steps);
765
- if (missing.length) warnings.push(`Warning: chain steps reference unknown agents: ${missing.join(", ")}.`);
766
- warnings.push(...chainStepWarnings(ctx, updated.steps));
767
- }
768
- if (updated.name !== oldName) {
769
- const renamed = renamePath("chain", target.filePath, updated.name, target.source, ctx);
770
- if (renamed.error) return result(renamed.error, true);
771
- updated.filePath = renamed.filePath!;
772
- }
773
- fs.writeFileSync(updated.filePath, updated.filePath.endsWith(".chain.json") ? serializeJsonChain(updated) : serializeChain(updated), "utf-8");
774
- const headline = updated.name === oldName
775
- ? `Updated chain '${updated.name}' at ${updated.filePath}.`
776
- : `Updated chain '${oldName}' to '${updated.name}' at ${updated.filePath}.`;
777
- return result([headline, ...warnings].join("\n"));
778
- }
779
-
780
- function handleDelete(params: ManagementParams, ctx: ManagementContext): SubagentExecutionResult {
781
- if (!params.agent && !params.chainName) return result("Specify 'agent' or 'chainName' for delete.", true);
782
- if (params.agent && params.chainName) return result("Specify either 'agent' or 'chainName', not both.", true);
783
- const scopeHint = asDisambiguationScope(params.agentScope);
784
- if (params.agent) {
785
- const targetOrError = resolveTarget("agent", params.agent, findAgents(params.agent, ctx, scopeHint ?? "both"), ctx, params.agentScope);
786
- if ("content" in targetOrError) return targetOrError;
787
- const target = targetOrError;
788
- fs.unlinkSync(target.filePath);
789
- const refs = discoverAgentsAll(ctx.cwd, discoveryOptions(ctx)).chains.filter((c) => c.steps.some((s) => s.agent === target.name)).map((c) => `${c.name} (${c.source})`);
790
- const lines = [`Deleted agent '${target.name}' at ${target.filePath}.`];
791
- if (refs.length) lines.push(`Warning: chains reference deleted agent '${target.name}': ${refs.join(", ")}.`);
792
- return result(lines.join("\n"));
793
- }
794
- const targetOrError = resolveTarget("chain", params.chainName!, findChains(params.chainName!, ctx, scopeHint ?? "both"), ctx, params.agentScope);
795
- if ("content" in targetOrError) return targetOrError;
796
- const target = targetOrError;
797
- fs.unlinkSync(target.filePath);
798
- return result(`Deleted chain '${target.name}' at ${target.filePath}.`);
799
- }
800
-
801
- export function handleManagementAction(action: string, params: ManagementParams, ctx: ManagementContext): SubagentExecutionResult {
802
- if (params.agentScope !== undefined && normalizeListScope(params.agentScope) === undefined) {
803
- return result("agentScope must be 'user', 'project', or 'both'.", true);
804
- }
805
- switch (action as ManagementAction) {
806
- case "list": return handleList(params, ctx);
807
- case "get": return handleGet(params, ctx);
808
- case "create": return handleCreate(params, ctx);
809
- case "update": return handleUpdate(params, ctx);
810
- case "delete": return handleDelete(params, ctx);
811
- default: return result(`Unknown action: ${action}`, true);
812
- }
76
+ const agent = params.agent ?? "";
77
+ const chain = params.chainName ?? "";
78
+ if (agent.length === 0 && chain.length === 0) {
79
+ return result("Specify 'agent' or 'chainName' for get.", true);
80
+ }
81
+ const scope = normalizeListScope(params.agentScope);
82
+ if (scope === undefined) {
83
+ return result("agentScope must be 'user', 'project', or 'both'.", true);
84
+ }
85
+ const blocks = [
86
+ ...(agent.length > 0 ? [getBlocks("agent", agent, ctx, scope)] : []),
87
+ ...(chain.length > 0 ? [getBlocks("chain", chain, ctx, scope)] : []),
88
+ ];
89
+ return result(
90
+ blocks.flatMap((block) => block.blocks).join("\n\n"),
91
+ !blocks.some((block) => block.found),
92
+ );
93
+ }
94
+ export function handleManagementAction(
95
+ action: string,
96
+ params: ManagementParams,
97
+ ctx: ManagementContext,
98
+ ): SubagentExecutionResult {
99
+ if (params.agentScope !== undefined && normalizeListScope(params.agentScope) === undefined) {
100
+ return result("agentScope must be 'user', 'project', or 'both'.", true);
101
+ }
102
+ switch (action) {
103
+ case "list":
104
+ return handleList(params, ctx);
105
+ case "get":
106
+ return handleGet(params, ctx);
107
+ case "create":
108
+ return handleCreate(params, ctx);
109
+ case "update":
110
+ return handleUpdate(params, ctx);
111
+ case "delete":
112
+ return handleDelete(params, ctx);
113
+ default:
114
+ return result(`Unknown action: ${action}`, true);
115
+ }
813
116
  }