@agimon-ai/doompi-team 0.0.1-alpha.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 (520) hide show
  1. package/LICENSE +25 -0
  2. package/README.md +46 -0
  3. package/dist/_virtual/_@oxc-project_runtime@0.127.0/helpers/decorate.cjs +1 -0
  4. package/dist/_virtual/_@oxc-project_runtime@0.127.0/helpers/decorate.mjs +1 -0
  5. package/dist/_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateMetadata.cjs +1 -0
  6. package/dist/_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateMetadata.mjs +1 -0
  7. package/dist/_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateParam.cjs +1 -0
  8. package/dist/_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateParam.mjs +1 -0
  9. package/dist/_virtual/_rolldown/runtime.cjs +1 -0
  10. package/dist/_virtual/_rolldown/runtime.mjs +1 -0
  11. package/dist/agents/discovery.cjs +2 -0
  12. package/dist/agents/discovery.cjs.map +1 -0
  13. package/dist/agents/discovery.mjs +2 -0
  14. package/dist/agents/discovery.mjs.map +1 -0
  15. package/dist/agents/frontmatter.cjs +10 -0
  16. package/dist/agents/frontmatter.cjs.map +1 -0
  17. package/dist/agents/frontmatter.mjs +10 -0
  18. package/dist/agents/frontmatter.mjs.map +1 -0
  19. package/dist/agents/loader.cjs +2 -0
  20. package/dist/agents/loader.cjs.map +1 -0
  21. package/dist/agents/loader.mjs +2 -0
  22. package/dist/agents/loader.mjs.map +1 -0
  23. package/dist/agents/memory.cjs +3 -0
  24. package/dist/agents/memory.cjs.map +1 -0
  25. package/dist/agents/memory.mjs +3 -0
  26. package/dist/agents/memory.mjs.map +1 -0
  27. package/dist/agents/projectRoot.cjs +2 -0
  28. package/dist/agents/projectRoot.cjs.map +1 -0
  29. package/dist/agents/projectRoot.mjs +2 -0
  30. package/dist/agents/projectRoot.mjs.map +1 -0
  31. package/dist/agents/settings.cjs +2 -0
  32. package/dist/agents/settings.cjs.map +1 -0
  33. package/dist/agents/settings.mjs +2 -0
  34. package/dist/agents/settings.mjs.map +1 -0
  35. package/dist/agents/skills.cjs +0 -0
  36. package/dist/agents/skills.cjs.map +1 -0
  37. package/dist/agents/skills.mjs +5 -0
  38. package/dist/agents/skills.mjs.map +1 -0
  39. package/dist/agents/types.d.cts +121 -0
  40. package/dist/agents/types.d.cts.map +1 -0
  41. package/dist/agents/types.d.mts +121 -0
  42. package/dist/agents/types.d.mts.map +1 -0
  43. package/dist/api/backgroundWork.cjs +1 -0
  44. package/dist/api/backgroundWork.d.cts +2 -0
  45. package/dist/api/backgroundWork.d.mts +2 -0
  46. package/dist/api/backgroundWork.mjs +1 -0
  47. package/dist/api/capabilityCeiling.cjs +1 -0
  48. package/dist/api/capabilityCeiling.d.cts +3 -0
  49. package/dist/api/capabilityCeiling.d.mts +3 -0
  50. package/dist/api/capabilityCeiling.mjs +2 -0
  51. package/dist/api/capabilityCeiling.mjs.map +1 -0
  52. package/dist/api/delegation.cjs +1 -0
  53. package/dist/api/delegation.d.cts +2 -0
  54. package/dist/api/delegation.d.mts +2 -0
  55. package/dist/api/delegation.mjs +1 -0
  56. package/dist/api/teamSnapshot.cjs +1 -0
  57. package/dist/api/teamSnapshot.d.cts +2 -0
  58. package/dist/api/teamSnapshot.d.mts +2 -0
  59. package/dist/api/teamSnapshot.mjs +2 -0
  60. package/dist/api/teamSnapshot.mjs.map +1 -0
  61. package/dist/container/bindOrRebind.cjs +2 -0
  62. package/dist/container/bindOrRebind.cjs.map +1 -0
  63. package/dist/container/bindOrRebind.mjs +2 -0
  64. package/dist/container/bindOrRebind.mjs.map +1 -0
  65. package/dist/container/globalBridge.cjs +2 -0
  66. package/dist/container/globalBridge.cjs.map +1 -0
  67. package/dist/container/globalBridge.d.cts +19 -0
  68. package/dist/container/globalBridge.d.cts.map +1 -0
  69. package/dist/container/globalBridge.d.mts +19 -0
  70. package/dist/container/globalBridge.d.mts.map +1 -0
  71. package/dist/container/globalBridge.mjs +2 -0
  72. package/dist/container/globalBridge.mjs.map +1 -0
  73. package/dist/container/index.cjs +2 -0
  74. package/dist/container/index.cjs.map +1 -0
  75. package/dist/container/index.d.cts +38 -0
  76. package/dist/container/index.d.cts.map +1 -0
  77. package/dist/container/index.d.mts +38 -0
  78. package/dist/container/index.d.mts.map +1 -0
  79. package/dist/container/index.mjs +2 -0
  80. package/dist/container/index.mjs.map +1 -0
  81. package/dist/container/modules/agents.cjs +2 -0
  82. package/dist/container/modules/agents.cjs.map +1 -0
  83. package/dist/container/modules/agents.d.cts +1 -0
  84. package/dist/container/modules/agents.d.mts +1 -0
  85. package/dist/container/modules/agents.mjs +2 -0
  86. package/dist/container/modules/agents.mjs.map +1 -0
  87. package/dist/container/modules/core.cjs +2 -0
  88. package/dist/container/modules/core.cjs.map +1 -0
  89. package/dist/container/modules/core.d.cts +1 -0
  90. package/dist/container/modules/core.d.mts +1 -0
  91. package/dist/container/modules/core.mjs +2 -0
  92. package/dist/container/modules/core.mjs.map +1 -0
  93. package/dist/container/modules/extensions.cjs +2 -0
  94. package/dist/container/modules/extensions.cjs.map +1 -0
  95. package/dist/container/modules/extensions.mjs +2 -0
  96. package/dist/container/modules/extensions.mjs.map +1 -0
  97. package/dist/container/modules/intercom.cjs +2 -0
  98. package/dist/container/modules/intercom.cjs.map +1 -0
  99. package/dist/container/modules/intercom.mjs +2 -0
  100. package/dist/container/modules/intercom.mjs.map +1 -0
  101. package/dist/container/modules/runs.cjs +2 -0
  102. package/dist/container/modules/runs.cjs.map +1 -0
  103. package/dist/container/modules/runs.mjs +2 -0
  104. package/dist/container/modules/runs.mjs.map +1 -0
  105. package/dist/container/types.cjs +2 -0
  106. package/dist/container/types.cjs.map +1 -0
  107. package/dist/container/types.d.cts +45 -0
  108. package/dist/container/types.d.cts.map +1 -0
  109. package/dist/container/types.d.mts +45 -0
  110. package/dist/container/types.d.mts.map +1 -0
  111. package/dist/container/types.mjs +2 -0
  112. package/dist/container/types.mjs.map +1 -0
  113. package/dist/env.cjs +2 -0
  114. package/dist/env.cjs.map +1 -0
  115. package/dist/env.d.cts +65 -0
  116. package/dist/env.d.cts.map +1 -0
  117. package/dist/env.d.mts +65 -0
  118. package/dist/env.d.mts.map +1 -0
  119. package/dist/env.mjs +2 -0
  120. package/dist/env.mjs.map +1 -0
  121. package/dist/extension.cjs +2 -0
  122. package/dist/extension.cjs.map +1 -0
  123. package/dist/extension.mjs +2 -0
  124. package/dist/extension.mjs.map +1 -0
  125. package/dist/extensions/config.cjs +2 -0
  126. package/dist/extensions/config.cjs.map +1 -0
  127. package/dist/extensions/config.mjs +2 -0
  128. package/dist/extensions/config.mjs.map +1 -0
  129. package/dist/extensions/delegationBridge.cjs +2 -0
  130. package/dist/extensions/delegationBridge.cjs.map +1 -0
  131. package/dist/extensions/delegationBridge.mjs +2 -0
  132. package/dist/extensions/delegationBridge.mjs.map +1 -0
  133. package/dist/extensions/doom.cjs +2 -0
  134. package/dist/extensions/doom.cjs.map +1 -0
  135. package/dist/extensions/doom.d.cts +8 -0
  136. package/dist/extensions/doom.d.cts.map +1 -0
  137. package/dist/extensions/doom.d.mts +8 -0
  138. package/dist/extensions/doom.d.mts.map +1 -0
  139. package/dist/extensions/doom.mjs +2 -0
  140. package/dist/extensions/doom.mjs.map +1 -0
  141. package/dist/extensions/fablePlanBridge.cjs +2 -0
  142. package/dist/extensions/fablePlanBridge.cjs.map +1 -0
  143. package/dist/extensions/fablePlanBridge.mjs +2 -0
  144. package/dist/extensions/fablePlanBridge.mjs.map +1 -0
  145. package/dist/extensions/managementActions.cjs +2 -0
  146. package/dist/extensions/managementActions.cjs.map +1 -0
  147. package/dist/extensions/managementActions.mjs +2 -0
  148. package/dist/extensions/managementActions.mjs.map +1 -0
  149. package/dist/extensions/operationJournal.cjs +2 -0
  150. package/dist/extensions/operationJournal.cjs.map +1 -0
  151. package/dist/extensions/operationJournal.mjs +2 -0
  152. package/dist/extensions/operationJournal.mjs.map +1 -0
  153. package/dist/extensions/orchestratorPrompt.cjs +35 -0
  154. package/dist/extensions/orchestratorPrompt.cjs.map +1 -0
  155. package/dist/extensions/orchestratorPrompt.mjs +35 -0
  156. package/dist/extensions/orchestratorPrompt.mjs.map +1 -0
  157. package/dist/extensions/pi.cjs +2 -0
  158. package/dist/extensions/pi.cjs.map +1 -0
  159. package/dist/extensions/pi.d.cts +2 -0
  160. package/dist/extensions/pi.d.mts +2 -0
  161. package/dist/extensions/pi.mjs +2 -0
  162. package/dist/extensions/pi.mjs.map +1 -0
  163. package/dist/extensions/schemas.cjs +1 -0
  164. package/dist/extensions/schemas.mjs +2 -0
  165. package/dist/extensions/schemas.mjs.map +1 -0
  166. package/dist/extensions/spawnPlan.cjs +3 -0
  167. package/dist/extensions/spawnPlan.cjs.map +1 -0
  168. package/dist/extensions/spawnPlan.mjs +3 -0
  169. package/dist/extensions/spawnPlan.mjs.map +1 -0
  170. package/dist/extensions/standard.cjs +2 -0
  171. package/dist/extensions/standard.cjs.map +1 -0
  172. package/dist/extensions/standard.d.cts +8 -0
  173. package/dist/extensions/standard.d.cts.map +1 -0
  174. package/dist/extensions/standard.d.mts +8 -0
  175. package/dist/extensions/standard.d.mts.map +1 -0
  176. package/dist/extensions/standard.mjs +2 -0
  177. package/dist/extensions/standard.mjs.map +1 -0
  178. package/dist/extensions/statusViews.cjs +7 -0
  179. package/dist/extensions/statusViews.cjs.map +1 -0
  180. package/dist/extensions/statusViews.mjs +7 -0
  181. package/dist/extensions/statusViews.mjs.map +1 -0
  182. package/dist/extensions/subagentPromptRuntime.cjs +18 -0
  183. package/dist/extensions/subagentPromptRuntime.cjs.map +1 -0
  184. package/dist/extensions/subagentPromptRuntime.d.cts +58 -0
  185. package/dist/extensions/subagentPromptRuntime.d.cts.map +1 -0
  186. package/dist/extensions/subagentPromptRuntime.d.mts +58 -0
  187. package/dist/extensions/subagentPromptRuntime.d.mts.map +1 -0
  188. package/dist/extensions/subagentPromptRuntime.mjs +18 -0
  189. package/dist/extensions/subagentPromptRuntime.mjs.map +1 -0
  190. package/dist/extensions/subagentPromptRuntimeEntry.cjs +2 -0
  191. package/dist/extensions/subagentPromptRuntimeEntry.cjs.map +1 -0
  192. package/dist/extensions/subagentPromptRuntimeEntry.d.cts +2 -0
  193. package/dist/extensions/subagentPromptRuntimeEntry.d.mts +2 -0
  194. package/dist/extensions/subagentPromptRuntimeEntry.mjs +2 -0
  195. package/dist/extensions/subagentPromptRuntimeEntry.mjs.map +1 -0
  196. package/dist/extensions/subagentTool.cjs +7 -0
  197. package/dist/extensions/subagentTool.cjs.map +1 -0
  198. package/dist/extensions/subagentTool.mjs +7 -0
  199. package/dist/extensions/subagentTool.mjs.map +1 -0
  200. package/dist/extensions/toolDescription.cjs +2 -0
  201. package/dist/extensions/toolDescription.cjs.map +1 -0
  202. package/dist/extensions/toolDescription.mjs +2 -0
  203. package/dist/extensions/toolDescription.mjs.map +1 -0
  204. package/dist/index.cjs +2 -0
  205. package/dist/index.cjs.map +1 -0
  206. package/dist/index.d.cts +34 -0
  207. package/dist/index.d.cts.map +1 -0
  208. package/dist/index.d.mts +34 -0
  209. package/dist/index.d.mts.map +1 -0
  210. package/dist/index.mjs +2 -0
  211. package/dist/index.mjs.map +1 -0
  212. package/dist/intercom/intercomBridge.cjs +2 -0
  213. package/dist/intercom/intercomBridge.cjs.map +1 -0
  214. package/dist/intercom/intercomBridge.mjs +2 -0
  215. package/dist/intercom/intercomBridge.mjs.map +1 -0
  216. package/dist/intercom/nativeTeamChannel.cjs +5 -0
  217. package/dist/intercom/nativeTeamChannel.cjs.map +1 -0
  218. package/dist/intercom/nativeTeamChannel.d.cts +22 -0
  219. package/dist/intercom/nativeTeamChannel.d.cts.map +1 -0
  220. package/dist/intercom/nativeTeamChannel.d.mts +22 -0
  221. package/dist/intercom/nativeTeamChannel.d.mts.map +1 -0
  222. package/dist/intercom/nativeTeamChannel.mjs +5 -0
  223. package/dist/intercom/nativeTeamChannel.mjs.map +1 -0
  224. package/dist/intercom/supervisorControlChannel.cjs +2 -0
  225. package/dist/intercom/supervisorControlChannel.cjs.map +1 -0
  226. package/dist/intercom/supervisorControlChannel.mjs +2 -0
  227. package/dist/intercom/supervisorControlChannel.mjs.map +1 -0
  228. package/dist/protocol/backgroundWork.cjs +2 -0
  229. package/dist/protocol/backgroundWork.cjs.map +1 -0
  230. package/dist/protocol/backgroundWork.d.cts +52 -0
  231. package/dist/protocol/backgroundWork.d.cts.map +1 -0
  232. package/dist/protocol/backgroundWork.d.mts +52 -0
  233. package/dist/protocol/backgroundWork.d.mts.map +1 -0
  234. package/dist/protocol/backgroundWork.mjs +2 -0
  235. package/dist/protocol/backgroundWork.mjs.map +1 -0
  236. package/dist/protocol/capabilityCeiling.cjs +2 -0
  237. package/dist/protocol/capabilityCeiling.cjs.map +1 -0
  238. package/dist/protocol/capabilityCeiling.d.cts +51 -0
  239. package/dist/protocol/capabilityCeiling.d.cts.map +1 -0
  240. package/dist/protocol/capabilityCeiling.d.mts +51 -0
  241. package/dist/protocol/capabilityCeiling.d.mts.map +1 -0
  242. package/dist/protocol/capabilityCeiling.mjs +2 -0
  243. package/dist/protocol/capabilityCeiling.mjs.map +1 -0
  244. package/dist/protocol/delegation.cjs +2 -0
  245. package/dist/protocol/delegation.cjs.map +1 -0
  246. package/dist/protocol/delegation.d.cts +269 -0
  247. package/dist/protocol/delegation.d.cts.map +1 -0
  248. package/dist/protocol/delegation.d.mts +269 -0
  249. package/dist/protocol/delegation.d.mts.map +1 -0
  250. package/dist/protocol/delegation.mjs +2 -0
  251. package/dist/protocol/delegation.mjs.map +1 -0
  252. package/dist/runs/background/asyncExecution.cjs +2 -0
  253. package/dist/runs/background/asyncExecution.cjs.map +1 -0
  254. package/dist/runs/background/asyncExecution.mjs +2 -0
  255. package/dist/runs/background/asyncExecution.mjs.map +1 -0
  256. package/dist/runs/background/asyncJobTracker.cjs +2 -0
  257. package/dist/runs/background/asyncJobTracker.cjs.map +1 -0
  258. package/dist/runs/background/asyncJobTracker.mjs +2 -0
  259. package/dist/runs/background/asyncJobTracker.mjs.map +1 -0
  260. package/dist/runs/background/cliRunnerEntry.cjs +2 -0
  261. package/dist/runs/background/cliRunnerEntry.cjs.map +1 -0
  262. package/dist/runs/background/cliRunnerEntry.d.cts +1 -0
  263. package/dist/runs/background/cliRunnerEntry.d.mts +1 -0
  264. package/dist/runs/background/cliRunnerEntry.mjs +2 -0
  265. package/dist/runs/background/cliRunnerEntry.mjs.map +1 -0
  266. package/dist/runs/background/completionBatcher.cjs +2 -0
  267. package/dist/runs/background/completionBatcher.cjs.map +1 -0
  268. package/dist/runs/background/completionBatcher.mjs +2 -0
  269. package/dist/runs/background/completionBatcher.mjs.map +1 -0
  270. package/dist/runs/background/notify.cjs +4 -0
  271. package/dist/runs/background/notify.cjs.map +1 -0
  272. package/dist/runs/background/notify.mjs +4 -0
  273. package/dist/runs/background/notify.mjs.map +1 -0
  274. package/dist/runs/background/parentWatchdog.cjs +2 -0
  275. package/dist/runs/background/parentWatchdog.cjs.map +1 -0
  276. package/dist/runs/background/parentWatchdog.mjs +2 -0
  277. package/dist/runs/background/parentWatchdog.mjs.map +1 -0
  278. package/dist/runs/background/processTerminal.cjs +2 -0
  279. package/dist/runs/background/processTerminal.cjs.map +1 -0
  280. package/dist/runs/background/processTerminal.mjs +2 -0
  281. package/dist/runs/background/processTerminal.mjs.map +1 -0
  282. package/dist/runs/background/resultWatcher.cjs +2 -0
  283. package/dist/runs/background/resultWatcher.cjs.map +1 -0
  284. package/dist/runs/background/resultWatcher.mjs +2 -0
  285. package/dist/runs/background/resultWatcher.mjs.map +1 -0
  286. package/dist/runs/background/runIdResolver.cjs +2 -0
  287. package/dist/runs/background/runIdResolver.cjs.map +1 -0
  288. package/dist/runs/background/runIdResolver.mjs +2 -0
  289. package/dist/runs/background/runIdResolver.mjs.map +1 -0
  290. package/dist/runs/background/runnerBootstrap.cjs +2 -0
  291. package/dist/runs/background/runnerBootstrap.cjs.map +1 -0
  292. package/dist/runs/background/runnerBootstrap.mjs +2 -0
  293. package/dist/runs/background/runnerBootstrap.mjs.map +1 -0
  294. package/dist/runs/background/runnerExecution.cjs +2 -0
  295. package/dist/runs/background/runnerExecution.cjs.map +1 -0
  296. package/dist/runs/background/runnerExecution.mjs +2 -0
  297. package/dist/runs/background/runnerExecution.mjs.map +1 -0
  298. package/dist/runs/background/runnerReporting.cjs +3 -0
  299. package/dist/runs/background/runnerReporting.cjs.map +1 -0
  300. package/dist/runs/background/runnerReporting.mjs +3 -0
  301. package/dist/runs/background/runnerReporting.mjs.map +1 -0
  302. package/dist/runs/background/runnerTeamMembership.cjs +2 -0
  303. package/dist/runs/background/runnerTeamMembership.cjs.map +1 -0
  304. package/dist/runs/background/runnerTeamMembership.mjs +2 -0
  305. package/dist/runs/background/runnerTeamMembership.mjs.map +1 -0
  306. package/dist/runs/background/spawnHandshake.cjs +2 -0
  307. package/dist/runs/background/spawnHandshake.cjs.map +1 -0
  308. package/dist/runs/background/spawnHandshake.mjs +2 -0
  309. package/dist/runs/background/spawnHandshake.mjs.map +1 -0
  310. package/dist/runs/background/staleRunReconciler.cjs +2 -0
  311. package/dist/runs/background/staleRunReconciler.cjs.map +1 -0
  312. package/dist/runs/background/staleRunReconciler.mjs +2 -0
  313. package/dist/runs/background/staleRunReconciler.mjs.map +1 -0
  314. package/dist/runs/background/statusReader.cjs +2 -0
  315. package/dist/runs/background/statusReader.cjs.map +1 -0
  316. package/dist/runs/background/statusReader.mjs +2 -0
  317. package/dist/runs/background/statusReader.mjs.map +1 -0
  318. package/dist/runs/background/statusWriter.cjs +2 -0
  319. package/dist/runs/background/statusWriter.cjs.map +1 -0
  320. package/dist/runs/background/statusWriter.mjs +2 -0
  321. package/dist/runs/background/statusWriter.mjs.map +1 -0
  322. package/dist/runs/background/subagentWait.cjs +2 -0
  323. package/dist/runs/background/subagentWait.cjs.map +1 -0
  324. package/dist/runs/background/subagentWait.mjs +2 -0
  325. package/dist/runs/background/subagentWait.mjs.map +1 -0
  326. package/dist/runs/background/terminalPersistence.cjs +2 -0
  327. package/dist/runs/background/terminalPersistence.cjs.map +1 -0
  328. package/dist/runs/background/terminalPersistence.mjs +2 -0
  329. package/dist/runs/background/terminalPersistence.mjs.map +1 -0
  330. package/dist/runs/registry/processGroup.cjs +2 -0
  331. package/dist/runs/registry/processGroup.cjs.map +1 -0
  332. package/dist/runs/registry/processGroup.mjs +2 -0
  333. package/dist/runs/registry/processGroup.mjs.map +1 -0
  334. package/dist/runs/registry/runRegistry.cjs +2 -0
  335. package/dist/runs/registry/runRegistry.cjs.map +1 -0
  336. package/dist/runs/registry/runRegistry.mjs +2 -0
  337. package/dist/runs/registry/runRegistry.mjs.map +1 -0
  338. package/dist/runs/registry/sessionLifecycle.cjs +2 -0
  339. package/dist/runs/registry/sessionLifecycle.cjs.map +1 -0
  340. package/dist/runs/registry/sessionLifecycle.mjs +2 -0
  341. package/dist/runs/registry/sessionLifecycle.mjs.map +1 -0
  342. package/dist/runs/registry/suspendedRuns.cjs +4 -0
  343. package/dist/runs/registry/suspendedRuns.cjs.map +1 -0
  344. package/dist/runs/registry/suspendedRuns.mjs +4 -0
  345. package/dist/runs/registry/suspendedRuns.mjs.map +1 -0
  346. package/dist/runs/sdkRunnerEntry.cjs +2 -0
  347. package/dist/runs/sdkRunnerEntry.cjs.map +1 -0
  348. package/dist/runs/sdkRunnerEntry.d.cts +1 -0
  349. package/dist/runs/sdkRunnerEntry.d.mts +1 -0
  350. package/dist/runs/sdkRunnerEntry.mjs +2 -0
  351. package/dist/runs/sdkRunnerEntry.mjs.map +1 -0
  352. package/dist/runs/shared/claudeFableProfile.cjs +4 -0
  353. package/dist/runs/shared/claudeFableProfile.cjs.map +1 -0
  354. package/dist/runs/shared/claudeFableProfile.mjs +4 -0
  355. package/dist/runs/shared/claudeFableProfile.mjs.map +1 -0
  356. package/dist/runs/shared/depthGuard.cjs +2 -0
  357. package/dist/runs/shared/depthGuard.cjs.map +1 -0
  358. package/dist/runs/shared/depthGuard.mjs +2 -0
  359. package/dist/runs/shared/depthGuard.mjs.map +1 -0
  360. package/dist/runs/shared/mcpDirectToolAllowlist.cjs +2 -0
  361. package/dist/runs/shared/mcpDirectToolAllowlist.cjs.map +1 -0
  362. package/dist/runs/shared/mcpDirectToolAllowlist.mjs +2 -0
  363. package/dist/runs/shared/mcpDirectToolAllowlist.mjs.map +1 -0
  364. package/dist/runs/shared/modelFallback.cjs +2 -0
  365. package/dist/runs/shared/modelFallback.cjs.map +1 -0
  366. package/dist/runs/shared/modelFallback.mjs +2 -0
  367. package/dist/runs/shared/modelFallback.mjs.map +1 -0
  368. package/dist/runs/shared/modelScope.cjs +2 -0
  369. package/dist/runs/shared/modelScope.cjs.map +1 -0
  370. package/dist/runs/shared/modelScope.mjs +2 -0
  371. package/dist/runs/shared/modelScope.mjs.map +1 -0
  372. package/dist/runs/shared/nestedPath.cjs +2 -0
  373. package/dist/runs/shared/nestedPath.cjs.map +1 -0
  374. package/dist/runs/shared/nestedPath.mjs +2 -0
  375. package/dist/runs/shared/nestedPath.mjs.map +1 -0
  376. package/dist/runs/shared/piArgs.cjs +2 -0
  377. package/dist/runs/shared/piArgs.cjs.map +1 -0
  378. package/dist/runs/shared/piArgs.mjs +2 -0
  379. package/dist/runs/shared/piArgs.mjs.map +1 -0
  380. package/dist/runs/shared/piSpawn.cjs +2 -0
  381. package/dist/runs/shared/piSpawn.cjs.map +1 -0
  382. package/dist/runs/shared/piSpawn.mjs +2 -0
  383. package/dist/runs/shared/piSpawn.mjs.map +1 -0
  384. package/dist/runs/shared/runWithConcurrency.cjs +2 -0
  385. package/dist/runs/shared/runWithConcurrency.cjs.map +1 -0
  386. package/dist/runs/shared/runWithConcurrency.mjs +2 -0
  387. package/dist/runs/shared/runWithConcurrency.mjs.map +1 -0
  388. package/dist/runs/shared/runtimeRegistry.cjs +2 -0
  389. package/dist/runs/shared/runtimeRegistry.cjs.map +1 -0
  390. package/dist/runs/shared/runtimeRegistry.mjs +2 -0
  391. package/dist/runs/shared/runtimeRegistry.mjs.map +1 -0
  392. package/dist/runs/shared/structuredOutput.cjs +2 -0
  393. package/dist/runs/shared/structuredOutput.cjs.map +1 -0
  394. package/dist/runs/shared/structuredOutput.mjs +2 -0
  395. package/dist/runs/shared/structuredOutput.mjs.map +1 -0
  396. package/dist/runs/shared/toolAvailability.cjs +2 -0
  397. package/dist/runs/shared/toolAvailability.cjs.map +1 -0
  398. package/dist/runs/shared/toolAvailability.mjs +2 -0
  399. package/dist/runs/shared/toolAvailability.mjs.map +1 -0
  400. package/dist/runs/shared/toolBudget.cjs +2 -0
  401. package/dist/runs/shared/toolBudget.cjs.map +1 -0
  402. package/dist/runs/shared/toolBudget.mjs +2 -0
  403. package/dist/runs/shared/toolBudget.mjs.map +1 -0
  404. package/dist/shared/artifacts.cjs +2 -0
  405. package/dist/shared/artifacts.cjs.map +1 -0
  406. package/dist/shared/artifacts.mjs +2 -0
  407. package/dist/shared/artifacts.mjs.map +1 -0
  408. package/dist/shared/atomicJson.cjs +2 -0
  409. package/dist/shared/atomicJson.cjs.map +1 -0
  410. package/dist/shared/atomicJson.mjs +2 -0
  411. package/dist/shared/atomicJson.mjs.map +1 -0
  412. package/dist/shared/boundedKeySet.cjs +2 -0
  413. package/dist/shared/boundedKeySet.cjs.map +1 -0
  414. package/dist/shared/boundedKeySet.mjs +2 -0
  415. package/dist/shared/boundedKeySet.mjs.map +1 -0
  416. package/dist/shared/childTranscript.cjs +5 -0
  417. package/dist/shared/childTranscript.cjs.map +1 -0
  418. package/dist/shared/childTranscript.mjs +5 -0
  419. package/dist/shared/childTranscript.mjs.map +1 -0
  420. package/dist/shared/configDir.cjs +2 -0
  421. package/dist/shared/configDir.cjs.map +1 -0
  422. package/dist/shared/configDir.mjs +2 -0
  423. package/dist/shared/configDir.mjs.map +1 -0
  424. package/dist/shared/errors.cjs +2 -0
  425. package/dist/shared/errors.cjs.map +1 -0
  426. package/dist/shared/errors.mjs +2 -0
  427. package/dist/shared/errors.mjs.map +1 -0
  428. package/dist/shared/fileSystemRetry.cjs +2 -0
  429. package/dist/shared/fileSystemRetry.cjs.map +1 -0
  430. package/dist/shared/fileSystemRetry.mjs +2 -0
  431. package/dist/shared/fileSystemRetry.mjs.map +1 -0
  432. package/dist/shared/formatters.cjs +2 -0
  433. package/dist/shared/formatters.cjs.map +1 -0
  434. package/dist/shared/formatters.mjs +2 -0
  435. package/dist/shared/formatters.mjs.map +1 -0
  436. package/dist/shared/lruCache.cjs +2 -0
  437. package/dist/shared/lruCache.cjs.map +1 -0
  438. package/dist/shared/lruCache.mjs +2 -0
  439. package/dist/shared/lruCache.mjs.map +1 -0
  440. package/dist/shared/modelInfo.cjs +2 -0
  441. package/dist/shared/modelInfo.cjs.map +1 -0
  442. package/dist/shared/modelInfo.mjs +2 -0
  443. package/dist/shared/modelInfo.mjs.map +1 -0
  444. package/dist/shared/modelResolution.cjs +2 -0
  445. package/dist/shared/modelResolution.cjs.map +1 -0
  446. package/dist/shared/modelResolution.mjs +2 -0
  447. package/dist/shared/modelResolution.mjs.map +1 -0
  448. package/dist/shared/paths.cjs +2 -0
  449. package/dist/shared/paths.cjs.map +1 -0
  450. package/dist/shared/paths.mjs +2 -0
  451. package/dist/shared/paths.mjs.map +1 -0
  452. package/dist/shared/pollScheduler.cjs +2 -0
  453. package/dist/shared/pollScheduler.cjs.map +1 -0
  454. package/dist/shared/pollScheduler.mjs +2 -0
  455. package/dist/shared/pollScheduler.mjs.map +1 -0
  456. package/dist/shared/scopeOwner.cjs +2 -0
  457. package/dist/shared/scopeOwner.cjs.map +1 -0
  458. package/dist/shared/scopeOwner.mjs +2 -0
  459. package/dist/shared/scopeOwner.mjs.map +1 -0
  460. package/dist/shared/versioned.cjs +2 -0
  461. package/dist/shared/versioned.cjs.map +1 -0
  462. package/dist/shared/versioned.mjs +2 -0
  463. package/dist/shared/versioned.mjs.map +1 -0
  464. package/dist/slash/chainExpression.cjs +2 -0
  465. package/dist/slash/chainExpression.cjs.map +1 -0
  466. package/dist/slash/chainExpression.mjs +2 -0
  467. package/dist/slash/chainExpression.mjs.map +1 -0
  468. package/dist/slash/doctor.cjs +5 -0
  469. package/dist/slash/doctor.cjs.map +1 -0
  470. package/dist/slash/doctor.mjs +5 -0
  471. package/dist/slash/doctor.mjs.map +1 -0
  472. package/dist/slash/slashCommands.cjs +4 -0
  473. package/dist/slash/slashCommands.cjs.map +1 -0
  474. package/dist/slash/slashCommands.mjs +4 -0
  475. package/dist/slash/slashCommands.mjs.map +1 -0
  476. package/dist/slash/spawnRequestMapping.cjs +2 -0
  477. package/dist/slash/spawnRequestMapping.cjs.map +1 -0
  478. package/dist/slash/spawnRequestMapping.mjs +2 -0
  479. package/dist/slash/spawnRequestMapping.mjs.map +1 -0
  480. package/dist/slash/subagentLaunch.cjs +2 -0
  481. package/dist/slash/subagentLaunch.cjs.map +1 -0
  482. package/dist/slash/subagentLaunch.mjs +2 -0
  483. package/dist/slash/subagentLaunch.mjs.map +1 -0
  484. package/dist/tui/agentCatalog.cjs +2 -0
  485. package/dist/tui/agentCatalog.cjs.map +1 -0
  486. package/dist/tui/agentCatalog.mjs +2 -0
  487. package/dist/tui/agentCatalog.mjs.map +1 -0
  488. package/dist/tui/agentResourceProjection.cjs +2 -0
  489. package/dist/tui/agentResourceProjection.cjs.map +1 -0
  490. package/dist/tui/agentResourceProjection.mjs +2 -0
  491. package/dist/tui/agentResourceProjection.mjs.map +1 -0
  492. package/dist/tui/completionNotice.cjs +5 -0
  493. package/dist/tui/completionNotice.cjs.map +1 -0
  494. package/dist/tui/completionNotice.mjs +5 -0
  495. package/dist/tui/completionNotice.mjs.map +1 -0
  496. package/dist/tui/fleet.cjs +3 -0
  497. package/dist/tui/fleet.cjs.map +1 -0
  498. package/dist/tui/fleet.mjs +3 -0
  499. package/dist/tui/fleet.mjs.map +1 -0
  500. package/dist/tui/fleetAgentView.cjs +2 -0
  501. package/dist/tui/fleetAgentView.cjs.map +1 -0
  502. package/dist/tui/fleetAgentView.mjs +2 -0
  503. package/dist/tui/fleetAgentView.mjs.map +1 -0
  504. package/dist/tui/fleetStatus.cjs +2 -0
  505. package/dist/tui/fleetStatus.cjs.map +1 -0
  506. package/dist/tui/fleetStatus.mjs +2 -0
  507. package/dist/tui/fleetStatus.mjs.map +1 -0
  508. package/dist/tui/fleetTranscript.cjs +5 -0
  509. package/dist/tui/fleetTranscript.cjs.map +1 -0
  510. package/dist/tui/fleetTranscript.mjs +5 -0
  511. package/dist/tui/fleetTranscript.mjs.map +1 -0
  512. package/dist/tui/register.cjs +2 -0
  513. package/dist/tui/register.cjs.map +1 -0
  514. package/dist/tui/register.mjs +2 -0
  515. package/dist/tui/register.mjs.map +1 -0
  516. package/dist/types.d.cts +59 -0
  517. package/dist/types.d.cts.map +1 -0
  518. package/dist/types.d.mts +59 -0
  519. package/dist/types.d.mts.map +1 -0
  520. package/package.json +86 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentCatalog.mjs","names":[],"sources":["../../src/tui/agentCatalog.ts"],"sourcesContent":["import type { ExtensionContext, Theme } from '@earendil-works/pi-coding-agent';\nimport {\n DOOM_FULLSCREEN_UI_OPTIONS,\n DOOM_OVERLAY_ACCENT,\n DoomOverlay,\n type DoomOverlayChrome,\n type DoomOverlayTui,\n} from '@agimon-ai/doompi-ui/components/doomOverlay';\nimport { Key, matchesKey, truncateToWidth, visibleWidth, wrapTextWithAnsi } from '@earendil-works/pi-tui';\n\nimport type { AgentConfig } from '../agents/types.ts';\nimport type {\n AgentCatalogEntry,\n AgentResourceProjection,\n ProjectedResource,\n ResourceTabProjection,\n} from './agentResourceProjection.ts';\n\nexport const AGENT_CATALOG_OVERLAY_OPTIONS = DOOM_FULLSCREEN_UI_OPTIONS.overlayOptions;\nexport type AgentResourceTab = 'tools' | 'skills' | 'extensions';\n\ntype ThemeBg = Parameters<Theme['bg']>[0];\ntype ThemeColor = Parameters<Theme['fg']>[0];\n\ninterface SplitLayout {\n leftContentWidth: number;\n rightContentWidth: number;\n gutterWidth: number;\n}\n\nconst TITLE = 'AGENTS';\nconst BREADCRUMB = 'SPC › a / agents › l / available';\nconst SELECTION_MARKER = '›';\nconst ELLIPSIS = '…';\nconst DEFAULT_PAGE_SIZE = 1;\nconst PI_RUNTIME = 'pi';\nconst DIVIDER = '│';\nconst PROJECTED_EFFECTIVE = 'PROJECTED EFFECTIVE';\nconst REMOVED_BY_PARENT = 'REMOVED BY PARENT';\nconst UNRESOLVED_AT_PREVIEW = 'UNRESOLVED AT PREVIEW';\nconst PROJECTION_ERROR = 'PROJECTION ERROR';\nconst GLOBAL_PREVIEW_NOTICE =\n 'Launch projection from the current parent-policy snapshot. Child resource loading can still change qualified resources.';\nconst TAB_ORDER: readonly AgentResourceTab[] = ['tools', 'skills', 'extensions'];\nconst FOOTER = '↑↓/jk cursor · PgUp/PgDn page · enter inspect · tab resource · J/K scroll · esc close';\nconst FOOTER_HINTS: readonly (readonly [string, string])[] = [\n ['↑↓/jk', 'move'],\n ['enter', 'view'],\n ['tab', 'cycle'],\n ['J/K', 'scroll'],\n];\n\nfunction fit(text: string, width: number): string {\n const safeWidth = Math.max(0, width);\n const clipped = truncateToWidth(text, safeWidth, ELLIPSIS);\n return clipped + ' '.repeat(Math.max(0, safeWidth - visibleWidth(clipped)));\n}\n\nfunction rightAligned(left: string, right: string, width: number): string {\n const safeWidth = Math.max(0, width);\n const rightWidth = visibleWidth(right);\n if (rightWidth + 2 >= safeWidth) return fit(left, safeWidth);\n const leftWidth = Math.max(1, safeWidth - rightWidth - 2);\n return `${fit(left, leftWidth)} ${fit(right, rightWidth)}`;\n}\n\nfunction plural(count: number, singular: string): string {\n return `${count} ${singular}${count === 1 ? '' : 's'}`;\n}\n\nexport function agentResourceSummary(agent: AgentConfig): string {\n const mcpTools = plural(agent.mcpDirectTools?.length ?? 0, 'MCP tool');\n const skills = plural(agent.skills?.length ?? 0, 'skill');\n const extensions = plural((agent.extensions?.length ?? 0) + (agent.subagentOnlyExtensions?.length ?? 0), 'extension');\n const configured = `${mcpTools} · ${skills} · ${extensions}`;\n return agent.tools === undefined\n ? `tools default · configured: ${configured}`\n : `configured: ${plural(agent.tools.length, 'tool')} · ${configured}`;\n}\n\nfunction appendWrapped(lines: string[], text: string, width: number, colour: ThemeColor, theme: Theme): void {\n for (const line of wrapTextWithAnsi(text, Math.max(1, width))) lines.push(theme.fg(colour, line));\n}\n\nfunction appendResources(\n lines: string[],\n heading: string,\n items: readonly ProjectedResource[],\n width: number,\n theme: Theme,\n): void {\n lines.push(theme.bold(theme.fg('accent', heading)));\n if (items.length === 0) {\n lines.push(theme.fg('dim', ' none'));\n } else {\n for (const item of items) {\n appendWrapped(lines, ` • ${item.name}`, width, 'text', theme);\n if (item.detail) appendWrapped(lines, ` ${item.detail}`, width, 'dim', theme);\n }\n }\n lines.push('');\n}\n\nfunction tabProjection(projection: AgentResourceProjection, tab: AgentResourceTab): ResourceTabProjection {\n if (tab === 'skills') return projection.skills;\n if (tab === 'extensions') return projection.extensions;\n return projection.tools;\n}\n\nfunction resourceLines(\n projection: AgentResourceProjection,\n tab: AgentResourceTab,\n width: number,\n theme: Theme,\n): string[] {\n const lines: string[] = [];\n if (projection.error) {\n lines.push(theme.bold(theme.fg('error', PROJECTION_ERROR)));\n appendWrapped(lines, projection.error, width, 'error', theme);\n lines.push('');\n }\n const resources = tabProjection(projection, tab);\n appendResources(lines, PROJECTED_EFFECTIVE, resources.effective, width, theme);\n appendResources(lines, REMOVED_BY_PARENT, resources.removed, width, theme);\n appendResources(lines, UNRESOLVED_AT_PREVIEW, resources.unresolved, width, theme);\n return lines;\n}\n\nfunction tabStrip(tab: AgentResourceTab, width: number, theme: Theme): string {\n const labels = TAB_ORDER.map((candidate) => {\n const label = candidate.toUpperCase();\n return candidate === tab ? theme.inverse(theme.bold(` ${label} `)) : theme.fg('dim', ` ${label} `);\n }).join(' ');\n return truncateToWidth(labels, Math.max(0, width), ELLIPSIS);\n}\n\nfunction splitLayout(width: number): SplitLayout {\n const paneBudget = Math.max(2, width - visibleWidth(DIVIDER));\n const leftPaneWidth = Math.max(1, Math.floor(paneBudget / 3));\n const rightPaneWidth = Math.max(1, paneBudget - leftPaneWidth);\n const gutterWidth = leftPaneWidth >= 3 && rightPaneWidth >= 3 ? 1 : 0;\n return {\n leftContentWidth: Math.max(1, leftPaneWidth - gutterWidth),\n rightContentWidth: Math.max(1, rightPaneWidth - gutterWidth),\n gutterWidth,\n };\n}\n\nexport class AgentCatalogComponent extends DoomOverlay {\n private readonly entries: AgentCatalogEntry[];\n private cursorIndex = 0;\n private inspectedIndex: number | undefined;\n private tab: AgentResourceTab = 'tools';\n private listPageSize = DEFAULT_PAGE_SIZE;\n private detailPageSize = DEFAULT_PAGE_SIZE;\n private detailOffset = 0;\n private detailTotal = 0;\n\n constructor(\n tui: DoomOverlayTui,\n theme: Theme,\n entries: readonly AgentCatalogEntry[],\n private readonly done: (result: undefined) => void,\n ) {\n super(tui, theme);\n this.entries = [...entries].sort((left, right) => left.agent.name.localeCompare(right.agent.name));\n }\n\n private cursorEntry(): AgentCatalogEntry | undefined {\n return this.entries[Math.min(this.cursorIndex, Math.max(0, this.entries.length - 1))];\n }\n\n private inspectedEntry(): AgentCatalogEntry | undefined {\n if (this.inspectedIndex === undefined) return undefined;\n return this.entries[this.inspectedIndex];\n }\n\n private moveCursor(delta: number): void {\n if (this.entries.length === 0) return;\n const next = Math.max(0, Math.min(this.entries.length - 1, this.cursorIndex + delta));\n if (next === this.cursorIndex) return;\n this.cursorIndex = next;\n this.invalidate();\n }\n\n private inspectCursor(): void {\n if (!this.cursorEntry()) return;\n this.inspectedIndex = this.cursorIndex;\n this.detailOffset = 0;\n this.invalidate();\n }\n\n private switchTab(tab: AgentResourceTab): void {\n if (this.tab === tab) return;\n this.tab = tab;\n this.detailOffset = 0;\n this.invalidate();\n }\n\n private cycleTab(): void {\n const current = TAB_ORDER.indexOf(this.tab);\n this.switchTab(TAB_ORDER[(current + 1) % TAB_ORDER.length] ?? 'tools');\n }\n\n private scrollDetail(delta: number): void {\n if (!this.inspectedEntry()) return;\n const maximum = Math.max(0, this.detailTotal - this.detailPageSize);\n const next = Math.max(0, Math.min(maximum, this.detailOffset + delta));\n if (next === this.detailOffset) return;\n this.detailOffset = next;\n this.invalidate();\n }\n\n handleInput(data: string): void {\n if (matchesKey(data, 'escape') || matchesKey(data, 'ctrl+c')) {\n this.done(undefined);\n return;\n }\n if (matchesKey(data, Key.shift('k'))) return this.scrollDetail(-1);\n if (matchesKey(data, Key.shift('j'))) return this.scrollDetail(1);\n if (matchesKey(data, 'up') || data === 'k') return this.moveCursor(-1);\n if (matchesKey(data, 'down') || data === 'j') return this.moveCursor(1);\n if (matchesKey(data, 'pageUp')) return this.moveCursor(-this.listPageSize);\n if (matchesKey(data, 'pageDown')) return this.moveCursor(this.listPageSize);\n if (matchesKey(data, 'enter')) return this.inspectCursor();\n if (matchesKey(data, 'tab')) return this.cycleTab();\n if (data === 't') return this.switchTab('tools');\n if (data === 's') return this.switchTab('skills');\n if (data === 'e') return this.switchTab('extensions');\n }\n\n protected getChrome(): DoomOverlayChrome {\n const cursor = this.cursorEntry();\n const inspected = this.inspectedEntry();\n const cursorPosition = this.entries.length ? String(this.cursorIndex + 1) : 'empty';\n const footerRight = !cursor\n ? 'empty'\n : inspected\n ? `C${cursorPosition} I${(this.inspectedIndex ?? 0) + 1}`\n : `C${cursorPosition} I-`;\n return {\n title: TITLE,\n accent: DOOM_OVERLAY_ACCENT,\n breadcrumb: BREADCRUMB,\n headerRight: `${this.entries.length} available · ${this.tab}`,\n footer: FOOTER,\n footerHints: FOOTER_HINTS,\n footerRight,\n };\n }\n\n protected renderBody(width: number, height: number): string[] {\n const layout = splitLayout(width);\n const left = this.renderList(layout.leftContentWidth, height);\n const right = this.renderDetail(layout.rightContentWidth, height);\n const gutter = ' '.repeat(layout.gutterWidth);\n const divider = this.theme.fg('borderMuted', DIVIDER);\n const lines: string[] = [];\n for (let index = 0; index < height; index++) {\n lines.push(\n `${fit(left[index] ?? '', layout.leftContentWidth)}${gutter}${divider}${gutter}${fit(\n right[index] ?? '',\n layout.rightContentWidth,\n )}`,\n );\n }\n return lines.map((line) => fit(line, width));\n }\n\n private renderList(width: number, height: number): string[] {\n const lines = [this.theme.bold(this.theme.fg('accent', `AGENTS ${this.entries.length}`))];\n if (this.entries.length === 0) {\n appendWrapped(lines, 'No enabled agents are available from this session cwd.', width, 'dim', this.theme);\n this.listPageSize = DEFAULT_PAGE_SIZE;\n return lines.slice(0, height);\n }\n\n this.listPageSize = Math.max(DEFAULT_PAGE_SIZE, height - 1);\n const start = Math.max(\n 0,\n Math.min(this.cursorIndex - this.listPageSize + 1, Math.max(0, this.entries.length - this.listPageSize)),\n );\n for (const [offset, entry] of this.entries.slice(start, start + this.listPageSize).entries()) {\n const index = start + offset;\n const current = index === this.cursorIndex;\n const marker = current ? this.theme.fg('accent', SELECTION_MARKER) : ' ';\n const runtime = entry.agent.runtime ?? PI_RUNTIME;\n const name = current ? this.theme.bold(entry.agent.name) : entry.agent.name;\n const row = rightAligned(`${marker} ${name}`, `${entry.agent.source} · ${runtime}`, width);\n const background: ThemeBg = current ? 'selectedBg' : 'userMessageBg';\n lines.push(this.theme.bg(background, fit(row, width)));\n }\n return lines.slice(0, height);\n }\n\n private renderDetail(width: number, height: number): string[] {\n const entry = this.inspectedEntry();\n if (!entry) {\n this.detailTotal = 0;\n this.detailPageSize = Math.max(DEFAULT_PAGE_SIZE, height);\n this.detailOffset = 0;\n const lines = [this.theme.bold(this.theme.fg('accent', 'AGENT RESOURCES')), ''];\n appendWrapped(lines, 'Press Enter to inspect the cursor agent.', width, 'text', this.theme);\n lines.push('');\n appendWrapped(lines, GLOBAL_PREVIEW_NOTICE, width, 'dim', this.theme);\n return lines.slice(0, height);\n }\n\n const runtime = entry.agent.runtime ?? PI_RUNTIME;\n const header = [\n rightAligned(\n this.theme.bold(this.theme.fg('accent', `INSPECTING ${entry.agent.name}`)),\n `${entry.agent.source} · ${runtime}`,\n width,\n ),\n ];\n appendWrapped(header, entry.agent.description, width, 'text', this.theme);\n appendWrapped(\n header,\n entry.resources.notice || GLOBAL_PREVIEW_NOTICE,\n width,\n entry.resources.configuredOnly ? 'warning' : 'dim',\n this.theme,\n );\n header.push(tabStrip(this.tab, width, this.theme), '');\n\n const resources = resourceLines(entry.resources, this.tab, width, this.theme);\n this.detailPageSize = Math.max(0, height - header.length);\n this.detailTotal = resources.length;\n this.detailOffset = Math.min(this.detailOffset, Math.max(0, resources.length - this.detailPageSize));\n return [...header, ...resources.slice(this.detailOffset, this.detailOffset + this.detailPageSize)].slice(0, height);\n }\n}\n\nexport async function openAgentCatalog(ctx: ExtensionContext, entries: readonly AgentCatalogEntry[]): Promise<void> {\n await ctx.ui.custom<undefined>(\n (tui, theme, _keybindings, done) => new AgentCatalogComponent(tui, theme, entries, done),\n DOOM_FULLSCREEN_UI_OPTIONS,\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ const e=require(`../agents/skills.cjs`),t=require(`../runs/shared/runtimeRegistry.cjs`),n=require(`../runs/shared/piArgs.cjs`),r=`Ambient Pi extensions`,i=`Ambient Pi skills`;function a(){return{effective:[],removed:[],unresolved:[]}}function o(e,t){return t?{name:e,detail:t}:{name:e}}function s(e){let t=new Set;return e.filter(e=>{let n=`${e.name}\0${e.detail??``}`;return t.has(n)?!1:(t.add(n),!0)})}function c(e){let t=e.capabilityCeiling?.sources??[];return t.length>0?`removed by capability ceiling from ${t.join(`, `)}`:`removed by capability ceiling`}function l(e,t,n){return t.excludedTools.includes(e)?n.exclusionSource?`excluded by active layer policy at ${n.exclusionSource}`:`excluded by active layer policy`:c(t)}function u(e,t){let n=new Set(t.requestedBuiltinTools);return(e.tools??[]).filter(e=>!n.has(e))}function d(e,t){return t.resolvedMcpSelections.some(t=>t.selector===e||t.selector.startsWith(`${e}/`))}function f(e,t){return e.tools===void 0?t.capabilityCeiling?.allowedTools?t.capabilityCeiling.allowedTools:t.excludedTools:t.requestedBuiltinTools}function p(e,t,n){let{toolPlan:r}=t,i=new Set(r.effectiveMcpTools),a=r.explicitToolAllowlist?r.effectiveToolAllowlist.map(t=>o(t,i.has(t)?`resolved MCP tool`:e.tools===void 0?`granted by parent capability ceiling`:`configured builtin tool`)):[],u=f(e,r).filter(e=>!r.declaredBuiltinTools.includes(e)).map(e=>o(e,l(e,r,n))),p=new Set(r.effectiveMcpTools),m=r.resolvedMcpSelections.filter(e=>!p.has(e.name)).map(e=>o(e.name,`${e.selector} · ${l(e.name,r,n)}`)),h=r.capabilityCeiling?.denyExtensions?(e.mcpDirectTools??[]).map(e=>o(e,`${c(r)} · MCP extensions denied`)):[],g=r.capabilityCeiling?.denyExtensions?[]:(e.mcpDirectTools??[]).filter(e=>!d(e,r)).map(e=>o(e,`MCP selector did not resolve from the current parent catalog`));return{effective:s(a),removed:s([...u,...m,...h]),unresolved:s([...r.explicitToolAllowlist?[]:[o(`Pi host-default tool set`,`resolved by Pi only after the child host loads resources`)],...g,o(`Request-specific internal tools`,`intercom and structured_output depend on the concrete spawn request`)])}}function m(t,n){let r=n.skills.resolveSkillsWithFallback(t.skills??[],n.cwd,n.cwd,t.skillPath,n.cwd),a=new Set(r.resolved.map(e=>e.name)),c=t.inheritSkills?n.skills.discoverAvailableSkills(n.cwd).filter(e=>!a.has(e.name)).map(e=>o(e.name,`ambient parent snapshot · ${e.source}`)):[];return{tab:{effective:s([...r.resolved.map(e=>o(e.name,`configured · ${e.source} · ${e.path}`)),...c]),removed:[],unresolved:s([...r.missing.map(e=>o(e,`configured skill was not found from the current session cwd`)),...t.inheritSkills?[o(i,`Pi rediscovers ambient skills when the child resource loader starts`)]:[]])},requireReadTool:e.buildSkillInjection(r.resolved).length>0}}function h(e,t){let n=new Set(t.toolPlan.runtimeExtensions),i=new Set(t.toolPlan.configuredExtensions),a=t.extensions.map(e=>o(e,n.has(e)?`internal runtime extension`:i.has(e)?`configured agent extension`:`inherited parent harness extension`)),l=t.toolPlan.capabilityCeiling?.denyExtensions?[...u(e,t.toolPlan),...e.extensions??[],...e.subagentOnlyExtensions??[]].map(e=>o(e,c(t.toolPlan))):[];return{effective:s(a),removed:s(l),unresolved:t.noAmbientExtensions?[]:[o(r,`Pi discovers additional ambient extensions only when the child loads`)]}}function g(e){let t=a();t.unresolved=s([...(e.tools??[]).map(e=>o(e,`configured for external runtime`)),...(e.mcpDirectTools??[]).map(e=>o(e,`configured MCP selector`)),...e.tools===void 0?[o(`Runtime-default tools`,`determined by the external runtime`)]:[]]);let n=a();n.unresolved=s([...(e.skills??[]).map(e=>o(e,`configured skill name`)),...e.inheritSkills?[o(i,`determined by the external runtime`)]:[]]);let c=a();return c.unresolved=s([...[...e.extensions??[],...e.subagentOnlyExtensions??[]].map(e=>o(e,`configured extension`)),...e.extensions===void 0?[o(r,`determined by the external runtime`)]:[]]),{tools:t,skills:n,extensions:c,notice:`Configured values only. Runtime '${e.runtime}' does not use the Pi launch projection.`,configuredOnly:!0}}function _(e){return{tools:a(),skills:a(),extensions:a(),notice:`Launch projection failed for this agent.`,configuredOnly:!1,error:e instanceof Error?e.message:String(e)}}function v(e,r){if(!t.isPiRuntime(e.runtime))return g(e);try{let t=m(e,r),i=n.resolvePiSdkResourcePlan({tools:e.tools,extensions:e.extensions,subagentOnlyExtensions:e.subagentOnlyExtensions,mcpDirectTools:e.mcpDirectTools,cwd:r.cwd,requireReadTool:t.requireReadTool,excludeTools:r.excludeTools?[...r.excludeTools]:void 0,capabilityCeiling:r.capabilityCeiling,inheritSkills:e.inheritSkills,environment:r.environment});return{tools:p(e,i,r),skills:t.tab,extensions:h(e,i),notice:`Launch projection from the current parent-policy and cwd snapshot. Child loading or request overrides may change qualified resources.`,configuredOnly:!1}}catch(e){return _(e)}}function y(e,t){return e.map(e=>({agent:e,resources:v(e,t)}))}exports.buildAgentCatalogEntries=y;
2
+ //# sourceMappingURL=agentResourceProjection.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentResourceProjection.cjs","names":["buildSkillInjection","isPiRuntime","resolvePiSdkResourcePlan"],"sources":["../../src/tui/agentResourceProjection.ts"],"sourcesContent":["import { buildSkillInjection, type ISkillDiscoveryService } from '../agents/skills.ts';\nimport type { AgentConfig } from '../agents/types.ts';\nimport type { ResolvedSubagentCapabilityCeiling } from '../protocol/capabilityCeiling.ts';\nimport { resolvePiSdkResourcePlan, type PiLaunchToolPlan, type PiSdkResourcePlan } from '../runs/shared/piArgs.ts';\nimport { isPiRuntime } from '../runs/shared/runtimeRegistry.ts';\n\nconst CONDITIONAL_TOOLS = 'Request-specific internal tools';\nconst HOST_DEFAULT_TOOLS = 'Pi host-default tool set';\nconst AMBIENT_EXTENSIONS = 'Ambient Pi extensions';\nconst AMBIENT_SKILLS = 'Ambient Pi skills';\n\nexport interface ProjectedResource {\n name: string;\n detail?: string;\n}\n\nexport interface ResourceTabProjection {\n effective: readonly ProjectedResource[];\n removed: readonly ProjectedResource[];\n unresolved: readonly ProjectedResource[];\n}\n\nexport interface AgentResourceProjection {\n tools: ResourceTabProjection;\n skills: ResourceTabProjection;\n extensions: ResourceTabProjection;\n notice: string;\n configuredOnly: boolean;\n error?: string;\n}\n\nexport interface AgentCatalogEntry {\n agent: AgentConfig;\n resources: AgentResourceProjection;\n}\n\nexport interface AgentResourceProjectionContext {\n cwd: string;\n skills: Pick<ISkillDiscoveryService, 'resolveSkillsWithFallback' | 'discoverAvailableSkills'>;\n capabilityCeiling?: ResolvedSubagentCapabilityCeiling;\n excludeTools?: readonly string[];\n exclusionSource?: string;\n environment?: NodeJS.ProcessEnv;\n}\n\nfunction emptyTab(): ResourceTabProjection {\n return { effective: [], removed: [], unresolved: [] };\n}\n\nfunction resource(name: string, detail?: string): ProjectedResource {\n return detail ? { name, detail } : { name };\n}\n\nfunction unique(items: readonly ProjectedResource[]): ProjectedResource[] {\n const seen = new Set<string>();\n return items.filter((item) => {\n const key = `${item.name}\\0${item.detail ?? ''}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\nfunction ceilingReason(toolPlan: PiLaunchToolPlan): string {\n const sources = toolPlan.capabilityCeiling?.sources ?? [];\n return sources.length > 0\n ? `removed by capability ceiling from ${sources.join(', ')}`\n : 'removed by capability ceiling';\n}\n\nfunction toolRemovalReason(name: string, toolPlan: PiLaunchToolPlan, context: AgentResourceProjectionContext): string {\n if (toolPlan.excludedTools.includes(name)) {\n return context.exclusionSource\n ? `excluded by active layer policy at ${context.exclusionSource}`\n : 'excluded by active layer policy';\n }\n return ceilingReason(toolPlan);\n}\n\nfunction pathShapedToolEntries(agent: AgentConfig, toolPlan: PiLaunchToolPlan): string[] {\n const builtinTools = new Set(toolPlan.requestedBuiltinTools);\n return (agent.tools ?? []).filter((tool) => !builtinTools.has(tool));\n}\n\nfunction selectorResolved(selector: string, toolPlan: PiLaunchToolPlan): boolean {\n return toolPlan.resolvedMcpSelections.some(\n (selection) => selection.selector === selector || selection.selector.startsWith(`${selector}/`),\n );\n}\n\nfunction removedBuiltinCandidates(agent: AgentConfig, toolPlan: PiLaunchToolPlan): string[] {\n if (agent.tools !== undefined) return toolPlan.requestedBuiltinTools;\n if (toolPlan.capabilityCeiling?.allowedTools) return toolPlan.capabilityCeiling.allowedTools;\n return toolPlan.excludedTools;\n}\n\nfunction toolProjection(\n agent: AgentConfig,\n plan: PiSdkResourcePlan,\n context: AgentResourceProjectionContext,\n): ResourceTabProjection {\n const { toolPlan } = plan;\n const mcpNames = new Set(toolPlan.effectiveMcpTools);\n const effective = toolPlan.explicitToolAllowlist\n ? toolPlan.effectiveToolAllowlist.map((name) =>\n resource(\n name,\n mcpNames.has(name)\n ? 'resolved MCP tool'\n : agent.tools === undefined\n ? 'granted by parent capability ceiling'\n : 'configured builtin tool',\n ),\n )\n : [];\n const removedBuiltins = removedBuiltinCandidates(agent, toolPlan)\n .filter((name) => !toolPlan.declaredBuiltinTools.includes(name))\n .map((name) => resource(name, toolRemovalReason(name, toolPlan, context)));\n const effectiveMcpNames = new Set(toolPlan.effectiveMcpTools);\n const removedMcp = toolPlan.resolvedMcpSelections\n .filter((selection) => !effectiveMcpNames.has(selection.name))\n .map((selection) =>\n resource(selection.name, `${selection.selector} · ${toolRemovalReason(selection.name, toolPlan, context)}`),\n );\n const deniedMcpSelectors = toolPlan.capabilityCeiling?.denyExtensions\n ? (agent.mcpDirectTools ?? []).map((selector) =>\n resource(selector, `${ceilingReason(toolPlan)} · MCP extensions denied`),\n )\n : [];\n const unresolvedSelectors = toolPlan.capabilityCeiling?.denyExtensions\n ? []\n : (agent.mcpDirectTools ?? [])\n .filter((selector) => !selectorResolved(selector, toolPlan))\n .map((selector) => resource(selector, 'MCP selector did not resolve from the current parent catalog'));\n return {\n effective: unique(effective),\n removed: unique([...removedBuiltins, ...removedMcp, ...deniedMcpSelectors]),\n unresolved: unique([\n ...(toolPlan.explicitToolAllowlist\n ? []\n : [resource(HOST_DEFAULT_TOOLS, 'resolved by Pi only after the child host loads resources')]),\n ...unresolvedSelectors,\n resource(CONDITIONAL_TOOLS, 'intercom and structured_output depend on the concrete spawn request'),\n ]),\n };\n}\n\nfunction skillProjection(\n agent: AgentConfig,\n context: AgentResourceProjectionContext,\n): { tab: ResourceTabProjection; requireReadTool: boolean } {\n const resolution = context.skills.resolveSkillsWithFallback(\n agent.skills ?? [],\n context.cwd,\n context.cwd,\n agent.skillPath,\n context.cwd,\n );\n const explicitNames = new Set(resolution.resolved.map((skill) => skill.name));\n const ambient = agent.inheritSkills\n ? context.skills\n .discoverAvailableSkills(context.cwd)\n .filter((skill) => !explicitNames.has(skill.name))\n .map((skill) => resource(skill.name, `ambient parent snapshot · ${skill.source}`))\n : [];\n return {\n tab: {\n effective: unique([\n ...resolution.resolved.map((skill) => resource(skill.name, `configured · ${skill.source} · ${skill.path}`)),\n ...ambient,\n ]),\n removed: [],\n unresolved: unique([\n ...resolution.missing.map((name) =>\n resource(name, 'configured skill was not found from the current session cwd'),\n ),\n ...(agent.inheritSkills\n ? [resource(AMBIENT_SKILLS, 'Pi rediscovers ambient skills when the child resource loader starts')]\n : []),\n ]),\n },\n requireReadTool: buildSkillInjection(resolution.resolved).length > 0,\n };\n}\n\nfunction extensionProjection(agent: AgentConfig, plan: PiSdkResourcePlan): ResourceTabProjection {\n const runtimeExtensions = new Set(plan.toolPlan.runtimeExtensions);\n const configuredExtensions = new Set(plan.toolPlan.configuredExtensions);\n const effective = plan.extensions.map((name) =>\n resource(\n name,\n runtimeExtensions.has(name)\n ? 'internal runtime extension'\n : configuredExtensions.has(name)\n ? 'configured agent extension'\n : 'inherited parent harness extension',\n ),\n );\n const removed = plan.toolPlan.capabilityCeiling?.denyExtensions\n ? [\n ...pathShapedToolEntries(agent, plan.toolPlan),\n ...(agent.extensions ?? []),\n ...(agent.subagentOnlyExtensions ?? []),\n ].map((name) => resource(name, ceilingReason(plan.toolPlan)))\n : [];\n return {\n effective: unique(effective),\n removed: unique(removed),\n unresolved: plan.noAmbientExtensions\n ? []\n : [resource(AMBIENT_EXTENSIONS, 'Pi discovers additional ambient extensions only when the child loads')],\n };\n}\n\nfunction configuredOnlyProjection(agent: AgentConfig): AgentResourceProjection {\n const tools = emptyTab();\n tools.unresolved = unique([\n ...(agent.tools ?? []).map((name) => resource(name, 'configured for external runtime')),\n ...(agent.mcpDirectTools ?? []).map((name) => resource(name, 'configured MCP selector')),\n ...(agent.tools === undefined ? [resource('Runtime-default tools', 'determined by the external runtime')] : []),\n ]);\n const skills = emptyTab();\n skills.unresolved = unique([\n ...(agent.skills ?? []).map((name) => resource(name, 'configured skill name')),\n ...(agent.inheritSkills ? [resource(AMBIENT_SKILLS, 'determined by the external runtime')] : []),\n ]);\n const extensions = emptyTab();\n extensions.unresolved = unique([\n ...[...(agent.extensions ?? []), ...(agent.subagentOnlyExtensions ?? [])].map((name) =>\n resource(name, 'configured extension'),\n ),\n ...(agent.extensions === undefined ? [resource(AMBIENT_EXTENSIONS, 'determined by the external runtime')] : []),\n ]);\n return {\n tools,\n skills,\n extensions,\n notice: `Configured values only. Runtime '${agent.runtime}' does not use the Pi launch projection.`,\n configuredOnly: true,\n };\n}\n\nfunction failedProjection(error: unknown): AgentResourceProjection {\n return {\n tools: emptyTab(),\n skills: emptyTab(),\n extensions: emptyTab(),\n notice: 'Launch projection failed for this agent.',\n configuredOnly: false,\n error: error instanceof Error ? error.message : String(error),\n };\n}\n\nexport function projectAgentResources(\n agent: AgentConfig,\n context: AgentResourceProjectionContext,\n): AgentResourceProjection {\n if (!isPiRuntime(agent.runtime)) return configuredOnlyProjection(agent);\n try {\n const skills = skillProjection(agent, context);\n const plan = resolvePiSdkResourcePlan({\n tools: agent.tools,\n extensions: agent.extensions,\n subagentOnlyExtensions: agent.subagentOnlyExtensions,\n mcpDirectTools: agent.mcpDirectTools,\n cwd: context.cwd,\n requireReadTool: skills.requireReadTool,\n excludeTools: context.excludeTools ? [...context.excludeTools] : undefined,\n capabilityCeiling: context.capabilityCeiling,\n inheritSkills: agent.inheritSkills,\n environment: context.environment,\n });\n return {\n tools: toolProjection(agent, plan, context),\n skills: skills.tab,\n extensions: extensionProjection(agent, plan),\n notice:\n 'Launch projection from the current parent-policy and cwd snapshot. Child loading or request overrides may change qualified resources.',\n configuredOnly: false,\n };\n } catch (error) {\n return failedProjection(error);\n }\n}\n\nexport function buildAgentCatalogEntries(\n agents: readonly AgentConfig[],\n context: AgentResourceProjectionContext,\n): AgentCatalogEntry[] {\n return agents.map((agent) => ({ agent, resources: projectAgentResources(agent, context) }));\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{buildSkillInjection as e,init_skills as t}from"../agents/skills.mjs";import{init_runtimeRegistry as n,isPiRuntime as r}from"../runs/shared/runtimeRegistry.mjs";import{init_piArgs as i,resolvePiSdkResourcePlan as a}from"../runs/shared/piArgs.mjs";t(),i(),n();const o=`Ambient Pi extensions`,s=`Ambient Pi skills`;function c(){return{effective:[],removed:[],unresolved:[]}}function l(e,t){return t?{name:e,detail:t}:{name:e}}function u(e){let t=new Set;return e.filter(e=>{let n=`${e.name}\0${e.detail??``}`;return t.has(n)?!1:(t.add(n),!0)})}function d(e){let t=e.capabilityCeiling?.sources??[];return t.length>0?`removed by capability ceiling from ${t.join(`, `)}`:`removed by capability ceiling`}function f(e,t,n){return t.excludedTools.includes(e)?n.exclusionSource?`excluded by active layer policy at ${n.exclusionSource}`:`excluded by active layer policy`:d(t)}function p(e,t){let n=new Set(t.requestedBuiltinTools);return(e.tools??[]).filter(e=>!n.has(e))}function m(e,t){return t.resolvedMcpSelections.some(t=>t.selector===e||t.selector.startsWith(`${e}/`))}function h(e,t){return e.tools===void 0?t.capabilityCeiling?.allowedTools?t.capabilityCeiling.allowedTools:t.excludedTools:t.requestedBuiltinTools}function g(e,t,n){let{toolPlan:r}=t,i=new Set(r.effectiveMcpTools),a=r.explicitToolAllowlist?r.effectiveToolAllowlist.map(t=>l(t,i.has(t)?`resolved MCP tool`:e.tools===void 0?`granted by parent capability ceiling`:`configured builtin tool`)):[],o=h(e,r).filter(e=>!r.declaredBuiltinTools.includes(e)).map(e=>l(e,f(e,r,n))),s=new Set(r.effectiveMcpTools),c=r.resolvedMcpSelections.filter(e=>!s.has(e.name)).map(e=>l(e.name,`${e.selector} · ${f(e.name,r,n)}`)),p=r.capabilityCeiling?.denyExtensions?(e.mcpDirectTools??[]).map(e=>l(e,`${d(r)} · MCP extensions denied`)):[],g=r.capabilityCeiling?.denyExtensions?[]:(e.mcpDirectTools??[]).filter(e=>!m(e,r)).map(e=>l(e,`MCP selector did not resolve from the current parent catalog`));return{effective:u(a),removed:u([...o,...c,...p]),unresolved:u([...r.explicitToolAllowlist?[]:[l(`Pi host-default tool set`,`resolved by Pi only after the child host loads resources`)],...g,l(`Request-specific internal tools`,`intercom and structured_output depend on the concrete spawn request`)])}}function _(t,n){let r=n.skills.resolveSkillsWithFallback(t.skills??[],n.cwd,n.cwd,t.skillPath,n.cwd),i=new Set(r.resolved.map(e=>e.name)),a=t.inheritSkills?n.skills.discoverAvailableSkills(n.cwd).filter(e=>!i.has(e.name)).map(e=>l(e.name,`ambient parent snapshot · ${e.source}`)):[];return{tab:{effective:u([...r.resolved.map(e=>l(e.name,`configured · ${e.source} · ${e.path}`)),...a]),removed:[],unresolved:u([...r.missing.map(e=>l(e,`configured skill was not found from the current session cwd`)),...t.inheritSkills?[l(s,`Pi rediscovers ambient skills when the child resource loader starts`)]:[]])},requireReadTool:e(r.resolved).length>0}}function v(e,t){let n=new Set(t.toolPlan.runtimeExtensions),r=new Set(t.toolPlan.configuredExtensions),i=t.extensions.map(e=>l(e,n.has(e)?`internal runtime extension`:r.has(e)?`configured agent extension`:`inherited parent harness extension`)),a=t.toolPlan.capabilityCeiling?.denyExtensions?[...p(e,t.toolPlan),...e.extensions??[],...e.subagentOnlyExtensions??[]].map(e=>l(e,d(t.toolPlan))):[];return{effective:u(i),removed:u(a),unresolved:t.noAmbientExtensions?[]:[l(o,`Pi discovers additional ambient extensions only when the child loads`)]}}function y(e){let t=c();t.unresolved=u([...(e.tools??[]).map(e=>l(e,`configured for external runtime`)),...(e.mcpDirectTools??[]).map(e=>l(e,`configured MCP selector`)),...e.tools===void 0?[l(`Runtime-default tools`,`determined by the external runtime`)]:[]]);let n=c();n.unresolved=u([...(e.skills??[]).map(e=>l(e,`configured skill name`)),...e.inheritSkills?[l(s,`determined by the external runtime`)]:[]]);let r=c();return r.unresolved=u([...[...e.extensions??[],...e.subagentOnlyExtensions??[]].map(e=>l(e,`configured extension`)),...e.extensions===void 0?[l(o,`determined by the external runtime`)]:[]]),{tools:t,skills:n,extensions:r,notice:`Configured values only. Runtime '${e.runtime}' does not use the Pi launch projection.`,configuredOnly:!0}}function b(e){return{tools:c(),skills:c(),extensions:c(),notice:`Launch projection failed for this agent.`,configuredOnly:!1,error:e instanceof Error?e.message:String(e)}}function x(e,t){if(!r(e.runtime))return y(e);try{let n=_(e,t),r=a({tools:e.tools,extensions:e.extensions,subagentOnlyExtensions:e.subagentOnlyExtensions,mcpDirectTools:e.mcpDirectTools,cwd:t.cwd,requireReadTool:n.requireReadTool,excludeTools:t.excludeTools?[...t.excludeTools]:void 0,capabilityCeiling:t.capabilityCeiling,inheritSkills:e.inheritSkills,environment:t.environment});return{tools:g(e,r,t),skills:n.tab,extensions:v(e,r),notice:`Launch projection from the current parent-policy and cwd snapshot. Child loading or request overrides may change qualified resources.`,configuredOnly:!1}}catch(e){return b(e)}}function S(e,t){return e.map(e=>({agent:e,resources:x(e,t)}))}export{S as buildAgentCatalogEntries};
2
+ //# sourceMappingURL=agentResourceProjection.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentResourceProjection.mjs","names":[],"sources":["../../src/tui/agentResourceProjection.ts"],"sourcesContent":["import { buildSkillInjection, type ISkillDiscoveryService } from '../agents/skills.ts';\nimport type { AgentConfig } from '../agents/types.ts';\nimport type { ResolvedSubagentCapabilityCeiling } from '../protocol/capabilityCeiling.ts';\nimport { resolvePiSdkResourcePlan, type PiLaunchToolPlan, type PiSdkResourcePlan } from '../runs/shared/piArgs.ts';\nimport { isPiRuntime } from '../runs/shared/runtimeRegistry.ts';\n\nconst CONDITIONAL_TOOLS = 'Request-specific internal tools';\nconst HOST_DEFAULT_TOOLS = 'Pi host-default tool set';\nconst AMBIENT_EXTENSIONS = 'Ambient Pi extensions';\nconst AMBIENT_SKILLS = 'Ambient Pi skills';\n\nexport interface ProjectedResource {\n name: string;\n detail?: string;\n}\n\nexport interface ResourceTabProjection {\n effective: readonly ProjectedResource[];\n removed: readonly ProjectedResource[];\n unresolved: readonly ProjectedResource[];\n}\n\nexport interface AgentResourceProjection {\n tools: ResourceTabProjection;\n skills: ResourceTabProjection;\n extensions: ResourceTabProjection;\n notice: string;\n configuredOnly: boolean;\n error?: string;\n}\n\nexport interface AgentCatalogEntry {\n agent: AgentConfig;\n resources: AgentResourceProjection;\n}\n\nexport interface AgentResourceProjectionContext {\n cwd: string;\n skills: Pick<ISkillDiscoveryService, 'resolveSkillsWithFallback' | 'discoverAvailableSkills'>;\n capabilityCeiling?: ResolvedSubagentCapabilityCeiling;\n excludeTools?: readonly string[];\n exclusionSource?: string;\n environment?: NodeJS.ProcessEnv;\n}\n\nfunction emptyTab(): ResourceTabProjection {\n return { effective: [], removed: [], unresolved: [] };\n}\n\nfunction resource(name: string, detail?: string): ProjectedResource {\n return detail ? { name, detail } : { name };\n}\n\nfunction unique(items: readonly ProjectedResource[]): ProjectedResource[] {\n const seen = new Set<string>();\n return items.filter((item) => {\n const key = `${item.name}\\0${item.detail ?? ''}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\nfunction ceilingReason(toolPlan: PiLaunchToolPlan): string {\n const sources = toolPlan.capabilityCeiling?.sources ?? [];\n return sources.length > 0\n ? `removed by capability ceiling from ${sources.join(', ')}`\n : 'removed by capability ceiling';\n}\n\nfunction toolRemovalReason(name: string, toolPlan: PiLaunchToolPlan, context: AgentResourceProjectionContext): string {\n if (toolPlan.excludedTools.includes(name)) {\n return context.exclusionSource\n ? `excluded by active layer policy at ${context.exclusionSource}`\n : 'excluded by active layer policy';\n }\n return ceilingReason(toolPlan);\n}\n\nfunction pathShapedToolEntries(agent: AgentConfig, toolPlan: PiLaunchToolPlan): string[] {\n const builtinTools = new Set(toolPlan.requestedBuiltinTools);\n return (agent.tools ?? []).filter((tool) => !builtinTools.has(tool));\n}\n\nfunction selectorResolved(selector: string, toolPlan: PiLaunchToolPlan): boolean {\n return toolPlan.resolvedMcpSelections.some(\n (selection) => selection.selector === selector || selection.selector.startsWith(`${selector}/`),\n );\n}\n\nfunction removedBuiltinCandidates(agent: AgentConfig, toolPlan: PiLaunchToolPlan): string[] {\n if (agent.tools !== undefined) return toolPlan.requestedBuiltinTools;\n if (toolPlan.capabilityCeiling?.allowedTools) return toolPlan.capabilityCeiling.allowedTools;\n return toolPlan.excludedTools;\n}\n\nfunction toolProjection(\n agent: AgentConfig,\n plan: PiSdkResourcePlan,\n context: AgentResourceProjectionContext,\n): ResourceTabProjection {\n const { toolPlan } = plan;\n const mcpNames = new Set(toolPlan.effectiveMcpTools);\n const effective = toolPlan.explicitToolAllowlist\n ? toolPlan.effectiveToolAllowlist.map((name) =>\n resource(\n name,\n mcpNames.has(name)\n ? 'resolved MCP tool'\n : agent.tools === undefined\n ? 'granted by parent capability ceiling'\n : 'configured builtin tool',\n ),\n )\n : [];\n const removedBuiltins = removedBuiltinCandidates(agent, toolPlan)\n .filter((name) => !toolPlan.declaredBuiltinTools.includes(name))\n .map((name) => resource(name, toolRemovalReason(name, toolPlan, context)));\n const effectiveMcpNames = new Set(toolPlan.effectiveMcpTools);\n const removedMcp = toolPlan.resolvedMcpSelections\n .filter((selection) => !effectiveMcpNames.has(selection.name))\n .map((selection) =>\n resource(selection.name, `${selection.selector} · ${toolRemovalReason(selection.name, toolPlan, context)}`),\n );\n const deniedMcpSelectors = toolPlan.capabilityCeiling?.denyExtensions\n ? (agent.mcpDirectTools ?? []).map((selector) =>\n resource(selector, `${ceilingReason(toolPlan)} · MCP extensions denied`),\n )\n : [];\n const unresolvedSelectors = toolPlan.capabilityCeiling?.denyExtensions\n ? []\n : (agent.mcpDirectTools ?? [])\n .filter((selector) => !selectorResolved(selector, toolPlan))\n .map((selector) => resource(selector, 'MCP selector did not resolve from the current parent catalog'));\n return {\n effective: unique(effective),\n removed: unique([...removedBuiltins, ...removedMcp, ...deniedMcpSelectors]),\n unresolved: unique([\n ...(toolPlan.explicitToolAllowlist\n ? []\n : [resource(HOST_DEFAULT_TOOLS, 'resolved by Pi only after the child host loads resources')]),\n ...unresolvedSelectors,\n resource(CONDITIONAL_TOOLS, 'intercom and structured_output depend on the concrete spawn request'),\n ]),\n };\n}\n\nfunction skillProjection(\n agent: AgentConfig,\n context: AgentResourceProjectionContext,\n): { tab: ResourceTabProjection; requireReadTool: boolean } {\n const resolution = context.skills.resolveSkillsWithFallback(\n agent.skills ?? [],\n context.cwd,\n context.cwd,\n agent.skillPath,\n context.cwd,\n );\n const explicitNames = new Set(resolution.resolved.map((skill) => skill.name));\n const ambient = agent.inheritSkills\n ? context.skills\n .discoverAvailableSkills(context.cwd)\n .filter((skill) => !explicitNames.has(skill.name))\n .map((skill) => resource(skill.name, `ambient parent snapshot · ${skill.source}`))\n : [];\n return {\n tab: {\n effective: unique([\n ...resolution.resolved.map((skill) => resource(skill.name, `configured · ${skill.source} · ${skill.path}`)),\n ...ambient,\n ]),\n removed: [],\n unresolved: unique([\n ...resolution.missing.map((name) =>\n resource(name, 'configured skill was not found from the current session cwd'),\n ),\n ...(agent.inheritSkills\n ? [resource(AMBIENT_SKILLS, 'Pi rediscovers ambient skills when the child resource loader starts')]\n : []),\n ]),\n },\n requireReadTool: buildSkillInjection(resolution.resolved).length > 0,\n };\n}\n\nfunction extensionProjection(agent: AgentConfig, plan: PiSdkResourcePlan): ResourceTabProjection {\n const runtimeExtensions = new Set(plan.toolPlan.runtimeExtensions);\n const configuredExtensions = new Set(plan.toolPlan.configuredExtensions);\n const effective = plan.extensions.map((name) =>\n resource(\n name,\n runtimeExtensions.has(name)\n ? 'internal runtime extension'\n : configuredExtensions.has(name)\n ? 'configured agent extension'\n : 'inherited parent harness extension',\n ),\n );\n const removed = plan.toolPlan.capabilityCeiling?.denyExtensions\n ? [\n ...pathShapedToolEntries(agent, plan.toolPlan),\n ...(agent.extensions ?? []),\n ...(agent.subagentOnlyExtensions ?? []),\n ].map((name) => resource(name, ceilingReason(plan.toolPlan)))\n : [];\n return {\n effective: unique(effective),\n removed: unique(removed),\n unresolved: plan.noAmbientExtensions\n ? []\n : [resource(AMBIENT_EXTENSIONS, 'Pi discovers additional ambient extensions only when the child loads')],\n };\n}\n\nfunction configuredOnlyProjection(agent: AgentConfig): AgentResourceProjection {\n const tools = emptyTab();\n tools.unresolved = unique([\n ...(agent.tools ?? []).map((name) => resource(name, 'configured for external runtime')),\n ...(agent.mcpDirectTools ?? []).map((name) => resource(name, 'configured MCP selector')),\n ...(agent.tools === undefined ? [resource('Runtime-default tools', 'determined by the external runtime')] : []),\n ]);\n const skills = emptyTab();\n skills.unresolved = unique([\n ...(agent.skills ?? []).map((name) => resource(name, 'configured skill name')),\n ...(agent.inheritSkills ? [resource(AMBIENT_SKILLS, 'determined by the external runtime')] : []),\n ]);\n const extensions = emptyTab();\n extensions.unresolved = unique([\n ...[...(agent.extensions ?? []), ...(agent.subagentOnlyExtensions ?? [])].map((name) =>\n resource(name, 'configured extension'),\n ),\n ...(agent.extensions === undefined ? [resource(AMBIENT_EXTENSIONS, 'determined by the external runtime')] : []),\n ]);\n return {\n tools,\n skills,\n extensions,\n notice: `Configured values only. Runtime '${agent.runtime}' does not use the Pi launch projection.`,\n configuredOnly: true,\n };\n}\n\nfunction failedProjection(error: unknown): AgentResourceProjection {\n return {\n tools: emptyTab(),\n skills: emptyTab(),\n extensions: emptyTab(),\n notice: 'Launch projection failed for this agent.',\n configuredOnly: false,\n error: error instanceof Error ? error.message : String(error),\n };\n}\n\nexport function projectAgentResources(\n agent: AgentConfig,\n context: AgentResourceProjectionContext,\n): AgentResourceProjection {\n if (!isPiRuntime(agent.runtime)) return configuredOnlyProjection(agent);\n try {\n const skills = skillProjection(agent, context);\n const plan = resolvePiSdkResourcePlan({\n tools: agent.tools,\n extensions: agent.extensions,\n subagentOnlyExtensions: agent.subagentOnlyExtensions,\n mcpDirectTools: agent.mcpDirectTools,\n cwd: context.cwd,\n requireReadTool: skills.requireReadTool,\n excludeTools: context.excludeTools ? [...context.excludeTools] : undefined,\n capabilityCeiling: context.capabilityCeiling,\n inheritSkills: agent.inheritSkills,\n environment: context.environment,\n });\n return {\n tools: toolProjection(agent, plan, context),\n skills: skills.tab,\n extensions: extensionProjection(agent, plan),\n notice:\n 'Launch projection from the current parent-policy and cwd snapshot. Child loading or request overrides may change qualified resources.',\n configuredOnly: false,\n };\n } catch (error) {\n return failedProjection(error);\n }\n}\n\nexport function buildAgentCatalogEntries(\n agents: readonly AgentConfig[],\n context: AgentResourceProjectionContext,\n): AgentCatalogEntry[] {\n return agents.map((agent) => ({ agent, resources: projectAgentResources(agent, context) }));\n}\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../shared/formatters.cjs`),t=require(`../runs/background/notify.cjs`);let n=require(`@earendil-works/pi-tui`);function r(e,t){return e===`completed`?t.fg(`success`,`✓`):e===`paused`?t.fg(`warning`,`■`):t.fg(`error`,`✗`)}function i(e,t){let n=e.trim(),r=(t?n.split(`
2
+ `):[n.split(`
3
+ `,1)[0]??``]).filter(e=>e.trim());return r.length>0?r:[`(no output)`]}function a(t,n,a){let o=[];t.taskInfo&&o.push(t.taskInfo),t.durationMs!==void 0&&o.push(e.formatDuration(t.durationMs));let s=` ${a.fg(`dim`,`·`)} `,c=`${r(t.status,a)} ${a.bold(t.agent)} ${a.fg(`dim`,t.status)}`;o.length>0&&(c+=`${s}${o.map(e=>a.fg(`dim`,e)).join(s)}`),t.runId&&(c+=`${s}${a.fg(`dim`,t.runId)}`);for(let e of i(t.resultPreview,n))c+=`\n ${a.fg(`dim`,`⎿ ${e}`)}`;return t.handoffPath&&(c+=`\n ${a.fg(`muted`,`Parallel handoff: ${t.handoffPath}`)}`),t.sessionLabel&&t.sessionValue&&(c+=`\n ${a.fg(`muted`,`${t.sessionLabel}: ${t.sessionValue}`)}`),c}function o(e,t,n){return e.length===1?a(e[0],t.expanded,n):[n.bold(`Background tasks completed (${e.length})`),...e.map(e=>a(e,t.expanded,n))].join(`
4
+ `)}function s(e){return!Array.isArray(e)||e.length===0?void 0:e.every(e=>typeof e==`object`&&!!e&&typeof e.agent==`string`)?e:void 0}function c(e){e.registerMessageRenderer(t.SUBAGENT_NOTIFY_MESSAGE_TYPE,(e,t,r)=>{let i=typeof e.content==`string`?e.content:``,a=s(e.details);return a?new n.Text(o(a,{expanded:t.expanded===!0},r),0,0):new n.Text(i,0,0)})}exports.registerCompletionRenderer=c;
5
+ //# sourceMappingURL=completionNotice.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completionNotice.cjs","names":["formatDuration","SUBAGENT_NOTIFY_MESSAGE_TYPE","Text"],"sources":["../../src/tui/completionNotice.ts"],"sourcesContent":["/**\n * Renders the `subagent-notify` custom message: what the parent session\n * actually SEES when a background run finishes. `CompletionNotifier` produces\n * the message (`runs/background/notify.ts`); this decides how it looks.\n *\n * WHY THERE IS NO CONTENT PARSER HERE:\n * The predecessor rendered from `message.details` when present and otherwise\n * re-derived the details by running a regex back over its own formatted\n * markdown (`parseSubagentNotifyContent`). That fallback existed because its\n * notifier sent no `details` at all for grouped completions, so the renderer\n * had a real case where re-parsing was the only source. This package sends\n * `details` on EVERY message, single and grouped alike (see\n * `CompletionNotifier.emit`), so the parser has no case left to serve and is\n * deliberately not ported: a regex that has to stay in lockstep with a\n * formatter living in another domain is a standing correctness liability, and\n * the one thing it protected against is now structurally impossible.\n *\n * The plain-text fallback below is NOT that parser. It covers a genuinely\n * different case: a message with no `details`, which can only reach a reader\n * from a persisted transcript written before this field existed. Showing its\n * raw content verbatim is correct there - it is exactly what the old renderer\n * did when its parse returned undefined.\n *\n * DESIGN PATTERNS:\n * - `options.expanded` gates preview lines the same way `fleetTranscript.ts`\n * gates its own body: collapsed shows the first non-empty line, expanded\n * shows all of them. A completion preview is frequently a multi-paragraph\n * summary, and unconditionally printing it would push the rest of the\n * session's scrollback away on every finished run\n */\n\nimport { Text } from '@earendil-works/pi-tui';\nimport type { Component } from '@earendil-works/pi-tui';\nimport type { ExtensionAPI, MessageRenderOptions, Theme } from '@earendil-works/pi-coding-agent';\n\nimport { formatDuration } from '../shared/formatters.ts';\nimport { type CompletionNotifyDetails, SUBAGENT_NOTIFY_MESSAGE_TYPE } from '../runs/background/notify.ts';\n\n/** Status glyphs. Paused is distinct from failed: the run can still be resumed. */\nfunction statusIcon(status: CompletionNotifyDetails['status'], theme: Theme): string {\n if (status === 'completed') return theme.fg('success', '✓');\n if (status === 'paused') return theme.fg('warning', '■');\n return theme.fg('error', '✗');\n}\n\nfunction previewLines(resultPreview: string, expanded: boolean): string[] {\n const trimmed = resultPreview.trim();\n const lines = expanded ? trimmed.split('\\n') : [trimmed.split('\\n', 1)[0] ?? ''];\n const kept = lines.filter((line) => line.trim());\n return kept.length > 0 ? kept : ['(no output)'];\n}\n\n/** One completion's block: header line, then its indented preview and metadata. */\nfunction renderDetail(detail: CompletionNotifyDetails, expanded: boolean, theme: Theme): string {\n const meta: string[] = [];\n if (detail.taskInfo) meta.push(detail.taskInfo);\n if (detail.durationMs !== undefined) meta.push(formatDuration(detail.durationMs));\n\n const separator = ` ${theme.fg('dim', '·')} `;\n let text = `${statusIcon(detail.status, theme)} ${theme.bold(detail.agent)} ${theme.fg('dim', detail.status)}`;\n if (meta.length > 0) text += `${separator}${meta.map((part) => theme.fg('dim', part)).join(separator)}`;\n // The run id is what every follow-up command takes, so it belongs on the\n // collapsed line too - not only in the expanded body a reader has to open.\n if (detail.runId) text += `${separator}${theme.fg('dim', detail.runId)}`;\n\n for (const line of previewLines(detail.resultPreview, expanded)) {\n text += `\\n ${theme.fg('dim', `⎿ ${line}`)}`;\n }\n if (detail.handoffPath) text += `\\n ${theme.fg('muted', `Parallel handoff: ${detail.handoffPath}`)}`;\n if (detail.sessionLabel && detail.sessionValue) {\n text += `\\n ${theme.fg('muted', `${detail.sessionLabel}: ${detail.sessionValue}`)}`;\n }\n return text;\n}\n\n/**\n * Exported for tests: the rendered string, before it is wrapped in a `Text`\n * component. Kept separate so the formatting is assertable without standing up\n * a TUI - the same split `fleetTranscript.ts` uses for `renderFleetTranscript`.\n */\nexport function renderCompletionNotice(\n details: CompletionNotifyDetails[],\n options: { expanded: boolean },\n theme: Theme,\n): string {\n if (details.length === 1) return renderDetail(details[0]!, options.expanded, theme);\n const header = theme.bold(`Background tasks completed (${details.length})`);\n // Collapsed multi-run notices stay one line per run: a fan-out of ten\n // children would otherwise emit thirty-plus lines in one go.\n return [header, ...details.map((detail) => renderDetail(detail, options.expanded, theme))].join('\\n');\n}\n\nfunction asDetails(value: unknown): CompletionNotifyDetails[] | undefined {\n if (!Array.isArray(value) || value.length === 0) return undefined;\n const isDetail = (entry: unknown): entry is CompletionNotifyDetails =>\n typeof entry === 'object' && entry !== null && typeof (entry as CompletionNotifyDetails).agent === 'string';\n return value.every(isDetail) ? value : undefined;\n}\n\nexport function registerCompletionRenderer(pi: ExtensionAPI): void {\n pi.registerMessageRenderer<CompletionNotifyDetails[]>(\n SUBAGENT_NOTIFY_MESSAGE_TYPE,\n (message, options: MessageRenderOptions, theme: Theme): Component => {\n const content = typeof message.content === 'string' ? message.content : '';\n const details = asDetails(message.details);\n // See the module header: no details means a pre-field transcript entry,\n // not a message to re-derive by parsing.\n if (!details) return new Text(content, 0, 0);\n return new Text(renderCompletionNotice(details, { expanded: options.expanded === true }, theme), 0, 0);\n },\n );\n}\n"],"mappings":"4KAuCA,SAAS,EAAW,EAA2C,EAAsB,CAGnF,OAFI,IAAW,YAAoB,EAAM,GAAG,UAAW,IAAI,CACvD,IAAW,SAAiB,EAAM,GAAG,UAAW,IAAI,CACjD,EAAM,GAAG,QAAS,IAAI,CAG/B,SAAS,EAAa,EAAuB,EAA6B,CACxE,IAAM,EAAU,EAAc,MAAM,CAE9B,GADQ,EAAW,EAAQ,MAAM;EAAK,CAAG,CAAC,EAAQ,MAAM;EAAM,EAAE,CAAC,IAAM,GAAG,EAC7D,OAAQ,GAAS,EAAK,MAAM,CAAC,CAChD,OAAO,EAAK,OAAS,EAAI,EAAO,CAAC,cAAc,CAIjD,SAAS,EAAa,EAAiC,EAAmB,EAAsB,CAC9F,IAAM,EAAiB,EAAE,CACrB,EAAO,UAAU,EAAK,KAAK,EAAO,SAAS,CAC3C,EAAO,aAAe,IAAA,IAAW,EAAK,KAAKA,EAAAA,eAAe,EAAO,WAAW,CAAC,CAEjF,IAAM,EAAY,IAAI,EAAM,GAAG,MAAO,IAAI,CAAC,GACvC,EAAO,GAAG,EAAW,EAAO,OAAQ,EAAM,CAAC,GAAG,EAAM,KAAK,EAAO,MAAM,CAAC,GAAG,EAAM,GAAG,MAAO,EAAO,OAAO,GACxG,EAAK,OAAS,IAAG,GAAQ,GAAG,IAAY,EAAK,IAAK,GAAS,EAAM,GAAG,MAAO,EAAK,CAAC,CAAC,KAAK,EAAU,IAGjG,EAAO,QAAO,GAAQ,GAAG,IAAY,EAAM,GAAG,MAAO,EAAO,MAAM,IAEtE,IAAK,IAAM,KAAQ,EAAa,EAAO,cAAe,EAAS,CAC7D,GAAQ,OAAO,EAAM,GAAG,MAAO,MAAM,IAAO,GAM9C,OAJI,EAAO,cAAa,GAAQ,OAAO,EAAM,GAAG,QAAS,qBAAqB,EAAO,cAAc,IAC/F,EAAO,cAAgB,EAAO,eAChC,GAAQ,OAAO,EAAM,GAAG,QAAS,GAAG,EAAO,aAAa,IAAI,EAAO,eAAe,IAE7E,EAQT,SAAgB,EACd,EACA,EACA,EACQ,CAKR,OAJI,EAAQ,SAAW,EAAU,EAAa,EAAQ,GAAK,EAAQ,SAAU,EAAM,CAI5E,CAHQ,EAAM,KAAK,+BAA+B,EAAQ,OAAO,GAG1D,CAAE,GAAG,EAAQ,IAAK,GAAW,EAAa,EAAQ,EAAQ,SAAU,EAAM,CAAC,CAAC,CAAC,KAAK;EAAK,CAGvG,SAAS,EAAU,EAAuD,CAIxE,MAHI,CAAC,MAAM,QAAQ,EAAM,EAAI,EAAM,SAAW,EAAG,OAG1C,EAAM,MAFK,GAChB,OAAO,GAAU,YAAY,GAAkB,OAAQ,EAAkC,OAAU,SACzE,CAAG,EAAQ,IAAA,GAGzC,SAAgB,EAA2B,EAAwB,CACjE,EAAG,wBACDC,EAAAA,8BACC,EAAS,EAA+B,IAA4B,CACnE,IAAM,EAAU,OAAO,EAAQ,SAAY,SAAW,EAAQ,QAAU,GAClE,EAAU,EAAU,EAAQ,QAAQ,CAI1C,OADK,EACE,IAAIC,EAAAA,KAAK,EAAuB,EAAS,CAAE,SAAU,EAAQ,WAAa,GAAM,CAAE,EAAM,CAAE,EAAG,EAAE,CADjF,IAAIA,EAAAA,KAAK,EAAS,EAAG,EAAE,EAG/C"}
@@ -0,0 +1,5 @@
1
+ import{formatDuration as e,init_formatters as t}from"../shared/formatters.mjs";import{SUBAGENT_NOTIFY_MESSAGE_TYPE as n,init_notify as r}from"../runs/background/notify.mjs";import{Text as i}from"@earendil-works/pi-tui";t(),r();function a(e,t){return e===`completed`?t.fg(`success`,`✓`):e===`paused`?t.fg(`warning`,`■`):t.fg(`error`,`✗`)}function o(e,t){let n=e.trim(),r=(t?n.split(`
2
+ `):[n.split(`
3
+ `,1)[0]??``]).filter(e=>e.trim());return r.length>0?r:[`(no output)`]}function s(t,n,r){let i=[];t.taskInfo&&i.push(t.taskInfo),t.durationMs!==void 0&&i.push(e(t.durationMs));let s=` ${r.fg(`dim`,`·`)} `,c=`${a(t.status,r)} ${r.bold(t.agent)} ${r.fg(`dim`,t.status)}`;i.length>0&&(c+=`${s}${i.map(e=>r.fg(`dim`,e)).join(s)}`),t.runId&&(c+=`${s}${r.fg(`dim`,t.runId)}`);for(let e of o(t.resultPreview,n))c+=`\n ${r.fg(`dim`,`⎿ ${e}`)}`;return t.handoffPath&&(c+=`\n ${r.fg(`muted`,`Parallel handoff: ${t.handoffPath}`)}`),t.sessionLabel&&t.sessionValue&&(c+=`\n ${r.fg(`muted`,`${t.sessionLabel}: ${t.sessionValue}`)}`),c}function c(e,t,n){return e.length===1?s(e[0],t.expanded,n):[n.bold(`Background tasks completed (${e.length})`),...e.map(e=>s(e,t.expanded,n))].join(`
4
+ `)}function l(e){return!Array.isArray(e)||e.length===0?void 0:e.every(e=>typeof e==`object`&&!!e&&typeof e.agent==`string`)?e:void 0}function u(e){e.registerMessageRenderer(n,(e,t,n)=>{let r=typeof e.content==`string`?e.content:``,a=l(e.details);return a?new i(c(a,{expanded:t.expanded===!0},n),0,0):new i(r,0,0)})}export{u as registerCompletionRenderer};
5
+ //# sourceMappingURL=completionNotice.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completionNotice.mjs","names":[],"sources":["../../src/tui/completionNotice.ts"],"sourcesContent":["/**\n * Renders the `subagent-notify` custom message: what the parent session\n * actually SEES when a background run finishes. `CompletionNotifier` produces\n * the message (`runs/background/notify.ts`); this decides how it looks.\n *\n * WHY THERE IS NO CONTENT PARSER HERE:\n * The predecessor rendered from `message.details` when present and otherwise\n * re-derived the details by running a regex back over its own formatted\n * markdown (`parseSubagentNotifyContent`). That fallback existed because its\n * notifier sent no `details` at all for grouped completions, so the renderer\n * had a real case where re-parsing was the only source. This package sends\n * `details` on EVERY message, single and grouped alike (see\n * `CompletionNotifier.emit`), so the parser has no case left to serve and is\n * deliberately not ported: a regex that has to stay in lockstep with a\n * formatter living in another domain is a standing correctness liability, and\n * the one thing it protected against is now structurally impossible.\n *\n * The plain-text fallback below is NOT that parser. It covers a genuinely\n * different case: a message with no `details`, which can only reach a reader\n * from a persisted transcript written before this field existed. Showing its\n * raw content verbatim is correct there - it is exactly what the old renderer\n * did when its parse returned undefined.\n *\n * DESIGN PATTERNS:\n * - `options.expanded` gates preview lines the same way `fleetTranscript.ts`\n * gates its own body: collapsed shows the first non-empty line, expanded\n * shows all of them. A completion preview is frequently a multi-paragraph\n * summary, and unconditionally printing it would push the rest of the\n * session's scrollback away on every finished run\n */\n\nimport { Text } from '@earendil-works/pi-tui';\nimport type { Component } from '@earendil-works/pi-tui';\nimport type { ExtensionAPI, MessageRenderOptions, Theme } from '@earendil-works/pi-coding-agent';\n\nimport { formatDuration } from '../shared/formatters.ts';\nimport { type CompletionNotifyDetails, SUBAGENT_NOTIFY_MESSAGE_TYPE } from '../runs/background/notify.ts';\n\n/** Status glyphs. Paused is distinct from failed: the run can still be resumed. */\nfunction statusIcon(status: CompletionNotifyDetails['status'], theme: Theme): string {\n if (status === 'completed') return theme.fg('success', '✓');\n if (status === 'paused') return theme.fg('warning', '■');\n return theme.fg('error', '✗');\n}\n\nfunction previewLines(resultPreview: string, expanded: boolean): string[] {\n const trimmed = resultPreview.trim();\n const lines = expanded ? trimmed.split('\\n') : [trimmed.split('\\n', 1)[0] ?? ''];\n const kept = lines.filter((line) => line.trim());\n return kept.length > 0 ? kept : ['(no output)'];\n}\n\n/** One completion's block: header line, then its indented preview and metadata. */\nfunction renderDetail(detail: CompletionNotifyDetails, expanded: boolean, theme: Theme): string {\n const meta: string[] = [];\n if (detail.taskInfo) meta.push(detail.taskInfo);\n if (detail.durationMs !== undefined) meta.push(formatDuration(detail.durationMs));\n\n const separator = ` ${theme.fg('dim', '·')} `;\n let text = `${statusIcon(detail.status, theme)} ${theme.bold(detail.agent)} ${theme.fg('dim', detail.status)}`;\n if (meta.length > 0) text += `${separator}${meta.map((part) => theme.fg('dim', part)).join(separator)}`;\n // The run id is what every follow-up command takes, so it belongs on the\n // collapsed line too - not only in the expanded body a reader has to open.\n if (detail.runId) text += `${separator}${theme.fg('dim', detail.runId)}`;\n\n for (const line of previewLines(detail.resultPreview, expanded)) {\n text += `\\n ${theme.fg('dim', `⎿ ${line}`)}`;\n }\n if (detail.handoffPath) text += `\\n ${theme.fg('muted', `Parallel handoff: ${detail.handoffPath}`)}`;\n if (detail.sessionLabel && detail.sessionValue) {\n text += `\\n ${theme.fg('muted', `${detail.sessionLabel}: ${detail.sessionValue}`)}`;\n }\n return text;\n}\n\n/**\n * Exported for tests: the rendered string, before it is wrapped in a `Text`\n * component. Kept separate so the formatting is assertable without standing up\n * a TUI - the same split `fleetTranscript.ts` uses for `renderFleetTranscript`.\n */\nexport function renderCompletionNotice(\n details: CompletionNotifyDetails[],\n options: { expanded: boolean },\n theme: Theme,\n): string {\n if (details.length === 1) return renderDetail(details[0]!, options.expanded, theme);\n const header = theme.bold(`Background tasks completed (${details.length})`);\n // Collapsed multi-run notices stay one line per run: a fan-out of ten\n // children would otherwise emit thirty-plus lines in one go.\n return [header, ...details.map((detail) => renderDetail(detail, options.expanded, theme))].join('\\n');\n}\n\nfunction asDetails(value: unknown): CompletionNotifyDetails[] | undefined {\n if (!Array.isArray(value) || value.length === 0) return undefined;\n const isDetail = (entry: unknown): entry is CompletionNotifyDetails =>\n typeof entry === 'object' && entry !== null && typeof (entry as CompletionNotifyDetails).agent === 'string';\n return value.every(isDetail) ? value : undefined;\n}\n\nexport function registerCompletionRenderer(pi: ExtensionAPI): void {\n pi.registerMessageRenderer<CompletionNotifyDetails[]>(\n SUBAGENT_NOTIFY_MESSAGE_TYPE,\n (message, options: MessageRenderOptions, theme: Theme): Component => {\n const content = typeof message.content === 'string' ? message.content : '';\n const details = asDetails(message.details);\n // See the module header: no details means a pre-field transcript entry,\n // not a message to re-derive by parsing.\n if (!details) return new Text(content, 0, 0);\n return new Text(renderCompletionNotice(details, { expanded: options.expanded === true }, theme), 0, 0);\n },\n );\n}\n"],"mappings":"8NAmCyD,IACiD,CAG1G,SAAS,EAAW,EAA2C,EAAsB,CAGnF,OAFI,IAAW,YAAoB,EAAM,GAAG,UAAW,IAAI,CACvD,IAAW,SAAiB,EAAM,GAAG,UAAW,IAAI,CACjD,EAAM,GAAG,QAAS,IAAI,CAG/B,SAAS,EAAa,EAAuB,EAA6B,CACxE,IAAM,EAAU,EAAc,MAAM,CAE9B,GADQ,EAAW,EAAQ,MAAM;EAAK,CAAG,CAAC,EAAQ,MAAM;EAAM,EAAE,CAAC,IAAM,GAAG,EAC7D,OAAQ,GAAS,EAAK,MAAM,CAAC,CAChD,OAAO,EAAK,OAAS,EAAI,EAAO,CAAC,cAAc,CAIjD,SAAS,EAAa,EAAiC,EAAmB,EAAsB,CAC9F,IAAM,EAAiB,EAAE,CACrB,EAAO,UAAU,EAAK,KAAK,EAAO,SAAS,CAC3C,EAAO,aAAe,IAAA,IAAW,EAAK,KAAK,EAAe,EAAO,WAAW,CAAC,CAEjF,IAAM,EAAY,IAAI,EAAM,GAAG,MAAO,IAAI,CAAC,GACvC,EAAO,GAAG,EAAW,EAAO,OAAQ,EAAM,CAAC,GAAG,EAAM,KAAK,EAAO,MAAM,CAAC,GAAG,EAAM,GAAG,MAAO,EAAO,OAAO,GACxG,EAAK,OAAS,IAAG,GAAQ,GAAG,IAAY,EAAK,IAAK,GAAS,EAAM,GAAG,MAAO,EAAK,CAAC,CAAC,KAAK,EAAU,IAGjG,EAAO,QAAO,GAAQ,GAAG,IAAY,EAAM,GAAG,MAAO,EAAO,MAAM,IAEtE,IAAK,IAAM,KAAQ,EAAa,EAAO,cAAe,EAAS,CAC7D,GAAQ,OAAO,EAAM,GAAG,MAAO,MAAM,IAAO,GAM9C,OAJI,EAAO,cAAa,GAAQ,OAAO,EAAM,GAAG,QAAS,qBAAqB,EAAO,cAAc,IAC/F,EAAO,cAAgB,EAAO,eAChC,GAAQ,OAAO,EAAM,GAAG,QAAS,GAAG,EAAO,aAAa,IAAI,EAAO,eAAe,IAE7E,EAQT,SAAgB,EACd,EACA,EACA,EACQ,CAKR,OAJI,EAAQ,SAAW,EAAU,EAAa,EAAQ,GAAK,EAAQ,SAAU,EAAM,CAI5E,CAHQ,EAAM,KAAK,+BAA+B,EAAQ,OAAO,GAG1D,CAAE,GAAG,EAAQ,IAAK,GAAW,EAAa,EAAQ,EAAQ,SAAU,EAAM,CAAC,CAAC,CAAC,KAAK;EAAK,CAGvG,SAAS,EAAU,EAAuD,CAIxE,MAHI,CAAC,MAAM,QAAQ,EAAM,EAAI,EAAM,SAAW,EAAG,OAG1C,EAAM,MAFK,GAChB,OAAO,GAAU,YAAY,GAAkB,OAAQ,EAAkC,OAAU,SACzE,CAAG,EAAQ,IAAA,GAGzC,SAAgB,EAA2B,EAAwB,CACjE,EAAG,wBACD,GACC,EAAS,EAA+B,IAA4B,CACnE,IAAM,EAAU,OAAO,EAAQ,SAAY,SAAW,EAAQ,QAAU,GAClE,EAAU,EAAU,EAAQ,QAAQ,CAI1C,OADK,EACE,IAAI,EAAK,EAAuB,EAAS,CAAE,SAAU,EAAQ,WAAa,GAAM,CAAE,EAAM,CAAE,EAAG,EAAE,CADjF,IAAI,EAAK,EAAS,EAAG,EAAE,EAG/C"}
@@ -0,0 +1,3 @@
1
+ const e=require(`../_virtual/_rolldown/runtime.cjs`),t=require(`../runs/background/statusReader.cjs`),n=require(`../shared/formatters.cjs`),r=require(`./fleetTranscript.cjs`),i=require(`./fleetAgentView.cjs`);let a=require(`node:fs`);a=e.__toESM(a,1);let o=require(`@earendil-works/pi-coding-agent`),s=require(`@earendil-works/pi-tui`),c=require(`@agimon-ai/doompi-ui/components/doomOverlay`),l=require(`@agimon-ai/doompi-ui/theme`);const u=[`interrupt`,`stop`,`resume`,`steer`],d={interrupt:`i`,stop:`x`,resume:`r`,steer:`m`},f={interrupt:`turn`,stop:`run, final`,resume:void 0,steer:void 0},p=new Map(u.map(e=>[d[e],e])),m={running:`running`,queued:`queued`,pending:`pending`,paused:`paused`,stopped:`stopped`,complete:`complete`,completed:`completed`,failed:`failed`},h=new Set([m.running,m.queued]),g=new Set([m.paused,m.complete,m.completed,m.failed]);function _(e){if(!e)return{interrupt:!1,stop:!1,resume:!1,steer:!1};let t=h.has(e.state);return{interrupt:t,stop:t,resume:g.has(e.state),steer:e.state===m.running}}function v(e,t){return t?e===`resume`?`resume unavailable · ${t.runId} is ${t.state}; resume targets paused, completed, or failed runs`:`${e} unavailable · ${t.runId} is ${t.state}`:`${e} unavailable · no run is selected`}function y(e){return{items:e.list().map(e=>({key:e.runId,runId:e.runId,agent:e.agent??e.runId.slice(0,8),state:e.status??`unknown`,updatedAt:e.updatedAt??e.startedAt??0,job:e})).sort((e,t)=>t.updatedAt-e.updatedAt)}}function b(e){return e.items.map(e=>`${e.runId}:${e.state}:${e.updatedAt}:${e.job.activityState??``}`).join(`|`)}function x(e,t){return e===m.running?t.fg(`accent`,`●`):e===m.queued||e===m.pending?t.fg(`muted`,`◦`):e===m.complete||e===m.completed?t.fg(`success`,`✓`):e===m.paused||e===m.stopped?t.fg(`warning`,`■`):t.fg(`error`,`✗`)}function S(e,t,r,a,o){let s=[e.runId.slice(0,12),t?.agent??e.agent,t?.model?n.formatModelThinking(t.model):void 0].filter(e=>!!e).join(` · `),c=t?.startedAt===void 0?void 0:n.formatDuration((t.endedAt??o)-t.startedAt),l=[t?.toolCount?`${t.toolCount} tools`:void 0,t?.tokens?`${n.formatTokens(t.tokens)} tokens`:void 0].filter(e=>!!e).join(` · `),u=[[`Run`,s],[`State`,[e.state,t?.activityState,c].filter(e=>!!e).join(` · `)],[`Doing`,t?.currentTool??`—`],[`Usage`,l||`—`]];return t?.attentionReason&&u.push([`Needs`,t.attentionReason]),t?.error&&u.push([`Error`,t.error]),t?.summary&&u.push([`Result`,t.summary]),u.map(([e,t])=>i.fieldRow(e,t,r,a))}function C(e,t,n){let r=_(e);return(0,s.truncateToWidth)(` ${u.map(e=>{let t=f[e],i=`${e}${t?` (${t})`:``}`;return r[e]?`${n.fg(`accent`,d[e])} ${i}`:n.fg(`dim`,`${d[e]} ${i}`)}).join(n.fg(`dim`,` · `))}`,t)}function w(e,t,n,r){let i=t=>t===e?r.fg(`accent`,r.bold(`[ ${t} ]`)):r.fg(`dim`,` ${t} `),a=r.fg(`dim`,e===`transcript`?`p agent · o ${t}`:`p transcript`);return E(` ${i(`transcript`)}${i(`agent`)}`,a,n)}function T(e,t){let n=(0,s.truncateToWidth)(e,Math.max(0,t));return n+` `.repeat(Math.max(0,t-(0,s.visibleWidth)(n)))}function E(e,t,n){let r=(0,s.visibleWidth)(t),i=Math.max(0,n-r-1);return T(e,i)+` `.repeat(Math.max(1,n-i-r))+T(t,r)}function D(e){try{let t=a.statSync(e);return`${t.size}:${t.mtimeMs}`}catch{return`missing`}}var O=class extends c.DoomOverlay{snapshot={items:[]};lastRenderKey=``;selected=0;selectedKey;detailScroll=0;detailAutoFollow=!0;detailLineCount=0;detailViewportHeight=8;bodyHeight=8;steerDraft;actionNotice;detailTab=`transcript`;verbosity=`compact`;transcriptTail;transcriptRender;agentCache;disposed=!1;unregister;markdownTheme;scheduler;tracker;done;options;constructor(e,t,n,r,i,a={}){super(e,t),this.markdownTheme=a.markdownTheme??(0,o.getMarkdownTheme)(),this.scheduler=n,this.tracker=r,this.done=i,this.options=a,this.selectedKey=a.initialKey,this.refresh(),this.lastRenderKey=this.pollRenderKey(),this.unregister=this.scheduler.register({id:`tui-fleet`,intervalMs:a.refreshMs??750,run:()=>this.onTick()})}onTick(){if(this.disposed)return!1;this.refresh();let e=this.pollRenderKey();return e===this.lastRenderKey?!1:(this.lastRenderKey=e,this.tui.requestRender(),!0)}pollRenderKey(){let e=this.snapshot.items[this.selected];if(!e)return`${b(this.snapshot)}::none`;let n=t.readAsyncRunStatus(e.runId)?.transcriptPath,r=n?`${n}:${D(n)}`:`none`,i=e.job,a=`${i.currentTool??``}:${i.toolCount??0}:${i.tokens??0}`;return`${b(this.snapshot)}::${e.runId}:${r}:${a}`}refresh(){let e=this.snapshot.items[this.selected]?.key??this.selectedKey;this.snapshot=y(this.tracker);let t=e?this.snapshot.items.findIndex(t=>t.key===e):-1;this.selected=t>=0?t:Math.min(this.selected,Math.max(0,this.snapshot.items.length-1)),this.selectedKey=this.snapshot.items[this.selected]?.key}moveSelection(e){this.snapshot.items.length!==0&&(this.selected=Math.max(0,Math.min(this.snapshot.items.length-1,this.selected+e)),this.selectedKey=this.snapshot.items[this.selected]?.key,this.lastRenderKey=this.pollRenderKey(),this.detailAutoFollow=!0,this.tui.requestRender())}scrollDetail(e){let t=Math.max(0,this.detailLineCount-this.detailViewportHeight);this.detailScroll=Math.max(0,Math.min(t,this.detailScroll+e)),this.detailAutoFollow=this.detailScroll>=t,this.tui.requestRender()}handleInput(e){if(this.steerDraft!==void 0)return this.handleSteerInput(e);if((0,s.matchesKey)(e,`escape`)||(0,s.matchesKey)(e,`ctrl+c`)||(0,s.matchesKey)(e,`q`)){this.done(void 0);return}if((0,s.matchesKey)(e,s.Key.shift(`k`)))return this.scrollDetail(-1);if((0,s.matchesKey)(e,s.Key.shift(`j`)))return this.scrollDetail(1);if((0,s.matchesKey)(e,`up`)||(0,s.matchesKey)(e,`k`))return this.moveSelection(-1);if((0,s.matchesKey)(e,`down`)||(0,s.matchesKey)(e,`j`))return this.moveSelection(1);if((0,s.matchesKey)(e,`pageUp`))return this.scrollDetail(-this.detailViewportHeight);if((0,s.matchesKey)(e,`pageDown`))return this.scrollDetail(this.detailViewportHeight);if((0,s.matchesKey)(e,`p`))return this.toggleTab();if((0,s.matchesKey)(e,`o`))return this.toggleVerbosity();if((0,s.matchesKey)(e,`ctrl+r`)){this.clearCaches(),this.refresh(),this.tui.requestRender();return}let t=p.get(e.toLowerCase());t&&this.triggerControl(t)}clearCaches(){this.transcriptTail=void 0,this.transcriptRender=void 0,this.agentCache=void 0}toggleTab(){this.detailTab=this.detailTab===`transcript`?`agent`:`transcript`,this.detailScroll=0,this.detailAutoFollow=this.detailTab===`transcript`,this.tui.requestRender()}toggleVerbosity(){this.verbosity=this.verbosity===`compact`?`full`:`compact`,this.tui.requestRender()}handleSteerInput(e){if((0,s.matchesKey)(e,`escape`)||(0,s.matchesKey)(e,`ctrl+c`)){this.steerDraft=void 0,this.setNotice(`steer cancelled · no message sent`);return}if(e===`\r`||e===`
2
+ `){let e=(this.steerDraft??``).trim();this.steerDraft=void 0;let t=this.snapshot.items[this.selected];if(!t||!e){this.setNotice(`steer cancelled · a non-empty message is required`);return}this.dispatch({action:`steer`,id:t.runId,message:e});return}if(e===``||e===`\b`){this.steerDraft=(this.steerDraft??``).slice(0,-1),this.tui.requestRender();return}e.length===1&&e>=` `&&(this.steerDraft=`${this.steerDraft??``}${e}`,this.tui.requestRender())}triggerControl(e){let t=this.snapshot.items[this.selected];if(!_(t)[e]){this.setNotice(v(e,t));return}if(t){if(e===`steer`){this.steerDraft=``,this.tui.requestRender();return}this.dispatch({action:e,id:t.runId})}}async dispatch(e){let t=this.options.dispatchAction;if(!t){this.setNotice(`${e.action} ${e.id} · unavailable · no subagent control channel is attached`);return}this.setNotice(`${e.action} ${e.id} · dispatching…`);try{let n=await t(e);if(this.disposed)return;this.setNotice(`${e.action} ${e.id} · ${n.status}${n.detail?` · ${n.detail}`:``}`)}catch(t){if(this.disposed)return;this.setNotice(`${e.action} ${e.id} · failed · ${t instanceof Error?t.message:String(t)}`)}}setNotice(e){this.actionNotice=e,this.tui.requestRender()}rosterLines(e){if(this.snapshot.items.length===0)return[this.theme.fg(`dim`,`No tracked runs`)];let t=Math.max(0,Math.min(this.selected-this.bodyHeight+1,Math.max(0,this.snapshot.items.length-this.bodyHeight)));return this.snapshot.items.slice(t,t+this.bodyHeight).map((n,r)=>{let i=t+r,a=i===this.selected?this.theme.fg(`accent`,`›`):` `,o=this.theme.fg((0,l.agentIdentityColor)(n.runId),i===this.selected?this.theme.bold(n.agent):n.agent);return E(`${a} ${x(n.state,this.theme)} ${o}`,this.theme.fg(`dim`,n.state),e)})}renderedTranscript(e,t){let n=e?.transcriptPath;if(!n)return this.transcriptTail=void 0,this.transcriptRender=void 0,{events:0,body:[]};let i=this.transcriptTail?.path===n?this.transcriptTail:void 0,a=r.readFleetTranscriptTail(n,i);this.transcriptTail=a;let o=r.renderFleetTranscript(a,t,this.theme,this.markdownTheme,{cwd:e?.cwd,verbosity:this.verbosity},i?this.transcriptRender:void 0);return this.transcriptRender=o,{events:a.events.length,body:o.lines}}renderedAgent(e,t,n){let r=i.agentSystemPromptFingerprint(t);if(this.agentCache&&this.agentCache.runId===e.runId&&this.agentCache.fingerprint===r&&this.agentCache.width===n)return this.agentCache.lines;let a=i.renderAgentView({status:t,state:e.state,agent:e.agent,runId:e.runId,prompt:i.readAgentSystemPrompt(t),width:n,theme:this.theme,markdownTheme:this.markdownTheme});return this.agentCache={runId:e.runId,fingerprint:r,width:n,lines:a},a}wrappedDetail(e,t,n){if(!e)return[`No tracked runs.`,``,`New runs appear here automatically while this inspector remains open.`];if(this.detailTab===`agent`)return this.renderedAgent(e,t,n);let{events:r,body:i}=this.renderedTranscript(t,n);if(r>0)return i;let a=t?t.transcriptPath?this.transcriptTail?.warning?`Transcript unavailable. The transcript artifact is missing or unreadable.`:`No transcript yet.`:`Transcript unavailable. Artifacts were disabled for this run, so nothing was recorded.`:`Transcript unavailable. No run status was found, so there is no transcript path to read.`,o=[];for(let e of(0,s.wrapTextWithAnsi)(a,Math.max(1,n)))o.push(e);return o}getChrome(){let e=this.snapshot.items[this.selected],t=this.snapshot.items.length?`${this.selected+1}/${this.snapshot.items.length}`:`0/0`;return{title:`AGENT RUNS`,accent:c.DOOM_OVERLAY_ACCENT,breadcrumb:`SPC › a / agents`,headerRight:e?`${x(e.state,this.theme)} ${this.theme.fg((0,l.agentIdentityColor)(e.runId),e.agent)} · ${e.state}`:`no runs`,footer:[`↑↓/jk select`,`J/K scroll`,`p agent`,`o detail`,`Ctrl+R refresh`,`Esc close`].join(` · `),footerRight:t}}renderBody(e,n){let r=(this.steerDraft===void 0?0:2)+(this.actionNotice===void 0?0:1),i=Math.max(0,n-r),a=e<36,o=a?Math.max(1,Math.floor((i-1)*.35)):i,c=a?Math.max(0,i-o-1):i;this.bodyHeight=o;let l=a?e:Math.max(22,Math.min(46,Math.floor((e-1)*.38))),u=a?e:Math.max(1,l-1),d=a?e:Math.max(1,e-u-3),f=this.rosterLines(u),p=this.snapshot.items[this.selected],m=p?t.readAsyncRunStatus(p.runId):void 0,h=this.wrappedDetail(p,m,d),g=p&&this.detailTab===`transcript`?[...S(p,m,d,this.theme,Date.now()),``,C(p,d,this.theme),w(this.detailTab,this.verbosity,d,this.theme)]:p?[w(this.detailTab,this.verbosity,d,this.theme)]:[],_=c-15>=g.length?g:[];this.detailViewportHeight=Math.max(1,c-_.length),this.detailLineCount=h.length;let v=Math.max(0,h.length-this.detailViewportHeight);(this.detailAutoFollow||this.detailScroll>v)&&(this.detailScroll=v);let y=[..._,...h.slice(this.detailScroll,this.detailScroll+this.detailViewportHeight)],b=[];if(a){for(let t=0;t<o;t++)b.push(T(f[t]??``,e));i>o&&b.push(this.theme.fg(`borderMuted`,`─`.repeat(e)));for(let t=0;t<c;t++)b.push(T(y[t]??``,e))}else for(let e=0;e<i;e++)b.push(`${T(f[e]??``,u)} ${this.theme.fg(`borderMuted`,`│`)} ${T(y[e]??``,d)}`);if(this.steerDraft!==void 0){let t=[` ${this.theme.fg(`accent`,`STEER MESSAGE`)} ${this.theme.fg(`dim`,`· run ${p?.runId??`—`}`)}`,` ${this.theme.fg(`accent`,`❯`)} ${this.steerDraft}▌`].map(t=>(0,s.truncateToWidth)(t,e));b.push(...t)}return this.actionNotice!==void 0&&b.push(T(` ${this.theme.fg(`muted`,this.actionNotice)}`,e)),b.slice(0,n).map(t=>(0,s.truncateToWidth)(t,e))}invalidate(){this.clearCaches(),this.refresh()}dispose(){this.disposed=!0,this.unregister()}};async function k(e,t,n,r={}){await e.ui.custom((e,i,a,o)=>new O(e,i,t,n,o,r),c.DOOM_FULLSCREEN_UI_OPTIONS)}exports.openSubagentFleet=k;
3
+ //# sourceMappingURL=fleet.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fleet.cjs","names":["formatModelThinking","formatDuration","formatTokens","fieldRow","fs","DoomOverlay","readAsyncRunStatus","Key","readFleetTranscriptTail","renderFleetTranscript","agentSystemPromptFingerprint","renderAgentView","readAgentSystemPrompt","DOOM_OVERLAY_ACCENT","DOOM_FULLSCREEN_UI_OPTIONS"],"sources":["../../src/tui/fleet.ts"],"sourcesContent":["/**\n * The fleet inspector overlay: a roster of this session's async runs, plus a\n * scrollable detail/transcript pane and runtime controls for the selected one.\n *\n * NOT A PORT - THE FIX IS THE POINT:\n * The predecessor (`doom-pi-subagents/src/tui/fleet.ts`) owned a private\n * `setInterval(750ms)` whose handler unconditionally nulled its own transcript\n * cache (`invalidate()`), so every tick re-read and re-parsed the selected\n * run's whole transcript file regardless of whether anything had changed.\n * This version registers with `PollScheduler` instead of owning a timer, and\n * NEVER blanks `transcriptCache` on a tick. A tick stats only the selected\n * transcript and requests a repaint when its size or modification time changes.\n * `renderedTranscript()` then uses the same fingerprint to decide whether the\n * next render needs one content read. Ctrl+R remains the deliberate manual\n * cache-clearing path.\n *\n * There is also no foreground-run concept here (doom-team is async-only - see\n * `spawnHandshake.ts`'s header), so every roster item is an async run. Roster\n * state comes from `IAsyncJobTracker`, the package's one source of truth for\n * run state; the fuller per-run detail a tracker record does not carry\n * (steps, summary) comes from `readAsyncRunStatus` (`statusReader.ts`), read\n * lazily only for the SELECTED item when the detail pane actually needs it,\n * not for the whole roster on every tick.\n *\n * DESIGN PATTERNS:\n * - The scheduler subscription's `run()` diffs the roster and selected\n * transcript fingerprint against the last values it saw, matching\n * `PollSubscription`'s \"return true only on real work\" contract so idle\n * backoff still applies when nothing in the fleet is moving\n * - Controls always list every action, unavailable ones dimmed rather than\n * hidden, so the key map never shifts under the user\n *\n * Child transcripts are written directly from Pi SDK events by the detached\n * runner. The exact artifact path is persisted in status.json so non-default\n * artifact policies remain readable here.\n */\n\nimport { getMarkdownTheme, type ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport {\n DOOM_OVERLAY_ACCENT,\n DoomOverlay,\n type DoomOverlayChrome,\n type DoomOverlayTui,\n DOOM_FULLSCREEN_UI_OPTIONS,\n} from '@agimon-ai/doompi-ui/components/doomOverlay';\nimport { agentIdentityColor } from '@agimon-ai/doompi-ui/theme';\nimport {\n Key,\n matchesKey,\n truncateToWidth,\n visibleWidth,\n wrapTextWithAnsi,\n type MarkdownTheme,\n} from '@earendil-works/pi-tui';\n\nimport * as fs from 'node:fs';\nimport { formatDuration, formatModelThinking, formatTokens } from '../shared/formatters.ts';\nimport type { AsyncRunStatus } from '../runs/background/asyncExecution.ts';\nimport type { ITrackedAsyncJobs, TrackedAsyncJob } from '../runs/background/asyncJobTracker.ts';\nimport type { IPollScheduler } from '../shared/pollScheduler.ts';\nimport { readAsyncRunStatus } from '../runs/background/statusReader.ts';\nimport {\n readFleetTranscriptTail,\n renderFleetTranscript,\n type FleetTranscriptRender,\n type FleetTranscriptTail,\n type FleetTranscriptVerbosity,\n} from './fleetTranscript.ts';\nimport { agentSystemPromptFingerprint, fieldRow, readAgentSystemPrompt, renderAgentView } from './fleetAgentView.ts';\n\nconst DEFAULT_REFRESH_INTERVAL_MS = 750;\nconst MIN_DETAIL_BODY_LINES = 15;\nconst FIELD_FALLBACK = '—';\nconst POLL_SUBSCRIBER_ID = 'tui-fleet';\n\n/** Which question the detail pane is answering. See `fleetAgentView.ts`'s header. */\nexport type FleetDetailTab = 'transcript' | 'agent';\n\ntype Theme = ExtensionContext['ui']['theme'];\nexport interface FleetItem {\n key: string;\n runId: string;\n agent: string;\n state: string;\n updatedAt: number;\n job: TrackedAsyncJob;\n}\n\nexport interface FleetSnapshot {\n items: FleetItem[];\n}\n\nexport type FleetActionName = 'interrupt' | 'stop' | 'resume' | 'steer';\n\nexport interface FleetActionRequest {\n action: FleetActionName;\n id: string;\n message?: string;\n}\n\nexport interface FleetActionResult {\n status: string;\n detail?: string;\n}\n\nexport type FleetActionDispatcher = (request: FleetActionRequest) => Promise<FleetActionResult>;\n\nexport interface FleetViewOptions {\n refreshMs?: number;\n initialKey?: string;\n markdownTheme?: MarkdownTheme;\n /** Injected so the overlay can be asserted on its emitted payload in tests. */\n dispatchAction?: FleetActionDispatcher;\n}\n\nconst CONTROL_ORDER: readonly FleetActionName[] = ['interrupt', 'stop', 'resume', 'steer'];\nconst CONTROL_KEY: Record<FleetActionName, string> = { interrupt: 'i', stop: 'x', resume: 'r', steer: 'm' };\n/**\n * Short inline qualifier for a control, or undefined where the verb is enough.\n *\n * Collapsed from a full sentence per action when the controls moved to one\n * line. What survives is only what changes a decision at the moment of\n * pressing the key - above all that `stop` cannot be undone, which is the one\n * hint whose loss would cost a user a run.\n */\nconst CONTROL_HINT: Record<FleetActionName, string | undefined> = {\n interrupt: 'turn',\n stop: 'run, final',\n resume: undefined,\n steer: undefined,\n};\nconst CONTROL_BY_KEY = new Map<string, FleetActionName>(CONTROL_ORDER.map((action) => [CONTROL_KEY[action], action]));\n/**\n * Run-state tokens as the tracker writes them. Named once because availability\n * checks and glyph rendering both branch on them, and a typo in either place\n * fails silently as \"unknown state\".\n */\nconst RUN_STATE = {\n running: 'running',\n queued: 'queued',\n pending: 'pending',\n paused: 'paused',\n stopped: 'stopped',\n complete: 'complete',\n completed: 'completed',\n failed: 'failed',\n} as const;\n\nconst LIVE_STATES = new Set<string>([RUN_STATE.running, RUN_STATE.queued]);\nconst RESUMABLE_STATES = new Set<string>([RUN_STATE.paused, RUN_STATE.complete, RUN_STATE.completed, RUN_STATE.failed]);\n\nfunction controlAvailability(item: FleetItem | undefined): Record<FleetActionName, boolean> {\n if (!item) return { interrupt: false, stop: false, resume: false, steer: false };\n const live = LIVE_STATES.has(item.state);\n return {\n interrupt: live,\n stop: live,\n resume: RESUMABLE_STATES.has(item.state),\n steer: item.state === RUN_STATE.running,\n };\n}\n\nfunction unavailableReason(action: FleetActionName, item: FleetItem | undefined): string {\n if (!item) return `${action} unavailable · no run is selected`;\n if (action === 'resume') {\n return `resume unavailable · ${item.runId} is ${item.state}; resume targets paused, completed, or failed runs`;\n }\n return `${action} unavailable · ${item.runId} is ${item.state}`;\n}\n\n/** One tracked job per roster row. Newest activity first. */\nexport function collectFleetSnapshot(tracker: ITrackedAsyncJobs): FleetSnapshot {\n const items = tracker\n .list()\n .map(\n (job): FleetItem => ({\n key: job.runId,\n runId: job.runId,\n agent: job.agent ?? job.runId.slice(0, 8),\n state: job.status ?? 'unknown',\n updatedAt: job.updatedAt ?? job.startedAt ?? 0,\n job,\n }),\n )\n .sort((left, right) => right.updatedAt - left.updatedAt);\n return { items };\n}\n\n/** A short string that changes iff anything a roster row displays changed. */\nfunction rosterRenderKey(snapshot: FleetSnapshot): string {\n return snapshot.items\n .map((item) => `${item.runId}:${item.state}:${item.updatedAt}:${item.job.activityState ?? ''}`)\n .join('|');\n}\n\nfunction statusGlyph(state: string, theme: Theme): string {\n if (state === RUN_STATE.running) return theme.fg('accent', '●');\n if (state === RUN_STATE.queued || state === RUN_STATE.pending) return theme.fg('muted', '◦');\n if (state === RUN_STATE.complete || state === RUN_STATE.completed) return theme.fg('success', '✓');\n if (state === RUN_STATE.paused || state === RUN_STATE.stopped) return theme.fg('warning', '■');\n return theme.fg('error', '✗');\n}\n\n/**\n * What the selected run is doing right now.\n *\n * Every value here was already being written to status.json and none of it was\n * being shown, which is why the pane could be watched for minutes without\n * telling you whether anything was happening. `Doing` and `Usage` keep their\n * rows even when empty so the header height does not change under a running\n * run and bounce the transcript below it.\n */\nfunction statusHeaderLines(\n item: FleetItem,\n status: AsyncRunStatus | undefined,\n width: number,\n theme: Theme,\n now: number,\n): string[] {\n const identity = [\n item.runId.slice(0, 12),\n status?.agent ?? item.agent,\n status?.model ? formatModelThinking(status.model) : undefined,\n ]\n .filter((part): part is string => Boolean(part))\n .join(' · ');\n const elapsed =\n status?.startedAt !== undefined ? formatDuration((status.endedAt ?? now) - status.startedAt) : undefined;\n const usage = [\n status?.toolCount ? `${status.toolCount} tools` : undefined,\n status?.tokens ? `${formatTokens(status.tokens)} tokens` : undefined,\n ]\n .filter((part): part is string => Boolean(part))\n .join(' · ');\n const rows: Array<[string, string]> = [\n ['Run', identity],\n ['State', [item.state, status?.activityState, elapsed].filter((part): part is string => Boolean(part)).join(' · ')],\n ['Doing', status?.currentTool ?? FIELD_FALLBACK],\n ['Usage', usage || FIELD_FALLBACK],\n ];\n if (status?.attentionReason) rows.push(['Needs', status.attentionReason]);\n if (status?.error) rows.push(['Error', status.error]);\n if (status?.summary) rows.push(['Result', status.summary]);\n return rows.map(([label, value]) => fieldRow(label, value, width, theme));\n}\n\n/**\n * Runtime controls on one line.\n *\n * Every action is still listed, unavailable ones dimmed rather than hidden, so\n * the key map never shifts under the user. The per-action hints moved to the\n * footer legend: five rows of them cost the transcript a third of the pane to\n * restate what the footer already says.\n */\nfunction controlLine(item: FleetItem | undefined, width: number, theme: Theme): string {\n const availability = controlAvailability(item);\n const parts = CONTROL_ORDER.map((action) => {\n const hint = CONTROL_HINT[action];\n const body = `${action}${hint ? ` (${hint})` : ''}`;\n return availability[action]\n ? `${theme.fg('accent', CONTROL_KEY[action])} ${body}`\n : theme.fg('dim', `${CONTROL_KEY[action]} ${body}`);\n });\n return truncateToWidth(` ${parts.join(theme.fg('dim', ' · '))}`, width);\n}\n\nfunction tabStrip(tab: FleetDetailTab, verbosity: FleetTranscriptVerbosity, width: number, theme: Theme): string {\n const label = (name: FleetDetailTab): string =>\n name === tab ? theme.fg('accent', theme.bold(`[ ${name} ]`)) : theme.fg('dim', ` ${name} `);\n const right = theme.fg('dim', tab === 'transcript' ? `p agent · o ${verbosity}` : 'p transcript');\n return rightAligned(` ${label('transcript')}${label('agent')}`, right, width);\n}\n\nfunction fit(text: string, width: number): string {\n const clipped = truncateToWidth(text, Math.max(0, width));\n return clipped + ' '.repeat(Math.max(0, width - visibleWidth(clipped)));\n}\n\nfunction rightAligned(left: string, right: string, width: number): string {\n const rightWidth = visibleWidth(right);\n const leftWidth = Math.max(0, width - rightWidth - 1);\n return fit(left, leftWidth) + ' '.repeat(Math.max(1, width - leftWidth - rightWidth)) + fit(right, rightWidth);\n}\n\n/**\n * Size and mtime of a transcript, for the poll tick.\n *\n * A tick may stat but must never read (see the module header), so this is\n * deliberately the cheapest thing that still changes when the file grows.\n */\nfunction transcriptFingerprint(filePath: string): string {\n try {\n const stat = fs.statSync(filePath);\n return `${stat.size}:${stat.mtimeMs}`;\n } catch {\n return 'missing';\n }\n}\n\n/** Rendered agent tab, cached so scrolling a long prompt does not re-render its markdown. */\ninterface FleetAgentCache {\n runId: string;\n fingerprint: string;\n width: number;\n lines: string[];\n}\n\nexport class SubagentFleetComponent extends DoomOverlay {\n private snapshot: FleetSnapshot = { items: [] };\n private lastRenderKey = '';\n private selected = 0;\n private selectedKey: string | undefined;\n private detailScroll = 0;\n private detailAutoFollow = true;\n private detailLineCount = 0;\n private detailViewportHeight = 8;\n private bodyHeight = 8;\n private steerDraft: string | undefined;\n private actionNotice: string | undefined;\n private detailTab: FleetDetailTab = 'transcript';\n private verbosity: FleetTranscriptVerbosity = 'compact';\n private transcriptTail: FleetTranscriptTail | undefined;\n private transcriptRender: FleetTranscriptRender | undefined;\n private agentCache: FleetAgentCache | undefined;\n private disposed = false;\n private readonly unregister: () => void;\n private readonly markdownTheme: MarkdownTheme;\n private readonly scheduler: IPollScheduler;\n private readonly tracker: ITrackedAsyncJobs;\n private readonly done: (result: undefined) => void;\n private readonly options: FleetViewOptions;\n\n constructor(\n tui: DoomOverlayTui,\n theme: Theme,\n scheduler: IPollScheduler,\n tracker: ITrackedAsyncJobs,\n done: (result: undefined) => void,\n options: FleetViewOptions = {},\n ) {\n super(tui, theme);\n this.markdownTheme = options.markdownTheme ?? getMarkdownTheme();\n this.scheduler = scheduler;\n this.tracker = tracker;\n this.done = done;\n this.options = options;\n this.selectedKey = options.initialKey;\n this.refresh();\n this.lastRenderKey = this.pollRenderKey();\n this.unregister = this.scheduler.register({\n id: POLL_SUBSCRIBER_ID,\n intervalMs: options.refreshMs ?? DEFAULT_REFRESH_INTERVAL_MS,\n run: () => this.onTick(),\n });\n }\n\n /**\n * One scheduler tick. The tracker read is in memory and only the selected\n * transcript is statted. Transcript contents remain render-owned and cached.\n */\n private onTick(): boolean {\n if (this.disposed) return false;\n this.refresh();\n const renderKey = this.pollRenderKey();\n if (renderKey === this.lastRenderKey) return false;\n this.lastRenderKey = renderKey;\n this.tui.requestRender();\n return true;\n }\n\n private pollRenderKey(): string {\n const selected = this.snapshot.items[this.selected];\n if (!selected) return `${rosterRenderKey(this.snapshot)}::none`;\n const transcriptPath = readAsyncRunStatus(selected.runId)?.transcriptPath;\n const transcriptKey = transcriptPath ? `${transcriptPath}:${transcriptFingerprint(transcriptPath)}` : 'none';\n // The live status header moves on values the roster row does not carry, so\n // a tick that only changes what the run is DOING still has to repaint.\n const job = selected.job;\n const activity = `${job.currentTool ?? ''}:${job.toolCount ?? 0}:${job.tokens ?? 0}`;\n return `${rosterRenderKey(this.snapshot)}::${selected.runId}:${transcriptKey}:${activity}`;\n }\n\n private refresh(): void {\n const previousKey = this.snapshot.items[this.selected]?.key ?? this.selectedKey;\n this.snapshot = collectFleetSnapshot(this.tracker);\n const preserved = previousKey ? this.snapshot.items.findIndex((item) => item.key === previousKey) : -1;\n this.selected = preserved >= 0 ? preserved : Math.min(this.selected, Math.max(0, this.snapshot.items.length - 1));\n this.selectedKey = this.snapshot.items[this.selected]?.key;\n }\n\n private moveSelection(delta: number): void {\n if (this.snapshot.items.length === 0) return;\n this.selected = Math.max(0, Math.min(this.snapshot.items.length - 1, this.selected + delta));\n this.selectedKey = this.snapshot.items[this.selected]?.key;\n this.lastRenderKey = this.pollRenderKey();\n this.detailAutoFollow = true;\n this.tui.requestRender();\n }\n\n private scrollDetail(delta: number): void {\n const maxScroll = Math.max(0, this.detailLineCount - this.detailViewportHeight);\n this.detailScroll = Math.max(0, Math.min(maxScroll, this.detailScroll + delta));\n this.detailAutoFollow = this.detailScroll >= maxScroll;\n this.tui.requestRender();\n }\n\n handleInput(data: string): void {\n if (this.steerDraft !== undefined) return this.handleSteerInput(data);\n if (matchesKey(data, 'escape') || matchesKey(data, 'ctrl+c') || matchesKey(data, 'q')) {\n this.done(undefined);\n return;\n }\n if (matchesKey(data, Key.shift('k'))) return this.scrollDetail(-1);\n if (matchesKey(data, Key.shift('j'))) return this.scrollDetail(1);\n if (matchesKey(data, 'up') || matchesKey(data, 'k')) return this.moveSelection(-1);\n if (matchesKey(data, 'down') || matchesKey(data, 'j')) return this.moveSelection(1);\n if (matchesKey(data, 'pageUp')) return this.scrollDetail(-this.detailViewportHeight);\n if (matchesKey(data, 'pageDown')) return this.scrollDetail(this.detailViewportHeight);\n if (matchesKey(data, 'p')) return this.toggleTab();\n if (matchesKey(data, 'o')) return this.toggleVerbosity();\n if (matchesKey(data, 'ctrl+r')) {\n // Manual refresh: the one deliberate cache-clearing path. Distinct from\n // every scheduler tick, which must not do this - see the module header.\n this.clearCaches();\n this.refresh();\n this.tui.requestRender();\n return;\n }\n const action = CONTROL_BY_KEY.get(data.toLowerCase());\n if (action) this.triggerControl(action);\n }\n\n private clearCaches(): void {\n this.transcriptTail = undefined;\n this.transcriptRender = undefined;\n this.agentCache = undefined;\n }\n\n private toggleTab(): void {\n this.detailTab = this.detailTab === 'transcript' ? 'agent' : 'transcript';\n // A transcript is read newest-last and a prompt is read from the top, so\n // each tab lands where its own content starts being useful.\n this.detailScroll = 0;\n this.detailAutoFollow = this.detailTab === 'transcript';\n this.tui.requestRender();\n }\n\n private toggleVerbosity(): void {\n this.verbosity = this.verbosity === 'compact' ? 'full' : 'compact';\n // No cache clearing needed: `renderFleetTranscript` treats a verbosity\n // change as a global one and re-renders every block itself.\n this.tui.requestRender();\n }\n\n private handleSteerInput(data: string): void {\n if (matchesKey(data, 'escape') || matchesKey(data, 'ctrl+c')) {\n this.steerDraft = undefined;\n this.setNotice('steer cancelled · no message sent');\n return;\n }\n if (data === '\\r' || data === '\\n') {\n const message = (this.steerDraft ?? '').trim();\n this.steerDraft = undefined;\n const item = this.snapshot.items[this.selected];\n if (!item || !message) {\n this.setNotice('steer cancelled · a non-empty message is required');\n return;\n }\n void this.dispatch({ action: 'steer', id: item.runId, message });\n return;\n }\n if (data === '\\x7f' || data === '\\b') {\n this.steerDraft = (this.steerDraft ?? '').slice(0, -1);\n this.tui.requestRender();\n return;\n }\n if (data.length === 1 && data >= ' ') {\n this.steerDraft = `${this.steerDraft ?? ''}${data}`;\n this.tui.requestRender();\n }\n }\n\n private triggerControl(action: FleetActionName): void {\n const item = this.snapshot.items[this.selected];\n if (!controlAvailability(item)[action]) {\n this.setNotice(unavailableReason(action, item));\n return;\n }\n if (!item) return;\n if (action === 'steer') {\n this.steerDraft = '';\n this.tui.requestRender();\n return;\n }\n void this.dispatch({ action, id: item.runId });\n }\n\n private async dispatch(request: FleetActionRequest): Promise<void> {\n const dispatchAction = this.options.dispatchAction;\n if (!dispatchAction) {\n this.setNotice(`${request.action} ${request.id} · unavailable · no subagent control channel is attached`);\n return;\n }\n this.setNotice(`${request.action} ${request.id} · dispatching…`);\n try {\n const result = await dispatchAction(request);\n if (this.disposed) return;\n this.setNotice(`${request.action} ${request.id} · ${result.status}${result.detail ? ` · ${result.detail}` : ''}`);\n } catch (cause) {\n if (this.disposed) return;\n this.setNotice(\n `${request.action} ${request.id} · failed · ${cause instanceof Error ? cause.message : String(cause)}`,\n );\n }\n }\n\n private setNotice(notice: string): void {\n this.actionNotice = notice;\n this.tui.requestRender();\n }\n\n private rosterLines(width: number): string[] {\n if (this.snapshot.items.length === 0) return [this.theme.fg('dim', 'No tracked runs')];\n const start = Math.max(\n 0,\n Math.min(this.selected - this.bodyHeight + 1, Math.max(0, this.snapshot.items.length - this.bodyHeight)),\n );\n return this.snapshot.items.slice(start, start + this.bodyHeight).map((item, offset) => {\n const index = start + offset;\n const marker = index === this.selected ? this.theme.fg('accent', '›') : ' ';\n const agent = this.theme.fg(\n agentIdentityColor(item.runId),\n index === this.selected ? this.theme.bold(item.agent) : item.agent,\n );\n const left = `${marker} ${statusGlyph(item.state, this.theme)} ${agent}`;\n return rightAligned(left, this.theme.fg('dim', item.state), width);\n });\n }\n\n /**\n * Reads and formats the selected run's transcript, cached by content\n * fingerprint. Only invoked from `render()`, never from a poll tick - so a\n * disk read only happens when the pane is actually about to be painted with\n * new content, not on a fixed clock.\n */\n private renderedTranscript(status: AsyncRunStatus | undefined, width: number): { events: number; body: string[] } {\n const target = status?.transcriptPath;\n if (!target) {\n this.transcriptTail = undefined;\n this.transcriptRender = undefined;\n return { events: 0, body: [] };\n }\n // Resuming is what keeps this proportional to what arrived rather than to\n // what the file holds; the returned tail supersedes the one passed in.\n const previous = this.transcriptTail?.path === target ? this.transcriptTail : undefined;\n const tail = readFleetTranscriptTail(target, previous);\n this.transcriptTail = tail;\n const render = renderFleetTranscript(\n tail,\n width,\n this.theme,\n this.markdownTheme,\n { cwd: status?.cwd, verbosity: this.verbosity },\n previous ? this.transcriptRender : undefined,\n );\n this.transcriptRender = render;\n return { events: tail.events.length, body: render.lines };\n }\n\n /**\n * The agent tab, cached on the prompt's own fingerprint.\n *\n * A recorded system prompt is kilobytes of markdown that never changes for\n * the life of a run, so rendering it once per (run, width) rather than once\n * per keypress is what makes scrolling it usable.\n */\n private renderedAgent(item: FleetItem, status: AsyncRunStatus | undefined, width: number): string[] {\n const fingerprint = agentSystemPromptFingerprint(status);\n if (\n this.agentCache &&\n this.agentCache.runId === item.runId &&\n this.agentCache.fingerprint === fingerprint &&\n this.agentCache.width === width\n ) {\n return this.agentCache.lines;\n }\n const lines = renderAgentView({\n status,\n state: item.state,\n agent: item.agent,\n runId: item.runId,\n prompt: readAgentSystemPrompt(status),\n width,\n theme: this.theme,\n markdownTheme: this.markdownTheme,\n });\n this.agentCache = { runId: item.runId, fingerprint, width, lines };\n return lines;\n }\n\n private wrappedDetail(selected: FleetItem | undefined, status: AsyncRunStatus | undefined, width: number): string[] {\n if (!selected) {\n return ['No tracked runs.', '', 'New runs appear here automatically while this inspector remains open.'];\n }\n if (this.detailTab === 'agent') return this.renderedAgent(selected, status, width);\n const { events, body } = this.renderedTranscript(status, width);\n if (events > 0) return body;\n const transcriptState = !status\n ? 'Transcript unavailable. No run status was found, so there is no transcript path to read.'\n : !status.transcriptPath\n ? 'Transcript unavailable. Artifacts were disabled for this run, so nothing was recorded.'\n : this.transcriptTail?.warning\n ? 'Transcript unavailable. The transcript artifact is missing or unreadable.'\n : 'No transcript yet.';\n const lines: string[] = [];\n for (const line of wrapTextWithAnsi(transcriptState, Math.max(1, width))) lines.push(line);\n return lines;\n }\n\n protected getChrome(): DoomOverlayChrome {\n const selected = this.snapshot.items[this.selected];\n const position = this.snapshot.items.length ? `${this.selected + 1}/${this.snapshot.items.length}` : '0/0';\n return {\n title: 'AGENT RUNS',\n accent: DOOM_OVERLAY_ACCENT,\n breadcrumb: 'SPC › a / agents',\n headerRight: selected\n ? `${statusGlyph(selected.state, this.theme)} ${this.theme.fg(agentIdentityColor(selected.runId), selected.agent)} · ${selected.state}`\n : 'no runs',\n // The per-run controls are listed in the pane itself, next to the state\n // they act on; repeating them here would cost the keys that are not.\n footer: ['↑↓/jk select', 'J/K scroll', 'p agent', 'o detail', 'Ctrl+R refresh', 'Esc close'].join(' · '),\n footerRight: position,\n };\n }\n\n protected renderBody(width: number, height: number): string[] {\n const transientRows = (this.steerDraft !== undefined ? 2 : 0) + (this.actionNotice !== undefined ? 1 : 0);\n const mainHeight = Math.max(0, height - transientRows);\n const narrow = width < 36;\n const rosterHeight = narrow ? Math.max(1, Math.floor((mainHeight - 1) * 0.35)) : mainHeight;\n const detailPaneHeight = narrow ? Math.max(0, mainHeight - rosterHeight - 1) : mainHeight;\n this.bodyHeight = rosterHeight;\n const rosterPane = narrow ? width : Math.max(22, Math.min(46, Math.floor((width - 1) * 0.38)));\n // Side by side, each pane gives up a column to the divider's gutters.\n const rosterWidth = narrow ? width : Math.max(1, rosterPane - 1);\n const detailWidth = narrow ? width : Math.max(1, width - rosterWidth - 3);\n const roster = this.rosterLines(rosterWidth);\n const selected = this.snapshot.items[this.selected];\n // One status read per paint, shared by the header and the detail body.\n const status = selected ? readAsyncRunStatus(selected.runId) : undefined;\n const body = this.wrappedDetail(selected, status, detailWidth);\n // The agent tab is its own self-describing document, so the live status\n // header would only repeat what it already states in full.\n const fixedHeader =\n selected && this.detailTab === 'transcript'\n ? [\n ...statusHeaderLines(selected, status, detailWidth, this.theme, Date.now()),\n '',\n controlLine(selected, detailWidth, this.theme),\n tabStrip(this.detailTab, this.verbosity, detailWidth, this.theme),\n ]\n : selected\n ? [tabStrip(this.detailTab, this.verbosity, detailWidth, this.theme)]\n : [];\n const fixedBudget = detailPaneHeight - MIN_DETAIL_BODY_LINES;\n const detailHeader = fixedBudget >= fixedHeader.length ? fixedHeader : [];\n this.detailViewportHeight = Math.max(1, detailPaneHeight - detailHeader.length);\n this.detailLineCount = body.length;\n const maxDetailScroll = Math.max(0, body.length - this.detailViewportHeight);\n if (this.detailAutoFollow) this.detailScroll = maxDetailScroll;\n else if (this.detailScroll > maxDetailScroll) this.detailScroll = maxDetailScroll;\n const visibleDetails = [\n ...detailHeader,\n ...body.slice(this.detailScroll, this.detailScroll + this.detailViewportHeight),\n ];\n\n const lines: string[] = [];\n if (narrow) {\n for (let index = 0; index < rosterHeight; index++) lines.push(fit(roster[index] ?? '', width));\n if (mainHeight > rosterHeight) lines.push(this.theme.fg('borderMuted', '─'.repeat(width)));\n for (let index = 0; index < detailPaneHeight; index++) lines.push(fit(visibleDetails[index] ?? '', width));\n } else {\n for (let index = 0; index < mainHeight; index++) {\n lines.push(\n `${fit(roster[index] ?? '', rosterWidth)} ${this.theme.fg('borderMuted', '│')} ${fit(\n visibleDetails[index] ?? '',\n detailWidth,\n )}`,\n );\n }\n }\n if (this.steerDraft !== undefined) {\n const steerLines = [\n ` ${this.theme.fg('accent', 'STEER MESSAGE')} ${this.theme.fg('dim', `· run ${selected?.runId ?? FIELD_FALLBACK}`)}`,\n ` ${this.theme.fg('accent', '❯')} ${this.steerDraft}▌`,\n ].map((line) => truncateToWidth(line, width));\n lines.push(...steerLines);\n }\n if (this.actionNotice !== undefined) {\n lines.push(fit(` ${this.theme.fg('muted', this.actionNotice)}`, width));\n }\n return lines.slice(0, height).map((line) => truncateToWidth(line, width));\n }\n\n /**\n * `Component`'s required \"re-render from scratch\" hook - the host calls\n * this on a theme change, not on a timer. Distinct from a poll tick (which\n * must NOT do this, see the module header): this is an explicit, external\n * signal that cached state is stale, the same category as Ctrl+R.\n */\n invalidate(): void {\n this.clearCaches();\n this.refresh();\n }\n\n dispose(): void {\n this.disposed = true;\n this.unregister();\n }\n}\n\n/** Opens the fleet overlay. `scheduler`/`tracker` are resolved by the caller (see `register.ts`) from the live container, not constructed here. */\nexport async function openSubagentFleet(\n ctx: ExtensionContext,\n scheduler: IPollScheduler,\n tracker: ITrackedAsyncJobs,\n options: FleetViewOptions = {},\n): Promise<void> {\n await ctx.ui.custom<undefined>(\n (tui, theme, _keybindings, done) => new SubagentFleetComponent(tui, theme, scheduler, tracker, done, options),\n DOOM_FULLSCREEN_UI_OPTIONS,\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import{init_statusReader as e,readAsyncRunStatus as t}from"../runs/background/statusReader.mjs";import{formatDuration as n,formatModelThinking as r,formatTokens as i,init_formatters as a}from"../shared/formatters.mjs";import{init_fleetTranscript as o,readFleetTranscriptTail as s,renderFleetTranscript as c}from"./fleetTranscript.mjs";import{agentSystemPromptFingerprint as l,fieldRow as u,readAgentSystemPrompt as d,renderAgentView as f}from"./fleetAgentView.mjs";import*as p from"node:fs";import{getMarkdownTheme as m}from"@earendil-works/pi-coding-agent";import{Key as h,matchesKey as g,truncateToWidth as _,visibleWidth as v,wrapTextWithAnsi as y}from"@earendil-works/pi-tui";import{DOOM_FULLSCREEN_UI_OPTIONS as b,DOOM_OVERLAY_ACCENT as x,DoomOverlay as S}from"@agimon-ai/doompi-ui/components/doomOverlay";import{agentIdentityColor as C}from"@agimon-ai/doompi-ui/theme";a(),e(),o();const w=[`interrupt`,`stop`,`resume`,`steer`],T={interrupt:`i`,stop:`x`,resume:`r`,steer:`m`},E={interrupt:`turn`,stop:`run, final`,resume:void 0,steer:void 0},D=new Map(w.map(e=>[T[e],e])),O={running:`running`,queued:`queued`,pending:`pending`,paused:`paused`,stopped:`stopped`,complete:`complete`,completed:`completed`,failed:`failed`},k=new Set([O.running,O.queued]),A=new Set([O.paused,O.complete,O.completed,O.failed]);function j(e){if(!e)return{interrupt:!1,stop:!1,resume:!1,steer:!1};let t=k.has(e.state);return{interrupt:t,stop:t,resume:A.has(e.state),steer:e.state===O.running}}function M(e,t){return t?e===`resume`?`resume unavailable · ${t.runId} is ${t.state}; resume targets paused, completed, or failed runs`:`${e} unavailable · ${t.runId} is ${t.state}`:`${e} unavailable · no run is selected`}function N(e){return{items:e.list().map(e=>({key:e.runId,runId:e.runId,agent:e.agent??e.runId.slice(0,8),state:e.status??`unknown`,updatedAt:e.updatedAt??e.startedAt??0,job:e})).sort((e,t)=>t.updatedAt-e.updatedAt)}}function P(e){return e.items.map(e=>`${e.runId}:${e.state}:${e.updatedAt}:${e.job.activityState??``}`).join(`|`)}function F(e,t){return e===O.running?t.fg(`accent`,`●`):e===O.queued||e===O.pending?t.fg(`muted`,`◦`):e===O.complete||e===O.completed?t.fg(`success`,`✓`):e===O.paused||e===O.stopped?t.fg(`warning`,`■`):t.fg(`error`,`✗`)}function I(e,t,a,o,s){let c=[e.runId.slice(0,12),t?.agent??e.agent,t?.model?r(t.model):void 0].filter(e=>!!e).join(` · `),l=t?.startedAt===void 0?void 0:n((t.endedAt??s)-t.startedAt),d=[t?.toolCount?`${t.toolCount} tools`:void 0,t?.tokens?`${i(t.tokens)} tokens`:void 0].filter(e=>!!e).join(` · `),f=[[`Run`,c],[`State`,[e.state,t?.activityState,l].filter(e=>!!e).join(` · `)],[`Doing`,t?.currentTool??`—`],[`Usage`,d||`—`]];return t?.attentionReason&&f.push([`Needs`,t.attentionReason]),t?.error&&f.push([`Error`,t.error]),t?.summary&&f.push([`Result`,t.summary]),f.map(([e,t])=>u(e,t,a,o))}function L(e,t,n){let r=j(e);return _(` ${w.map(e=>{let t=E[e],i=`${e}${t?` (${t})`:``}`;return r[e]?`${n.fg(`accent`,T[e])} ${i}`:n.fg(`dim`,`${T[e]} ${i}`)}).join(n.fg(`dim`,` · `))}`,t)}function R(e,t,n,r){let i=t=>t===e?r.fg(`accent`,r.bold(`[ ${t} ]`)):r.fg(`dim`,` ${t} `),a=r.fg(`dim`,e===`transcript`?`p agent · o ${t}`:`p transcript`);return B(` ${i(`transcript`)}${i(`agent`)}`,a,n)}function z(e,t){let n=_(e,Math.max(0,t));return n+` `.repeat(Math.max(0,t-v(n)))}function B(e,t,n){let r=v(t),i=Math.max(0,n-r-1);return z(e,i)+` `.repeat(Math.max(1,n-i-r))+z(t,r)}function V(e){try{let t=p.statSync(e);return`${t.size}:${t.mtimeMs}`}catch{return`missing`}}var H=class extends S{snapshot={items:[]};lastRenderKey=``;selected=0;selectedKey;detailScroll=0;detailAutoFollow=!0;detailLineCount=0;detailViewportHeight=8;bodyHeight=8;steerDraft;actionNotice;detailTab=`transcript`;verbosity=`compact`;transcriptTail;transcriptRender;agentCache;disposed=!1;unregister;markdownTheme;scheduler;tracker;done;options;constructor(e,t,n,r,i,a={}){super(e,t),this.markdownTheme=a.markdownTheme??m(),this.scheduler=n,this.tracker=r,this.done=i,this.options=a,this.selectedKey=a.initialKey,this.refresh(),this.lastRenderKey=this.pollRenderKey(),this.unregister=this.scheduler.register({id:`tui-fleet`,intervalMs:a.refreshMs??750,run:()=>this.onTick()})}onTick(){if(this.disposed)return!1;this.refresh();let e=this.pollRenderKey();return e===this.lastRenderKey?!1:(this.lastRenderKey=e,this.tui.requestRender(),!0)}pollRenderKey(){let e=this.snapshot.items[this.selected];if(!e)return`${P(this.snapshot)}::none`;let n=t(e.runId)?.transcriptPath,r=n?`${n}:${V(n)}`:`none`,i=e.job,a=`${i.currentTool??``}:${i.toolCount??0}:${i.tokens??0}`;return`${P(this.snapshot)}::${e.runId}:${r}:${a}`}refresh(){let e=this.snapshot.items[this.selected]?.key??this.selectedKey;this.snapshot=N(this.tracker);let t=e?this.snapshot.items.findIndex(t=>t.key===e):-1;this.selected=t>=0?t:Math.min(this.selected,Math.max(0,this.snapshot.items.length-1)),this.selectedKey=this.snapshot.items[this.selected]?.key}moveSelection(e){this.snapshot.items.length!==0&&(this.selected=Math.max(0,Math.min(this.snapshot.items.length-1,this.selected+e)),this.selectedKey=this.snapshot.items[this.selected]?.key,this.lastRenderKey=this.pollRenderKey(),this.detailAutoFollow=!0,this.tui.requestRender())}scrollDetail(e){let t=Math.max(0,this.detailLineCount-this.detailViewportHeight);this.detailScroll=Math.max(0,Math.min(t,this.detailScroll+e)),this.detailAutoFollow=this.detailScroll>=t,this.tui.requestRender()}handleInput(e){if(this.steerDraft!==void 0)return this.handleSteerInput(e);if(g(e,`escape`)||g(e,`ctrl+c`)||g(e,`q`)){this.done(void 0);return}if(g(e,h.shift(`k`)))return this.scrollDetail(-1);if(g(e,h.shift(`j`)))return this.scrollDetail(1);if(g(e,`up`)||g(e,`k`))return this.moveSelection(-1);if(g(e,`down`)||g(e,`j`))return this.moveSelection(1);if(g(e,`pageUp`))return this.scrollDetail(-this.detailViewportHeight);if(g(e,`pageDown`))return this.scrollDetail(this.detailViewportHeight);if(g(e,`p`))return this.toggleTab();if(g(e,`o`))return this.toggleVerbosity();if(g(e,`ctrl+r`)){this.clearCaches(),this.refresh(),this.tui.requestRender();return}let t=D.get(e.toLowerCase());t&&this.triggerControl(t)}clearCaches(){this.transcriptTail=void 0,this.transcriptRender=void 0,this.agentCache=void 0}toggleTab(){this.detailTab=this.detailTab===`transcript`?`agent`:`transcript`,this.detailScroll=0,this.detailAutoFollow=this.detailTab===`transcript`,this.tui.requestRender()}toggleVerbosity(){this.verbosity=this.verbosity===`compact`?`full`:`compact`,this.tui.requestRender()}handleSteerInput(e){if(g(e,`escape`)||g(e,`ctrl+c`)){this.steerDraft=void 0,this.setNotice(`steer cancelled · no message sent`);return}if(e===`\r`||e===`
2
+ `){let e=(this.steerDraft??``).trim();this.steerDraft=void 0;let t=this.snapshot.items[this.selected];if(!t||!e){this.setNotice(`steer cancelled · a non-empty message is required`);return}this.dispatch({action:`steer`,id:t.runId,message:e});return}if(e===``||e===`\b`){this.steerDraft=(this.steerDraft??``).slice(0,-1),this.tui.requestRender();return}e.length===1&&e>=` `&&(this.steerDraft=`${this.steerDraft??``}${e}`,this.tui.requestRender())}triggerControl(e){let t=this.snapshot.items[this.selected];if(!j(t)[e]){this.setNotice(M(e,t));return}if(t){if(e===`steer`){this.steerDraft=``,this.tui.requestRender();return}this.dispatch({action:e,id:t.runId})}}async dispatch(e){let t=this.options.dispatchAction;if(!t){this.setNotice(`${e.action} ${e.id} · unavailable · no subagent control channel is attached`);return}this.setNotice(`${e.action} ${e.id} · dispatching…`);try{let n=await t(e);if(this.disposed)return;this.setNotice(`${e.action} ${e.id} · ${n.status}${n.detail?` · ${n.detail}`:``}`)}catch(t){if(this.disposed)return;this.setNotice(`${e.action} ${e.id} · failed · ${t instanceof Error?t.message:String(t)}`)}}setNotice(e){this.actionNotice=e,this.tui.requestRender()}rosterLines(e){if(this.snapshot.items.length===0)return[this.theme.fg(`dim`,`No tracked runs`)];let t=Math.max(0,Math.min(this.selected-this.bodyHeight+1,Math.max(0,this.snapshot.items.length-this.bodyHeight)));return this.snapshot.items.slice(t,t+this.bodyHeight).map((n,r)=>{let i=t+r,a=i===this.selected?this.theme.fg(`accent`,`›`):` `,o=this.theme.fg(C(n.runId),i===this.selected?this.theme.bold(n.agent):n.agent);return B(`${a} ${F(n.state,this.theme)} ${o}`,this.theme.fg(`dim`,n.state),e)})}renderedTranscript(e,t){let n=e?.transcriptPath;if(!n)return this.transcriptTail=void 0,this.transcriptRender=void 0,{events:0,body:[]};let r=this.transcriptTail?.path===n?this.transcriptTail:void 0,i=s(n,r);this.transcriptTail=i;let a=c(i,t,this.theme,this.markdownTheme,{cwd:e?.cwd,verbosity:this.verbosity},r?this.transcriptRender:void 0);return this.transcriptRender=a,{events:i.events.length,body:a.lines}}renderedAgent(e,t,n){let r=l(t);if(this.agentCache&&this.agentCache.runId===e.runId&&this.agentCache.fingerprint===r&&this.agentCache.width===n)return this.agentCache.lines;let i=f({status:t,state:e.state,agent:e.agent,runId:e.runId,prompt:d(t),width:n,theme:this.theme,markdownTheme:this.markdownTheme});return this.agentCache={runId:e.runId,fingerprint:r,width:n,lines:i},i}wrappedDetail(e,t,n){if(!e)return[`No tracked runs.`,``,`New runs appear here automatically while this inspector remains open.`];if(this.detailTab===`agent`)return this.renderedAgent(e,t,n);let{events:r,body:i}=this.renderedTranscript(t,n);if(r>0)return i;let a=t?t.transcriptPath?this.transcriptTail?.warning?`Transcript unavailable. The transcript artifact is missing or unreadable.`:`No transcript yet.`:`Transcript unavailable. Artifacts were disabled for this run, so nothing was recorded.`:`Transcript unavailable. No run status was found, so there is no transcript path to read.`,o=[];for(let e of y(a,Math.max(1,n)))o.push(e);return o}getChrome(){let e=this.snapshot.items[this.selected],t=this.snapshot.items.length?`${this.selected+1}/${this.snapshot.items.length}`:`0/0`;return{title:`AGENT RUNS`,accent:x,breadcrumb:`SPC › a / agents`,headerRight:e?`${F(e.state,this.theme)} ${this.theme.fg(C(e.runId),e.agent)} · ${e.state}`:`no runs`,footer:[`↑↓/jk select`,`J/K scroll`,`p agent`,`o detail`,`Ctrl+R refresh`,`Esc close`].join(` · `),footerRight:t}}renderBody(e,n){let r=(this.steerDraft===void 0?0:2)+(this.actionNotice===void 0?0:1),i=Math.max(0,n-r),a=e<36,o=a?Math.max(1,Math.floor((i-1)*.35)):i,s=a?Math.max(0,i-o-1):i;this.bodyHeight=o;let c=a?e:Math.max(22,Math.min(46,Math.floor((e-1)*.38))),l=a?e:Math.max(1,c-1),u=a?e:Math.max(1,e-l-3),d=this.rosterLines(l),f=this.snapshot.items[this.selected],p=f?t(f.runId):void 0,m=this.wrappedDetail(f,p,u),h=f&&this.detailTab===`transcript`?[...I(f,p,u,this.theme,Date.now()),``,L(f,u,this.theme),R(this.detailTab,this.verbosity,u,this.theme)]:f?[R(this.detailTab,this.verbosity,u,this.theme)]:[],g=s-15>=h.length?h:[];this.detailViewportHeight=Math.max(1,s-g.length),this.detailLineCount=m.length;let v=Math.max(0,m.length-this.detailViewportHeight);(this.detailAutoFollow||this.detailScroll>v)&&(this.detailScroll=v);let y=[...g,...m.slice(this.detailScroll,this.detailScroll+this.detailViewportHeight)],b=[];if(a){for(let t=0;t<o;t++)b.push(z(d[t]??``,e));i>o&&b.push(this.theme.fg(`borderMuted`,`─`.repeat(e)));for(let t=0;t<s;t++)b.push(z(y[t]??``,e))}else for(let e=0;e<i;e++)b.push(`${z(d[e]??``,l)} ${this.theme.fg(`borderMuted`,`│`)} ${z(y[e]??``,u)}`);if(this.steerDraft!==void 0){let t=[` ${this.theme.fg(`accent`,`STEER MESSAGE`)} ${this.theme.fg(`dim`,`· run ${f?.runId??`—`}`)}`,` ${this.theme.fg(`accent`,`❯`)} ${this.steerDraft}▌`].map(t=>_(t,e));b.push(...t)}return this.actionNotice!==void 0&&b.push(z(` ${this.theme.fg(`muted`,this.actionNotice)}`,e)),b.slice(0,n).map(t=>_(t,e))}invalidate(){this.clearCaches(),this.refresh()}dispose(){this.disposed=!0,this.unregister()}};async function U(e,t,n,r={}){await e.ui.custom((e,i,a,o)=>new H(e,i,t,n,o,r),b)}export{U as openSubagentFleet};
3
+ //# sourceMappingURL=fleet.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fleet.mjs","names":[],"sources":["../../src/tui/fleet.ts"],"sourcesContent":["/**\n * The fleet inspector overlay: a roster of this session's async runs, plus a\n * scrollable detail/transcript pane and runtime controls for the selected one.\n *\n * NOT A PORT - THE FIX IS THE POINT:\n * The predecessor (`doom-pi-subagents/src/tui/fleet.ts`) owned a private\n * `setInterval(750ms)` whose handler unconditionally nulled its own transcript\n * cache (`invalidate()`), so every tick re-read and re-parsed the selected\n * run's whole transcript file regardless of whether anything had changed.\n * This version registers with `PollScheduler` instead of owning a timer, and\n * NEVER blanks `transcriptCache` on a tick. A tick stats only the selected\n * transcript and requests a repaint when its size or modification time changes.\n * `renderedTranscript()` then uses the same fingerprint to decide whether the\n * next render needs one content read. Ctrl+R remains the deliberate manual\n * cache-clearing path.\n *\n * There is also no foreground-run concept here (doom-team is async-only - see\n * `spawnHandshake.ts`'s header), so every roster item is an async run. Roster\n * state comes from `IAsyncJobTracker`, the package's one source of truth for\n * run state; the fuller per-run detail a tracker record does not carry\n * (steps, summary) comes from `readAsyncRunStatus` (`statusReader.ts`), read\n * lazily only for the SELECTED item when the detail pane actually needs it,\n * not for the whole roster on every tick.\n *\n * DESIGN PATTERNS:\n * - The scheduler subscription's `run()` diffs the roster and selected\n * transcript fingerprint against the last values it saw, matching\n * `PollSubscription`'s \"return true only on real work\" contract so idle\n * backoff still applies when nothing in the fleet is moving\n * - Controls always list every action, unavailable ones dimmed rather than\n * hidden, so the key map never shifts under the user\n *\n * Child transcripts are written directly from Pi SDK events by the detached\n * runner. The exact artifact path is persisted in status.json so non-default\n * artifact policies remain readable here.\n */\n\nimport { getMarkdownTheme, type ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport {\n DOOM_OVERLAY_ACCENT,\n DoomOverlay,\n type DoomOverlayChrome,\n type DoomOverlayTui,\n DOOM_FULLSCREEN_UI_OPTIONS,\n} from '@agimon-ai/doompi-ui/components/doomOverlay';\nimport { agentIdentityColor } from '@agimon-ai/doompi-ui/theme';\nimport {\n Key,\n matchesKey,\n truncateToWidth,\n visibleWidth,\n wrapTextWithAnsi,\n type MarkdownTheme,\n} from '@earendil-works/pi-tui';\n\nimport * as fs from 'node:fs';\nimport { formatDuration, formatModelThinking, formatTokens } from '../shared/formatters.ts';\nimport type { AsyncRunStatus } from '../runs/background/asyncExecution.ts';\nimport type { ITrackedAsyncJobs, TrackedAsyncJob } from '../runs/background/asyncJobTracker.ts';\nimport type { IPollScheduler } from '../shared/pollScheduler.ts';\nimport { readAsyncRunStatus } from '../runs/background/statusReader.ts';\nimport {\n readFleetTranscriptTail,\n renderFleetTranscript,\n type FleetTranscriptRender,\n type FleetTranscriptTail,\n type FleetTranscriptVerbosity,\n} from './fleetTranscript.ts';\nimport { agentSystemPromptFingerprint, fieldRow, readAgentSystemPrompt, renderAgentView } from './fleetAgentView.ts';\n\nconst DEFAULT_REFRESH_INTERVAL_MS = 750;\nconst MIN_DETAIL_BODY_LINES = 15;\nconst FIELD_FALLBACK = '—';\nconst POLL_SUBSCRIBER_ID = 'tui-fleet';\n\n/** Which question the detail pane is answering. See `fleetAgentView.ts`'s header. */\nexport type FleetDetailTab = 'transcript' | 'agent';\n\ntype Theme = ExtensionContext['ui']['theme'];\nexport interface FleetItem {\n key: string;\n runId: string;\n agent: string;\n state: string;\n updatedAt: number;\n job: TrackedAsyncJob;\n}\n\nexport interface FleetSnapshot {\n items: FleetItem[];\n}\n\nexport type FleetActionName = 'interrupt' | 'stop' | 'resume' | 'steer';\n\nexport interface FleetActionRequest {\n action: FleetActionName;\n id: string;\n message?: string;\n}\n\nexport interface FleetActionResult {\n status: string;\n detail?: string;\n}\n\nexport type FleetActionDispatcher = (request: FleetActionRequest) => Promise<FleetActionResult>;\n\nexport interface FleetViewOptions {\n refreshMs?: number;\n initialKey?: string;\n markdownTheme?: MarkdownTheme;\n /** Injected so the overlay can be asserted on its emitted payload in tests. */\n dispatchAction?: FleetActionDispatcher;\n}\n\nconst CONTROL_ORDER: readonly FleetActionName[] = ['interrupt', 'stop', 'resume', 'steer'];\nconst CONTROL_KEY: Record<FleetActionName, string> = { interrupt: 'i', stop: 'x', resume: 'r', steer: 'm' };\n/**\n * Short inline qualifier for a control, or undefined where the verb is enough.\n *\n * Collapsed from a full sentence per action when the controls moved to one\n * line. What survives is only what changes a decision at the moment of\n * pressing the key - above all that `stop` cannot be undone, which is the one\n * hint whose loss would cost a user a run.\n */\nconst CONTROL_HINT: Record<FleetActionName, string | undefined> = {\n interrupt: 'turn',\n stop: 'run, final',\n resume: undefined,\n steer: undefined,\n};\nconst CONTROL_BY_KEY = new Map<string, FleetActionName>(CONTROL_ORDER.map((action) => [CONTROL_KEY[action], action]));\n/**\n * Run-state tokens as the tracker writes them. Named once because availability\n * checks and glyph rendering both branch on them, and a typo in either place\n * fails silently as \"unknown state\".\n */\nconst RUN_STATE = {\n running: 'running',\n queued: 'queued',\n pending: 'pending',\n paused: 'paused',\n stopped: 'stopped',\n complete: 'complete',\n completed: 'completed',\n failed: 'failed',\n} as const;\n\nconst LIVE_STATES = new Set<string>([RUN_STATE.running, RUN_STATE.queued]);\nconst RESUMABLE_STATES = new Set<string>([RUN_STATE.paused, RUN_STATE.complete, RUN_STATE.completed, RUN_STATE.failed]);\n\nfunction controlAvailability(item: FleetItem | undefined): Record<FleetActionName, boolean> {\n if (!item) return { interrupt: false, stop: false, resume: false, steer: false };\n const live = LIVE_STATES.has(item.state);\n return {\n interrupt: live,\n stop: live,\n resume: RESUMABLE_STATES.has(item.state),\n steer: item.state === RUN_STATE.running,\n };\n}\n\nfunction unavailableReason(action: FleetActionName, item: FleetItem | undefined): string {\n if (!item) return `${action} unavailable · no run is selected`;\n if (action === 'resume') {\n return `resume unavailable · ${item.runId} is ${item.state}; resume targets paused, completed, or failed runs`;\n }\n return `${action} unavailable · ${item.runId} is ${item.state}`;\n}\n\n/** One tracked job per roster row. Newest activity first. */\nexport function collectFleetSnapshot(tracker: ITrackedAsyncJobs): FleetSnapshot {\n const items = tracker\n .list()\n .map(\n (job): FleetItem => ({\n key: job.runId,\n runId: job.runId,\n agent: job.agent ?? job.runId.slice(0, 8),\n state: job.status ?? 'unknown',\n updatedAt: job.updatedAt ?? job.startedAt ?? 0,\n job,\n }),\n )\n .sort((left, right) => right.updatedAt - left.updatedAt);\n return { items };\n}\n\n/** A short string that changes iff anything a roster row displays changed. */\nfunction rosterRenderKey(snapshot: FleetSnapshot): string {\n return snapshot.items\n .map((item) => `${item.runId}:${item.state}:${item.updatedAt}:${item.job.activityState ?? ''}`)\n .join('|');\n}\n\nfunction statusGlyph(state: string, theme: Theme): string {\n if (state === RUN_STATE.running) return theme.fg('accent', '●');\n if (state === RUN_STATE.queued || state === RUN_STATE.pending) return theme.fg('muted', '◦');\n if (state === RUN_STATE.complete || state === RUN_STATE.completed) return theme.fg('success', '✓');\n if (state === RUN_STATE.paused || state === RUN_STATE.stopped) return theme.fg('warning', '■');\n return theme.fg('error', '✗');\n}\n\n/**\n * What the selected run is doing right now.\n *\n * Every value here was already being written to status.json and none of it was\n * being shown, which is why the pane could be watched for minutes without\n * telling you whether anything was happening. `Doing` and `Usage` keep their\n * rows even when empty so the header height does not change under a running\n * run and bounce the transcript below it.\n */\nfunction statusHeaderLines(\n item: FleetItem,\n status: AsyncRunStatus | undefined,\n width: number,\n theme: Theme,\n now: number,\n): string[] {\n const identity = [\n item.runId.slice(0, 12),\n status?.agent ?? item.agent,\n status?.model ? formatModelThinking(status.model) : undefined,\n ]\n .filter((part): part is string => Boolean(part))\n .join(' · ');\n const elapsed =\n status?.startedAt !== undefined ? formatDuration((status.endedAt ?? now) - status.startedAt) : undefined;\n const usage = [\n status?.toolCount ? `${status.toolCount} tools` : undefined,\n status?.tokens ? `${formatTokens(status.tokens)} tokens` : undefined,\n ]\n .filter((part): part is string => Boolean(part))\n .join(' · ');\n const rows: Array<[string, string]> = [\n ['Run', identity],\n ['State', [item.state, status?.activityState, elapsed].filter((part): part is string => Boolean(part)).join(' · ')],\n ['Doing', status?.currentTool ?? FIELD_FALLBACK],\n ['Usage', usage || FIELD_FALLBACK],\n ];\n if (status?.attentionReason) rows.push(['Needs', status.attentionReason]);\n if (status?.error) rows.push(['Error', status.error]);\n if (status?.summary) rows.push(['Result', status.summary]);\n return rows.map(([label, value]) => fieldRow(label, value, width, theme));\n}\n\n/**\n * Runtime controls on one line.\n *\n * Every action is still listed, unavailable ones dimmed rather than hidden, so\n * the key map never shifts under the user. The per-action hints moved to the\n * footer legend: five rows of them cost the transcript a third of the pane to\n * restate what the footer already says.\n */\nfunction controlLine(item: FleetItem | undefined, width: number, theme: Theme): string {\n const availability = controlAvailability(item);\n const parts = CONTROL_ORDER.map((action) => {\n const hint = CONTROL_HINT[action];\n const body = `${action}${hint ? ` (${hint})` : ''}`;\n return availability[action]\n ? `${theme.fg('accent', CONTROL_KEY[action])} ${body}`\n : theme.fg('dim', `${CONTROL_KEY[action]} ${body}`);\n });\n return truncateToWidth(` ${parts.join(theme.fg('dim', ' · '))}`, width);\n}\n\nfunction tabStrip(tab: FleetDetailTab, verbosity: FleetTranscriptVerbosity, width: number, theme: Theme): string {\n const label = (name: FleetDetailTab): string =>\n name === tab ? theme.fg('accent', theme.bold(`[ ${name} ]`)) : theme.fg('dim', ` ${name} `);\n const right = theme.fg('dim', tab === 'transcript' ? `p agent · o ${verbosity}` : 'p transcript');\n return rightAligned(` ${label('transcript')}${label('agent')}`, right, width);\n}\n\nfunction fit(text: string, width: number): string {\n const clipped = truncateToWidth(text, Math.max(0, width));\n return clipped + ' '.repeat(Math.max(0, width - visibleWidth(clipped)));\n}\n\nfunction rightAligned(left: string, right: string, width: number): string {\n const rightWidth = visibleWidth(right);\n const leftWidth = Math.max(0, width - rightWidth - 1);\n return fit(left, leftWidth) + ' '.repeat(Math.max(1, width - leftWidth - rightWidth)) + fit(right, rightWidth);\n}\n\n/**\n * Size and mtime of a transcript, for the poll tick.\n *\n * A tick may stat but must never read (see the module header), so this is\n * deliberately the cheapest thing that still changes when the file grows.\n */\nfunction transcriptFingerprint(filePath: string): string {\n try {\n const stat = fs.statSync(filePath);\n return `${stat.size}:${stat.mtimeMs}`;\n } catch {\n return 'missing';\n }\n}\n\n/** Rendered agent tab, cached so scrolling a long prompt does not re-render its markdown. */\ninterface FleetAgentCache {\n runId: string;\n fingerprint: string;\n width: number;\n lines: string[];\n}\n\nexport class SubagentFleetComponent extends DoomOverlay {\n private snapshot: FleetSnapshot = { items: [] };\n private lastRenderKey = '';\n private selected = 0;\n private selectedKey: string | undefined;\n private detailScroll = 0;\n private detailAutoFollow = true;\n private detailLineCount = 0;\n private detailViewportHeight = 8;\n private bodyHeight = 8;\n private steerDraft: string | undefined;\n private actionNotice: string | undefined;\n private detailTab: FleetDetailTab = 'transcript';\n private verbosity: FleetTranscriptVerbosity = 'compact';\n private transcriptTail: FleetTranscriptTail | undefined;\n private transcriptRender: FleetTranscriptRender | undefined;\n private agentCache: FleetAgentCache | undefined;\n private disposed = false;\n private readonly unregister: () => void;\n private readonly markdownTheme: MarkdownTheme;\n private readonly scheduler: IPollScheduler;\n private readonly tracker: ITrackedAsyncJobs;\n private readonly done: (result: undefined) => void;\n private readonly options: FleetViewOptions;\n\n constructor(\n tui: DoomOverlayTui,\n theme: Theme,\n scheduler: IPollScheduler,\n tracker: ITrackedAsyncJobs,\n done: (result: undefined) => void,\n options: FleetViewOptions = {},\n ) {\n super(tui, theme);\n this.markdownTheme = options.markdownTheme ?? getMarkdownTheme();\n this.scheduler = scheduler;\n this.tracker = tracker;\n this.done = done;\n this.options = options;\n this.selectedKey = options.initialKey;\n this.refresh();\n this.lastRenderKey = this.pollRenderKey();\n this.unregister = this.scheduler.register({\n id: POLL_SUBSCRIBER_ID,\n intervalMs: options.refreshMs ?? DEFAULT_REFRESH_INTERVAL_MS,\n run: () => this.onTick(),\n });\n }\n\n /**\n * One scheduler tick. The tracker read is in memory and only the selected\n * transcript is statted. Transcript contents remain render-owned and cached.\n */\n private onTick(): boolean {\n if (this.disposed) return false;\n this.refresh();\n const renderKey = this.pollRenderKey();\n if (renderKey === this.lastRenderKey) return false;\n this.lastRenderKey = renderKey;\n this.tui.requestRender();\n return true;\n }\n\n private pollRenderKey(): string {\n const selected = this.snapshot.items[this.selected];\n if (!selected) return `${rosterRenderKey(this.snapshot)}::none`;\n const transcriptPath = readAsyncRunStatus(selected.runId)?.transcriptPath;\n const transcriptKey = transcriptPath ? `${transcriptPath}:${transcriptFingerprint(transcriptPath)}` : 'none';\n // The live status header moves on values the roster row does not carry, so\n // a tick that only changes what the run is DOING still has to repaint.\n const job = selected.job;\n const activity = `${job.currentTool ?? ''}:${job.toolCount ?? 0}:${job.tokens ?? 0}`;\n return `${rosterRenderKey(this.snapshot)}::${selected.runId}:${transcriptKey}:${activity}`;\n }\n\n private refresh(): void {\n const previousKey = this.snapshot.items[this.selected]?.key ?? this.selectedKey;\n this.snapshot = collectFleetSnapshot(this.tracker);\n const preserved = previousKey ? this.snapshot.items.findIndex((item) => item.key === previousKey) : -1;\n this.selected = preserved >= 0 ? preserved : Math.min(this.selected, Math.max(0, this.snapshot.items.length - 1));\n this.selectedKey = this.snapshot.items[this.selected]?.key;\n }\n\n private moveSelection(delta: number): void {\n if (this.snapshot.items.length === 0) return;\n this.selected = Math.max(0, Math.min(this.snapshot.items.length - 1, this.selected + delta));\n this.selectedKey = this.snapshot.items[this.selected]?.key;\n this.lastRenderKey = this.pollRenderKey();\n this.detailAutoFollow = true;\n this.tui.requestRender();\n }\n\n private scrollDetail(delta: number): void {\n const maxScroll = Math.max(0, this.detailLineCount - this.detailViewportHeight);\n this.detailScroll = Math.max(0, Math.min(maxScroll, this.detailScroll + delta));\n this.detailAutoFollow = this.detailScroll >= maxScroll;\n this.tui.requestRender();\n }\n\n handleInput(data: string): void {\n if (this.steerDraft !== undefined) return this.handleSteerInput(data);\n if (matchesKey(data, 'escape') || matchesKey(data, 'ctrl+c') || matchesKey(data, 'q')) {\n this.done(undefined);\n return;\n }\n if (matchesKey(data, Key.shift('k'))) return this.scrollDetail(-1);\n if (matchesKey(data, Key.shift('j'))) return this.scrollDetail(1);\n if (matchesKey(data, 'up') || matchesKey(data, 'k')) return this.moveSelection(-1);\n if (matchesKey(data, 'down') || matchesKey(data, 'j')) return this.moveSelection(1);\n if (matchesKey(data, 'pageUp')) return this.scrollDetail(-this.detailViewportHeight);\n if (matchesKey(data, 'pageDown')) return this.scrollDetail(this.detailViewportHeight);\n if (matchesKey(data, 'p')) return this.toggleTab();\n if (matchesKey(data, 'o')) return this.toggleVerbosity();\n if (matchesKey(data, 'ctrl+r')) {\n // Manual refresh: the one deliberate cache-clearing path. Distinct from\n // every scheduler tick, which must not do this - see the module header.\n this.clearCaches();\n this.refresh();\n this.tui.requestRender();\n return;\n }\n const action = CONTROL_BY_KEY.get(data.toLowerCase());\n if (action) this.triggerControl(action);\n }\n\n private clearCaches(): void {\n this.transcriptTail = undefined;\n this.transcriptRender = undefined;\n this.agentCache = undefined;\n }\n\n private toggleTab(): void {\n this.detailTab = this.detailTab === 'transcript' ? 'agent' : 'transcript';\n // A transcript is read newest-last and a prompt is read from the top, so\n // each tab lands where its own content starts being useful.\n this.detailScroll = 0;\n this.detailAutoFollow = this.detailTab === 'transcript';\n this.tui.requestRender();\n }\n\n private toggleVerbosity(): void {\n this.verbosity = this.verbosity === 'compact' ? 'full' : 'compact';\n // No cache clearing needed: `renderFleetTranscript` treats a verbosity\n // change as a global one and re-renders every block itself.\n this.tui.requestRender();\n }\n\n private handleSteerInput(data: string): void {\n if (matchesKey(data, 'escape') || matchesKey(data, 'ctrl+c')) {\n this.steerDraft = undefined;\n this.setNotice('steer cancelled · no message sent');\n return;\n }\n if (data === '\\r' || data === '\\n') {\n const message = (this.steerDraft ?? '').trim();\n this.steerDraft = undefined;\n const item = this.snapshot.items[this.selected];\n if (!item || !message) {\n this.setNotice('steer cancelled · a non-empty message is required');\n return;\n }\n void this.dispatch({ action: 'steer', id: item.runId, message });\n return;\n }\n if (data === '\\x7f' || data === '\\b') {\n this.steerDraft = (this.steerDraft ?? '').slice(0, -1);\n this.tui.requestRender();\n return;\n }\n if (data.length === 1 && data >= ' ') {\n this.steerDraft = `${this.steerDraft ?? ''}${data}`;\n this.tui.requestRender();\n }\n }\n\n private triggerControl(action: FleetActionName): void {\n const item = this.snapshot.items[this.selected];\n if (!controlAvailability(item)[action]) {\n this.setNotice(unavailableReason(action, item));\n return;\n }\n if (!item) return;\n if (action === 'steer') {\n this.steerDraft = '';\n this.tui.requestRender();\n return;\n }\n void this.dispatch({ action, id: item.runId });\n }\n\n private async dispatch(request: FleetActionRequest): Promise<void> {\n const dispatchAction = this.options.dispatchAction;\n if (!dispatchAction) {\n this.setNotice(`${request.action} ${request.id} · unavailable · no subagent control channel is attached`);\n return;\n }\n this.setNotice(`${request.action} ${request.id} · dispatching…`);\n try {\n const result = await dispatchAction(request);\n if (this.disposed) return;\n this.setNotice(`${request.action} ${request.id} · ${result.status}${result.detail ? ` · ${result.detail}` : ''}`);\n } catch (cause) {\n if (this.disposed) return;\n this.setNotice(\n `${request.action} ${request.id} · failed · ${cause instanceof Error ? cause.message : String(cause)}`,\n );\n }\n }\n\n private setNotice(notice: string): void {\n this.actionNotice = notice;\n this.tui.requestRender();\n }\n\n private rosterLines(width: number): string[] {\n if (this.snapshot.items.length === 0) return [this.theme.fg('dim', 'No tracked runs')];\n const start = Math.max(\n 0,\n Math.min(this.selected - this.bodyHeight + 1, Math.max(0, this.snapshot.items.length - this.bodyHeight)),\n );\n return this.snapshot.items.slice(start, start + this.bodyHeight).map((item, offset) => {\n const index = start + offset;\n const marker = index === this.selected ? this.theme.fg('accent', '›') : ' ';\n const agent = this.theme.fg(\n agentIdentityColor(item.runId),\n index === this.selected ? this.theme.bold(item.agent) : item.agent,\n );\n const left = `${marker} ${statusGlyph(item.state, this.theme)} ${agent}`;\n return rightAligned(left, this.theme.fg('dim', item.state), width);\n });\n }\n\n /**\n * Reads and formats the selected run's transcript, cached by content\n * fingerprint. Only invoked from `render()`, never from a poll tick - so a\n * disk read only happens when the pane is actually about to be painted with\n * new content, not on a fixed clock.\n */\n private renderedTranscript(status: AsyncRunStatus | undefined, width: number): { events: number; body: string[] } {\n const target = status?.transcriptPath;\n if (!target) {\n this.transcriptTail = undefined;\n this.transcriptRender = undefined;\n return { events: 0, body: [] };\n }\n // Resuming is what keeps this proportional to what arrived rather than to\n // what the file holds; the returned tail supersedes the one passed in.\n const previous = this.transcriptTail?.path === target ? this.transcriptTail : undefined;\n const tail = readFleetTranscriptTail(target, previous);\n this.transcriptTail = tail;\n const render = renderFleetTranscript(\n tail,\n width,\n this.theme,\n this.markdownTheme,\n { cwd: status?.cwd, verbosity: this.verbosity },\n previous ? this.transcriptRender : undefined,\n );\n this.transcriptRender = render;\n return { events: tail.events.length, body: render.lines };\n }\n\n /**\n * The agent tab, cached on the prompt's own fingerprint.\n *\n * A recorded system prompt is kilobytes of markdown that never changes for\n * the life of a run, so rendering it once per (run, width) rather than once\n * per keypress is what makes scrolling it usable.\n */\n private renderedAgent(item: FleetItem, status: AsyncRunStatus | undefined, width: number): string[] {\n const fingerprint = agentSystemPromptFingerprint(status);\n if (\n this.agentCache &&\n this.agentCache.runId === item.runId &&\n this.agentCache.fingerprint === fingerprint &&\n this.agentCache.width === width\n ) {\n return this.agentCache.lines;\n }\n const lines = renderAgentView({\n status,\n state: item.state,\n agent: item.agent,\n runId: item.runId,\n prompt: readAgentSystemPrompt(status),\n width,\n theme: this.theme,\n markdownTheme: this.markdownTheme,\n });\n this.agentCache = { runId: item.runId, fingerprint, width, lines };\n return lines;\n }\n\n private wrappedDetail(selected: FleetItem | undefined, status: AsyncRunStatus | undefined, width: number): string[] {\n if (!selected) {\n return ['No tracked runs.', '', 'New runs appear here automatically while this inspector remains open.'];\n }\n if (this.detailTab === 'agent') return this.renderedAgent(selected, status, width);\n const { events, body } = this.renderedTranscript(status, width);\n if (events > 0) return body;\n const transcriptState = !status\n ? 'Transcript unavailable. No run status was found, so there is no transcript path to read.'\n : !status.transcriptPath\n ? 'Transcript unavailable. Artifacts were disabled for this run, so nothing was recorded.'\n : this.transcriptTail?.warning\n ? 'Transcript unavailable. The transcript artifact is missing or unreadable.'\n : 'No transcript yet.';\n const lines: string[] = [];\n for (const line of wrapTextWithAnsi(transcriptState, Math.max(1, width))) lines.push(line);\n return lines;\n }\n\n protected getChrome(): DoomOverlayChrome {\n const selected = this.snapshot.items[this.selected];\n const position = this.snapshot.items.length ? `${this.selected + 1}/${this.snapshot.items.length}` : '0/0';\n return {\n title: 'AGENT RUNS',\n accent: DOOM_OVERLAY_ACCENT,\n breadcrumb: 'SPC › a / agents',\n headerRight: selected\n ? `${statusGlyph(selected.state, this.theme)} ${this.theme.fg(agentIdentityColor(selected.runId), selected.agent)} · ${selected.state}`\n : 'no runs',\n // The per-run controls are listed in the pane itself, next to the state\n // they act on; repeating them here would cost the keys that are not.\n footer: ['↑↓/jk select', 'J/K scroll', 'p agent', 'o detail', 'Ctrl+R refresh', 'Esc close'].join(' · '),\n footerRight: position,\n };\n }\n\n protected renderBody(width: number, height: number): string[] {\n const transientRows = (this.steerDraft !== undefined ? 2 : 0) + (this.actionNotice !== undefined ? 1 : 0);\n const mainHeight = Math.max(0, height - transientRows);\n const narrow = width < 36;\n const rosterHeight = narrow ? Math.max(1, Math.floor((mainHeight - 1) * 0.35)) : mainHeight;\n const detailPaneHeight = narrow ? Math.max(0, mainHeight - rosterHeight - 1) : mainHeight;\n this.bodyHeight = rosterHeight;\n const rosterPane = narrow ? width : Math.max(22, Math.min(46, Math.floor((width - 1) * 0.38)));\n // Side by side, each pane gives up a column to the divider's gutters.\n const rosterWidth = narrow ? width : Math.max(1, rosterPane - 1);\n const detailWidth = narrow ? width : Math.max(1, width - rosterWidth - 3);\n const roster = this.rosterLines(rosterWidth);\n const selected = this.snapshot.items[this.selected];\n // One status read per paint, shared by the header and the detail body.\n const status = selected ? readAsyncRunStatus(selected.runId) : undefined;\n const body = this.wrappedDetail(selected, status, detailWidth);\n // The agent tab is its own self-describing document, so the live status\n // header would only repeat what it already states in full.\n const fixedHeader =\n selected && this.detailTab === 'transcript'\n ? [\n ...statusHeaderLines(selected, status, detailWidth, this.theme, Date.now()),\n '',\n controlLine(selected, detailWidth, this.theme),\n tabStrip(this.detailTab, this.verbosity, detailWidth, this.theme),\n ]\n : selected\n ? [tabStrip(this.detailTab, this.verbosity, detailWidth, this.theme)]\n : [];\n const fixedBudget = detailPaneHeight - MIN_DETAIL_BODY_LINES;\n const detailHeader = fixedBudget >= fixedHeader.length ? fixedHeader : [];\n this.detailViewportHeight = Math.max(1, detailPaneHeight - detailHeader.length);\n this.detailLineCount = body.length;\n const maxDetailScroll = Math.max(0, body.length - this.detailViewportHeight);\n if (this.detailAutoFollow) this.detailScroll = maxDetailScroll;\n else if (this.detailScroll > maxDetailScroll) this.detailScroll = maxDetailScroll;\n const visibleDetails = [\n ...detailHeader,\n ...body.slice(this.detailScroll, this.detailScroll + this.detailViewportHeight),\n ];\n\n const lines: string[] = [];\n if (narrow) {\n for (let index = 0; index < rosterHeight; index++) lines.push(fit(roster[index] ?? '', width));\n if (mainHeight > rosterHeight) lines.push(this.theme.fg('borderMuted', '─'.repeat(width)));\n for (let index = 0; index < detailPaneHeight; index++) lines.push(fit(visibleDetails[index] ?? '', width));\n } else {\n for (let index = 0; index < mainHeight; index++) {\n lines.push(\n `${fit(roster[index] ?? '', rosterWidth)} ${this.theme.fg('borderMuted', '│')} ${fit(\n visibleDetails[index] ?? '',\n detailWidth,\n )}`,\n );\n }\n }\n if (this.steerDraft !== undefined) {\n const steerLines = [\n ` ${this.theme.fg('accent', 'STEER MESSAGE')} ${this.theme.fg('dim', `· run ${selected?.runId ?? FIELD_FALLBACK}`)}`,\n ` ${this.theme.fg('accent', '❯')} ${this.steerDraft}▌`,\n ].map((line) => truncateToWidth(line, width));\n lines.push(...steerLines);\n }\n if (this.actionNotice !== undefined) {\n lines.push(fit(` ${this.theme.fg('muted', this.actionNotice)}`, width));\n }\n return lines.slice(0, height).map((line) => truncateToWidth(line, width));\n }\n\n /**\n * `Component`'s required \"re-render from scratch\" hook - the host calls\n * this on a theme change, not on a timer. Distinct from a poll tick (which\n * must NOT do this, see the module header): this is an explicit, external\n * signal that cached state is stale, the same category as Ctrl+R.\n */\n invalidate(): void {\n this.clearCaches();\n this.refresh();\n }\n\n dispose(): void {\n this.disposed = true;\n this.unregister();\n }\n}\n\n/** Opens the fleet overlay. `scheduler`/`tracker` are resolved by the caller (see `register.ts`) from the live container, not constructed here. */\nexport async function openSubagentFleet(\n ctx: ExtensionContext,\n scheduler: IPollScheduler,\n tracker: ITrackedAsyncJobs,\n options: FleetViewOptions = {},\n): Promise<void> {\n await ctx.ui.custom<undefined>(\n (tui, theme, _keybindings, done) => new SubagentFleetComponent(tui, theme, scheduler, tracker, done, options),\n DOOM_FULLSCREEN_UI_OPTIONS,\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ const e=require(`../_virtual/_rolldown/runtime.cjs`),t=require(`../shared/formatters.cjs`);let n=require(`node:fs`);n=e.__toESM(n,1);let r=require(`@earendil-works/pi-tui`);function i(e,t,n,i){return(0,r.truncateToWidth)(` ${i.fg(`dim`,e.padEnd(8))}${t}`,n)}function a(e){if(!e)return{source:`none`};if(e.systemPromptPath)try{return{text:n.readFileSync(e.systemPromptPath,`utf-8`),source:`run`}}catch(e){return{source:`none`,warning:e instanceof Error?e.message:String(e)}}let t=e.inlineAgent?.systemPrompt;return t?{text:t,source:`inline`}:{source:`none`}}function o(e){if(!e)return`none`;if(e.systemPromptPath)try{let t=n.statSync(e.systemPromptPath);return`${e.systemPromptPath}:${t.size}:${t.mtimeMs}`}catch{return`${e.systemPromptPath}:missing`}return e.inlineAgent?.systemPrompt?`inline:${e.inlineAgent.systemPrompt.length}`:`none`}function s(e){if(e.noTools)return`none (tools disabled)`;let t=e.tools?.length?e.tools.join(`, `):void 0,n=e.excludeTools?.length?`excluding ${e.excludeTools.join(`, `)}`:void 0;return[t??`inherited defaults`,n].filter(Boolean).join(` · `)}function c(e){return e.source===`run`?`recorded at spawn`:e.source===`inline`?`inline agent definition`:`not recorded`}function l(e){let{status:n,width:a,theme:o,prompt:l}=e,u=Math.max(1,a),d=[];if(d.push(i(`Run`,e.runId,u,o)),d.push(i(`Agent`,n?.agent??e.agent,u,o)),d.push(i(`State`,e.state,u,o)),d.push(i(`Model`,n?.model?t.formatModelThinking(n.model):`—`,u,o)),d.push(i(`Runtime`,n?.runtime??`pi`,u,o)),d.push(i(`Cwd`,n?.cwd??`—`,u,o)),d.push(i(`Tools`,n?s(n):`—`,u,o)),n?.startedAt!==void 0){let r=t.formatDuration((n.endedAt??e.now??Date.now())-n.startedAt);d.push(i(`Started`,`${new Date(n.startedAt).toISOString()} · ${r}`,u,o))}if(n?.task){d.push(``,(0,r.truncateToWidth)(` ${o.fg(`accent`,o.bold(`TASK`))}`,u));for(let e of(0,r.wrapTextWithAnsi)(n.task,u))d.push(e)}if(d.push(``,(0,r.truncateToWidth)(` ${o.fg(`accent`,o.bold(`SYSTEM PROMPT`))} ${o.fg(`dim`,`· ${c(l)}`)}`,u)),l.text){let t=e.markdownTheme?new r.Markdown(l.text,0,0,e.markdownTheme).render(u):(0,r.wrapTextWithAnsi)(l.text,u);d.push(...t)}else{let e=l.warning?`The recorded system prompt could not be read: ${l.warning}`:n?.runtime&&n.runtime!==`pi`?`This run uses the '${n.runtime}' runtime, which is launched as an external CLI and has no recorded system prompt.`:`No system prompt was recorded for this run. Runs started before the prompt sidecar existed do not have one.`;for(let t of(0,r.wrapTextWithAnsi)(e,u))d.push(o.fg(`muted`,t))}return d}exports.agentSystemPromptFingerprint=o,exports.fieldRow=i,exports.readAgentSystemPrompt=a,exports.renderAgentView=l;
2
+ //# sourceMappingURL=fleetAgentView.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fleetAgentView.cjs","names":["fs","formatModelThinking","formatDuration","Markdown"],"sources":["../../src/tui/fleetAgentView.ts"],"sourcesContent":["/**\n * The fleet detail pane's `agent` tab: what a run was configured with, and the\n * system prompt it was actually launched with.\n *\n * WHY A TAB RATHER THAN MORE HEADER:\n * The transcript answers \"what has this run done\"; this answers \"what was it\n * told to do\". The second question is asked far less often than the first but\n * needs far more room when it is, so the two share the pane by swapping rather\n * than by competing for the same fixed rows.\n *\n * WHERE THE PROMPT COMES FROM:\n * `asyncExecution.ts` records it to a sidecar at spawn (see\n * `SYSTEM_PROMPT_FILE_NAME`), because the launch config that carried it is\n * deleted as soon as the child handshakes and the agent definition on disk can\n * change while a run is still going. Re-resolving the agent by name here would\n * therefore show what the NEXT run would get, not what this one did. Runs that\n * predate the sidecar, and inline agents, fall back in `readAgentSystemPrompt`;\n * when neither has it the pane says so rather than showing a plausible guess.\n *\n * DESIGN PATTERNS:\n * - Reading is the caller's business: `readAgentSystemPrompt` is separate from\n * rendering so the overlay can cache the file read on a content fingerprint,\n * the same discipline `fleet.ts` applies to transcripts\n */\n\nimport * as fs from 'node:fs';\n\nimport { truncateToWidth, wrapTextWithAnsi, type MarkdownTheme } from '@earendil-works/pi-tui';\nimport { Markdown } from '@earendil-works/pi-tui';\n\nimport type { AsyncRunStatus } from '../runs/background/asyncExecution.ts';\nimport { formatDuration, formatModelThinking } from '../shared/formatters.ts';\nimport type { FleetTranscriptTheme } from './fleetTranscript.ts';\n\nexport const FIELD_LABEL_WIDTH = 8;\nconst FIELD_FALLBACK = '—';\n\n/** A dim fixed-width label with its value, shared by both detail tabs. */\nexport function fieldRow(label: string, value: string, width: number, theme: FleetTranscriptTheme): string {\n return truncateToWidth(` ${theme.fg('dim', label.padEnd(FIELD_LABEL_WIDTH))}${value}`, width);\n}\n\nexport type AgentSystemPromptSource = 'run' | 'inline' | 'none';\n\nexport interface AgentSystemPrompt {\n text?: string;\n /** Which fallback supplied the text, so the pane can say how sure it is. */\n source: AgentSystemPromptSource;\n warning?: string;\n}\n\n/**\n * Resolve a run's system prompt from what was recorded for it.\n *\n * Never throws: a missing sidecar is the normal state for a run started before\n * it was written, and for every non-`pi` runtime.\n */\nexport function readAgentSystemPrompt(status: AsyncRunStatus | undefined): AgentSystemPrompt {\n if (!status) return { source: 'none' };\n if (status.systemPromptPath) {\n try {\n return { text: fs.readFileSync(status.systemPromptPath, 'utf-8'), source: 'run' };\n } catch (cause) {\n return { source: 'none', warning: cause instanceof Error ? cause.message : String(cause) };\n }\n }\n const inline = status.inlineAgent?.systemPrompt;\n if (inline) return { text: inline, source: 'inline' };\n return { source: 'none' };\n}\n\n/** A stable fingerprint of the prompt source, for the overlay's read cache. */\nexport function agentSystemPromptFingerprint(status: AsyncRunStatus | undefined): string {\n if (!status) return 'none';\n if (status.systemPromptPath) {\n try {\n const stat = fs.statSync(status.systemPromptPath);\n return `${status.systemPromptPath}:${stat.size}:${stat.mtimeMs}`;\n } catch {\n return `${status.systemPromptPath}:missing`;\n }\n }\n return status.inlineAgent?.systemPrompt ? `inline:${status.inlineAgent.systemPrompt.length}` : 'none';\n}\n\nfunction toolsSummary(status: AsyncRunStatus): string {\n if (status.noTools) return 'none (tools disabled)';\n const allowed = status.tools?.length ? status.tools.join(', ') : undefined;\n const excluded = status.excludeTools?.length ? `excluding ${status.excludeTools.join(', ')}` : undefined;\n return [allowed ?? 'inherited defaults', excluded].filter(Boolean).join(' · ');\n}\n\nfunction sourceNote(prompt: AgentSystemPrompt): string {\n if (prompt.source === 'run') return 'recorded at spawn';\n if (prompt.source === 'inline') return 'inline agent definition';\n return 'not recorded';\n}\n\nexport interface AgentViewInput {\n status: AsyncRunStatus | undefined;\n /** Roster state, which stays authoritative even when no status file was found. */\n state: string;\n agent: string;\n runId: string;\n prompt: AgentSystemPrompt;\n width: number;\n theme: FleetTranscriptTheme;\n markdownTheme?: MarkdownTheme;\n now?: number;\n}\n\n/** The agent tab body. Scrolled by the caller, so this returns every line it has. */\nexport function renderAgentView(input: AgentViewInput): string[] {\n const { status, width, theme, prompt } = input;\n const safeWidth = Math.max(1, width);\n const lines: string[] = [];\n\n lines.push(fieldRow('Run', input.runId, safeWidth, theme));\n lines.push(fieldRow('Agent', status?.agent ?? input.agent, safeWidth, theme));\n lines.push(fieldRow('State', input.state, safeWidth, theme));\n lines.push(fieldRow('Model', status?.model ? formatModelThinking(status.model) : FIELD_FALLBACK, safeWidth, theme));\n lines.push(fieldRow('Runtime', status?.runtime ?? 'pi', safeWidth, theme));\n lines.push(fieldRow('Cwd', status?.cwd ?? FIELD_FALLBACK, safeWidth, theme));\n lines.push(fieldRow('Tools', status ? toolsSummary(status) : FIELD_FALLBACK, safeWidth, theme));\n if (status?.startedAt !== undefined) {\n const elapsed = formatDuration((status.endedAt ?? input.now ?? Date.now()) - status.startedAt);\n lines.push(fieldRow('Started', `${new Date(status.startedAt).toISOString()} · ${elapsed}`, safeWidth, theme));\n }\n\n if (status?.task) {\n lines.push('', truncateToWidth(` ${theme.fg('accent', theme.bold('TASK'))}`, safeWidth));\n for (const line of wrapTextWithAnsi(status.task, safeWidth)) lines.push(line);\n }\n\n lines.push(\n '',\n truncateToWidth(\n ` ${theme.fg('accent', theme.bold('SYSTEM PROMPT'))} ${theme.fg('dim', `· ${sourceNote(prompt)}`)}`,\n safeWidth,\n ),\n );\n if (prompt.text) {\n const body = input.markdownTheme\n ? new Markdown(prompt.text, 0, 0, input.markdownTheme).render(safeWidth)\n : wrapTextWithAnsi(prompt.text, safeWidth);\n lines.push(...body);\n } else {\n const reason = prompt.warning\n ? `The recorded system prompt could not be read: ${prompt.warning}`\n : status?.runtime && status.runtime !== 'pi'\n ? `This run uses the '${status.runtime}' runtime, which is launched as an external CLI and has no recorded system prompt.`\n : 'No system prompt was recorded for this run. Runs started before the prompt sidecar existed do not have one.';\n for (const line of wrapTextWithAnsi(reason, safeWidth)) lines.push(theme.fg('muted', line));\n }\n return lines;\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{formatDuration as e,formatModelThinking as t,init_formatters as n}from"../shared/formatters.mjs";import*as r from"node:fs";import{Markdown as i,truncateToWidth as a,wrapTextWithAnsi as o}from"@earendil-works/pi-tui";n();function s(e,t,n,r){return a(` ${r.fg(`dim`,e.padEnd(8))}${t}`,n)}function c(e){if(!e)return{source:`none`};if(e.systemPromptPath)try{return{text:r.readFileSync(e.systemPromptPath,`utf-8`),source:`run`}}catch(e){return{source:`none`,warning:e instanceof Error?e.message:String(e)}}let t=e.inlineAgent?.systemPrompt;return t?{text:t,source:`inline`}:{source:`none`}}function l(e){if(!e)return`none`;if(e.systemPromptPath)try{let t=r.statSync(e.systemPromptPath);return`${e.systemPromptPath}:${t.size}:${t.mtimeMs}`}catch{return`${e.systemPromptPath}:missing`}return e.inlineAgent?.systemPrompt?`inline:${e.inlineAgent.systemPrompt.length}`:`none`}function u(e){if(e.noTools)return`none (tools disabled)`;let t=e.tools?.length?e.tools.join(`, `):void 0,n=e.excludeTools?.length?`excluding ${e.excludeTools.join(`, `)}`:void 0;return[t??`inherited defaults`,n].filter(Boolean).join(` · `)}function d(e){return e.source===`run`?`recorded at spawn`:e.source===`inline`?`inline agent definition`:`not recorded`}function f(n){let{status:r,width:c,theme:l,prompt:f}=n,p=Math.max(1,c),m=[];if(m.push(s(`Run`,n.runId,p,l)),m.push(s(`Agent`,r?.agent??n.agent,p,l)),m.push(s(`State`,n.state,p,l)),m.push(s(`Model`,r?.model?t(r.model):`—`,p,l)),m.push(s(`Runtime`,r?.runtime??`pi`,p,l)),m.push(s(`Cwd`,r?.cwd??`—`,p,l)),m.push(s(`Tools`,r?u(r):`—`,p,l)),r?.startedAt!==void 0){let t=e((r.endedAt??n.now??Date.now())-r.startedAt);m.push(s(`Started`,`${new Date(r.startedAt).toISOString()} · ${t}`,p,l))}if(r?.task){m.push(``,a(` ${l.fg(`accent`,l.bold(`TASK`))}`,p));for(let e of o(r.task,p))m.push(e)}if(m.push(``,a(` ${l.fg(`accent`,l.bold(`SYSTEM PROMPT`))} ${l.fg(`dim`,`· ${d(f)}`)}`,p)),f.text){let e=n.markdownTheme?new i(f.text,0,0,n.markdownTheme).render(p):o(f.text,p);m.push(...e)}else{let e=f.warning?`The recorded system prompt could not be read: ${f.warning}`:r?.runtime&&r.runtime!==`pi`?`This run uses the '${r.runtime}' runtime, which is launched as an external CLI and has no recorded system prompt.`:`No system prompt was recorded for this run. Runs started before the prompt sidecar existed do not have one.`;for(let t of o(e,p))m.push(l.fg(`muted`,t))}return m}export{l as agentSystemPromptFingerprint,s as fieldRow,c as readAgentSystemPrompt,f as renderAgentView};
2
+ //# sourceMappingURL=fleetAgentView.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fleetAgentView.mjs","names":[],"sources":["../../src/tui/fleetAgentView.ts"],"sourcesContent":["/**\n * The fleet detail pane's `agent` tab: what a run was configured with, and the\n * system prompt it was actually launched with.\n *\n * WHY A TAB RATHER THAN MORE HEADER:\n * The transcript answers \"what has this run done\"; this answers \"what was it\n * told to do\". The second question is asked far less often than the first but\n * needs far more room when it is, so the two share the pane by swapping rather\n * than by competing for the same fixed rows.\n *\n * WHERE THE PROMPT COMES FROM:\n * `asyncExecution.ts` records it to a sidecar at spawn (see\n * `SYSTEM_PROMPT_FILE_NAME`), because the launch config that carried it is\n * deleted as soon as the child handshakes and the agent definition on disk can\n * change while a run is still going. Re-resolving the agent by name here would\n * therefore show what the NEXT run would get, not what this one did. Runs that\n * predate the sidecar, and inline agents, fall back in `readAgentSystemPrompt`;\n * when neither has it the pane says so rather than showing a plausible guess.\n *\n * DESIGN PATTERNS:\n * - Reading is the caller's business: `readAgentSystemPrompt` is separate from\n * rendering so the overlay can cache the file read on a content fingerprint,\n * the same discipline `fleet.ts` applies to transcripts\n */\n\nimport * as fs from 'node:fs';\n\nimport { truncateToWidth, wrapTextWithAnsi, type MarkdownTheme } from '@earendil-works/pi-tui';\nimport { Markdown } from '@earendil-works/pi-tui';\n\nimport type { AsyncRunStatus } from '../runs/background/asyncExecution.ts';\nimport { formatDuration, formatModelThinking } from '../shared/formatters.ts';\nimport type { FleetTranscriptTheme } from './fleetTranscript.ts';\n\nexport const FIELD_LABEL_WIDTH = 8;\nconst FIELD_FALLBACK = '—';\n\n/** A dim fixed-width label with its value, shared by both detail tabs. */\nexport function fieldRow(label: string, value: string, width: number, theme: FleetTranscriptTheme): string {\n return truncateToWidth(` ${theme.fg('dim', label.padEnd(FIELD_LABEL_WIDTH))}${value}`, width);\n}\n\nexport type AgentSystemPromptSource = 'run' | 'inline' | 'none';\n\nexport interface AgentSystemPrompt {\n text?: string;\n /** Which fallback supplied the text, so the pane can say how sure it is. */\n source: AgentSystemPromptSource;\n warning?: string;\n}\n\n/**\n * Resolve a run's system prompt from what was recorded for it.\n *\n * Never throws: a missing sidecar is the normal state for a run started before\n * it was written, and for every non-`pi` runtime.\n */\nexport function readAgentSystemPrompt(status: AsyncRunStatus | undefined): AgentSystemPrompt {\n if (!status) return { source: 'none' };\n if (status.systemPromptPath) {\n try {\n return { text: fs.readFileSync(status.systemPromptPath, 'utf-8'), source: 'run' };\n } catch (cause) {\n return { source: 'none', warning: cause instanceof Error ? cause.message : String(cause) };\n }\n }\n const inline = status.inlineAgent?.systemPrompt;\n if (inline) return { text: inline, source: 'inline' };\n return { source: 'none' };\n}\n\n/** A stable fingerprint of the prompt source, for the overlay's read cache. */\nexport function agentSystemPromptFingerprint(status: AsyncRunStatus | undefined): string {\n if (!status) return 'none';\n if (status.systemPromptPath) {\n try {\n const stat = fs.statSync(status.systemPromptPath);\n return `${status.systemPromptPath}:${stat.size}:${stat.mtimeMs}`;\n } catch {\n return `${status.systemPromptPath}:missing`;\n }\n }\n return status.inlineAgent?.systemPrompt ? `inline:${status.inlineAgent.systemPrompt.length}` : 'none';\n}\n\nfunction toolsSummary(status: AsyncRunStatus): string {\n if (status.noTools) return 'none (tools disabled)';\n const allowed = status.tools?.length ? status.tools.join(', ') : undefined;\n const excluded = status.excludeTools?.length ? `excluding ${status.excludeTools.join(', ')}` : undefined;\n return [allowed ?? 'inherited defaults', excluded].filter(Boolean).join(' · ');\n}\n\nfunction sourceNote(prompt: AgentSystemPrompt): string {\n if (prompt.source === 'run') return 'recorded at spawn';\n if (prompt.source === 'inline') return 'inline agent definition';\n return 'not recorded';\n}\n\nexport interface AgentViewInput {\n status: AsyncRunStatus | undefined;\n /** Roster state, which stays authoritative even when no status file was found. */\n state: string;\n agent: string;\n runId: string;\n prompt: AgentSystemPrompt;\n width: number;\n theme: FleetTranscriptTheme;\n markdownTheme?: MarkdownTheme;\n now?: number;\n}\n\n/** The agent tab body. Scrolled by the caller, so this returns every line it has. */\nexport function renderAgentView(input: AgentViewInput): string[] {\n const { status, width, theme, prompt } = input;\n const safeWidth = Math.max(1, width);\n const lines: string[] = [];\n\n lines.push(fieldRow('Run', input.runId, safeWidth, theme));\n lines.push(fieldRow('Agent', status?.agent ?? input.agent, safeWidth, theme));\n lines.push(fieldRow('State', input.state, safeWidth, theme));\n lines.push(fieldRow('Model', status?.model ? formatModelThinking(status.model) : FIELD_FALLBACK, safeWidth, theme));\n lines.push(fieldRow('Runtime', status?.runtime ?? 'pi', safeWidth, theme));\n lines.push(fieldRow('Cwd', status?.cwd ?? FIELD_FALLBACK, safeWidth, theme));\n lines.push(fieldRow('Tools', status ? toolsSummary(status) : FIELD_FALLBACK, safeWidth, theme));\n if (status?.startedAt !== undefined) {\n const elapsed = formatDuration((status.endedAt ?? input.now ?? Date.now()) - status.startedAt);\n lines.push(fieldRow('Started', `${new Date(status.startedAt).toISOString()} · ${elapsed}`, safeWidth, theme));\n }\n\n if (status?.task) {\n lines.push('', truncateToWidth(` ${theme.fg('accent', theme.bold('TASK'))}`, safeWidth));\n for (const line of wrapTextWithAnsi(status.task, safeWidth)) lines.push(line);\n }\n\n lines.push(\n '',\n truncateToWidth(\n ` ${theme.fg('accent', theme.bold('SYSTEM PROMPT'))} ${theme.fg('dim', `· ${sourceNote(prompt)}`)}`,\n safeWidth,\n ),\n );\n if (prompt.text) {\n const body = input.markdownTheme\n ? new Markdown(prompt.text, 0, 0, input.markdownTheme).render(safeWidth)\n : wrapTextWithAnsi(prompt.text, safeWidth);\n lines.push(...body);\n } else {\n const reason = prompt.warning\n ? `The recorded system prompt could not be read: ${prompt.warning}`\n : status?.runtime && status.runtime !== 'pi'\n ? `This run uses the '${status.runtime}' runtime, which is launched as an external CLI and has no recorded system prompt.`\n : 'No system prompt was recorded for this run. Runs started before the prompt sidecar existed do not have one.';\n for (const line of wrapTextWithAnsi(reason, safeWidth)) lines.push(theme.fg('muted', line));\n }\n return lines;\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../runs/background/asyncJobTracker.cjs`);let t=require(`@agimon-ai/doompi-ui/theme`);const n=[`◐`,`●`,`◑`],r=new Set([`complete`,`completed`]),i=new Set([`paused`,`stopped`]),a=new Set([`working`,`tool`,`finalizing`,`active_long_running`]);function o(e){let t=0;for(let n of e)t=Math.imul(t,31)+(n.codePointAt(0)??0)>>>0;return t%n.length}function s(e){return e.list().toSorted((e,t)=>(e.startedAt??2**53-1)-(t.startedAt??2**53-1)||e.runId.localeCompare(t.runId))}function c(t){return s(t).filter(t=>!t.status||!e.TERMINAL_ASYNC_JOB_STATES.has(t.status))}function l(e,s){let c=(0,t.agentIdentityColor)(e.runId);return e.status&&r.has(e.status)?{glyph:`✓`,color:c}:e.status===`failed`?{glyph:`✗`,color:c}:e.status&&i.has(e.status)?{glyph:`■`,color:c}:e.activityState===`needs_attention`?{glyph:`!`,color:`warning`}:!e.activityState||!a.has(e.activityState)?{glyph:`○`,color:c}:{glyph:n[(s+o(e.runId))%n.length],color:c}}function u(e,t,n,r){let i=r-n.length,a=Math.min(e.length,i),o=``;for(;a<e.length&&(o=`…+${e.length-a}`,!(a+o.length<=i));)--a;let s=t.slice(0,Math.max(0,a));return{text:`${n}${s.map(e=>e.glyph).join(``)}${o}`,segments:[{text:n},...s.map(e=>({text:e.glyph,color:e.color})),...o?[{text:o,color:`dim`}]:[]]}}function d(e,t=0){let n=s(e);if(n.length===0)return;let r=n.map(e=>l(e,t)),i=u(n,r,`Agents `,80),o=u(n,r,`A `,24),d=c(e).some(e=>e.activityState!==void 0&&a.has(e.activityState));return{text:i.text,footer:{fullText:i.text,compactText:o.text,fullSegments:i.segments,compactSegments:o.segments},fingerprint:`${n.map(e=>`${e.runId}:${e.agent??``}:${e.status??``}:${e.activityState??``}`).join(`|`)}:${d?t:`static`}`,pulsing:d}}exports.AGENT_PULSE_FRAMES=n,exports.FLEET_STATUS_KEY=`doom-team-agents`,exports.agentFleetStatus=d;
2
+ //# sourceMappingURL=fleetStatus.cjs.map