@fitchmultz/pi-subagents 0.44.6 → 0.45.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 (947) hide show
  1. package/CHANGELOG.md +265 -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 +79 -0
  111. package/dist/pi-intercom/bridge-http.js +86 -0
  112. package/dist/pi-intercom/bridge-protocol.js +106 -0
  113. package/dist/pi-intercom/bridge-routes.js +64 -0
  114. package/dist/pi-intercom/bridge-session.js +416 -0
  115. package/dist/pi-intercom/bridge.js +182 -603
  116. package/dist/pi-intercom/broker/broker.js +236 -244
  117. package/dist/pi-intercom/broker/client.js +189 -304
  118. package/dist/pi-intercom/broker/connection.js +165 -0
  119. package/dist/pi-intercom/broker/framing.js +5 -3
  120. package/dist/pi-intercom/broker/paths.js +4 -1
  121. package/dist/pi-intercom/broker/pid.js +53 -25
  122. package/dist/pi-intercom/broker/snapshot-reader.js +78 -0
  123. package/dist/pi-intercom/broker/snapshots.js +188 -0
  124. package/dist/pi-intercom/broker/spawn.js +36 -25
  125. package/dist/pi-intercom/config.js +85 -71
  126. package/dist/pi-intercom/connection.js +297 -0
  127. package/dist/pi-intercom/identity.js +58 -0
  128. package/dist/pi-intercom/inbound-delivery.js +356 -0
  129. package/dist/pi-intercom/inbound-journal.js +303 -0
  130. package/dist/pi-intercom/inbound-record.js +113 -0
  131. package/dist/pi-intercom/inbound.js +179 -0
  132. package/dist/pi-intercom/index.js +79 -2933
  133. package/dist/pi-intercom/inspection.js +62 -0
  134. package/dist/pi-intercom/interview.js +236 -0
  135. package/dist/pi-intercom/lifecycle.js +168 -0
  136. package/dist/pi-intercom/message-format.js +69 -0
  137. package/dist/pi-intercom/outbound.js +304 -0
  138. package/dist/pi-intercom/peer-awareness.js +66 -0
  139. package/dist/pi-intercom/reply-tracker.js +62 -43
  140. package/dist/pi-intercom/reply-wait.js +201 -0
  141. package/dist/pi-intercom/runtime-types.js +3 -0
  142. package/dist/pi-intercom/session-events.js +180 -0
  143. package/dist/pi-intercom/session-targets.js +42 -34
  144. package/dist/pi-intercom/subagent-events.js +238 -0
  145. package/dist/pi-intercom/subagent-live-events.js +129 -86
  146. package/dist/pi-intercom/supervisor.js +282 -0
  147. package/dist/pi-intercom/tool-arguments.js +74 -0
  148. package/dist/pi-intercom/tool-registration.js +95 -0
  149. package/dist/pi-intercom/tool-results.js +38 -0
  150. package/dist/pi-intercom/tool-schemas.js +82 -0
  151. package/dist/pi-intercom/tools.js +51 -0
  152. package/dist/pi-intercom/topic-actions.js +177 -0
  153. package/dist/pi-intercom/topics.js +177 -92
  154. package/dist/pi-intercom/transport.js +1 -0
  155. package/dist/pi-intercom/types.js +151 -114
  156. package/dist/pi-intercom/ui/compose-paste.js +93 -0
  157. package/dist/pi-intercom/ui/compose.js +121 -143
  158. package/dist/pi-intercom/ui/inline-message.js +59 -59
  159. package/dist/pi-intercom/ui/message-renderers.js +147 -0
  160. package/dist/pi-intercom/ui/overlay.js +181 -0
  161. package/dist/pi-intercom/ui/session-format.js +124 -0
  162. package/dist/pi-intercom/ui/session-list.js +76 -43
  163. package/dist/pi-intercom/ui/tool-renderers.js +110 -0
  164. package/dist/pi-intercom/ui/topic-view.js +88 -0
  165. package/dist/pi-intercom/validation.js +59 -0
  166. package/dist/runs/background/async-chain-plan.js +265 -0
  167. package/dist/runs/background/async-control.js +134 -58
  168. package/dist/runs/background/async-execution.js +136 -633
  169. package/dist/runs/background/async-job-admission.js +40 -0
  170. package/dist/runs/background/async-job-projection.js +169 -0
  171. package/dist/runs/background/async-job-tracker.js +297 -327
  172. package/dist/runs/background/async-launch.js +216 -0
  173. package/dist/runs/background/async-plan.js +116 -0
  174. package/dist/runs/background/async-result-file.js +47 -23
  175. package/dist/runs/background/async-resume.js +195 -253
  176. package/dist/runs/background/async-run-discovery.js +213 -0
  177. package/dist/runs/background/async-run-location.js +135 -0
  178. package/dist/runs/background/async-run-record.js +1 -0
  179. package/dist/runs/background/async-run-repair.js +223 -0
  180. package/dist/runs/background/async-run-summary.js +1 -0
  181. package/dist/runs/background/async-single-plan.js +105 -0
  182. package/dist/runs/background/async-status-projection.js +155 -0
  183. package/dist/runs/background/async-status-render.js +117 -0
  184. package/dist/runs/background/async-status-validation.js +181 -0
  185. package/dist/runs/background/async-status.js +3 -442
  186. package/dist/runs/background/async-value.js +21 -0
  187. package/dist/runs/background/completion-dedupe.js +36 -12
  188. package/dist/runs/background/completion-delivery.js +211 -205
  189. package/dist/runs/background/completion-receipts.js +237 -0
  190. package/dist/runs/background/legacy-status-acceptance.js +34 -0
  191. package/dist/runs/background/notify.js +96 -48
  192. package/dist/runs/background/parallel-groups.js +36 -19
  193. package/dist/runs/background/result-payload.js +178 -0
  194. package/dist/runs/background/result-watcher.js +348 -339
  195. package/dist/runs/background/run-id-resolver.js +53 -33
  196. package/dist/runs/background/run-schemas.js +189 -0
  197. package/dist/runs/background/run-status-contracts.js +14 -0
  198. package/dist/runs/background/run-status-render.js +270 -0
  199. package/dist/runs/background/run-status.js +231 -339
  200. package/dist/runs/background/runner-attempt-output.js +155 -0
  201. package/dist/runs/background/runner-attempt.js +263 -0
  202. package/dist/runs/background/runner-child-executor.js +166 -0
  203. package/dist/runs/background/runner-child-observer.js +192 -0
  204. package/dist/runs/background/runner-completion-summary.js +71 -0
  205. package/dist/runs/background/runner-completion.js +211 -0
  206. package/dist/runs/background/runner-config.js +1 -0
  207. package/dist/runs/background/runner-contract.js +1 -0
  208. package/dist/runs/background/runner-dynamic.js +121 -0
  209. package/dist/runs/background/runner-finalization.js +149 -0
  210. package/dist/runs/background/runner-graph.js +68 -0
  211. package/dist/runs/background/runner-initial-status.js +60 -0
  212. package/dist/runs/background/runner-lifecycle.js +142 -0
  213. package/dist/runs/background/runner-monitor.js +309 -0
  214. package/dist/runs/background/runner-parallel.js +204 -0
  215. package/dist/runs/background/runner-prepare-step.js +86 -0
  216. package/dist/runs/background/runner-reporting.js +153 -0
  217. package/dist/runs/background/runner-status.js +148 -0
  218. package/dist/runs/background/runner-step-output.js +92 -0
  219. package/dist/runs/background/runner-step-record.js +45 -0
  220. package/dist/runs/background/runner-step.js +112 -0
  221. package/dist/runs/background/runner-streaming.js +173 -0
  222. package/dist/runs/background/runner-workflow.js +213 -0
  223. package/dist/runs/background/stale-run-reconciler.js +155 -292
  224. package/dist/runs/background/subagent-runner-launcher.js +33 -13
  225. package/dist/runs/background/subagent-runner.js +51 -1842
  226. package/dist/runs/background/top-level-async.js +2 -1
  227. package/dist/runs/foreground/chain-clarify.js +293 -1017
  228. package/dist/runs/foreground/clarification-draft.js +87 -0
  229. package/dist/runs/foreground/clarify-contracts.js +1 -0
  230. package/dist/runs/foreground/clarify-invocation.js +129 -38
  231. package/dist/runs/foreground/clarify-text-editor.js +210 -0
  232. package/dist/runs/foreground/clarify-view.js +167 -0
  233. package/dist/runs/foreground/execution-input.js +226 -353
  234. package/dist/runs/foreground/execution-routing.js +33 -0
  235. package/dist/runs/foreground/execution-timeout.js +81 -0
  236. package/dist/runs/foreground/foreground-control.js +222 -763
  237. package/dist/runs/foreground/foreground-memory.js +99 -0
  238. package/dist/runs/foreground/invocation-context.js +55 -0
  239. package/dist/runs/foreground/invocation-execution.js +331 -0
  240. package/dist/runs/foreground/invocation-expansion.js +48 -0
  241. package/dist/runs/foreground/management-actions.js +295 -0
  242. package/dist/runs/foreground/nested-control.js +179 -0
  243. package/dist/runs/foreground/question-continuation.js +78 -0
  244. package/dist/runs/foreground/question-control.js +155 -50
  245. package/dist/runs/foreground/resume-target.js +221 -0
  246. package/dist/runs/foreground/revival-launch-policy.js +58 -0
  247. package/dist/runs/foreground/run-async-path.js +190 -178
  248. package/dist/runs/foreground/run-interrupt.js +164 -0
  249. package/dist/runs/foreground/run-nudge.js +278 -0
  250. package/dist/runs/foreground/saved-revival.js +251 -0
  251. package/dist/runs/foreground/subagent-executor.js +135 -424
  252. package/dist/runs/foreground/subagent-params.js +67 -30
  253. package/dist/runs/foreground/wait-observation.js +104 -0
  254. package/dist/runs/foreground/wait-registration.js +17 -0
  255. package/dist/runs/foreground/wait-run.js +283 -123
  256. package/dist/runs/shared/acceptance-contract.js +193 -99
  257. package/dist/runs/shared/acceptance-defaults.js +1 -0
  258. package/dist/runs/shared/acceptance-evaluation.js +201 -181
  259. package/dist/runs/shared/acceptance-finalization.js +256 -180
  260. package/dist/runs/shared/acceptance-outcome.js +53 -0
  261. package/dist/runs/shared/acceptance-reports.js +137 -72
  262. package/dist/runs/shared/acceptance-submission.js +167 -0
  263. package/dist/runs/shared/acceptance-verification.js +100 -0
  264. package/dist/runs/shared/chain-outputs.js +80 -52
  265. package/dist/runs/shared/child-attempt-types.js +1 -0
  266. package/dist/runs/shared/child-attempt.js +314 -667
  267. package/dist/runs/shared/child-boundaries.js +173 -0
  268. package/dist/runs/shared/child-context-filter.js +44 -0
  269. package/dist/runs/shared/child-event-observer.js +390 -0
  270. package/dist/runs/shared/child-execution-cwd.js +73 -43
  271. package/dist/runs/shared/child-execution-outcome.js +72 -0
  272. package/dist/runs/shared/child-invocation.js +54 -0
  273. package/dist/runs/shared/child-message-validation.js +215 -0
  274. package/dist/runs/shared/child-native-accounting.js +106 -0
  275. package/dist/runs/shared/child-native-observation.js +69 -0
  276. package/dist/runs/shared/child-observation-spool.js +164 -0
  277. package/dist/runs/shared/child-observations.js +157 -76
  278. package/dist/runs/shared/child-presence.js +3 -0
  279. package/dist/runs/shared/child-route-env.js +119 -0
  280. package/dist/runs/shared/child-stream-observer.js +221 -0
  281. package/dist/runs/shared/child-stream-projection.js +137 -0
  282. package/dist/runs/shared/child-structured-tool.js +27 -0
  283. package/dist/runs/shared/claude-code.js +121 -158
  284. package/dist/runs/shared/claude-model.js +42 -0
  285. package/dist/runs/shared/claude-session.js +83 -0
  286. package/dist/runs/shared/claude-types.js +1 -0
  287. package/dist/runs/shared/completion-guard.js +18 -18
  288. package/dist/runs/shared/control-event-policy.js +8 -0
  289. package/dist/runs/shared/control-notification-owner.js +13 -0
  290. package/dist/runs/shared/dynamic-fanout.js +188 -173
  291. package/dist/runs/shared/dynamic-item.js +102 -0
  292. package/dist/runs/shared/history-index.js +62 -36
  293. package/dist/runs/shared/legacy-async-recovery.js +114 -0
  294. package/dist/runs/shared/legacy-output-recovery.js +148 -0
  295. package/dist/runs/shared/mcp-config-schema.js +36 -0
  296. package/dist/runs/shared/mcp-direct-tool-allowlist.js +147 -116
  297. package/dist/runs/shared/model-fallback.js +97 -38
  298. package/dist/runs/shared/mutating-tool-guard.js +128 -88
  299. package/dist/runs/shared/native-finalization-types.js +1 -0
  300. package/dist/runs/shared/native-finalization.js +155 -76
  301. package/dist/runs/shared/native-usage.js +238 -98
  302. package/dist/runs/shared/nested-control-records.js +128 -0
  303. package/dist/runs/shared/nested-events.js +8 -700
  304. package/dist/runs/shared/nested-path.js +32 -28
  305. package/dist/runs/shared/nested-projection.js +155 -0
  306. package/dist/runs/shared/nested-protocol.js +18 -0
  307. package/dist/runs/shared/nested-registry.js +191 -0
  308. package/dist/runs/shared/nested-render.js +106 -58
  309. package/dist/runs/shared/nested-route.js +220 -0
  310. package/dist/runs/shared/nested-validation.js +216 -0
  311. package/dist/runs/shared/owned-child-evidence.js +125 -0
  312. package/dist/runs/shared/owned-run-list.js +146 -0
  313. package/dist/runs/shared/owned-run-observation.js +267 -0
  314. package/dist/runs/shared/owned-run-progress.js +109 -0
  315. package/dist/runs/shared/owned-run-read-state.js +1 -0
  316. package/dist/runs/shared/owned-run-results.js +202 -0
  317. package/dist/runs/shared/owned-run-status.js +180 -0
  318. package/dist/runs/shared/owned-run-view.js +51 -0
  319. package/dist/runs/shared/owned-workflow-details.js +17 -0
  320. package/dist/runs/shared/owner-output.js +43 -0
  321. package/dist/runs/shared/parallel-utils.js +36 -28
  322. package/dist/runs/shared/parent-receipts.js +90 -32
  323. package/dist/runs/shared/parent-usage.js +169 -57
  324. package/dist/runs/shared/pi-args.js +108 -201
  325. package/dist/runs/shared/pi-launch-input.js +1 -0
  326. package/dist/runs/shared/pi-session-launch.js +86 -0
  327. package/dist/runs/shared/pi-spawn.js +35 -21
  328. package/dist/runs/shared/run-history-queries.js +126 -35
  329. package/dist/runs/shared/run-history.js +101 -35
  330. package/dist/runs/shared/run-metadata-paths.js +14 -0
  331. package/dist/runs/shared/run-metadata.js +158 -0
  332. package/dist/runs/shared/run-persistence.js +131 -0
  333. package/dist/runs/shared/run-records.js +9 -679
  334. package/dist/runs/shared/run-restoration.js +338 -0
  335. package/dist/runs/shared/run-state-owner.js +26 -0
  336. package/dist/runs/shared/session-cwd-preload.js +27 -18
  337. package/dist/runs/shared/single-output.js +148 -70
  338. package/dist/runs/shared/stable-value.js +15 -0
  339. package/dist/runs/shared/streaming-text.js +23 -12
  340. package/dist/runs/shared/structured-output.js +25 -13
  341. package/dist/runs/shared/subagent-control.js +167 -100
  342. package/dist/runs/shared/subagent-prompt-runtime.js +27 -130
  343. package/dist/runs/shared/subagent-tool-loop-guard.js +81 -52
  344. package/dist/runs/shared/supervisor-question-state.js +145 -0
  345. package/dist/runs/shared/supervisor-questions.js +185 -254
  346. package/dist/runs/shared/workflow-graph.js +259 -167
  347. package/dist/runs/shared/workflow-policy.js +120 -48
  348. package/dist/runs/shared/worktree-contract.js +1 -0
  349. package/dist/runs/shared/worktree-hook.js +138 -0
  350. package/dist/runs/shared/worktree-location.js +47 -0
  351. package/dist/runs/shared/worktree-preservation.js +8 -0
  352. package/dist/runs/shared/worktree-process.js +107 -0
  353. package/dist/runs/shared/worktree.js +183 -322
  354. package/dist/shared/agent-context-policy.js +34 -44
  355. package/dist/shared/agent-dir.js +14 -0
  356. package/dist/shared/artifacts.js +30 -12
  357. package/dist/shared/atomic-json.js +4 -1
  358. package/dist/shared/chain-files.js +72 -0
  359. package/dist/shared/concurrency.js +18 -0
  360. package/dist/shared/content-preview.js +115 -0
  361. package/dist/shared/cooperative.js +5 -2
  362. package/dist/shared/execution-cwd.js +13 -5
  363. package/dist/shared/file-coalescer.js +2 -1
  364. package/dist/shared/fork-context.js +10 -12
  365. package/dist/shared/formatters.js +45 -19
  366. package/dist/shared/journal-frames.js +164 -0
  367. package/dist/shared/journal-projections.js +121 -0
  368. package/dist/shared/journal-reader.js +6 -407
  369. package/dist/shared/json-projection.js +191 -0
  370. package/dist/shared/lazy-tools.js +19 -8
  371. package/dist/shared/message-output.js +116 -0
  372. package/dist/shared/model-info.js +31 -14
  373. package/dist/shared/native-import.js +20 -0
  374. package/dist/shared/native-journal.js +140 -0
  375. package/dist/shared/native-session.js +5 -2
  376. package/dist/shared/native-tui.js +7 -2
  377. package/dist/shared/native-typebox.js +15 -3
  378. package/dist/shared/output-page.js +63 -0
  379. package/dist/shared/post-exit-stdio-guard.js +128 -88
  380. package/dist/shared/prompt-sections.js +2 -0
  381. package/dist/shared/session-entries.js +70 -35
  382. package/dist/shared/session-identity.js +5 -3
  383. package/dist/shared/settings.js +62 -192
  384. package/dist/shared/status-format.js +97 -37
  385. package/dist/shared/task-file-policy.js +24 -0
  386. package/dist/shared/temp-root.js +44 -15
  387. package/dist/shared/types/acceptance.js +1 -0
  388. package/dist/shared/types/async.js +1 -0
  389. package/dist/shared/types/config.js +1 -0
  390. package/dist/shared/types/details.js +1 -0
  391. package/dist/shared/types/history.js +1 -0
  392. package/dist/shared/types/inputs.js +1 -0
  393. package/dist/shared/types/intercom.js +1 -0
  394. package/dist/shared/types/launch.js +1 -0
  395. package/dist/shared/types/messages.js +1 -0
  396. package/dist/shared/types/nested.js +1 -0
  397. package/dist/shared/types/owned-runs.js +1 -0
  398. package/dist/shared/types/progress.js +1 -0
  399. package/dist/shared/types/questions.js +1 -0
  400. package/dist/shared/types/results.js +1 -0
  401. package/dist/shared/types/state.js +1 -0
  402. package/dist/shared/types/usage.js +1 -0
  403. package/dist/shared/types/workflow.js +1 -0
  404. package/dist/shared/types.js +75 -30
  405. package/dist/shared/unknown.js +52 -0
  406. package/dist/shared/utils.js +54 -260
  407. package/dist/slash/command-discovery.js +82 -0
  408. package/dist/slash/command-input.js +190 -0
  409. package/dist/slash/prompt-template-bridge.js +94 -270
  410. package/dist/slash/prompt-template-contract.js +77 -0
  411. package/dist/slash/prompt-template-results.js +125 -0
  412. package/dist/slash/request-protocol.js +68 -0
  413. package/dist/slash/result-delivery.js +237 -0
  414. package/dist/slash/saved-chain.js +78 -0
  415. package/dist/slash/slash-bridge.js +123 -89
  416. package/dist/slash/slash-commands.js +101 -572
  417. package/dist/slash/slash-live-state.js +68 -47
  418. package/dist/tui/action-hints.js +50 -22
  419. package/dist/tui/activity-lines.js +32 -0
  420. package/dist/tui/agent-browser.js +290 -0
  421. package/dist/tui/agent-controls.js +289 -0
  422. package/dist/tui/agent-conversation.js +444 -0
  423. package/dist/tui/agent-dock.js +171 -0
  424. package/dist/tui/agent-history.js +50 -183
  425. package/dist/tui/agent-model.js +62 -0
  426. package/dist/tui/agent-picker.js +262 -0
  427. package/dist/tui/agent-view.js +232 -1537
  428. package/dist/tui/compact-results.js +193 -0
  429. package/dist/tui/conversation-details.js +190 -0
  430. package/dist/tui/conversation-frame.js +135 -0
  431. package/dist/tui/conversation-history.js +201 -0
  432. package/dist/tui/conversation-menu.js +78 -0
  433. package/dist/tui/conversation-notices.js +79 -0
  434. package/dist/tui/conversation-selection.js +58 -0
  435. package/dist/tui/conversation-viewport.js +129 -0
  436. package/dist/tui/direction-message.js +27 -0
  437. package/dist/tui/display.js +282 -0
  438. package/dist/tui/editor-viewport.js +18 -0
  439. package/dist/tui/expanded-content.js +87 -0
  440. package/dist/tui/expanded-multi.js +170 -0
  441. package/dist/tui/expanded-single.js +65 -0
  442. package/dist/tui/history-cards.js +216 -0
  443. package/dist/tui/history-display.js +238 -0
  444. package/dist/tui/history-json.js +16 -0
  445. package/dist/tui/history-metadata.js +152 -0
  446. package/dist/tui/history-record.js +251 -0
  447. package/dist/tui/history-text.js +34 -0
  448. package/dist/tui/indexed-history.js +116 -0
  449. package/dist/tui/nested-widget.js +120 -0
  450. package/dist/tui/picker-page.js +59 -0
  451. package/dist/tui/render.js +58 -1501
  452. package/dist/tui/result-facts.js +64 -0
  453. package/dist/tui/task-observation.js +59 -0
  454. package/dist/tui/task-store.js +366 -0
  455. package/dist/tui/text-values.js +16 -0
  456. package/dist/tui/view-connections.js +47 -0
  457. package/dist/tui/view-model.js +94 -0
  458. package/dist/tui/view-persistence.js +51 -0
  459. package/dist/tui/view-ports.js +1 -0
  460. package/dist/tui/view-session.js +37 -0
  461. package/dist/tui/widget-details.js +144 -0
  462. package/dist/tui/widget-status.js +245 -0
  463. package/dist/tui/widget.js +145 -0
  464. package/dist/tui/workflow-labels.js +223 -0
  465. package/dist/tui/workflow-outcomes.js +124 -0
  466. package/docs/code-quality.md +38 -0
  467. package/docs/development.md +99 -0
  468. package/docs/intercom-bridge.md +23 -18
  469. package/docs/intercom.md +132 -106
  470. package/docs/performance.md +19 -17
  471. package/docs/reference.md +1472 -0
  472. package/generated/RunValidators.d.ts +28 -0
  473. package/generated/RunValidators.js +2 -0
  474. package/package.json +27 -6
  475. package/prompts/parallel-cleanup.md +3 -0
  476. package/prompts/parallel-context-build.md +3 -0
  477. package/prompts/parallel-handoff-plan.md +6 -0
  478. package/prompts/parallel-research.md +4 -0
  479. package/prompts/parallel-review.md +2 -0
  480. package/prompts/review-loop.md +2 -0
  481. package/scripts/build.mjs +129 -85
  482. package/scripts/check-compat.mjs +48 -11
  483. package/scripts/compat-host.mjs +35 -7
  484. package/scripts/generate-run-schemas.mjs +210 -0
  485. package/scripts/intercom-bridge-credentials.mjs +155 -28
  486. package/scripts/intercom-remote.mjs +175 -50
  487. package/scripts/local-install-smoke.mjs +47 -37
  488. package/scripts/native-package-smoke.mjs +135 -25
  489. package/scripts/package-smoke.mjs +360 -140
  490. package/scripts/prepare.mjs +54 -34
  491. package/scripts/real-pi-processes.mjs +261 -0
  492. package/scripts/real-pi-smoke.mjs +432 -351
  493. package/scripts/run-tests.mjs +29 -15
  494. package/skills/pi-intercom/SKILL.md +11 -11
  495. package/skills/pi-intercom/references/peer-sessions.md +7 -2
  496. package/skills/pi-subagents/SKILL.md +1 -1
  497. package/skills/pi-subagents/references/full-orchestration-guide.md +254 -112
  498. package/src/agents/agent-defaults.ts +13 -0
  499. package/src/agents/agent-definition.ts +253 -0
  500. package/src/agents/agent-management.ts +111 -808
  501. package/src/agents/agent-scope.ts +7 -3
  502. package/src/agents/agent-selection.ts +26 -16
  503. package/src/agents/agent-serializer.ts +84 -93
  504. package/src/agents/agents.ts +199 -906
  505. package/src/agents/builtin-overrides.ts +297 -0
  506. package/src/agents/chain-serializer.ts +3 -329
  507. package/src/agents/config-values.ts +57 -0
  508. package/src/agents/discovery-paths.ts +134 -0
  509. package/src/agents/frontmatter.ts +35 -17
  510. package/src/agents/identity.ts +49 -18
  511. package/src/agents/json-chain.ts +305 -0
  512. package/src/agents/management-config.ts +342 -0
  513. package/src/agents/management-format.ts +243 -0
  514. package/src/agents/management-persistence.ts +408 -0
  515. package/src/agents/management-targets.ts +260 -0
  516. package/src/agents/management-warnings.ts +115 -0
  517. package/src/agents/markdown-chain.ts +237 -0
  518. package/src/agents/package-agents.ts +231 -0
  519. package/src/agents/skill-files.ts +182 -0
  520. package/src/agents/skill-search-paths.ts +289 -0
  521. package/src/agents/skill-types.ts +31 -0
  522. package/src/agents/skills.ts +152 -610
  523. package/src/extension/acceptance-schema.ts +88 -0
  524. package/src/extension/chain-schema.ts +276 -0
  525. package/src/extension/child-runtime.ts +302 -0
  526. package/src/extension/compact-tools.ts +259 -102
  527. package/src/extension/config-schema.ts +59 -0
  528. package/src/extension/config.ts +39 -17
  529. package/src/extension/control-notice-schema.ts +55 -0
  530. package/src/extension/control-notices.ts +57 -33
  531. package/src/extension/delegation-bridges.ts +59 -0
  532. package/src/extension/doctor.ts +171 -135
  533. package/src/extension/everyday-schemas.ts +252 -0
  534. package/src/extension/fanout-child.ts +29 -308
  535. package/src/extension/index.ts +17 -642
  536. package/src/extension/message-renderers.ts +334 -0
  537. package/src/extension/nested-control-inbox.ts +196 -0
  538. package/src/extension/parent-runtime.ts +405 -0
  539. package/src/extension/primary-tool.ts +130 -0
  540. package/src/extension/result-snapshot.ts +35 -0
  541. package/src/extension/runtime-reload.ts +72 -0
  542. package/src/extension/runtime-storage.ts +49 -0
  543. package/src/extension/schema-overrides.ts +114 -0
  544. package/src/extension/schemas.ts +451 -418
  545. package/src/extension/tool-input.ts +40 -13
  546. package/src/extension/tool-result.ts +45 -14
  547. package/src/history/answer-texts.ts +74 -0
  548. package/src/history/canonical-result.ts +127 -51
  549. package/src/history/canonical-selection.ts +54 -0
  550. package/src/history/database-generation.ts +86 -0
  551. package/src/history/database.ts +86 -48
  552. package/src/history/entry-ingestion.ts +129 -0
  553. package/src/history/index.ts +426 -148
  554. package/src/history/ingest.ts +372 -342
  555. package/src/history/output-digests.ts +41 -0
  556. package/src/history/preview.ts +235 -0
  557. package/src/history/prune.ts +48 -0
  558. package/src/history/queries.ts +122 -256
  559. package/src/history/query-scope.ts +278 -0
  560. package/src/history/rows.ts +118 -0
  561. package/src/history/run-projection.ts +164 -0
  562. package/src/history/run-queries.ts +199 -0
  563. package/src/history/schema.ts +34 -0
  564. package/src/history/search-queries.ts +216 -0
  565. package/src/history/selected-record.ts +140 -0
  566. package/src/history/source-file.ts +51 -0
  567. package/src/history/source-watches.ts +156 -0
  568. package/src/history/store.ts +310 -197
  569. package/src/history/text-chunks.ts +181 -0
  570. package/src/history/text.ts +43 -0
  571. package/src/history/transcript-queries.ts +251 -0
  572. package/src/history/types.ts +27 -164
  573. package/src/history/values.ts +36 -0
  574. package/src/history/wire-inputs.ts +141 -0
  575. package/src/history/wire-models.ts +51 -0
  576. package/src/history/worker-runtime.ts +502 -0
  577. package/src/history/worker.ts +94 -336
  578. package/src/intercom/intercom-bridge.ts +136 -69
  579. package/src/intercom/live-intercom.ts +197 -92
  580. package/src/intercom/nested-result-tree.ts +213 -0
  581. package/src/intercom/result-delivery.ts +56 -0
  582. package/src/intercom/result-intercom.ts +364 -382
  583. package/src/pi-intercom/agent-dir.ts +9 -3
  584. package/src/pi-intercom/async.ts +33 -0
  585. package/src/pi-intercom/bridge-ask.ts +64 -0
  586. package/src/pi-intercom/bridge-config.ts +101 -0
  587. package/src/pi-intercom/bridge-http.ts +97 -0
  588. package/src/pi-intercom/bridge-protocol.ts +123 -0
  589. package/src/pi-intercom/bridge-routes.ts +90 -0
  590. package/src/pi-intercom/bridge-session.ts +506 -0
  591. package/src/pi-intercom/bridge.ts +258 -547
  592. package/src/pi-intercom/broker/broker.ts +326 -263
  593. package/src/pi-intercom/broker/client.ts +273 -354
  594. package/src/pi-intercom/broker/connection.ts +192 -0
  595. package/src/pi-intercom/broker/framing.ts +11 -6
  596. package/src/pi-intercom/broker/paths.ts +28 -25
  597. package/src/pi-intercom/broker/pid.ts +68 -24
  598. package/src/pi-intercom/broker/snapshot-reader.ts +91 -0
  599. package/src/pi-intercom/broker/snapshots.ts +241 -0
  600. package/src/pi-intercom/broker/spawn.ts +58 -34
  601. package/src/pi-intercom/config.ts +113 -108
  602. package/src/pi-intercom/connection.ts +346 -0
  603. package/src/pi-intercom/identity.ts +71 -0
  604. package/src/pi-intercom/inbound-delivery.ts +450 -0
  605. package/src/pi-intercom/inbound-journal.ts +350 -0
  606. package/src/pi-intercom/inbound-record.ts +141 -0
  607. package/src/pi-intercom/inbound.ts +237 -0
  608. package/src/pi-intercom/index.ts +86 -2923
  609. package/src/pi-intercom/inspection.ts +82 -0
  610. package/src/pi-intercom/interview.ts +295 -0
  611. package/src/pi-intercom/lifecycle.ts +183 -0
  612. package/src/pi-intercom/message-format.ts +77 -0
  613. package/src/pi-intercom/outbound.ts +418 -0
  614. package/src/pi-intercom/peer-awareness.ts +84 -0
  615. package/src/pi-intercom/reply-tracker.ts +121 -59
  616. package/src/pi-intercom/reply-wait.ts +247 -0
  617. package/src/pi-intercom/runtime-types.ts +97 -0
  618. package/src/pi-intercom/session-events.ts +247 -0
  619. package/src/pi-intercom/session-targets.ts +124 -72
  620. package/src/pi-intercom/subagent-events.ts +299 -0
  621. package/src/pi-intercom/subagent-live-events.ts +212 -109
  622. package/src/pi-intercom/supervisor.ts +362 -0
  623. package/src/pi-intercom/tool-arguments.ts +120 -0
  624. package/src/pi-intercom/tool-registration.ts +121 -0
  625. package/src/pi-intercom/tool-results.ts +54 -0
  626. package/src/pi-intercom/tool-schemas.ts +134 -0
  627. package/src/pi-intercom/tools.ts +80 -0
  628. package/src/pi-intercom/topic-actions.ts +243 -0
  629. package/src/pi-intercom/topics.ts +267 -121
  630. package/src/pi-intercom/transport.ts +14 -0
  631. package/src/pi-intercom/types.ts +288 -190
  632. package/src/pi-intercom/ui/compose-paste.ts +109 -0
  633. package/src/pi-intercom/ui/compose.ts +173 -157
  634. package/src/pi-intercom/ui/inline-message.ts +80 -62
  635. package/src/pi-intercom/ui/message-renderers.ts +182 -0
  636. package/src/pi-intercom/ui/overlay.ts +238 -0
  637. package/src/pi-intercom/ui/session-format.ts +146 -0
  638. package/src/pi-intercom/ui/session-list.ts +145 -62
  639. package/src/pi-intercom/ui/tool-renderers.ts +148 -0
  640. package/src/pi-intercom/ui/topic-view.ts +107 -0
  641. package/src/pi-intercom/validation.ts +69 -0
  642. package/src/runs/background/async-chain-plan.ts +451 -0
  643. package/src/runs/background/async-control.ts +201 -71
  644. package/src/runs/background/async-execution.ts +206 -829
  645. package/src/runs/background/async-job-admission.ts +54 -0
  646. package/src/runs/background/async-job-projection.ts +225 -0
  647. package/src/runs/background/async-job-tracker.ts +416 -360
  648. package/src/runs/background/async-launch.ts +319 -0
  649. package/src/runs/background/async-plan.ts +285 -0
  650. package/src/runs/background/async-result-file.ts +79 -37
  651. package/src/runs/background/async-resume.ts +338 -285
  652. package/src/runs/background/async-run-discovery.ts +270 -0
  653. package/src/runs/background/async-run-location.ts +194 -0
  654. package/src/runs/background/async-run-record.ts +14 -0
  655. package/src/runs/background/async-run-repair.ts +307 -0
  656. package/src/runs/background/async-run-summary.ts +71 -0
  657. package/src/runs/background/async-single-plan.ts +168 -0
  658. package/src/runs/background/async-status-projection.ts +188 -0
  659. package/src/runs/background/async-status-render.ts +164 -0
  660. package/src/runs/background/async-status-validation.ts +238 -0
  661. package/src/runs/background/async-status.ts +9 -481
  662. package/src/runs/background/async-value.ts +29 -0
  663. package/src/runs/background/completion-dedupe.ts +103 -54
  664. package/src/runs/background/completion-delivery.ts +313 -187
  665. package/src/runs/background/completion-receipts.ts +309 -0
  666. package/src/runs/background/legacy-status-acceptance.ts +38 -0
  667. package/src/runs/background/notify.ts +167 -106
  668. package/src/runs/background/parallel-groups.ts +95 -46
  669. package/src/runs/background/result-payload.ts +268 -0
  670. package/src/runs/background/result-watcher.ts +484 -387
  671. package/src/runs/background/run-id-resolver.ts +126 -57
  672. package/src/runs/background/run-schemas.ts +240 -0
  673. package/src/runs/background/run-status-contracts.ts +46 -0
  674. package/src/runs/background/run-status-render.ts +364 -0
  675. package/src/runs/background/run-status.ts +338 -356
  676. package/src/runs/background/runner-attempt-output.ts +281 -0
  677. package/src/runs/background/runner-attempt.ts +354 -0
  678. package/src/runs/background/runner-child-executor.ts +232 -0
  679. package/src/runs/background/runner-child-observer.ts +270 -0
  680. package/src/runs/background/runner-completion-summary.ts +106 -0
  681. package/src/runs/background/runner-completion.ts +274 -0
  682. package/src/runs/background/runner-config.ts +52 -0
  683. package/src/runs/background/runner-contract.ts +51 -0
  684. package/src/runs/background/runner-dynamic.ts +185 -0
  685. package/src/runs/background/runner-finalization.ts +203 -0
  686. package/src/runs/background/runner-graph.ts +91 -0
  687. package/src/runs/background/runner-initial-status.ts +72 -0
  688. package/src/runs/background/runner-lifecycle.ts +159 -0
  689. package/src/runs/background/runner-monitor.ts +399 -0
  690. package/src/runs/background/runner-parallel.ts +280 -0
  691. package/src/runs/background/runner-prepare-step.ts +128 -0
  692. package/src/runs/background/runner-reporting.ts +192 -0
  693. package/src/runs/background/runner-status.ts +220 -0
  694. package/src/runs/background/runner-step-output.ts +158 -0
  695. package/src/runs/background/runner-step-record.ts +76 -0
  696. package/src/runs/background/runner-step.ts +150 -0
  697. package/src/runs/background/runner-streaming.ts +220 -0
  698. package/src/runs/background/runner-workflow.ts +284 -0
  699. package/src/runs/background/stale-run-reconciler.ts +279 -336
  700. package/src/runs/background/subagent-runner-launcher.ts +67 -35
  701. package/src/runs/background/subagent-runner.ts +80 -2048
  702. package/src/runs/background/top-level-async.ts +9 -7
  703. package/src/runs/foreground/chain-clarify.ts +499 -1334
  704. package/src/runs/foreground/clarification-draft.ts +92 -0
  705. package/src/runs/foreground/clarify-contracts.ts +33 -0
  706. package/src/runs/foreground/clarify-invocation.ts +192 -65
  707. package/src/runs/foreground/clarify-text-editor.ts +229 -0
  708. package/src/runs/foreground/clarify-view.ts +222 -0
  709. package/src/runs/foreground/execution-input.ts +358 -424
  710. package/src/runs/foreground/execution-routing.ts +41 -0
  711. package/src/runs/foreground/execution-timeout.ts +92 -0
  712. package/src/runs/foreground/foreground-control.ts +333 -812
  713. package/src/runs/foreground/foreground-memory.ts +132 -0
  714. package/src/runs/foreground/invocation-context.ts +88 -0
  715. package/src/runs/foreground/invocation-execution.ts +465 -0
  716. package/src/runs/foreground/invocation-expansion.ts +58 -0
  717. package/src/runs/foreground/management-actions.ts +360 -0
  718. package/src/runs/foreground/nested-control.ts +248 -0
  719. package/src/runs/foreground/question-continuation.ts +112 -0
  720. package/src/runs/foreground/question-control.ts +297 -70
  721. package/src/runs/foreground/resume-target.ts +330 -0
  722. package/src/runs/foreground/revival-launch-policy.ts +112 -0
  723. package/src/runs/foreground/run-async-path.ts +307 -223
  724. package/src/runs/foreground/run-interrupt.ts +202 -0
  725. package/src/runs/foreground/run-nudge.ts +355 -0
  726. package/src/runs/foreground/saved-revival.ts +356 -0
  727. package/src/runs/foreground/subagent-executor.ts +195 -493
  728. package/src/runs/foreground/subagent-params.ts +314 -242
  729. package/src/runs/foreground/wait-observation.ts +160 -0
  730. package/src/runs/foreground/wait-registration.ts +18 -0
  731. package/src/runs/foreground/wait-run.ts +361 -119
  732. package/src/runs/shared/acceptance-contract.ts +410 -209
  733. package/src/runs/shared/acceptance-defaults.ts +1 -0
  734. package/src/runs/shared/acceptance-evaluation.ts +314 -240
  735. package/src/runs/shared/acceptance-finalization.ts +447 -305
  736. package/src/runs/shared/acceptance-outcome.ts +69 -0
  737. package/src/runs/shared/acceptance-reports.ts +220 -126
  738. package/src/runs/shared/acceptance-submission.ts +251 -0
  739. package/src/runs/shared/acceptance-verification.ts +118 -0
  740. package/src/runs/shared/acceptance.ts +25 -25
  741. package/src/runs/shared/chain-outputs.ts +190 -98
  742. package/src/runs/shared/child-attempt-types.ts +118 -0
  743. package/src/runs/shared/child-attempt.ts +372 -608
  744. package/src/runs/shared/child-boundaries.ts +217 -0
  745. package/src/runs/shared/child-context-filter.ts +53 -0
  746. package/src/runs/shared/child-event-observer.ts +496 -0
  747. package/src/runs/shared/child-execution-cwd.ts +139 -68
  748. package/src/runs/shared/child-execution-outcome.ts +103 -0
  749. package/src/runs/shared/child-invocation.ts +74 -0
  750. package/src/runs/shared/child-message-validation.ts +233 -0
  751. package/src/runs/shared/child-native-accounting.ts +154 -0
  752. package/src/runs/shared/child-native-observation.ts +79 -0
  753. package/src/runs/shared/child-observation-spool.ts +188 -0
  754. package/src/runs/shared/child-observations.ts +219 -89
  755. package/src/runs/shared/child-presence.ts +6 -0
  756. package/src/runs/shared/child-route-env.ts +142 -0
  757. package/src/runs/shared/child-stream-observer.ts +302 -0
  758. package/src/runs/shared/child-stream-projection.ts +160 -0
  759. package/src/runs/shared/child-structured-tool.ts +38 -0
  760. package/src/runs/shared/claude-code.ts +201 -228
  761. package/src/runs/shared/claude-model.ts +67 -0
  762. package/src/runs/shared/claude-session.ts +124 -0
  763. package/src/runs/shared/claude-types.ts +31 -0
  764. package/src/runs/shared/completion-guard.ts +35 -26
  765. package/src/runs/shared/control-event-policy.ts +15 -0
  766. package/src/runs/shared/control-notification-owner.ts +20 -0
  767. package/src/runs/shared/dynamic-fanout.ts +402 -238
  768. package/src/runs/shared/dynamic-item.ts +114 -0
  769. package/src/runs/shared/history-index.ts +112 -51
  770. package/src/runs/shared/legacy-async-recovery.ts +153 -0
  771. package/src/runs/shared/legacy-output-recovery.ts +214 -0
  772. package/src/runs/shared/mcp-config-schema.ts +46 -0
  773. package/src/runs/shared/mcp-direct-tool-allowlist.ts +396 -307
  774. package/src/runs/shared/model-fallback.ts +302 -180
  775. package/src/runs/shared/mutating-tool-guard.ts +259 -158
  776. package/src/runs/shared/native-finalization-types.ts +29 -0
  777. package/src/runs/shared/native-finalization.ts +233 -109
  778. package/src/runs/shared/native-usage.ts +379 -96
  779. package/src/runs/shared/nested-control-records.ts +178 -0
  780. package/src/runs/shared/nested-events.ts +45 -752
  781. package/src/runs/shared/nested-path.ts +47 -34
  782. package/src/runs/shared/nested-projection.ts +230 -0
  783. package/src/runs/shared/nested-protocol.ts +67 -0
  784. package/src/runs/shared/nested-registry.ts +273 -0
  785. package/src/runs/shared/nested-render.ts +198 -100
  786. package/src/runs/shared/nested-route.ts +292 -0
  787. package/src/runs/shared/nested-validation.ts +291 -0
  788. package/src/runs/shared/owned-child-evidence.ts +184 -0
  789. package/src/runs/shared/owned-run-list.ts +187 -0
  790. package/src/runs/shared/owned-run-observation.ts +368 -0
  791. package/src/runs/shared/owned-run-progress.ts +172 -0
  792. package/src/runs/shared/owned-run-read-state.ts +7 -0
  793. package/src/runs/shared/owned-run-results.ts +289 -0
  794. package/src/runs/shared/owned-run-status.ts +239 -0
  795. package/src/runs/shared/owned-run-view.ts +65 -0
  796. package/src/runs/shared/owned-workflow-details.ts +24 -0
  797. package/src/runs/shared/owner-output.ts +73 -0
  798. package/src/runs/shared/parallel-utils.ts +93 -129
  799. package/src/runs/shared/parent-receipts.ts +177 -50
  800. package/src/runs/shared/parent-usage.ts +314 -91
  801. package/src/runs/shared/pi-args.ts +241 -311
  802. package/src/runs/shared/pi-launch-input.ts +48 -0
  803. package/src/runs/shared/pi-session-launch.ts +94 -0
  804. package/src/runs/shared/pi-spawn.ts +57 -33
  805. package/src/runs/shared/run-history-queries.ts +189 -38
  806. package/src/runs/shared/run-history.ts +197 -76
  807. package/src/runs/shared/run-id-ambiguity.ts +7 -3
  808. package/src/runs/shared/run-metadata-paths.ts +17 -0
  809. package/src/runs/shared/run-metadata.ts +240 -0
  810. package/src/runs/shared/run-persistence.ts +181 -0
  811. package/src/runs/shared/run-records.ts +19 -607
  812. package/src/runs/shared/run-restoration.ts +455 -0
  813. package/src/runs/shared/run-state-owner.ts +31 -0
  814. package/src/runs/shared/session-cwd-preload.ts +39 -19
  815. package/src/runs/shared/single-output.ts +358 -205
  816. package/src/runs/shared/stable-value.ts +15 -0
  817. package/src/runs/shared/streaming-text.ts +39 -12
  818. package/src/runs/shared/structured-output.ts +76 -46
  819. package/src/runs/shared/subagent-control.ts +330 -197
  820. package/src/runs/shared/subagent-prompt-runtime.ts +92 -174
  821. package/src/runs/shared/subagent-tool-loop-guard.ts +118 -68
  822. package/src/runs/shared/supervisor-question-state.ts +221 -0
  823. package/src/runs/shared/supervisor-questions.ts +396 -401
  824. package/src/runs/shared/workflow-graph.ts +400 -198
  825. package/src/runs/shared/workflow-policy.ts +245 -110
  826. package/src/runs/shared/worktree-contract.ts +29 -0
  827. package/src/runs/shared/worktree-hook.ts +181 -0
  828. package/src/runs/shared/worktree-location.ts +61 -0
  829. package/src/runs/shared/worktree-preservation.ts +10 -0
  830. package/src/runs/shared/worktree-process.ts +132 -0
  831. package/src/runs/shared/worktree.ts +459 -587
  832. package/src/shared/agent-context-policy.ts +176 -145
  833. package/src/shared/agent-dir.ts +15 -0
  834. package/src/shared/artifacts.ts +99 -68
  835. package/src/shared/atomic-json.ts +14 -11
  836. package/src/shared/chain-files.ts +72 -0
  837. package/src/shared/concurrency.ts +27 -0
  838. package/src/shared/content-preview.ts +117 -0
  839. package/src/shared/cooperative.ts +17 -13
  840. package/src/shared/execution-cwd.ts +34 -9
  841. package/src/shared/file-coalescer.ts +24 -22
  842. package/src/shared/fork-context.ts +52 -48
  843. package/src/shared/formatters.ts +88 -47
  844. package/src/shared/journal-frames.ts +197 -0
  845. package/src/shared/journal-projections.ts +133 -0
  846. package/src/shared/journal-reader.ts +18 -333
  847. package/src/shared/json-projection.ts +224 -0
  848. package/src/shared/lazy-tools.ts +76 -27
  849. package/src/shared/message-output.ts +146 -0
  850. package/src/shared/model-info.ts +94 -58
  851. package/src/shared/native-import.ts +25 -0
  852. package/src/shared/native-journal.ts +172 -0
  853. package/src/shared/native-session.ts +8 -3
  854. package/src/shared/native-tui.ts +13 -3
  855. package/src/shared/native-typebox.ts +18 -3
  856. package/src/shared/output-page.ts +76 -0
  857. package/src/shared/post-exit-stdio-guard.ts +232 -172
  858. package/src/shared/prompt-sections.ts +13 -7
  859. package/src/shared/session-entries.ts +103 -44
  860. package/src/shared/session-identity.ts +17 -10
  861. package/src/shared/settings.ts +182 -367
  862. package/src/shared/status-format.ts +207 -98
  863. package/src/shared/stream-json.d.ts +10 -0
  864. package/src/shared/task-file-policy.ts +35 -0
  865. package/src/shared/temp-root.ts +122 -71
  866. package/src/shared/types/acceptance.ts +149 -0
  867. package/src/shared/types/async.ts +247 -0
  868. package/src/shared/types/config.ts +139 -0
  869. package/src/shared/types/details.ts +104 -0
  870. package/src/shared/types/history.ts +217 -0
  871. package/src/shared/types/inputs.ts +4 -0
  872. package/src/shared/types/intercom.ts +57 -0
  873. package/src/shared/types/launch.ts +39 -0
  874. package/src/shared/types/messages.ts +104 -0
  875. package/src/shared/types/nested.ts +153 -0
  876. package/src/shared/types/owned-runs.ts +148 -0
  877. package/src/shared/types/progress.ts +106 -0
  878. package/src/shared/types/questions.ts +103 -0
  879. package/src/shared/types/results.ts +119 -0
  880. package/src/shared/types/state.ts +56 -0
  881. package/src/shared/types/usage.ts +36 -0
  882. package/src/shared/types/workflow.ts +187 -0
  883. package/src/shared/types.ts +222 -1161
  884. package/src/shared/ui-mode.ts +1 -1
  885. package/src/shared/unknown.ts +59 -0
  886. package/src/shared/utils.ts +111 -305
  887. package/src/slash/command-discovery.ts +109 -0
  888. package/src/slash/command-input.ts +232 -0
  889. package/src/slash/prompt-template-bridge.ts +153 -400
  890. package/src/slash/prompt-template-contract.ts +152 -0
  891. package/src/slash/prompt-template-results.ts +189 -0
  892. package/src/slash/request-protocol.ts +87 -0
  893. package/src/slash/result-delivery.ts +312 -0
  894. package/src/slash/saved-chain.ts +115 -0
  895. package/src/slash/slash-bridge.ts +202 -156
  896. package/src/slash/slash-commands.ts +176 -598
  897. package/src/slash/slash-live-state.ts +287 -229
  898. package/src/tui/action-hints.ts +147 -61
  899. package/src/tui/activity-lines.ts +40 -0
  900. package/src/tui/agent-browser.ts +354 -0
  901. package/src/tui/agent-controls.ts +355 -0
  902. package/src/tui/agent-conversation.ts +514 -0
  903. package/src/tui/agent-dock.ts +250 -0
  904. package/src/tui/agent-history.ts +78 -203
  905. package/src/tui/agent-model.ts +78 -0
  906. package/src/tui/agent-picker.ts +325 -0
  907. package/src/tui/agent-view.ts +391 -1310
  908. package/src/tui/compact-results.ts +342 -0
  909. package/src/tui/conversation-details.ts +206 -0
  910. package/src/tui/conversation-frame.ts +184 -0
  911. package/src/tui/conversation-history.ts +246 -0
  912. package/src/tui/conversation-menu.ts +119 -0
  913. package/src/tui/conversation-notices.ts +116 -0
  914. package/src/tui/conversation-selection.ts +66 -0
  915. package/src/tui/conversation-viewport.ts +169 -0
  916. package/src/tui/direction-message.ts +35 -0
  917. package/src/tui/display.ts +409 -0
  918. package/src/tui/editor-viewport.ts +19 -0
  919. package/src/tui/expanded-content.ts +134 -0
  920. package/src/tui/expanded-multi.ts +264 -0
  921. package/src/tui/expanded-single.ts +92 -0
  922. package/src/tui/history-cards.ts +316 -0
  923. package/src/tui/history-display.ts +334 -0
  924. package/src/tui/history-json.ts +17 -0
  925. package/src/tui/history-metadata.ts +177 -0
  926. package/src/tui/history-record.ts +321 -0
  927. package/src/tui/history-text.ts +34 -0
  928. package/src/tui/indexed-history.ts +149 -0
  929. package/src/tui/nested-widget.ts +192 -0
  930. package/src/tui/picker-page.ts +80 -0
  931. package/src/tui/render.ts +100 -1546
  932. package/src/tui/result-facts.ts +99 -0
  933. package/src/tui/task-observation.ts +96 -0
  934. package/src/tui/task-store.ts +432 -0
  935. package/src/tui/text-values.ts +20 -0
  936. package/src/tui/view-connections.ts +64 -0
  937. package/src/tui/view-model.ts +181 -0
  938. package/src/tui/view-persistence.ts +57 -0
  939. package/src/tui/view-ports.ts +55 -0
  940. package/src/tui/view-session.ts +42 -0
  941. package/src/tui/widget-details.ts +220 -0
  942. package/src/tui/widget-status.ts +331 -0
  943. package/src/tui/widget.ts +208 -0
  944. package/src/tui/workflow-labels.ts +340 -0
  945. package/src/tui/workflow-outcomes.ts +150 -0
  946. package/tsconfig.build.json +11 -10
  947. package/tsconfig.json +30 -17
@@ -7,18 +7,21 @@ import net from "net";
7
7
  import { getPiAgentDir } from "../agent-dir.js";
8
8
  import { getBrokerSocketPath, getLegacyBrokerSocketPath, isOwnedBrokerSocket } from "./paths.js";
9
9
  import { isBrokerPidReused } from "./pid.js";
10
+ import { errorMessage, hasErrorCode } from "../../shared/unknown.js";
10
11
  const INTERCOM_DIR = join(getPiAgentDir(), "intercom");
11
12
  const EXTENSION_DIR = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "..");
12
13
  const BROKER_PID = join(INTERCOM_DIR, "broker.pid");
13
14
  const BROKER_SPAWN_LOCK = join(INTERCOM_DIR, "broker.spawn.lock");
14
15
  function sleep(ms) {
15
- return new Promise(resolve => setTimeout(resolve, ms));
16
+ return new Promise((resolve) => {
17
+ setTimeout(resolve, ms);
18
+ });
16
19
  }
17
20
  function usesLegacyTsxDefault(brokerCommand, brokerArgs) {
18
- return brokerCommand === "npx"
19
- && brokerArgs.length === 2
20
- && brokerArgs[0] === "--no-install"
21
- && brokerArgs[1] === "tsx";
21
+ return (brokerCommand === "npx" &&
22
+ brokerArgs.length === 2 &&
23
+ brokerArgs[0] === "--no-install" &&
24
+ brokerArgs[1] === "tsx");
22
25
  }
23
26
  export function getBrokerLaunchSpec(brokerPath, brokerCommand, brokerArgs) {
24
27
  if (usesLegacyTsxDefault(brokerCommand, brokerArgs)) {
@@ -41,7 +44,7 @@ export function getBrokerSpawnOptions() {
41
44
  };
42
45
  }
43
46
  function toError(error) {
44
- return error instanceof Error ? error : new Error(String(error));
47
+ return error instanceof Error ? error : new Error(errorMessage(error));
45
48
  }
46
49
  export async function spawnBrokerIfNeeded(brokerCommand, brokerArgs) {
47
50
  await mkdir(INTERCOM_DIR, { recursive: true });
@@ -73,7 +76,7 @@ export async function spawnBrokerIfNeeded(brokerCommand, brokerArgs) {
73
76
  };
74
77
  const onExit = (code, signal) => {
75
78
  cleanup();
76
- if (signal) {
79
+ if (signal !== null) {
77
80
  reject(new Error(`Intercom broker exited before startup with signal ${signal}`));
78
81
  return;
79
82
  }
@@ -81,10 +84,12 @@ export async function spawnBrokerIfNeeded(brokerCommand, brokerArgs) {
81
84
  };
82
85
  child.once("error", onError);
83
86
  child.once("exit", onExit);
84
- waitForBroker().then(() => {
87
+ waitForBroker()
88
+ .then(() => {
85
89
  cleanup();
86
90
  resolve();
87
- }, (error) => {
91
+ })
92
+ .catch((error) => {
88
93
  cleanup();
89
94
  reject(toError(error));
90
95
  });
@@ -98,8 +103,9 @@ export async function isBrokerRunning() {
98
103
  return checkSocketConnectable();
99
104
  }
100
105
  function readLivePid() {
101
- if (!existsSync(BROKER_PID))
106
+ if (!existsSync(BROKER_PID)) {
102
107
  return null;
108
+ }
103
109
  let raw;
104
110
  try {
105
111
  raw = readFileSync(BROKER_PID, "utf-8");
@@ -108,30 +114,34 @@ function readLivePid() {
108
114
  return null;
109
115
  }
110
116
  const pid = parseInt(raw.trim(), 10);
111
- if (!Number.isFinite(pid) || pid <= 0)
117
+ if (!Number.isFinite(pid) || pid <= 0) {
112
118
  return null;
119
+ }
113
120
  try {
114
121
  process.kill(pid, 0);
115
122
  }
116
123
  catch (error) {
117
- return error.code === "EPERM" ? pid : null;
124
+ return hasErrorCode(error, "EPERM") ? pid : null;
118
125
  }
119
126
  return isBrokerPidReused(pid, raw) ? null : pid;
120
127
  }
121
128
  export async function stopUnhealthyBrokerBeforeSpawn() {
122
- if (await checkSocketConnectable())
129
+ if (await checkSocketConnectable()) {
123
130
  return;
131
+ }
124
132
  const pid = readLivePid();
125
- if (pid === null)
133
+ if (pid === null) {
126
134
  return;
135
+ }
127
136
  throw new Error(`Intercom broker PID ${pid} may still own accepted work but its socket is unhealthy; refusing to spawn a second broker. Let the broker exit normally, then retry.`);
128
137
  }
129
138
  async function checkSocketConnectable() {
130
139
  const preferred = getBrokerSocketPath();
131
- if (isOwnedBrokerSocket(preferred) && await checkOneSocket(preferred))
140
+ if (isOwnedBrokerSocket(preferred) && (await checkOneSocket(preferred))) {
132
141
  return true;
142
+ }
133
143
  const legacy = getLegacyBrokerSocketPath();
134
- return legacy !== preferred && isOwnedBrokerSocket(legacy) && await checkOneSocket(legacy);
144
+ return legacy !== preferred && isOwnedBrokerSocket(legacy) && (await checkOneSocket(legacy));
135
145
  }
136
146
  function checkOneSocket(brokerSocket) {
137
147
  return new Promise((resolve) => {
@@ -148,7 +158,7 @@ function checkOneSocket(brokerSocket) {
148
158
  socket.on("connect", onConnect);
149
159
  socket.on("error", onError);
150
160
  const timeout = setTimeout(() => finish(false), 1000);
151
- timeout.unref?.();
161
+ timeout.unref();
152
162
  });
153
163
  }
154
164
  function acquireSpawnLock() {
@@ -159,16 +169,11 @@ function acquireSpawnLock() {
159
169
  return true;
160
170
  }
161
171
  catch (error) {
162
- if (!(error instanceof Error) || error.code !== "EEXIST") {
172
+ if (!hasErrorCode(error, "EEXIST")) {
163
173
  throw error;
164
174
  }
165
175
  if (isSpawnLockStale()) {
166
- try {
167
- unlinkSync(BROKER_SPAWN_LOCK);
168
- }
169
- catch {
170
- // If we can't delete the stale lock, retry a few times before giving up
171
- }
176
+ releaseSpawnLock();
172
177
  continue;
173
178
  }
174
179
  return false;
@@ -181,7 +186,9 @@ function isSpawnLockStale() {
181
186
  return false;
182
187
  }
183
188
  try {
184
- const [pidLine = "", createdAtLine = "0"] = readFileSync(BROKER_SPAWN_LOCK, "utf-8").trim().split("\n");
189
+ const [pidLine = "", createdAtLine = "0"] = readFileSync(BROKER_SPAWN_LOCK, "utf-8")
190
+ .trim()
191
+ .split("\n");
185
192
  const pid = Number.parseInt(pidLine, 10);
186
193
  const createdAt = Number.parseInt(createdAtLine, 10);
187
194
  const ageMs = Date.now() - createdAt;
@@ -212,9 +219,13 @@ function releaseSpawnLock() {
212
219
  async function waitForBroker(timeoutMs = 5000) {
213
220
  const start = Date.now();
214
221
  while (Date.now() - start < timeoutMs) {
222
+ // Each probe must finish before the next to avoid parallel socket attempts.
223
+ // oxlint-disable-next-line no-await-in-loop
215
224
  if (await checkSocketConnectable()) {
216
225
  return;
217
226
  }
227
+ // Polling waits between probes rather than starting an unbounded batch.
228
+ // oxlint-disable-next-line no-await-in-loop
218
229
  await sleep(100);
219
230
  }
220
231
  throw new Error("Broker failed to start within timeout");
@@ -1,10 +1,8 @@
1
- import { existsSync, readFileSync } from "fs";
2
- import { join } from "path";
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
3
  import { Key } from "@earendil-works/pi-tui";
4
4
  import { getPiAgentDir } from "./agent-dir.js";
5
- function getConfigPath() {
6
- return join(getPiAgentDir(), "intercom", "config.json");
7
- }
5
+ import { isRecord, isUnknownArray } from "./validation.js";
8
6
  const defaults = {
9
7
  shortcut: Key.altShift("m"),
10
8
  brokerCommand: process.execPath,
@@ -20,80 +18,96 @@ function isShortcut(value) {
20
18
  const prefix = value.match(/^(?:(?:ctrl|shift|alt|super)\+)+/)?.[0] ?? "";
21
19
  const modifiers = prefix.split("+").filter(Boolean);
22
20
  const key = value.slice(prefix.length);
23
- return new Set(modifiers).size === modifiers.length && (namedKeys.has(key) || /^[a-z0-9]$/.test(key));
21
+ return (new Set(modifiers).size === modifiers.length && (namedKeys.has(key) || /^[a-z0-9]$/.test(key)));
22
+ }
23
+ function configuredString(parsed, key) {
24
+ if (!Object.hasOwn(parsed, key)) {
25
+ return defaults[key];
26
+ }
27
+ const value = parsed[key];
28
+ if (typeof value !== "string") {
29
+ throw new Error(`"${key}" must be a string`);
30
+ }
31
+ if (key === "status") {
32
+ return value;
33
+ }
34
+ if (value.trim() === "") {
35
+ throw new Error('"brokerCommand" must not be empty');
36
+ }
37
+ return value.trim();
38
+ }
39
+ function brokerCommand(parsed) {
40
+ return configuredString(parsed, "brokerCommand") ?? defaults.brokerCommand;
41
+ }
42
+ function configuredShortcut(parsed) {
43
+ if (!Object.hasOwn(parsed, "shortcut")) {
44
+ return defaults.shortcut;
45
+ }
46
+ if (typeof parsed.shortcut !== "string") {
47
+ throw new Error('"shortcut" must be a native key identifier');
48
+ }
49
+ const shortcut = parsed.shortcut.trim();
50
+ if (!isShortcut(shortcut)) {
51
+ throw new Error('"shortcut" must be a native key identifier, for example alt+shift+m');
52
+ }
53
+ return shortcut;
54
+ }
55
+ function configuredArgs(parsed) {
56
+ if (!Object.hasOwn(parsed, "brokerArgs")) {
57
+ return defaults.brokerArgs;
58
+ }
59
+ if (!isUnknownArray(parsed.brokerArgs)) {
60
+ throw new Error('"brokerArgs" must be an array');
61
+ }
62
+ return parsed.brokerArgs.map((arg) => {
63
+ if (typeof arg !== "string") {
64
+ throw new Error('"brokerArgs" items must be strings');
65
+ }
66
+ return arg;
67
+ });
68
+ }
69
+ function configuredBoolean(parsed, key) {
70
+ if (!Object.hasOwn(parsed, key)) {
71
+ return defaults[key];
72
+ }
73
+ const value = parsed[key];
74
+ if (typeof value !== "boolean") {
75
+ throw new Error(`"${key}" must be a boolean`);
76
+ }
77
+ return value;
78
+ }
79
+ function configuredTimeout(parsed, key) {
80
+ if (!Object.hasOwn(parsed, key)) {
81
+ return defaults[key];
82
+ }
83
+ const value = parsed[key];
84
+ const min = key === "askTimeoutMs" ? 1000 : 500;
85
+ if (typeof value !== "number" || !Number.isFinite(value) || value < min) {
86
+ throw new Error(`"${key}" must be a finite number >= ${min}`);
87
+ }
88
+ return value;
24
89
  }
25
90
  export function loadConfig() {
26
- const configPath = getConfigPath();
91
+ const configPath = join(getPiAgentDir(), "intercom", "config.json");
27
92
  if (!existsSync(configPath)) {
28
93
  return { ...defaults };
29
94
  }
30
95
  try {
31
- const raw = readFileSync(configPath, "utf-8");
32
- const parsed = JSON.parse(raw);
33
- if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
96
+ const parsed = JSON.parse(readFileSync(configPath, "utf-8"));
97
+ if (!isRecord(parsed)) {
34
98
  throw new Error("Config must be a JSON object");
35
99
  }
36
- const parsedConfig = parsed;
37
- const config = { ...defaults };
38
- if (Object.hasOwn(parsedConfig, "shortcut")) {
39
- if (typeof parsedConfig.shortcut !== "string")
40
- throw new Error('"shortcut" must be a native key identifier');
41
- const shortcut = parsedConfig.shortcut.trim();
42
- if (!isShortcut(shortcut))
43
- throw new Error('"shortcut" must be a native key identifier, for example alt+shift+m');
44
- config.shortcut = shortcut;
45
- }
46
- if (Object.hasOwn(parsedConfig, "brokerCommand")) {
47
- if (typeof parsedConfig.brokerCommand !== "string") {
48
- throw new Error(`"brokerCommand" must be a string`);
49
- }
50
- const brokerCommand = parsedConfig.brokerCommand.trim();
51
- if (!brokerCommand) {
52
- throw new Error(`"brokerCommand" must not be empty`);
53
- }
54
- config.brokerCommand = brokerCommand;
55
- }
56
- if (Object.hasOwn(parsedConfig, "brokerArgs")) {
57
- if (!Array.isArray(parsedConfig.brokerArgs)) {
58
- throw new Error(`"brokerArgs" must be an array`);
59
- }
60
- const brokerArgs = [];
61
- for (const arg of parsedConfig.brokerArgs) {
62
- if (typeof arg !== "string") {
63
- throw new Error(`"brokerArgs" items must be strings`);
64
- }
65
- brokerArgs.push(arg);
66
- }
67
- config.brokerArgs = brokerArgs;
68
- }
69
- if (Object.hasOwn(parsedConfig, "confirmSend")) {
70
- if (typeof parsedConfig.confirmSend !== "boolean") {
71
- throw new Error(`"confirmSend" must be a boolean`);
72
- }
73
- config.confirmSend = parsedConfig.confirmSend;
74
- }
75
- if (Object.hasOwn(parsedConfig, "replyHint")) {
76
- if (typeof parsedConfig.replyHint !== "boolean") {
77
- throw new Error(`"replyHint" must be a boolean`);
78
- }
79
- config.replyHint = parsedConfig.replyHint;
80
- }
81
- if (Object.hasOwn(parsedConfig, "status")) {
82
- if (typeof parsedConfig.status !== "string") {
83
- throw new Error(`"status" must be a string`);
84
- }
85
- config.status = parsedConfig.status;
86
- }
87
- for (const [key, min] of [["askTimeoutMs", 1000], ["sendTimeoutMs", 500], ["listTimeoutMs", 500]]) {
88
- if (Object.hasOwn(parsedConfig, key)) {
89
- const value = parsedConfig[key];
90
- if (typeof value !== "number" || !Number.isFinite(value) || value < min) {
91
- throw new Error(`"${key}" must be a finite number >= ${min}`);
92
- }
93
- config[key] = value;
94
- }
95
- }
96
- return config;
100
+ return {
101
+ shortcut: configuredShortcut(parsed),
102
+ brokerCommand: brokerCommand(parsed),
103
+ brokerArgs: configuredArgs(parsed),
104
+ confirmSend: configuredBoolean(parsed, "confirmSend"),
105
+ replyHint: configuredBoolean(parsed, "replyHint"),
106
+ status: configuredString(parsed, "status"),
107
+ askTimeoutMs: configuredTimeout(parsed, "askTimeoutMs"),
108
+ sendTimeoutMs: configuredTimeout(parsed, "sendTimeoutMs"),
109
+ listTimeoutMs: configuredTimeout(parsed, "listTimeoutMs"),
110
+ };
97
111
  }
98
112
  catch (error) {
99
113
  console.error(`Failed to load intercom config at ${configPath}:`, error);
@@ -0,0 +1,297 @@
1
+ import { createHash } from "node:crypto";
2
+ import { IntercomClient } from "./broker/client.js";
3
+ import { spawnBrokerIfNeeded } from "./broker/spawn.js";
4
+ import { asError, errorMessage } from "./validation.js";
5
+ import { formatTargetOptions, resolveSessionTarget } from "./session-targets.js";
6
+ /** Owns socket registration, coalesced connects and the reconnect/startup timers. */
7
+ export class IntercomConnection {
8
+ client = null;
9
+ reconnectTimer = null;
10
+ startupTimer = null;
11
+ connecting = null;
12
+ connectingGeneration = null;
13
+ attempt = 0;
14
+ syncError;
15
+ lifecycle;
16
+ config;
17
+ topics;
18
+ hooks;
19
+ constructor(lifecycle, config, topics, hooks) {
20
+ this.lifecycle = lifecycle;
21
+ this.config = config;
22
+ this.topics = topics;
23
+ this.hooks = hooks;
24
+ }
25
+ get active() {
26
+ return this.client;
27
+ }
28
+ get topicSyncError() {
29
+ return this.syncError;
30
+ }
31
+ get isConnecting() {
32
+ return this.startupTimer !== null || this.connecting !== null;
33
+ }
34
+ clearTopicSyncError() {
35
+ this.syncError = undefined;
36
+ }
37
+ start(ctx, generation) {
38
+ this.attempt = 0;
39
+ this.syncError = undefined;
40
+ this.clearTimers();
41
+ this.scheduleStartup(ctx, generation);
42
+ }
43
+ clearStartup() {
44
+ if (this.startupTimer) {
45
+ clearTimeout(this.startupTimer);
46
+ this.startupTimer = null;
47
+ }
48
+ }
49
+ clearReconnect() {
50
+ if (this.reconnectTimer) {
51
+ clearTimeout(this.reconnectTimer);
52
+ this.reconnectTimer = null;
53
+ }
54
+ }
55
+ clearTimers() {
56
+ this.clearStartup();
57
+ this.clearReconnect();
58
+ }
59
+ scheduleStartup(ctx, generation) {
60
+ this.clearStartup();
61
+ this.startupTimer = setTimeout(() => {
62
+ this.startupTimer = null;
63
+ if (!this.lifecycle.live(ctx, generation)) {
64
+ return;
65
+ }
66
+ this.ensure("startup").catch(() => {
67
+ if (!this.lifecycle.live(ctx, generation)) {
68
+ return;
69
+ }
70
+ this.client = null;
71
+ this.scheduleReconnect();
72
+ });
73
+ }, 0);
74
+ this.startupTimer.unref();
75
+ }
76
+ scheduleReconnect() {
77
+ if (this.reconnectTimer || this.connecting || !this.lifecycle.live()) {
78
+ return;
79
+ }
80
+ const generation = this.lifecycle.generation;
81
+ const delays = [1000, 2000, 5000, 10000, 30000];
82
+ const delay = delays[Math.min(this.attempt, delays.length - 1)] ?? 30000;
83
+ this.reconnectTimer = setTimeout(() => {
84
+ this.reconnectTimer = null;
85
+ if (this.lifecycle.generation !== generation || !this.lifecycle.live()) {
86
+ return;
87
+ }
88
+ this.attempt += 1;
89
+ this.ensure("background").catch(() => {
90
+ /* ensure owns the next retry after settlement. */
91
+ });
92
+ }, delay);
93
+ this.reconnectTimer.unref();
94
+ }
95
+ syncIdentity(sessionId) {
96
+ if (this.client && this.lifecycle.live()) {
97
+ this.client.updatePresence({
98
+ ...this.lifecycle.identity(sessionId),
99
+ status: this.lifecycle.status(),
100
+ ...this.lifecycle.health(this.hooks.pendingAsks()),
101
+ });
102
+ }
103
+ }
104
+ syncStatus() {
105
+ if (this.client && this.lifecycle.currentSessionId !== null && this.lifecycle.live()) {
106
+ this.client.updatePresence({
107
+ status: this.lifecycle.status(),
108
+ ...this.lifecycle.health(this.hooks.pendingAsks()),
109
+ });
110
+ }
111
+ }
112
+ createClient() {
113
+ const next = new IntercomClient({
114
+ sendTimeoutMs: this.config.sendTimeoutMs,
115
+ listTimeoutMs: this.config.listTimeoutMs,
116
+ });
117
+ this.client = next;
118
+ next.on("message", (from, message) => {
119
+ const ctx = this.lifecycle.live();
120
+ if (this.client !== next || !ctx) {
121
+ return;
122
+ }
123
+ this.hooks.incoming(ctx, from, message).catch((error) => {
124
+ console.error("Intercom inbound delivery failed:", error);
125
+ });
126
+ });
127
+ next.on("session_left", (id) => {
128
+ if (this.client !== next) {
129
+ return;
130
+ }
131
+ this.topics.disconnected(id);
132
+ this.hooks.peerLeft(id);
133
+ });
134
+ next.on("disconnected", (error) => {
135
+ if (this.client !== next) {
136
+ return;
137
+ }
138
+ this.hooks.disconnected(error);
139
+ this.client = null;
140
+ this.topics.disconnected();
141
+ this.clearReconnect();
142
+ this.scheduleReconnect();
143
+ });
144
+ next.on("error", () => {
145
+ /* Disconnect owns recovery; suppress socket noise in the TUI. */
146
+ });
147
+ return next;
148
+ }
149
+ async restoreTopics(active) {
150
+ const changes = [
151
+ ...[...this.topics.presence().topics].map((topic) => ({
152
+ action: "restore",
153
+ topic,
154
+ })),
155
+ ...[...this.topics.presence().subscriptions].map((subscription) => ({
156
+ action: "restore",
157
+ subscription,
158
+ })),
159
+ ];
160
+ let failure;
161
+ for (const change of changes) {
162
+ try {
163
+ // Restore order preserves publication/subscription admission and bounded transport pressure.
164
+ // oxlint-disable-next-line no-await-in-loop
165
+ await active.updateTopics(change);
166
+ }
167
+ catch (error) {
168
+ if (!active.isConnected()) {
169
+ throw error;
170
+ }
171
+ failure ??= errorMessage(error);
172
+ }
173
+ }
174
+ return failure;
175
+ }
176
+ async synchronizeTopics(next, ctx, generation) {
177
+ if (!next.supportsTopics) {
178
+ this.topics.disconnected();
179
+ return;
180
+ }
181
+ const failure = await this.restoreTopics(next);
182
+ const sessions = await next.listSessions();
183
+ if (!this.lifecycle.live(ctx, generation)) {
184
+ return;
185
+ }
186
+ this.syncError = failure;
187
+ this.topics.refresh(sessions);
188
+ if (failure !== undefined && failure !== "" && next.sessionId !== null) {
189
+ this.topics.disconnected(next.sessionId);
190
+ }
191
+ }
192
+ async connect(reason, ctx, generation, sessionId) {
193
+ const next = this.createClient();
194
+ try {
195
+ if (reason !== "peer-awareness") {
196
+ await spawnBrokerIfNeeded(this.config.brokerCommand, this.config.brokerArgs);
197
+ }
198
+ await next.connect(await this.lifecycle.registration(this.hooks.pendingAsks()), `pi-${createHash("sha256").update(sessionId).digest("hex").slice(0, 32)}`);
199
+ if (!this.lifecycle.live(ctx, generation)) {
200
+ await next.disconnect();
201
+ throw new Error("Intercom runtime no longer active");
202
+ }
203
+ this.client = next;
204
+ this.syncIdentity(ctx.sessionManager.getSessionId());
205
+ this.attempt = 0;
206
+ await this.synchronizeTopics(next, ctx, generation);
207
+ return next;
208
+ }
209
+ catch (error) {
210
+ if (this.client === next) {
211
+ this.client = null;
212
+ }
213
+ // A failed topic snapshot can leave a registered socket alive; the attempt still owns it.
214
+ await next.disconnect().catch((cleanupError) => {
215
+ console.error("Intercom failed connection cleanup:", cleanupError);
216
+ });
217
+ throw asError(error);
218
+ }
219
+ }
220
+ async ensure(reason) {
221
+ const generation = this.lifecycle.generation;
222
+ const restoring = this.hooks.restoring();
223
+ if (restoring) {
224
+ await restoring;
225
+ }
226
+ const ctx = this.lifecycle.live();
227
+ if (!ctx || generation !== this.lifecycle.generation) {
228
+ throw new Error("Intercom shutting down");
229
+ }
230
+ if (this.connecting && this.connectingGeneration === generation) {
231
+ return this.connecting;
232
+ }
233
+ if (this.client?.isConnected() === true) {
234
+ return this.client;
235
+ }
236
+ const sessionId = this.lifecycle.currentSessionId;
237
+ if (sessionId === null) {
238
+ throw new Error("Intercom runtime not initialized");
239
+ }
240
+ this.clearReconnect();
241
+ // Publish ownership before registration, which can synchronously invoke subscribers.
242
+ const attempt = Promise.resolve().then(() => this.connect(reason, ctx, generation, sessionId));
243
+ this.connecting = attempt;
244
+ this.connectingGeneration = generation;
245
+ return await this.finishAttempt(attempt, ctx, generation);
246
+ }
247
+ async finishAttempt(attempt, ctx, generation) {
248
+ let retry = false;
249
+ try {
250
+ return await attempt;
251
+ }
252
+ catch (error) {
253
+ retry = this.lifecycle.live(ctx, generation) !== null;
254
+ throw error;
255
+ }
256
+ finally {
257
+ if (this.connecting === attempt) {
258
+ this.connecting = null;
259
+ this.connectingGeneration = null;
260
+ }
261
+ if (retry) {
262
+ this.scheduleReconnect();
263
+ }
264
+ }
265
+ }
266
+ async shutdown() {
267
+ this.clearTimers();
268
+ // The bounded launcher attempt is joined before socket shutdown.
269
+ await Promise.allSettled([this.connecting]);
270
+ if (this.client) {
271
+ await this.client.disconnect();
272
+ this.client = null;
273
+ }
274
+ }
275
+ }
276
+ export async function resolveConnectedTarget(active, name) {
277
+ const sessions = await active.listSessions();
278
+ const resolution = resolveSessionTarget(sessions, name);
279
+ if (resolution.status === "found" && resolution.target) {
280
+ return resolution.target.id;
281
+ }
282
+ if (resolution.status === "ambiguous") {
283
+ throw new Error(`Target "${name}" matches multiple sessions. Use one of these targets: ${formatTargetOptions(resolution.matches, sessions)}.`);
284
+ }
285
+ if (resolution.status === "prefix_too_short") {
286
+ throw new Error(`Target "${name}" is too short. Use the displayed target from intercom list, such as ${formatTargetOptions(resolution.matches, sessions)}.`);
287
+ }
288
+ return null;
289
+ }
290
+ export async function resolvePeerHealth(active, id) {
291
+ try {
292
+ return (await active.listSessions()).find((session) => session.id === id) ?? null;
293
+ }
294
+ catch {
295
+ return null; /* Unknown health must not skip an ordinary blocking reply. */
296
+ }
297
+ }
@@ -0,0 +1,58 @@
1
+ function environmentText(name) {
2
+ return process.env[name]?.trim() ?? "";
3
+ }
4
+ export function readChildOrchestratorMetadata() {
5
+ const orchestratorTarget = environmentText("PI_SUBAGENT_ORCHESTRATOR_TARGET");
6
+ const runId = environmentText("PI_SUBAGENT_RUN_ID");
7
+ const agent = environmentText("PI_SUBAGENT_CHILD_AGENT");
8
+ const index = environmentText("PI_SUBAGENT_CHILD_INDEX");
9
+ if ([orchestratorTarget, runId, agent, index].includes("")) {
10
+ return null;
11
+ }
12
+ const sessionName = environmentText("PI_SUBAGENT_INTERCOM_SESSION_NAME");
13
+ return {
14
+ orchestratorTarget,
15
+ runId,
16
+ agent,
17
+ index,
18
+ ...(sessionName !== "" ? { sessionName } : {}),
19
+ };
20
+ }
21
+ export function formatChildOrchestratorMessage(kind, metadata, message) {
22
+ const headings = {
23
+ ask: "Subagent needs a supervisor decision.",
24
+ interview: "Subagent requests a structured supervisor interview.",
25
+ update: "Subagent progress update.",
26
+ };
27
+ return [
28
+ headings[kind],
29
+ `Run: ${metadata.runId}`,
30
+ `Agent: ${metadata.agent}`,
31
+ `Child index: ${metadata.index}`,
32
+ metadata.sessionName !== undefined && metadata.sessionName !== ""
33
+ ? `Child intercom target: ${metadata.sessionName}`
34
+ : undefined,
35
+ "",
36
+ message,
37
+ ]
38
+ .filter((line) => line !== undefined)
39
+ .join("\n");
40
+ }
41
+ export function resolveIntercomPresenceName(sessionName, sessionId) {
42
+ const name = sessionName?.trim();
43
+ if (name !== undefined && name !== "") {
44
+ return name;
45
+ }
46
+ const normalized = sessionId.startsWith("session-")
47
+ ? sessionId.slice("session-".length)
48
+ : sessionId;
49
+ return `subagent-chat-${normalized.slice(0, 8)}`;
50
+ }
51
+ export function buildPresenceIdentity(pi, sessionId) {
52
+ const name = process.env.PI_SUBAGENT_INTERCOM_SESSION_NAME?.trim();
53
+ return {
54
+ name: name !== undefined && name !== ""
55
+ ? name
56
+ : resolveIntercomPresenceName(pi.getSessionName(), sessionId),
57
+ };
58
+ }