@agimon-ai/doompi-team 0.0.1-alpha.2 → 0.0.1-alpha.20

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 (727) hide show
  1. package/README.md +33 -17
  2. package/dist/adapters/asyncJobTracker.cjs +2 -0
  3. package/dist/adapters/asyncJobTracker.cjs.map +1 -0
  4. package/dist/adapters/asyncJobTracker.mjs +2 -0
  5. package/dist/adapters/asyncJobTracker.mjs.map +1 -0
  6. package/dist/adapters/atomicJson.cjs +2 -0
  7. package/dist/adapters/atomicJson.cjs.map +1 -0
  8. package/dist/adapters/atomicJson.mjs +2 -0
  9. package/dist/adapters/atomicJson.mjs.map +1 -0
  10. package/dist/adapters/pi/extension.cjs +2 -0
  11. package/dist/adapters/pi/extension.cjs.map +1 -0
  12. package/dist/adapters/pi/extension.mjs +2 -0
  13. package/dist/adapters/pi/extension.mjs.map +1 -0
  14. package/dist/adapters/pollScheduler.cjs +2 -0
  15. package/dist/adapters/pollScheduler.cjs.map +1 -0
  16. package/dist/adapters/pollScheduler.mjs +2 -0
  17. package/dist/adapters/pollScheduler.mjs.map +1 -0
  18. package/dist/adapters/process/childTranscript.cjs +5 -0
  19. package/dist/adapters/process/childTranscript.cjs.map +1 -0
  20. package/dist/adapters/process/childTranscript.mjs +5 -0
  21. package/dist/adapters/process/childTranscript.mjs.map +1 -0
  22. package/dist/adapters/process/env.cjs +2 -0
  23. package/dist/adapters/process/env.cjs.map +1 -0
  24. package/dist/adapters/process/env.d.cts +69 -0
  25. package/dist/adapters/process/env.d.cts.map +1 -0
  26. package/dist/adapters/process/env.d.mts +69 -0
  27. package/dist/adapters/process/env.d.mts.map +1 -0
  28. package/dist/adapters/process/env.mjs +2 -0
  29. package/dist/adapters/process/env.mjs.map +1 -0
  30. package/dist/adapters/process/sdkRunnerEntry.cjs +2 -0
  31. package/dist/adapters/process/sdkRunnerEntry.cjs.map +1 -0
  32. package/dist/adapters/process/sdkRunnerEntry.d.cts +5 -0
  33. package/dist/adapters/process/sdkRunnerEntry.d.cts.map +1 -0
  34. package/dist/adapters/process/sdkRunnerEntry.d.mts +5 -0
  35. package/dist/adapters/process/sdkRunnerEntry.d.mts.map +1 -0
  36. package/dist/adapters/process/sdkRunnerEntry.mjs +2 -0
  37. package/dist/adapters/process/sdkRunnerEntry.mjs.map +1 -0
  38. package/dist/adapters/processTerminal.cjs +2 -0
  39. package/dist/adapters/processTerminal.cjs.map +1 -0
  40. package/dist/adapters/processTerminal.mjs +2 -0
  41. package/dist/adapters/processTerminal.mjs.map +1 -0
  42. package/dist/adapters/resultWatcher.cjs +2 -0
  43. package/dist/adapters/resultWatcher.cjs.map +1 -0
  44. package/dist/adapters/resultWatcher.mjs +2 -0
  45. package/dist/adapters/resultWatcher.mjs.map +1 -0
  46. package/dist/adapters/runIdResolver.cjs +2 -0
  47. package/dist/adapters/runIdResolver.cjs.map +1 -0
  48. package/dist/adapters/runIdResolver.mjs +2 -0
  49. package/dist/adapters/runIdResolver.mjs.map +1 -0
  50. package/dist/adapters/runRegistry.cjs +2 -0
  51. package/dist/adapters/runRegistry.cjs.map +1 -0
  52. package/dist/adapters/runRegistry.mjs +2 -0
  53. package/dist/adapters/runRegistry.mjs.map +1 -0
  54. package/dist/adapters/scopeOwner.cjs +2 -0
  55. package/dist/adapters/scopeOwner.cjs.map +1 -0
  56. package/dist/adapters/scopeOwner.mjs +2 -0
  57. package/dist/adapters/scopeOwner.mjs.map +1 -0
  58. package/dist/adapters/staleRunReconciler.cjs +2 -0
  59. package/dist/adapters/staleRunReconciler.cjs.map +1 -0
  60. package/dist/adapters/staleRunReconciler.mjs +2 -0
  61. package/dist/adapters/staleRunReconciler.mjs.map +1 -0
  62. package/dist/adapters/statusReader.cjs +2 -0
  63. package/dist/adapters/statusReader.cjs.map +1 -0
  64. package/dist/adapters/statusReader.mjs +2 -0
  65. package/dist/adapters/statusReader.mjs.map +1 -0
  66. package/dist/adapters/suspendedRuns.cjs +6 -0
  67. package/dist/adapters/suspendedRuns.cjs.map +1 -0
  68. package/dist/adapters/suspendedRuns.mjs +6 -0
  69. package/dist/adapters/suspendedRuns.mjs.map +1 -0
  70. package/dist/api/backgroundWork.cjs +1 -1
  71. package/dist/api/backgroundWork.d.cts +2 -2
  72. package/dist/api/backgroundWork.d.mts +2 -2
  73. package/dist/api/backgroundWork.mjs +1 -1
  74. package/dist/api/capabilityCeiling.cjs +1 -1
  75. package/dist/api/capabilityCeiling.d.cts +3 -3
  76. package/dist/api/capabilityCeiling.d.mts +3 -3
  77. package/dist/api/capabilityCeiling.mjs +1 -2
  78. package/dist/api/delegation.cjs +1 -1
  79. package/dist/api/delegation.d.cts +1 -1
  80. package/dist/api/delegation.d.mts +1 -1
  81. package/dist/api/delegation.mjs +1 -1
  82. package/dist/api/teamSnapshot.cjs +1 -1
  83. package/dist/api/teamSnapshot.d.cts +2 -2
  84. package/dist/api/teamSnapshot.d.mts +2 -2
  85. package/dist/api/teamSnapshot.mjs +1 -2
  86. package/dist/commands/slash/chainExpression.cjs.map +1 -0
  87. package/dist/commands/slash/chainExpression.mjs.map +1 -0
  88. package/dist/commands/slash/doctor.cjs +5 -0
  89. package/dist/commands/slash/doctor.cjs.map +1 -0
  90. package/dist/commands/slash/doctor.mjs +5 -0
  91. package/dist/{slash/doctor.cjs.map → commands/slash/doctor.mjs.map} +1 -1
  92. package/dist/{slash → commands/slash}/slashCommands.cjs +1 -1
  93. package/dist/commands/slash/slashCommands.cjs.map +1 -0
  94. package/dist/{slash → commands/slash}/slashCommands.mjs +2 -2
  95. package/dist/commands/slash/slashCommands.mjs.map +1 -0
  96. package/dist/commands/slash/spawnRequestMapping.cjs.map +1 -0
  97. package/dist/commands/slash/spawnRequestMapping.mjs.map +1 -0
  98. package/dist/commands/slash/subagentLaunch.cjs +2 -0
  99. package/dist/commands/slash/subagentLaunch.cjs.map +1 -0
  100. package/dist/commands/slash/subagentLaunch.mjs +2 -0
  101. package/dist/commands/slash/subagentLaunch.mjs.map +1 -0
  102. package/dist/container/globalBridge.cjs.map +1 -1
  103. package/dist/container/globalBridge.d.cts +1 -1
  104. package/dist/container/globalBridge.d.mts +1 -1
  105. package/dist/container/globalBridge.mjs.map +1 -1
  106. package/dist/container/index.cjs +1 -1
  107. package/dist/container/index.cjs.map +1 -1
  108. package/dist/container/index.d.cts +2 -1
  109. package/dist/container/index.d.cts.map +1 -1
  110. package/dist/container/index.d.mts +2 -1
  111. package/dist/container/index.d.mts.map +1 -1
  112. package/dist/container/index.mjs +1 -1
  113. package/dist/container/index.mjs.map +1 -1
  114. package/dist/container/modules/agents.cjs +1 -1
  115. package/dist/container/modules/agents.cjs.map +1 -1
  116. package/dist/container/modules/agents.mjs +1 -1
  117. package/dist/container/modules/agents.mjs.map +1 -1
  118. package/dist/container/modules/core.cjs +1 -1
  119. package/dist/container/modules/core.cjs.map +1 -1
  120. package/dist/container/modules/core.mjs +1 -1
  121. package/dist/container/modules/core.mjs.map +1 -1
  122. package/dist/container/modules/extensions.cjs +1 -1
  123. package/dist/container/modules/extensions.cjs.map +1 -1
  124. package/dist/container/modules/extensions.mjs +1 -1
  125. package/dist/container/modules/extensions.mjs.map +1 -1
  126. package/dist/container/modules/intercom.cjs +1 -1
  127. package/dist/container/modules/intercom.cjs.map +1 -1
  128. package/dist/container/modules/intercom.mjs +1 -1
  129. package/dist/container/modules/intercom.mjs.map +1 -1
  130. package/dist/container/modules/runs.cjs +1 -1
  131. package/dist/container/modules/runs.cjs.map +1 -1
  132. package/dist/container/modules/runs.mjs +1 -1
  133. package/dist/container/modules/runs.mjs.map +1 -1
  134. package/dist/container/types.cjs +1 -1
  135. package/dist/container/types.cjs.map +1 -1
  136. package/dist/container/types.d.cts +1 -0
  137. package/dist/container/types.d.cts.map +1 -1
  138. package/dist/container/types.d.mts +1 -0
  139. package/dist/container/types.d.mts.map +1 -1
  140. package/dist/container/types.mjs +1 -1
  141. package/dist/container/types.mjs.map +1 -1
  142. package/dist/env.cjs +1 -2
  143. package/dist/env.d.cts +2 -65
  144. package/dist/env.d.mts +2 -65
  145. package/dist/env.mjs +1 -1
  146. package/dist/env.mjs.map +1 -1
  147. package/dist/extensions/config.cjs.map +1 -1
  148. package/dist/extensions/config.mjs.map +1 -1
  149. package/dist/extensions/delegationBridge.cjs.map +1 -1
  150. package/dist/extensions/delegationBridge.mjs.map +1 -1
  151. package/dist/extensions/doom.cjs +1 -1
  152. package/dist/extensions/doom.cjs.map +1 -1
  153. package/dist/extensions/doom.mjs +1 -1
  154. package/dist/extensions/doom.mjs.map +1 -1
  155. package/dist/extensions/fablePlanBridge.cjs +1 -1
  156. package/dist/extensions/fablePlanBridge.cjs.map +1 -1
  157. package/dist/extensions/fablePlanBridge.mjs +1 -1
  158. package/dist/extensions/fablePlanBridge.mjs.map +1 -1
  159. package/dist/extensions/managementActions.cjs +1 -1
  160. package/dist/extensions/managementActions.cjs.map +1 -1
  161. package/dist/extensions/managementActions.mjs +1 -1
  162. package/dist/extensions/managementActions.mjs.map +1 -1
  163. package/dist/extensions/operationJournal.cjs +1 -1
  164. package/dist/extensions/operationJournal.cjs.map +1 -1
  165. package/dist/extensions/operationJournal.mjs +1 -1
  166. package/dist/extensions/operationJournal.mjs.map +1 -1
  167. package/dist/extensions/orchestratorPrompt.cjs +5 -6
  168. package/dist/extensions/orchestratorPrompt.cjs.map +1 -1
  169. package/dist/extensions/orchestratorPrompt.mjs +5 -6
  170. package/dist/extensions/orchestratorPrompt.mjs.map +1 -1
  171. package/dist/extensions/schemas.mjs.map +1 -1
  172. package/dist/extensions/spawnPlan.cjs +3 -2
  173. package/dist/extensions/spawnPlan.cjs.map +1 -1
  174. package/dist/extensions/spawnPlan.mjs +3 -2
  175. package/dist/extensions/spawnPlan.mjs.map +1 -1
  176. package/dist/extensions/standard.cjs +1 -1
  177. package/dist/extensions/standard.cjs.map +1 -1
  178. package/dist/extensions/standard.mjs +1 -1
  179. package/dist/extensions/standard.mjs.map +1 -1
  180. package/dist/extensions/statusViews.cjs +1 -1
  181. package/dist/extensions/statusViews.cjs.map +1 -1
  182. package/dist/extensions/statusViews.mjs +2 -2
  183. package/dist/extensions/statusViews.mjs.map +1 -1
  184. package/dist/extensions/subagentPromptRuntime.cjs +11 -11
  185. package/dist/extensions/subagentPromptRuntime.cjs.map +1 -1
  186. package/dist/extensions/subagentPromptRuntime.d.cts.map +1 -1
  187. package/dist/extensions/subagentPromptRuntime.d.mts.map +1 -1
  188. package/dist/extensions/subagentPromptRuntime.mjs +5 -5
  189. package/dist/extensions/subagentPromptRuntime.mjs.map +1 -1
  190. package/dist/extensions/subagentTool.cjs +5 -6
  191. package/dist/extensions/subagentTool.cjs.map +1 -1
  192. package/dist/extensions/subagentTool.mjs +5 -6
  193. package/dist/extensions/subagentTool.mjs.map +1 -1
  194. package/dist/extensions/toolDescription.cjs +1 -1
  195. package/dist/extensions/toolDescription.cjs.map +1 -1
  196. package/dist/extensions/toolDescription.mjs +1 -1
  197. package/dist/extensions/toolDescription.mjs.map +1 -1
  198. package/dist/index.cjs +1 -1
  199. package/dist/index.cjs.map +1 -1
  200. package/dist/index.d.cts +2 -2
  201. package/dist/index.d.cts.map +1 -1
  202. package/dist/index.d.mts +2 -2
  203. package/dist/index.d.mts.map +1 -1
  204. package/dist/index.mjs +1 -1
  205. package/dist/index.mjs.map +1 -1
  206. package/dist/runs/background/cliRunnerEntry.cjs +1 -2
  207. package/dist/runs/background/cliRunnerEntry.mjs +1 -2
  208. package/dist/runs/sdkRunnerEntry.cjs +1 -2
  209. package/dist/runs/sdkRunnerEntry.d.cts +2 -1
  210. package/dist/runs/sdkRunnerEntry.d.mts +2 -1
  211. package/dist/runs/sdkRunnerEntry.mjs +1 -2
  212. package/dist/schemas/team/backgroundWork.cjs +2 -0
  213. package/dist/schemas/team/backgroundWork.cjs.map +1 -0
  214. package/dist/{protocol → schemas/team}/backgroundWork.d.cts +2 -2
  215. package/dist/schemas/team/backgroundWork.d.cts.map +1 -0
  216. package/dist/{protocol → schemas/team}/backgroundWork.d.mts +2 -2
  217. package/dist/schemas/team/backgroundWork.d.mts.map +1 -0
  218. package/dist/schemas/team/backgroundWork.mjs +2 -0
  219. package/dist/{protocol/backgroundWork.cjs.map → schemas/team/backgroundWork.mjs.map} +1 -1
  220. package/dist/schemas/team/capabilityCeiling.cjs +2 -0
  221. package/dist/schemas/team/capabilityCeiling.cjs.map +1 -0
  222. package/dist/{protocol → schemas/team}/capabilityCeiling.d.cts +3 -3
  223. package/dist/schemas/team/capabilityCeiling.d.cts.map +1 -0
  224. package/dist/{protocol → schemas/team}/capabilityCeiling.d.mts +3 -3
  225. package/dist/schemas/team/capabilityCeiling.d.mts.map +1 -0
  226. package/dist/schemas/team/capabilityCeiling.mjs +2 -0
  227. package/dist/schemas/team/capabilityCeiling.mjs.map +1 -0
  228. package/dist/schemas/team/delegation.cjs.map +1 -0
  229. package/dist/{protocol → schemas/team}/delegation.d.cts +1 -1
  230. package/dist/schemas/team/delegation.d.cts.map +1 -0
  231. package/dist/{protocol → schemas/team}/delegation.d.mts +1 -1
  232. package/dist/schemas/team/delegation.d.mts.map +1 -0
  233. package/dist/schemas/team/delegation.mjs.map +1 -0
  234. package/dist/schemas/team/packageConfig.cjs +2 -0
  235. package/dist/schemas/team/packageConfig.cjs.map +1 -0
  236. package/dist/schemas/team/packageConfig.mjs +2 -0
  237. package/dist/schemas/team/packageConfig.mjs.map +1 -0
  238. package/dist/services/agents/discovery.cjs +2 -0
  239. package/dist/services/agents/discovery.cjs.map +1 -0
  240. package/dist/services/agents/discovery.mjs +2 -0
  241. package/dist/services/agents/discovery.mjs.map +1 -0
  242. package/dist/services/agents/frontmatter.cjs.map +1 -0
  243. package/dist/{agents → services/agents}/frontmatter.mjs +1 -1
  244. package/dist/services/agents/frontmatter.mjs.map +1 -0
  245. package/dist/services/agents/loader.cjs +2 -0
  246. package/dist/services/agents/loader.cjs.map +1 -0
  247. package/dist/services/agents/loader.mjs +2 -0
  248. package/dist/services/agents/loader.mjs.map +1 -0
  249. package/dist/services/agents/memory.cjs +3 -0
  250. package/dist/services/agents/memory.cjs.map +1 -0
  251. package/dist/{agents → services/agents}/memory.mjs +1 -1
  252. package/dist/services/agents/memory.mjs.map +1 -0
  253. package/dist/services/agents/projectRoot.cjs +2 -0
  254. package/dist/services/agents/projectRoot.cjs.map +1 -0
  255. package/dist/services/agents/projectRoot.mjs +2 -0
  256. package/dist/services/agents/projectRoot.mjs.map +1 -0
  257. package/dist/services/agents/settings.cjs +2 -0
  258. package/dist/services/agents/settings.cjs.map +1 -0
  259. package/dist/services/agents/settings.mjs +2 -0
  260. package/dist/services/agents/settings.mjs.map +1 -0
  261. package/dist/services/agents/skills.cjs +0 -0
  262. package/dist/services/agents/skills.cjs.map +1 -0
  263. package/dist/services/agents/skills.mjs +5 -0
  264. package/dist/services/agents/skills.mjs.map +1 -0
  265. package/dist/{agents → services/agents}/types.d.cts +4 -4
  266. package/dist/services/agents/types.d.cts.map +1 -0
  267. package/dist/{agents → services/agents}/types.d.mts +4 -4
  268. package/dist/services/agents/types.d.mts.map +1 -0
  269. package/dist/services/api/backgroundWork.cjs +1 -0
  270. package/dist/services/api/backgroundWork.d.cts +1 -0
  271. package/dist/services/api/backgroundWork.d.mts +1 -0
  272. package/dist/services/api/backgroundWork.mjs +1 -0
  273. package/dist/services/api/capabilityCeiling.cjs +1 -0
  274. package/dist/services/api/capabilityCeiling.d.cts +2 -0
  275. package/dist/services/api/capabilityCeiling.d.mts +2 -0
  276. package/dist/services/api/capabilityCeiling.mjs +2 -0
  277. package/dist/services/api/capabilityCeiling.mjs.map +1 -0
  278. package/dist/services/api/teamSnapshot.cjs +1 -0
  279. package/dist/services/api/teamSnapshot.d.cts +1 -0
  280. package/dist/services/api/teamSnapshot.d.mts +1 -0
  281. package/dist/services/api/teamSnapshot.mjs +2 -0
  282. package/dist/services/api/teamSnapshot.mjs.map +1 -0
  283. package/dist/services/intercom/intercomBridge.cjs.map +1 -0
  284. package/dist/services/intercom/intercomBridge.mjs.map +1 -0
  285. package/dist/services/intercom/nativeTeamChannel.cjs +5 -0
  286. package/dist/services/intercom/nativeTeamChannel.cjs.map +1 -0
  287. package/dist/{intercom → services/intercom}/nativeTeamChannel.d.cts +1 -1
  288. package/dist/services/intercom/nativeTeamChannel.d.cts.map +1 -0
  289. package/dist/{intercom → services/intercom}/nativeTeamChannel.d.mts +1 -1
  290. package/dist/services/intercom/nativeTeamChannel.d.mts.map +1 -0
  291. package/dist/services/intercom/nativeTeamChannel.mjs +5 -0
  292. package/dist/services/intercom/nativeTeamChannel.mjs.map +1 -0
  293. package/dist/services/intercom/supervisorControlChannel.cjs +2 -0
  294. package/dist/services/intercom/supervisorControlChannel.cjs.map +1 -0
  295. package/dist/{intercom → services/intercom}/supervisorControlChannel.mjs +1 -1
  296. package/dist/services/intercom/supervisorControlChannel.mjs.map +1 -0
  297. package/dist/services/runs/background/asyncExecution.cjs +2 -0
  298. package/dist/services/runs/background/asyncExecution.cjs.map +1 -0
  299. package/dist/services/runs/background/asyncExecution.mjs +2 -0
  300. package/dist/services/runs/background/asyncExecution.mjs.map +1 -0
  301. package/dist/services/runs/background/asyncJobTracker.cjs +1 -0
  302. package/dist/services/runs/background/asyncJobTracker.mjs +2 -0
  303. package/dist/services/runs/background/asyncJobTracker.mjs.map +1 -0
  304. package/dist/services/runs/background/cliRunnerEntry.cjs +2 -0
  305. package/dist/services/runs/background/cliRunnerEntry.cjs.map +1 -0
  306. package/dist/services/runs/background/cliRunnerEntry.mjs +2 -0
  307. package/dist/services/runs/background/cliRunnerEntry.mjs.map +1 -0
  308. package/dist/services/runs/background/completionBatcher.cjs.map +1 -0
  309. package/dist/services/runs/background/completionBatcher.mjs +2 -0
  310. package/dist/services/runs/background/completionBatcher.mjs.map +1 -0
  311. package/dist/{runs → services/runs}/background/notify.cjs +1 -1
  312. package/dist/services/runs/background/notify.cjs.map +1 -0
  313. package/dist/{runs → services/runs}/background/notify.mjs +1 -1
  314. package/dist/services/runs/background/notify.mjs.map +1 -0
  315. package/dist/services/runs/background/parentWatchdog.cjs.map +1 -0
  316. package/dist/services/runs/background/parentWatchdog.mjs.map +1 -0
  317. package/dist/services/runs/background/processTerminal.cjs +1 -0
  318. package/dist/services/runs/background/processTerminal.mjs +2 -0
  319. package/dist/services/runs/background/processTerminal.mjs.map +1 -0
  320. package/dist/services/runs/background/resultWatcher.cjs +1 -0
  321. package/dist/services/runs/background/resultWatcher.mjs +2 -0
  322. package/dist/services/runs/background/resultWatcher.mjs.map +1 -0
  323. package/dist/services/runs/background/runIdResolver.cjs +1 -0
  324. package/dist/services/runs/background/runIdResolver.mjs +2 -0
  325. package/dist/services/runs/background/runIdResolver.mjs.map +1 -0
  326. package/dist/services/runs/background/runnerBootstrap.cjs +2 -0
  327. package/dist/services/runs/background/runnerBootstrap.cjs.map +1 -0
  328. package/dist/services/runs/background/runnerBootstrap.mjs +2 -0
  329. package/dist/services/runs/background/runnerBootstrap.mjs.map +1 -0
  330. package/dist/services/runs/background/runnerExecution.cjs +2 -0
  331. package/dist/services/runs/background/runnerExecution.cjs.map +1 -0
  332. package/dist/services/runs/background/runnerExecution.mjs +2 -0
  333. package/dist/services/runs/background/runnerExecution.mjs.map +1 -0
  334. package/dist/{runs → services/runs}/background/runnerReporting.cjs +2 -2
  335. package/dist/services/runs/background/runnerReporting.cjs.map +1 -0
  336. package/dist/{runs → services/runs}/background/runnerReporting.mjs +2 -2
  337. package/dist/services/runs/background/runnerReporting.mjs.map +1 -0
  338. package/dist/services/runs/background/runnerTeamMembership.cjs +2 -0
  339. package/dist/services/runs/background/runnerTeamMembership.cjs.map +1 -0
  340. package/dist/services/runs/background/runnerTeamMembership.mjs +2 -0
  341. package/dist/services/runs/background/runnerTeamMembership.mjs.map +1 -0
  342. package/dist/services/runs/background/spawnHandshake.cjs +2 -0
  343. package/dist/services/runs/background/spawnHandshake.cjs.map +1 -0
  344. package/dist/services/runs/background/spawnHandshake.mjs +2 -0
  345. package/dist/services/runs/background/spawnHandshake.mjs.map +1 -0
  346. package/dist/services/runs/background/staleRunReconciler.cjs +1 -0
  347. package/dist/services/runs/background/staleRunReconciler.mjs +2 -0
  348. package/dist/services/runs/background/staleRunReconciler.mjs.map +1 -0
  349. package/dist/services/runs/background/statusReader.cjs +1 -0
  350. package/dist/services/runs/background/statusReader.mjs +2 -0
  351. package/dist/services/runs/background/statusReader.mjs.map +1 -0
  352. package/dist/services/runs/background/statusWriter.cjs +2 -0
  353. package/dist/services/runs/background/statusWriter.cjs.map +1 -0
  354. package/dist/services/runs/background/statusWriter.mjs +2 -0
  355. package/dist/services/runs/background/statusWriter.mjs.map +1 -0
  356. package/dist/services/runs/background/subagentWait.cjs +2 -0
  357. package/dist/services/runs/background/subagentWait.cjs.map +1 -0
  358. package/dist/services/runs/background/subagentWait.mjs +2 -0
  359. package/dist/services/runs/background/subagentWait.mjs.map +1 -0
  360. package/dist/{runs/background/terminalPersistence.mjs → services/runs/background/terminalPersistence.cjs} +2 -2
  361. package/dist/services/runs/background/terminalPersistence.cjs.map +1 -0
  362. package/dist/services/runs/background/terminalPersistence.mjs +2 -0
  363. package/dist/services/runs/background/terminalPersistence.mjs.map +1 -0
  364. package/dist/services/runs/extensionErrorTelemetry.cjs +2 -0
  365. package/dist/services/runs/extensionErrorTelemetry.cjs.map +1 -0
  366. package/dist/services/runs/extensionErrorTelemetry.mjs +2 -0
  367. package/dist/services/runs/extensionErrorTelemetry.mjs.map +1 -0
  368. package/dist/services/runs/registry/processGroup.cjs.map +1 -0
  369. package/dist/services/runs/registry/processGroup.mjs.map +1 -0
  370. package/dist/services/runs/registry/runRegistry.cjs +1 -0
  371. package/dist/services/runs/registry/runRegistry.mjs +2 -0
  372. package/dist/services/runs/registry/runRegistry.mjs.map +1 -0
  373. package/dist/services/runs/registry/sessionLifecycle.cjs +2 -0
  374. package/dist/services/runs/registry/sessionLifecycle.cjs.map +1 -0
  375. package/dist/services/runs/registry/sessionLifecycle.mjs +2 -0
  376. package/dist/services/runs/registry/sessionLifecycle.mjs.map +1 -0
  377. package/dist/services/runs/registry/suspendedRuns.cjs +1 -0
  378. package/dist/services/runs/registry/suspendedRuns.mjs +2 -0
  379. package/dist/services/runs/registry/suspendedRuns.mjs.map +1 -0
  380. package/dist/services/runs/sdkRunnerEntry.cjs +1 -0
  381. package/dist/services/runs/sdkRunnerEntry.mjs +1 -0
  382. package/dist/services/runs/shared/claudeFableProfile.cjs +4 -0
  383. package/dist/services/runs/shared/claudeFableProfile.cjs.map +1 -0
  384. package/dist/services/runs/shared/claudeFableProfile.mjs +4 -0
  385. package/dist/services/runs/shared/claudeFableProfile.mjs.map +1 -0
  386. package/dist/services/runs/shared/depthGuard.cjs +2 -0
  387. package/dist/services/runs/shared/depthGuard.cjs.map +1 -0
  388. package/dist/services/runs/shared/depthGuard.mjs +2 -0
  389. package/dist/services/runs/shared/depthGuard.mjs.map +1 -0
  390. package/dist/services/runs/shared/mcpDirectToolAllowlist.cjs +2 -0
  391. package/dist/services/runs/shared/mcpDirectToolAllowlist.cjs.map +1 -0
  392. package/dist/services/runs/shared/mcpDirectToolAllowlist.mjs +2 -0
  393. package/dist/services/runs/shared/mcpDirectToolAllowlist.mjs.map +1 -0
  394. package/dist/services/runs/shared/modelFallback.cjs +2 -0
  395. package/dist/services/runs/shared/modelFallback.cjs.map +1 -0
  396. package/dist/services/runs/shared/modelFallback.mjs +2 -0
  397. package/dist/services/runs/shared/modelFallback.mjs.map +1 -0
  398. package/dist/services/runs/shared/modelScope.cjs +2 -0
  399. package/dist/services/runs/shared/modelScope.cjs.map +1 -0
  400. package/dist/services/runs/shared/modelScope.mjs +2 -0
  401. package/dist/services/runs/shared/modelScope.mjs.map +1 -0
  402. package/dist/services/runs/shared/nestedPath.cjs +2 -0
  403. package/dist/services/runs/shared/nestedPath.cjs.map +1 -0
  404. package/dist/services/runs/shared/nestedPath.mjs +2 -0
  405. package/dist/services/runs/shared/nestedPath.mjs.map +1 -0
  406. package/dist/services/runs/shared/piArgs.cjs +2 -0
  407. package/dist/services/runs/shared/piArgs.cjs.map +1 -0
  408. package/dist/services/runs/shared/piArgs.mjs +2 -0
  409. package/dist/services/runs/shared/piArgs.mjs.map +1 -0
  410. package/dist/services/runs/shared/piSpawn.cjs +2 -0
  411. package/dist/services/runs/shared/piSpawn.cjs.map +1 -0
  412. package/dist/services/runs/shared/piSpawn.mjs +2 -0
  413. package/dist/services/runs/shared/piSpawn.mjs.map +1 -0
  414. package/dist/services/runs/shared/runWithConcurrency.cjs +2 -0
  415. package/dist/services/runs/shared/runWithConcurrency.cjs.map +1 -0
  416. package/dist/services/runs/shared/runWithConcurrency.d.cts +25 -0
  417. package/dist/services/runs/shared/runWithConcurrency.d.cts.map +1 -0
  418. package/dist/services/runs/shared/runWithConcurrency.d.mts +25 -0
  419. package/dist/services/runs/shared/runWithConcurrency.d.mts.map +1 -0
  420. package/dist/services/runs/shared/runWithConcurrency.mjs +2 -0
  421. package/dist/services/runs/shared/runWithConcurrency.mjs.map +1 -0
  422. package/dist/services/runs/shared/runtimeRegistry.cjs +2 -0
  423. package/dist/services/runs/shared/runtimeRegistry.cjs.map +1 -0
  424. package/dist/services/runs/shared/runtimeRegistry.mjs +2 -0
  425. package/dist/services/runs/shared/runtimeRegistry.mjs.map +1 -0
  426. package/dist/services/runs/shared/structuredOutput.cjs +2 -0
  427. package/dist/{runs → services/runs}/shared/structuredOutput.cjs.map +1 -1
  428. package/dist/services/runs/shared/structuredOutput.mjs +2 -0
  429. package/dist/{runs → services/runs}/shared/structuredOutput.mjs.map +1 -1
  430. package/dist/services/runs/shared/toolAvailability.cjs +2 -0
  431. package/dist/services/runs/shared/toolAvailability.cjs.map +1 -0
  432. package/dist/services/runs/shared/toolAvailability.mjs +2 -0
  433. package/dist/services/runs/shared/toolAvailability.mjs.map +1 -0
  434. package/dist/services/runs/shared/toolBudget.cjs +2 -0
  435. package/dist/services/runs/shared/toolBudget.cjs.map +1 -0
  436. package/dist/services/runs/shared/toolBudget.mjs +2 -0
  437. package/dist/services/runs/shared/toolBudget.mjs.map +1 -0
  438. package/dist/shared/artifacts.cjs.map +1 -1
  439. package/dist/shared/artifacts.mjs.map +1 -1
  440. package/dist/shared/atomicJson.cjs +1 -2
  441. package/dist/shared/atomicJson.mjs +1 -1
  442. package/dist/shared/atomicJson.mjs.map +1 -1
  443. package/dist/shared/childTranscript.cjs +1 -5
  444. package/dist/shared/childTranscript.mjs +1 -4
  445. package/dist/shared/childTranscript.mjs.map +1 -1
  446. package/dist/shared/fileSystemRetry.cjs +1 -1
  447. package/dist/shared/fileSystemRetry.cjs.map +1 -1
  448. package/dist/shared/fileSystemRetry.mjs +1 -1
  449. package/dist/shared/fileSystemRetry.mjs.map +1 -1
  450. package/dist/shared/formatters.cjs.map +1 -1
  451. package/dist/shared/formatters.mjs.map +1 -1
  452. package/dist/shared/paths.cjs +1 -1
  453. package/dist/shared/paths.cjs.map +1 -1
  454. package/dist/shared/paths.mjs +1 -1
  455. package/dist/shared/paths.mjs.map +1 -1
  456. package/dist/shared/pollScheduler.cjs +1 -2
  457. package/dist/shared/pollScheduler.mjs +1 -1
  458. package/dist/shared/pollScheduler.mjs.map +1 -1
  459. package/dist/shared/scopeOwner.cjs +1 -2
  460. package/dist/shared/scopeOwner.mjs +1 -1
  461. package/dist/shared/scopeOwner.mjs.map +1 -1
  462. package/dist/tui/agentCatalog.cjs +1 -1
  463. package/dist/tui/agentCatalog.cjs.map +1 -1
  464. package/dist/tui/agentCatalog.mjs +1 -1
  465. package/dist/tui/agentCatalog.mjs.map +1 -1
  466. package/dist/tui/agentResourceProjection.cjs +1 -1
  467. package/dist/tui/agentResourceProjection.cjs.map +1 -1
  468. package/dist/tui/agentResourceProjection.mjs +1 -1
  469. package/dist/tui/agentResourceProjection.mjs.map +1 -1
  470. package/dist/tui/completionNotice.cjs +1 -1
  471. package/dist/tui/completionNotice.cjs.map +1 -1
  472. package/dist/tui/completionNotice.mjs +1 -1
  473. package/dist/tui/completionNotice.mjs.map +1 -1
  474. package/dist/tui/fleet.cjs +2 -2
  475. package/dist/tui/fleet.cjs.map +1 -1
  476. package/dist/tui/fleet.mjs +2 -2
  477. package/dist/tui/fleet.mjs.map +1 -1
  478. package/dist/tui/fleetAgentView.cjs.map +1 -1
  479. package/dist/tui/fleetAgentView.mjs.map +1 -1
  480. package/dist/tui/fleetStatus.cjs +1 -1
  481. package/dist/tui/fleetStatus.cjs.map +1 -1
  482. package/dist/tui/fleetStatus.mjs +1 -1
  483. package/dist/tui/fleetStatus.mjs.map +1 -1
  484. package/dist/tui/fleetTranscript.cjs +1 -1
  485. package/dist/tui/fleetTranscript.cjs.map +1 -1
  486. package/dist/tui/fleetTranscript.mjs +1 -1
  487. package/dist/tui/fleetTranscript.mjs.map +1 -1
  488. package/dist/tui/register.cjs +1 -1
  489. package/dist/tui/register.cjs.map +1 -1
  490. package/dist/tui/register.mjs +1 -1
  491. package/dist/tui/register.mjs.map +1 -1
  492. package/dist/tui/subagentToolRender.cjs +3 -0
  493. package/dist/tui/subagentToolRender.cjs.map +1 -0
  494. package/dist/tui/subagentToolRender.mjs +3 -0
  495. package/dist/tui/subagentToolRender.mjs.map +1 -0
  496. package/dist/{types.d.cts → types/index.d.cts} +2 -2
  497. package/dist/types/index.d.cts.map +1 -0
  498. package/dist/{types.d.mts → types/index.d.mts} +2 -2
  499. package/dist/types/index.d.mts.map +1 -0
  500. package/package.json +23 -16
  501. package/dist/agents/discovery.cjs +0 -2
  502. package/dist/agents/discovery.cjs.map +0 -1
  503. package/dist/agents/discovery.mjs +0 -2
  504. package/dist/agents/discovery.mjs.map +0 -1
  505. package/dist/agents/frontmatter.cjs.map +0 -1
  506. package/dist/agents/frontmatter.mjs.map +0 -1
  507. package/dist/agents/loader.cjs +0 -2
  508. package/dist/agents/loader.cjs.map +0 -1
  509. package/dist/agents/loader.mjs +0 -2
  510. package/dist/agents/loader.mjs.map +0 -1
  511. package/dist/agents/memory.cjs +0 -3
  512. package/dist/agents/memory.cjs.map +0 -1
  513. package/dist/agents/memory.mjs.map +0 -1
  514. package/dist/agents/projectRoot.cjs +0 -2
  515. package/dist/agents/projectRoot.cjs.map +0 -1
  516. package/dist/agents/projectRoot.mjs +0 -2
  517. package/dist/agents/projectRoot.mjs.map +0 -1
  518. package/dist/agents/settings.cjs +0 -2
  519. package/dist/agents/settings.cjs.map +0 -1
  520. package/dist/agents/settings.mjs +0 -2
  521. package/dist/agents/settings.mjs.map +0 -1
  522. package/dist/agents/skills.cjs +0 -0
  523. package/dist/agents/skills.cjs.map +0 -1
  524. package/dist/agents/skills.mjs +0 -5
  525. package/dist/agents/skills.mjs.map +0 -1
  526. package/dist/agents/types.d.cts.map +0 -1
  527. package/dist/agents/types.d.mts.map +0 -1
  528. package/dist/api/capabilityCeiling.mjs.map +0 -1
  529. package/dist/api/teamSnapshot.mjs.map +0 -1
  530. package/dist/env.cjs.map +0 -1
  531. package/dist/env.d.cts.map +0 -1
  532. package/dist/env.d.mts.map +0 -1
  533. package/dist/extension.cjs +0 -2
  534. package/dist/extension.cjs.map +0 -1
  535. package/dist/extension.mjs +0 -2
  536. package/dist/extension.mjs.map +0 -1
  537. package/dist/intercom/intercomBridge.cjs.map +0 -1
  538. package/dist/intercom/intercomBridge.mjs.map +0 -1
  539. package/dist/intercom/nativeTeamChannel.cjs +0 -5
  540. package/dist/intercom/nativeTeamChannel.cjs.map +0 -1
  541. package/dist/intercom/nativeTeamChannel.d.cts.map +0 -1
  542. package/dist/intercom/nativeTeamChannel.d.mts.map +0 -1
  543. package/dist/intercom/nativeTeamChannel.mjs +0 -5
  544. package/dist/intercom/nativeTeamChannel.mjs.map +0 -1
  545. package/dist/intercom/supervisorControlChannel.cjs +0 -2
  546. package/dist/intercom/supervisorControlChannel.cjs.map +0 -1
  547. package/dist/intercom/supervisorControlChannel.mjs.map +0 -1
  548. package/dist/protocol/backgroundWork.cjs +0 -2
  549. package/dist/protocol/backgroundWork.d.cts.map +0 -1
  550. package/dist/protocol/backgroundWork.d.mts.map +0 -1
  551. package/dist/protocol/backgroundWork.mjs +0 -2
  552. package/dist/protocol/backgroundWork.mjs.map +0 -1
  553. package/dist/protocol/capabilityCeiling.cjs +0 -2
  554. package/dist/protocol/capabilityCeiling.cjs.map +0 -1
  555. package/dist/protocol/capabilityCeiling.d.cts.map +0 -1
  556. package/dist/protocol/capabilityCeiling.d.mts.map +0 -1
  557. package/dist/protocol/capabilityCeiling.mjs +0 -2
  558. package/dist/protocol/capabilityCeiling.mjs.map +0 -1
  559. package/dist/protocol/delegation.cjs.map +0 -1
  560. package/dist/protocol/delegation.d.cts.map +0 -1
  561. package/dist/protocol/delegation.d.mts.map +0 -1
  562. package/dist/protocol/delegation.mjs.map +0 -1
  563. package/dist/runs/background/asyncExecution.cjs +0 -2
  564. package/dist/runs/background/asyncExecution.cjs.map +0 -1
  565. package/dist/runs/background/asyncExecution.mjs +0 -2
  566. package/dist/runs/background/asyncExecution.mjs.map +0 -1
  567. package/dist/runs/background/asyncJobTracker.cjs +0 -2
  568. package/dist/runs/background/asyncJobTracker.cjs.map +0 -1
  569. package/dist/runs/background/asyncJobTracker.mjs +0 -2
  570. package/dist/runs/background/asyncJobTracker.mjs.map +0 -1
  571. package/dist/runs/background/cliRunnerEntry.cjs.map +0 -1
  572. package/dist/runs/background/cliRunnerEntry.mjs.map +0 -1
  573. package/dist/runs/background/completionBatcher.cjs.map +0 -1
  574. package/dist/runs/background/completionBatcher.mjs +0 -2
  575. package/dist/runs/background/completionBatcher.mjs.map +0 -1
  576. package/dist/runs/background/notify.cjs.map +0 -1
  577. package/dist/runs/background/notify.mjs.map +0 -1
  578. package/dist/runs/background/parentWatchdog.cjs.map +0 -1
  579. package/dist/runs/background/parentWatchdog.mjs.map +0 -1
  580. package/dist/runs/background/processTerminal.cjs +0 -2
  581. package/dist/runs/background/processTerminal.cjs.map +0 -1
  582. package/dist/runs/background/processTerminal.mjs +0 -2
  583. package/dist/runs/background/processTerminal.mjs.map +0 -1
  584. package/dist/runs/background/resultWatcher.cjs +0 -2
  585. package/dist/runs/background/resultWatcher.cjs.map +0 -1
  586. package/dist/runs/background/resultWatcher.mjs +0 -2
  587. package/dist/runs/background/resultWatcher.mjs.map +0 -1
  588. package/dist/runs/background/runIdResolver.cjs +0 -2
  589. package/dist/runs/background/runIdResolver.cjs.map +0 -1
  590. package/dist/runs/background/runIdResolver.mjs +0 -2
  591. package/dist/runs/background/runIdResolver.mjs.map +0 -1
  592. package/dist/runs/background/runnerBootstrap.cjs +0 -2
  593. package/dist/runs/background/runnerBootstrap.cjs.map +0 -1
  594. package/dist/runs/background/runnerBootstrap.mjs +0 -2
  595. package/dist/runs/background/runnerBootstrap.mjs.map +0 -1
  596. package/dist/runs/background/runnerExecution.cjs +0 -2
  597. package/dist/runs/background/runnerExecution.cjs.map +0 -1
  598. package/dist/runs/background/runnerExecution.mjs +0 -2
  599. package/dist/runs/background/runnerExecution.mjs.map +0 -1
  600. package/dist/runs/background/runnerReporting.cjs.map +0 -1
  601. package/dist/runs/background/runnerReporting.mjs.map +0 -1
  602. package/dist/runs/background/runnerTeamMembership.cjs +0 -2
  603. package/dist/runs/background/runnerTeamMembership.cjs.map +0 -1
  604. package/dist/runs/background/runnerTeamMembership.mjs +0 -2
  605. package/dist/runs/background/runnerTeamMembership.mjs.map +0 -1
  606. package/dist/runs/background/spawnHandshake.cjs +0 -2
  607. package/dist/runs/background/spawnHandshake.cjs.map +0 -1
  608. package/dist/runs/background/spawnHandshake.mjs +0 -2
  609. package/dist/runs/background/spawnHandshake.mjs.map +0 -1
  610. package/dist/runs/background/staleRunReconciler.cjs +0 -2
  611. package/dist/runs/background/staleRunReconciler.cjs.map +0 -1
  612. package/dist/runs/background/staleRunReconciler.mjs +0 -2
  613. package/dist/runs/background/staleRunReconciler.mjs.map +0 -1
  614. package/dist/runs/background/statusReader.cjs +0 -2
  615. package/dist/runs/background/statusReader.cjs.map +0 -1
  616. package/dist/runs/background/statusReader.mjs +0 -2
  617. package/dist/runs/background/statusReader.mjs.map +0 -1
  618. package/dist/runs/background/statusWriter.cjs +0 -2
  619. package/dist/runs/background/statusWriter.cjs.map +0 -1
  620. package/dist/runs/background/statusWriter.mjs +0 -2
  621. package/dist/runs/background/statusWriter.mjs.map +0 -1
  622. package/dist/runs/background/subagentWait.cjs +0 -2
  623. package/dist/runs/background/subagentWait.cjs.map +0 -1
  624. package/dist/runs/background/subagentWait.mjs +0 -2
  625. package/dist/runs/background/subagentWait.mjs.map +0 -1
  626. package/dist/runs/background/terminalPersistence.cjs +0 -2
  627. package/dist/runs/background/terminalPersistence.cjs.map +0 -1
  628. package/dist/runs/background/terminalPersistence.mjs.map +0 -1
  629. package/dist/runs/registry/processGroup.cjs.map +0 -1
  630. package/dist/runs/registry/processGroup.mjs.map +0 -1
  631. package/dist/runs/registry/runRegistry.cjs +0 -2
  632. package/dist/runs/registry/runRegistry.cjs.map +0 -1
  633. package/dist/runs/registry/runRegistry.mjs +0 -2
  634. package/dist/runs/registry/runRegistry.mjs.map +0 -1
  635. package/dist/runs/registry/sessionLifecycle.cjs +0 -2
  636. package/dist/runs/registry/sessionLifecycle.cjs.map +0 -1
  637. package/dist/runs/registry/sessionLifecycle.mjs +0 -2
  638. package/dist/runs/registry/sessionLifecycle.mjs.map +0 -1
  639. package/dist/runs/registry/suspendedRuns.cjs +0 -4
  640. package/dist/runs/registry/suspendedRuns.cjs.map +0 -1
  641. package/dist/runs/registry/suspendedRuns.mjs +0 -4
  642. package/dist/runs/registry/suspendedRuns.mjs.map +0 -1
  643. package/dist/runs/sdkRunnerEntry.cjs.map +0 -1
  644. package/dist/runs/sdkRunnerEntry.mjs.map +0 -1
  645. package/dist/runs/shared/claudeFableProfile.cjs +0 -4
  646. package/dist/runs/shared/claudeFableProfile.cjs.map +0 -1
  647. package/dist/runs/shared/claudeFableProfile.mjs +0 -4
  648. package/dist/runs/shared/claudeFableProfile.mjs.map +0 -1
  649. package/dist/runs/shared/depthGuard.cjs +0 -2
  650. package/dist/runs/shared/depthGuard.cjs.map +0 -1
  651. package/dist/runs/shared/depthGuard.mjs +0 -2
  652. package/dist/runs/shared/depthGuard.mjs.map +0 -1
  653. package/dist/runs/shared/mcpDirectToolAllowlist.cjs +0 -2
  654. package/dist/runs/shared/mcpDirectToolAllowlist.cjs.map +0 -1
  655. package/dist/runs/shared/mcpDirectToolAllowlist.mjs +0 -2
  656. package/dist/runs/shared/mcpDirectToolAllowlist.mjs.map +0 -1
  657. package/dist/runs/shared/modelFallback.cjs +0 -2
  658. package/dist/runs/shared/modelFallback.cjs.map +0 -1
  659. package/dist/runs/shared/modelFallback.mjs +0 -2
  660. package/dist/runs/shared/modelFallback.mjs.map +0 -1
  661. package/dist/runs/shared/modelScope.cjs +0 -2
  662. package/dist/runs/shared/modelScope.cjs.map +0 -1
  663. package/dist/runs/shared/modelScope.mjs +0 -2
  664. package/dist/runs/shared/modelScope.mjs.map +0 -1
  665. package/dist/runs/shared/nestedPath.cjs +0 -2
  666. package/dist/runs/shared/nestedPath.cjs.map +0 -1
  667. package/dist/runs/shared/nestedPath.mjs +0 -2
  668. package/dist/runs/shared/nestedPath.mjs.map +0 -1
  669. package/dist/runs/shared/piArgs.cjs +0 -2
  670. package/dist/runs/shared/piArgs.cjs.map +0 -1
  671. package/dist/runs/shared/piArgs.mjs +0 -2
  672. package/dist/runs/shared/piArgs.mjs.map +0 -1
  673. package/dist/runs/shared/piSpawn.cjs +0 -2
  674. package/dist/runs/shared/piSpawn.cjs.map +0 -1
  675. package/dist/runs/shared/piSpawn.mjs +0 -2
  676. package/dist/runs/shared/piSpawn.mjs.map +0 -1
  677. package/dist/runs/shared/runWithConcurrency.cjs +0 -2
  678. package/dist/runs/shared/runWithConcurrency.cjs.map +0 -1
  679. package/dist/runs/shared/runWithConcurrency.mjs +0 -2
  680. package/dist/runs/shared/runWithConcurrency.mjs.map +0 -1
  681. package/dist/runs/shared/runtimeRegistry.cjs +0 -2
  682. package/dist/runs/shared/runtimeRegistry.cjs.map +0 -1
  683. package/dist/runs/shared/runtimeRegistry.mjs +0 -2
  684. package/dist/runs/shared/runtimeRegistry.mjs.map +0 -1
  685. package/dist/runs/shared/structuredOutput.cjs +0 -2
  686. package/dist/runs/shared/structuredOutput.mjs +0 -2
  687. package/dist/runs/shared/toolAvailability.cjs +0 -2
  688. package/dist/runs/shared/toolAvailability.cjs.map +0 -1
  689. package/dist/runs/shared/toolAvailability.mjs +0 -2
  690. package/dist/runs/shared/toolAvailability.mjs.map +0 -1
  691. package/dist/runs/shared/toolBudget.cjs +0 -2
  692. package/dist/runs/shared/toolBudget.cjs.map +0 -1
  693. package/dist/runs/shared/toolBudget.mjs +0 -2
  694. package/dist/runs/shared/toolBudget.mjs.map +0 -1
  695. package/dist/shared/atomicJson.cjs.map +0 -1
  696. package/dist/shared/childTranscript.cjs.map +0 -1
  697. package/dist/shared/pollScheduler.cjs.map +0 -1
  698. package/dist/shared/scopeOwner.cjs.map +0 -1
  699. package/dist/slash/chainExpression.cjs.map +0 -1
  700. package/dist/slash/chainExpression.mjs.map +0 -1
  701. package/dist/slash/doctor.cjs +0 -5
  702. package/dist/slash/doctor.mjs +0 -5
  703. package/dist/slash/doctor.mjs.map +0 -1
  704. package/dist/slash/slashCommands.cjs.map +0 -1
  705. package/dist/slash/slashCommands.mjs.map +0 -1
  706. package/dist/slash/spawnRequestMapping.cjs.map +0 -1
  707. package/dist/slash/spawnRequestMapping.mjs.map +0 -1
  708. package/dist/slash/subagentLaunch.cjs +0 -2
  709. package/dist/slash/subagentLaunch.cjs.map +0 -1
  710. package/dist/slash/subagentLaunch.mjs +0 -2
  711. package/dist/slash/subagentLaunch.mjs.map +0 -1
  712. package/dist/types.d.cts.map +0 -1
  713. package/dist/types.d.mts.map +0 -1
  714. /package/dist/{slash → commands/slash}/chainExpression.cjs +0 -0
  715. /package/dist/{slash → commands/slash}/chainExpression.mjs +0 -0
  716. /package/dist/{slash → commands/slash}/spawnRequestMapping.cjs +0 -0
  717. /package/dist/{slash → commands/slash}/spawnRequestMapping.mjs +0 -0
  718. /package/dist/{protocol → schemas/team}/delegation.cjs +0 -0
  719. /package/dist/{protocol → schemas/team}/delegation.mjs +0 -0
  720. /package/dist/{agents → services/agents}/frontmatter.cjs +0 -0
  721. /package/dist/{intercom → services/intercom}/intercomBridge.cjs +0 -0
  722. /package/dist/{intercom → services/intercom}/intercomBridge.mjs +0 -0
  723. /package/dist/{runs → services/runs}/background/completionBatcher.cjs +0 -0
  724. /package/dist/{runs → services/runs}/background/parentWatchdog.cjs +0 -0
  725. /package/dist/{runs → services/runs}/background/parentWatchdog.mjs +0 -0
  726. /package/dist/{runs → services/runs}/registry/processGroup.cjs +0 -0
  727. /package/dist/{runs → services/runs}/registry/processGroup.mjs +0 -0
package/README.md CHANGED
@@ -1,13 +1,18 @@
1
1
  # @agimon-ai/doompi-team
2
2
 
3
- Async-only subagent team runtime for Pi: named agents, peer messaging, shared task board.
3
+ **Subagents should leave a paper trail.**
4
4
 
5
- Named subagents that run asynchronously against a shared task board, sequentially or in
6
- parallel, with peer messaging and a model policy per layer.
5
+ This is Doompi's async-only team runtime: named agents, background runs, peer messaging,
6
+ and one task board shared with the parent. Agents can work in parallel and use the model
7
+ policy owned by the selected Team package entry without turning the main conversation
8
+ into a wall of child transcripts.
7
9
 
8
- Part of [Doompi](https://www.npmjs.com/package/@agimon-ai/doompi), a coding agent that loads
9
- only the skills and tools you name. This package is composed by Doompi and is not usually
10
- installed on its own.
10
+ Runs are detached from an environment snapshot and may outlive the parent that launched
11
+ them. Each child gets its own resolved harness state, so recovery does not depend on the
12
+ parent still being around to explain itself.
13
+
14
+ This is part of [Doompi](https://www.npmjs.com/package/@agimon-ai/doompi). Most users load
15
+ it through a major-mode layer.
11
16
 
12
17
  ## Install
13
18
 
@@ -17,29 +22,40 @@ npm install @agimon-ai/doompi-team
17
22
 
18
23
  ## How it loads
19
24
 
20
- Name it in a layer in `.doom/modes.yaml`, then add that layer to a major mode:
25
+ Put the package in a layer, then add that layer to a major mode. When Team needs
26
+ configuration, use the package-object form so the options stay with their owner:
21
27
 
22
28
  ```yaml
23
29
  layers:
24
30
  team:
25
- packages: ['@agimon-ai/doompi-team/extensions/doom']
31
+ packages:
32
+ - name: '@agimon-ai/doompi-team'
33
+ config:
34
+ models:
35
+ - model: openai-codex/gpt-5.6-luna
36
+ thinking: xhigh
37
+ excludeTools: [ask_user_question, intercom, subagent]
26
38
 
27
39
  majorMode:
28
- dev: [team]
40
+ dev:
41
+ description: Development mode with delegated Team agents.
42
+ layers: [team]
29
43
  ```
30
44
 
31
- ## Leader
32
-
33
- `SPC a` opens the subagent fleet, once the extension is loaded.
45
+ Use the shorter string form when no Team configuration is needed. The package's Pi
46
+ manifest selects the Doom adapter. Later selected Team entries replace `models`; their
47
+ `excludeTools` values are unioned in layer order. A sibling `layer.config` block is
48
+ invalid because it cannot say which package owns the options.
34
49
 
35
- ## Notes
50
+ ## Leader
36
51
 
37
- Subagents run detached from an environment snapshot and can outlive the parent that spawned
38
- them, so each one gets a harness state file of its own.
52
+ - `SPC a l` lists the agents available to this session.
53
+ - `SPC a r` opens current-session runs and their controls.
39
54
 
40
- ## Entry points
55
+ ## Public API
41
56
 
42
- 8 subpaths are declared in the `exports` field of `package.json`.
57
+ The root export contains the team runtime. Supported subpaths expose agent discovery,
58
+ background-run services, and the Doom adapter; `package.json` carries the complete list.
43
59
 
44
60
  ## License
45
61
 
@@ -0,0 +1,2 @@
1
+ const e=require(`../_virtual/_rolldown/runtime.cjs`),t=require(`../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorate.cjs`),n=require(`../container/types.cjs`),r=require(`../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateMetadata.cjs`),i=require(`../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateParam.cjs`),a=require(`../shared/paths.cjs`),o=require(`../services/runs/background/statusWriter.cjs`),s=require(`./statusReader.cjs`);require(`../services/runs/background/statusReader.cjs`);let c=require(`node:fs`);c=e.__toESM(c,1);let l=require(`node:path`);l=e.__toESM(l,1);let u=require(`inversify`);const d=new Set([`complete`,`completed`,`failed`,`paused`,`stopped`]);function f(e,t){let n=e.list().map(e=>e.runId).filter(e=>e===t||e.startsWith(t)),r=n.find(e=>e===t);if(r)return r;if(n.length===1)return n[0];throw n.length===0?Error(`No current-session run found for '${t}'.`):Error(`Multiple current-session runs match '${t}'. Use a longer id.`)}const p=`__unscoped__`;function m(e){return l.join(a.currentRunsDir(),e,o.STATUS_FILE_NAME)}function h(e){return typeof e==`object`&&e&&`code`in e?e.code:void 0}function g(e){return h(e)===`ENOENT`}const _=new Set([`starting`,`working`,`tool`,`waiting_for_reply`,`needs_attention`,`finalizing`,`active_long_running`]);function v(e){return typeof e==`string`&&_.has(e)?e:void 0}let y=class{constructor(e){this.scheduler=e}pollIntervalMs=250;retentionMs=1e4;now(){return Date.now()}readFile(e){try{return c.readFileSync(e,`utf-8`)}catch(e){if(g(e))return;throw e}}async readFileAsync(e){try{return await c.promises.readFile(e,`utf-8`)}catch(e){if(g(e))return;throw e}}sessions=new Map;unregisterPoll;session(e){let t=this.sessions.get(e);return t||(t={jobs:new Map,terminalAt:new Map},this.sessions.set(e,t)),t}forSession(e){if(!e.trim())throw Error(`Pi session identity is required to track subagent runs.`);return{track:t=>this.trackInSession(e,t),untrack:t=>this.untrackInSession(e,t),list:()=>this.listInSession(e),get:t=>this.getInSession(e,t),reset:()=>this.resetSession(e)}}parseStatus(e,t){if(t===void 0)return;let n=s.parseAsyncRunStatus(t,m(e));if(n.kind!==`ok`)return;let r=n.status;return{agent:r.agent,status:r.state,startedAt:r.startedAt,updatedAt:r.lastUpdate,error:r.error,activityState:v(r.activityState),attentionReason:r.attentionReason,runtime:r.runtime,tokens:r.tokens,currentTool:r.currentTool,toolCount:r.toolCount}}readStatus(e){return this.parseStatus(e,this.readFile(m(e)))}async readStatusAsync(e){return this.parseStatus(e,await this.readFileAsync(m(e)))}applyStatus(e,t,n){let r=this.session(e),i=r.jobs.get(t);if(n===void 0)return i||r.jobs.set(t,{runId:t,status:void 0}),!1;let a={runId:t,...n};r.jobs.set(t,a);let o=i?.status!==void 0&&d.has(i.status),s=a.status!==void 0&&d.has(a.status);return s&&!o&&r.terminalAt.set(t,this.now()),s||r.terminalAt.delete(t),!i||i.status!==a.status||i.updatedAt!==a.updatedAt||i.tokens!==a.tokens||i.currentTool!==a.currentTool||i.toolCount!==a.toolCount}refresh(e,t){return this.applyStatus(e,t,this.readStatus(t))}async refreshAsync(e,t){return this.applyStatus(e,t,await this.readStatusAsync(t))}async run(){let e=!1,t=this.now();for(let[n,r]of this.sessions){for(let t of r.jobs.keys())await this.refreshAsync(n,t)&&(e=!0);for(let[n,i]of r.terminalAt)t-i<=this.retentionMs||(r.jobs.delete(n),r.terminalAt.delete(n),e=!0);r.jobs.size===0&&this.sessions.delete(n)}return e}track(e){this.trackInSession(p,e)}untrack(e){this.untrackInSession(p,e)}list(){return this.listInSession(p)}get(e){return this.getInSession(p,e)}reset(){this.resetSession(p)}trackInSession(e,t){this.refresh(e,t)}untrackInSession(e,t){let n=this.sessions.get(e);n?.jobs.delete(t),n?.terminalAt.delete(t),n?.jobs.size===0&&this.sessions.delete(e)}listInSession(e){return[...this.sessions.get(e)?.jobs.values()??[]]}getInSession(e,t){return this.sessions.get(e)?.jobs.get(t)}resetSession(e){this.sessions.delete(e)}start(){this.stop(),this.unregisterPoll=this.scheduler.register({id:`async-job-tracker`,intervalMs:this.pollIntervalMs,run:()=>this.run()})}stop(){this.unregisterPoll?.(),this.unregisterPoll=void 0,this.sessions.clear()}};y=t.__decorate([(0,u.injectable)(),i.__decorateParam(0,(0,u.inject)(n.DOOM_TEAM_TYPES.PollScheduler)),r.__decorateMetadata(`design:paramtypes`,[Object])],y),Object.defineProperty(exports,`AsyncJobTracker`,{enumerable:!0,get:function(){return y}}),exports.TERMINAL_ASYNC_JOB_STATES=d,exports.resolveTrackedRunId=f;
2
+ //# sourceMappingURL=asyncJobTracker.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asyncJobTracker.cjs","names":["path","currentRunsDir","STATUS_FILE_NAME","fs","parseAsyncRunStatus","DOOM_TEAM_TYPES"],"sources":["../../src/adapters/asyncJobTracker.ts"],"sourcesContent":["/**\n * Live, in-memory registry of the async runs this session currently cares\n * about, refreshed from `status.json` on a `PollScheduler` tick.\n *\n * WHY THIS IS SMALLER THAN THE PREDECESSOR:\n * `doom-pi-subagents/src/runs/background/asyncJobTracker.ts` is 590 lines\n * doing four different jobs: this registry, TUI widget rendering\n * (`renderWidget`/`widgetRenderKey`/`ctx.ui.requestRender`), forwarding\n * control events and steering notices by byte-range-tailing each run's\n * `events.jsonl`, and projecting nested/parallel-group run trees. Only the\n * registry is ported. The other three have no consumer in this package yet:\n * TUI rendering is `G8` (slash commands + TUI), and nested/chain/parallel run\n * modes are `G7`+ (this package is currently single-run async-only - see\n * `spawnHandshake.ts`'s header). Porting rendering or event-tailing logic\n * with nothing to render to or forward to would be untested, unreachable\n * code; it is deferred to whichever later port actually needs it, not\n * dropped silently - this note is where to look for it.\n *\n * DESIGN PATTERNS:\n * - The in-memory map is a pure CACHE, never authoritative on its own:\n * `status.json` (owned by `CoalescedStatusWriter` elsewhere) is the only\n * source of truth. `track()` reads it synchronously immediately, so a\n * caller that already knows a run's id sees *something* right away rather\n * than waiting out the first poll\n * - Restart survivability follows from the point above rather than a second\n * persistence layer: this package has not built session-scoped run\n * ownership yet (which ids \"belong\" to a restarted session is not\n * something this module can determine on its own - see the AVOID entry),\n * so recovery is the caller re-`track()`-ing whatever ids it still cares\n * about from ITS OWN durable record. The very next poll tick repopulates\n * that job's status straight from disk. There is no separate store to keep\n * in sync, and therefore no window where memory could diverge from disk\n * that a restart would not immediately close\n * - Registered with `PollScheduler`, not a private timer: this polls\n * potentially many jobs' status files on an unbounded, periodic cadence\n * with no low-latency requirement - the exact shape `PollScheduler` exists\n * for. Contrast `completionBatcher.ts`/`spawnHandshake.ts`, which own\n * their own timers because they are short-lived, single-shot, and need\n * sub-200ms responsiveness `PollScheduler`'s floor cannot give them; this\n * registry needs neither\n * - Retention-then-eviction happens on the SAME poll tick as the status\n * refresh, rather than the predecessor's per-job `setTimeout`\n * (`scheduleCleanup`): a terminal job aged past `retentionMs` is simply\n * dropped the next time `run()` walks the map. One clock, not one timer per\n * job\n *\n * AVOID:\n * - Scanning `currentRunsDir()` to guess which run ids \"belong\" to this session on\n * startup. This package has no session-scoped run ownership concept yet;\n * inventing one here to answer \"what should I restore\" would be a guess,\n * not a fact this module has standing to assert. Restoration is the\n * caller's job (see the design note above)\n * - Growing `terminalStates` independently of `staleRunReconciler.ts`'s own\n * (unexported) copy; both must treat the same state strings as terminal,\n * or a job could be evicted here while the reconciler still thinks it is\n * in flight, or vice versa\n *\n * `activityState`/`attentionReason` (added for `subagentWait.ts`):\n * `DeliverableGuard.evaluate()` computes `activityState: 'needs_attention'`\n * and a `reason` (e.g. `'missing-deliverable'`), but returns it rather than\n * writing it anywhere - it has no standing to touch `status.json` itself (see\n * that module's header). Something upstream of this tracker - the run's own\n * runner main loop, not yet built - is responsible for folding that result\n * into `status.json` through `CoalescedStatusWriter`. This tracker's job is\n * only to read whatever ends up there, the same as every other field: it does\n * not compute attention, detect it, or decide when a run needs it.\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { inject, injectable } from 'inversify';\nimport { DOOM_TEAM_TYPES } from '../container/types.ts';\nimport { parseAsyncRunStatus } from '../services/runs/background/statusReader.ts';\nimport { STATUS_FILE_NAME } from '../services/runs/background/statusWriter.ts';\nimport { currentRunsDir } from '../shared/paths.ts';\nimport type { IPollScheduler } from '../shared/pollScheduler.ts';\nimport type { ActivityState } from '../types/index.ts';\n\n/**\n * States that mean \"already finished\"; matches `staleRunReconciler.ts`'s\n * own (unexported) set. Exported so a caller outside this module (the slash\n * layer's poll-until-terminal helper) can recognize the same terminal set\n * `TrackedAsyncJob.status` uses, rather than declaring a third copy of this\n * literal.\n */\nexport const TERMINAL_ASYNC_JOB_STATES = new Set(['complete', 'completed', 'failed', 'paused', 'stopped']);\n\n/** How long a terminal job stays queryable before eviction. */\nconst DEFAULT_RETENTION_MS = 10_000;\n/** How often tracked jobs' status is refreshed from disk. */\nconst DEFAULT_POLL_INTERVAL_MS = 250;\n\nconst POLL_SUBSCRIBER_ID = 'async-job-tracker';\n\n/**\n * The minimum shape this module reads. A run's actual `status.json` carries\n * far more (this package has no shared status type yet - see\n * `staleRunReconciler.ts`'s `ReconcilableStatus` for the same caveat);\n * everything else is simply not read here.\n */\nexport interface TrackedAsyncJob {\n runId: string;\n /** Named agent executing this run. Absent until the first readable status. */\n agent?: string;\n /** `status.json`'s `state` field. `undefined` until the first successful read. */\n status: string | undefined;\n startedAt?: number;\n updatedAt?: number;\n error?: string;\n /** `status.json`'s `activityState` field, e.g. `'needs_attention'`. See the module doc. */\n activityState?: ActivityState;\n /** `status.json`'s `reason` field, present alongside `activityState` (e.g. `'missing-deliverable'`). */\n attentionReason?: string;\n /** Which runtime is executing this run. Absent means the default `pi` path. */\n runtime?: string;\n tokens?: number;\n currentTool?: string;\n toolCount?: number;\n}\n\nexport interface ITrackedAsyncJobs {\n /**\n * Start tracking `runId`: reads its current status synchronously (so a\n * caller sees something immediately) and adds it to the poll rotation.\n * Calling this again for an id already tracked simply re-reads it now,\n * the same idempotent-refresh idiom as `CoalescedStatusWriter.open()`.\n */\n track(runId: string): void;\n /** Stop tracking `runId` immediately, without waiting out its retention window. */\n untrack(runId: string): void;\n /** Every currently tracked job (in-flight, or terminal within its retention window). */\n list(): TrackedAsyncJob[];\n get(runId: string): TrackedAsyncJob | undefined;\n /** Drop every tracked job. */\n reset(): void;\n}\n\nexport interface IAsyncJobTracker extends ITrackedAsyncJobs {\n /** Return the isolated run collection owned by one Pi session context. */\n forSession(sessionId: string): ITrackedAsyncJobs;\n /** Register with `PollScheduler`. Call once; a second call is a reset, same as `ResultWatcher.start()`. */\n start(): void;\n /** Unregister from `PollScheduler` and drop every tracked job. */\n stop(): void;\n}\n\n/** Resolve an exact id or unique prefix only inside one Pi session's run collection. */\nexport function resolveTrackedRunId(jobs: ITrackedAsyncJobs, id: string): string {\n const matches = jobs\n .list()\n .map((job) => job.runId)\n .filter((runId) => runId === id || runId.startsWith(id));\n const exact = matches.find((runId) => runId === id);\n if (exact) return exact;\n if (matches.length === 1) return matches[0]!;\n if (matches.length === 0) throw new Error(`No current-session run found for '${id}'.`);\n throw new Error(`Multiple current-session runs match '${id}'. Use a longer id.`);\n}\n\ninterface SessionJobs {\n jobs: Map<string, TrackedAsyncJob>;\n terminalAt: Map<string, number>;\n}\n\nconst UNSCOPED_SESSION = '__unscoped__';\n\nfunction statusPathFor(runId: string): string {\n return path.join(currentRunsDir(), runId, STATUS_FILE_NAME);\n}\n\nfunction errorCode(error: unknown): string | undefined {\n return typeof error === 'object' && error !== null && 'code' in error\n ? (error as NodeJS.ErrnoException).code\n : undefined;\n}\n\nfunction isNotFound(error: unknown): boolean {\n return errorCode(error) === 'ENOENT';\n}\n\ninterface ReadStatusResult {\n agent: string;\n status: string | undefined;\n startedAt?: number;\n updatedAt?: number;\n error?: string;\n activityState?: ActivityState;\n attentionReason?: string;\n runtime?: string;\n tokens?: number;\n currentTool?: string;\n toolCount?: number;\n}\n\nconst VALID_ACTIVITY_STATES: ReadonlySet<string> = new Set<ActivityState>([\n 'starting',\n 'working',\n 'tool',\n 'waiting_for_reply',\n 'needs_attention',\n 'finalizing',\n 'active_long_running',\n]);\n\nfunction asActivityState(value: unknown): ActivityState | undefined {\n return typeof value === 'string' && VALID_ACTIVITY_STATES.has(value) ? (value as ActivityState) : undefined;\n}\n\n@injectable()\nexport class AsyncJobTracker implements IAsyncJobTracker {\n constructor(@inject(DOOM_TEAM_TYPES.PollScheduler) private readonly scheduler: IPollScheduler) {}\n\n /**\n * Seams for tests, as protected members rather than constructor arguments:\n * inversify cannot resolve a primitive. See `pollScheduler.ts` and\n * `agents/discovery.ts` for the same pattern.\n */\n protected readonly pollIntervalMs: number = DEFAULT_POLL_INTERVAL_MS;\n protected readonly retentionMs: number = DEFAULT_RETENTION_MS;\n\n protected now(): number {\n return Date.now();\n }\n\n protected readFile(filePath: string): string | undefined {\n try {\n return fs.readFileSync(filePath, 'utf-8');\n } catch (error) {\n if (isNotFound(error)) return undefined;\n throw error;\n }\n }\n\n protected async readFileAsync(filePath: string): Promise<string | undefined> {\n try {\n return await fs.promises.readFile(filePath, 'utf-8');\n } catch (error) {\n if (isNotFound(error)) return undefined;\n throw error;\n }\n }\n\n private readonly sessions = new Map<string, SessionJobs>();\n private unregisterPoll: (() => void) | undefined;\n\n private session(sessionId: string): SessionJobs {\n let session = this.sessions.get(sessionId);\n if (!session) {\n session = { jobs: new Map(), terminalAt: new Map() };\n this.sessions.set(sessionId, session);\n }\n return session;\n }\n\n forSession(sessionId: string): ITrackedAsyncJobs {\n if (!sessionId.trim()) throw new Error('Pi session identity is required to track subagent runs.');\n return {\n track: (runId) => this.trackInSession(sessionId, runId),\n untrack: (runId) => this.untrackInSession(sessionId, runId),\n list: () => this.listInSession(sessionId),\n get: (runId) => this.getInSession(sessionId, runId),\n reset: () => this.resetSession(sessionId),\n };\n }\n\n private parseStatus(runId: string, raw: string | undefined): ReadStatusResult | undefined {\n if (raw === undefined) return undefined;\n const result = parseAsyncRunStatus(raw, statusPathFor(runId));\n if (result.kind !== 'ok') return undefined;\n const status = result.status;\n return {\n agent: status.agent,\n status: status.state,\n startedAt: status.startedAt,\n updatedAt: status.lastUpdate,\n error: status.error,\n activityState: asActivityState(status.activityState),\n attentionReason: status.attentionReason,\n runtime: status.runtime,\n tokens: status.tokens,\n currentTool: status.currentTool,\n toolCount: status.toolCount,\n };\n }\n\n private readStatus(runId: string): ReadStatusResult | undefined {\n return this.parseStatus(runId, this.readFile(statusPathFor(runId)));\n }\n\n private async readStatusAsync(runId: string): Promise<ReadStatusResult | undefined> {\n return this.parseStatus(runId, await this.readFileAsync(statusPathFor(runId)));\n }\n\n private applyStatus(sessionId: string, runId: string, read: ReadStatusResult | undefined): boolean {\n const session = this.session(sessionId);\n const existing = session.jobs.get(runId);\n if (read === undefined) {\n // A run may not have created its file yet, and a torn read must not blank\n // a previously known status for one polling pass.\n if (existing) return false;\n session.jobs.set(runId, { runId, status: undefined });\n return false;\n }\n\n const job: TrackedAsyncJob = { runId, ...read };\n session.jobs.set(runId, job);\n const wasTerminal = existing?.status !== undefined && TERMINAL_ASYNC_JOB_STATES.has(existing.status);\n const isTerminal = job.status !== undefined && TERMINAL_ASYNC_JOB_STATES.has(job.status);\n if (isTerminal && !wasTerminal) session.terminalAt.set(runId, this.now());\n if (!isTerminal) session.terminalAt.delete(runId);\n return (\n !existing ||\n existing.status !== job.status ||\n existing.updatedAt !== job.updatedAt ||\n existing.tokens !== job.tokens ||\n existing.currentTool !== job.currentTool ||\n existing.toolCount !== job.toolCount\n );\n }\n\n private refresh(sessionId: string, runId: string): boolean {\n return this.applyStatus(sessionId, runId, this.readStatus(runId));\n }\n\n private async refreshAsync(sessionId: string, runId: string): Promise<boolean> {\n return this.applyStatus(sessionId, runId, await this.readStatusAsync(runId));\n }\n\n /** One scheduler tick: asynchronously refresh every tracked status, then evict expired terminal jobs. */\n protected async run(): Promise<boolean> {\n let changed = false;\n const now = this.now();\n for (const [sessionId, session] of this.sessions) {\n for (const runId of session.jobs.keys()) {\n if (await this.refreshAsync(sessionId, runId)) changed = true;\n }\n for (const [runId, terminatedAt] of session.terminalAt) {\n if (now - terminatedAt <= this.retentionMs) continue;\n session.jobs.delete(runId);\n session.terminalAt.delete(runId);\n changed = true;\n }\n if (session.jobs.size === 0) this.sessions.delete(sessionId);\n }\n\n return changed;\n }\n\n track(runId: string): void {\n this.trackInSession(UNSCOPED_SESSION, runId);\n }\n\n untrack(runId: string): void {\n this.untrackInSession(UNSCOPED_SESSION, runId);\n }\n\n list(): TrackedAsyncJob[] {\n return this.listInSession(UNSCOPED_SESSION);\n }\n\n get(runId: string): TrackedAsyncJob | undefined {\n return this.getInSession(UNSCOPED_SESSION, runId);\n }\n\n reset(): void {\n this.resetSession(UNSCOPED_SESSION);\n }\n\n private trackInSession(sessionId: string, runId: string): void {\n this.refresh(sessionId, runId);\n }\n\n private untrackInSession(sessionId: string, runId: string): void {\n const session = this.sessions.get(sessionId);\n session?.jobs.delete(runId);\n session?.terminalAt.delete(runId);\n if (session?.jobs.size === 0) this.sessions.delete(sessionId);\n }\n\n private listInSession(sessionId: string): TrackedAsyncJob[] {\n return [...(this.sessions.get(sessionId)?.jobs.values() ?? [])];\n }\n\n private getInSession(sessionId: string, runId: string): TrackedAsyncJob | undefined {\n return this.sessions.get(sessionId)?.jobs.get(runId);\n }\n\n private resetSession(sessionId: string): void {\n this.sessions.delete(sessionId);\n }\n\n start(): void {\n this.stop();\n this.unregisterPoll = this.scheduler.register({\n id: POLL_SUBSCRIBER_ID,\n intervalMs: this.pollIntervalMs,\n run: () => this.run(),\n });\n }\n\n stop(): void {\n this.unregisterPoll?.();\n this.unregisterPoll = undefined;\n this.sessions.clear();\n }\n}\n"],"mappings":"8mBAqFA,MAAa,EAA4B,IAAI,IAAI,CAAC,WAAY,YAAa,SAAU,SAAU,UAAU,CAAC,CA8D1G,SAAgB,EAAoB,EAAyB,EAAoB,CAC/E,IAAM,EAAU,EACb,MAAM,CACN,IAAK,GAAQ,EAAI,MAAM,CACvB,OAAQ,GAAU,IAAU,GAAM,EAAM,WAAW,EAAG,CAAC,CACpD,EAAQ,EAAQ,KAAM,GAAU,IAAU,EAAG,CACnD,GAAI,EAAO,OAAO,EAClB,GAAI,EAAQ,SAAW,EAAG,OAAO,EAAQ,GAEzC,MADI,EAAQ,SAAW,EAAa,MAAM,qCAAqC,EAAG,IAAI,CAC5E,MAAM,wCAAwC,EAAG,qBAAqB,CAQlF,MAAM,EAAmB,eAEzB,SAAS,EAAc,EAAuB,CAC5C,OAAOA,EAAK,KAAKC,EAAAA,gBAAgB,CAAE,EAAOC,EAAAA,iBAAiB,CAG7D,SAAS,EAAU,EAAoC,CACrD,OAAO,OAAO,GAAU,UAAY,GAAkB,SAAU,EAC3D,EAAgC,KACjC,IAAA,GAGN,SAAS,EAAW,EAAyB,CAC3C,OAAO,EAAU,EAAM,GAAK,SAiB9B,MAAM,EAA6C,IAAI,IAAmB,CACxE,WACA,UACA,OACA,oBACA,kBACA,aACA,sBACD,CAAC,CAEF,SAAS,EAAgB,EAA2C,CAClE,OAAO,OAAO,GAAU,UAAY,EAAsB,IAAI,EAAM,CAAI,EAA0B,IAAA,GAI7F,IAAA,EAAA,KAAkD,CACvD,YAAY,EAAmF,CAA3B,KAAA,UAAA,EAOpE,eAA4C,IAC5C,YAAyC,IAEzC,KAAwB,CACtB,OAAO,KAAK,KAAK,CAGnB,SAAmB,EAAsC,CACvD,GAAI,CACF,OAAOC,EAAG,aAAa,EAAU,QAAQ,OAClC,EAAO,CACd,GAAI,EAAW,EAAM,CAAE,OACvB,MAAM,GAIV,MAAgB,cAAc,EAA+C,CAC3E,GAAI,CACF,OAAO,MAAMA,EAAG,SAAS,SAAS,EAAU,QAAQ,OAC7C,EAAO,CACd,GAAI,EAAW,EAAM,CAAE,OACvB,MAAM,GAIV,SAA4B,IAAI,IAChC,eAEA,QAAgB,EAAgC,CAC9C,IAAI,EAAU,KAAK,SAAS,IAAI,EAAU,CAK1C,OAJK,IACH,EAAU,CAAE,KAAM,IAAI,IAAO,WAAY,IAAI,IAAO,CACpD,KAAK,SAAS,IAAI,EAAW,EAAQ,EAEhC,EAGT,WAAW,EAAsC,CAC/C,GAAI,CAAC,EAAU,MAAM,CAAE,MAAU,MAAM,0DAA0D,CACjG,MAAO,CACL,MAAQ,GAAU,KAAK,eAAe,EAAW,EAAM,CACvD,QAAU,GAAU,KAAK,iBAAiB,EAAW,EAAM,CAC3D,SAAY,KAAK,cAAc,EAAU,CACzC,IAAM,GAAU,KAAK,aAAa,EAAW,EAAM,CACnD,UAAa,KAAK,aAAa,EAAU,CAC1C,CAGH,YAAoB,EAAe,EAAuD,CACxF,GAAI,IAAQ,IAAA,GAAW,OACvB,IAAM,EAASC,EAAAA,oBAAoB,EAAK,EAAc,EAAM,CAAC,CAC7D,GAAI,EAAO,OAAS,KAAM,OAC1B,IAAM,EAAS,EAAO,OACtB,MAAO,CACL,MAAO,EAAO,MACd,OAAQ,EAAO,MACf,UAAW,EAAO,UAClB,UAAW,EAAO,WAClB,MAAO,EAAO,MACd,cAAe,EAAgB,EAAO,cAAc,CACpD,gBAAiB,EAAO,gBACxB,QAAS,EAAO,QAChB,OAAQ,EAAO,OACf,YAAa,EAAO,YACpB,UAAW,EAAO,UACnB,CAGH,WAAmB,EAA6C,CAC9D,OAAO,KAAK,YAAY,EAAO,KAAK,SAAS,EAAc,EAAM,CAAC,CAAC,CAGrE,MAAc,gBAAgB,EAAsD,CAClF,OAAO,KAAK,YAAY,EAAO,MAAM,KAAK,cAAc,EAAc,EAAM,CAAC,CAAC,CAGhF,YAAoB,EAAmB,EAAe,EAA6C,CACjG,IAAM,EAAU,KAAK,QAAQ,EAAU,CACjC,EAAW,EAAQ,KAAK,IAAI,EAAM,CACxC,GAAI,IAAS,IAAA,GAKX,OAFI,GACJ,EAAQ,KAAK,IAAI,EAAO,CAAE,QAAO,OAAQ,IAAA,GAAW,CAAC,CADhC,GAKvB,IAAM,EAAuB,CAAE,QAAO,GAAG,EAAM,CAC/C,EAAQ,KAAK,IAAI,EAAO,EAAI,CAC5B,IAAM,EAAc,GAAU,SAAW,IAAA,IAAa,EAA0B,IAAI,EAAS,OAAO,CAC9F,EAAa,EAAI,SAAW,IAAA,IAAa,EAA0B,IAAI,EAAI,OAAO,CAGxF,OAFI,GAAc,CAAC,GAAa,EAAQ,WAAW,IAAI,EAAO,KAAK,KAAK,CAAC,CACpE,GAAY,EAAQ,WAAW,OAAO,EAAM,CAE/C,CAAC,GACD,EAAS,SAAW,EAAI,QACxB,EAAS,YAAc,EAAI,WAC3B,EAAS,SAAW,EAAI,QACxB,EAAS,cAAgB,EAAI,aAC7B,EAAS,YAAc,EAAI,UAI/B,QAAgB,EAAmB,EAAwB,CACzD,OAAO,KAAK,YAAY,EAAW,EAAO,KAAK,WAAW,EAAM,CAAC,CAGnE,MAAc,aAAa,EAAmB,EAAiC,CAC7E,OAAO,KAAK,YAAY,EAAW,EAAO,MAAM,KAAK,gBAAgB,EAAM,CAAC,CAI9E,MAAgB,KAAwB,CACtC,IAAI,EAAU,GACR,EAAM,KAAK,KAAK,CACtB,IAAK,GAAM,CAAC,EAAW,KAAY,KAAK,SAAU,CAChD,IAAK,IAAM,KAAS,EAAQ,KAAK,MAAM,CACjC,MAAM,KAAK,aAAa,EAAW,EAAM,GAAE,EAAU,IAE3D,IAAK,GAAM,CAAC,EAAO,KAAiB,EAAQ,WACtC,EAAM,GAAgB,KAAK,cAC/B,EAAQ,KAAK,OAAO,EAAM,CAC1B,EAAQ,WAAW,OAAO,EAAM,CAChC,EAAU,IAER,EAAQ,KAAK,OAAS,GAAG,KAAK,SAAS,OAAO,EAAU,CAG9D,OAAO,EAGT,MAAM,EAAqB,CACzB,KAAK,eAAe,EAAkB,EAAM,CAG9C,QAAQ,EAAqB,CAC3B,KAAK,iBAAiB,EAAkB,EAAM,CAGhD,MAA0B,CACxB,OAAO,KAAK,cAAc,EAAiB,CAG7C,IAAI,EAA4C,CAC9C,OAAO,KAAK,aAAa,EAAkB,EAAM,CAGnD,OAAc,CACZ,KAAK,aAAa,EAAiB,CAGrC,eAAuB,EAAmB,EAAqB,CAC7D,KAAK,QAAQ,EAAW,EAAM,CAGhC,iBAAyB,EAAmB,EAAqB,CAC/D,IAAM,EAAU,KAAK,SAAS,IAAI,EAAU,CAC5C,GAAS,KAAK,OAAO,EAAM,CAC3B,GAAS,WAAW,OAAO,EAAM,CAC7B,GAAS,KAAK,OAAS,GAAG,KAAK,SAAS,OAAO,EAAU,CAG/D,cAAsB,EAAsC,CAC1D,MAAO,CAAC,GAAI,KAAK,SAAS,IAAI,EAAU,EAAE,KAAK,QAAQ,EAAI,EAAE,CAAE,CAGjE,aAAqB,EAAmB,EAA4C,CAClF,OAAO,KAAK,SAAS,IAAI,EAAU,EAAE,KAAK,IAAI,EAAM,CAGtD,aAAqB,EAAyB,CAC5C,KAAK,SAAS,OAAO,EAAU,CAGjC,OAAc,CACZ,KAAK,MAAM,CACX,KAAK,eAAiB,KAAK,UAAU,SAAS,CAC5C,GAAI,oBACJ,WAAY,KAAK,eACjB,QAAW,KAAK,KAAK,CACtB,CAAC,CAGJ,MAAa,CACX,KAAK,kBAAkB,CACvB,KAAK,eAAiB,IAAA,GACtB,KAAK,SAAS,OAAO,qCAnMZ,kCAESC,EAAAA,gBAAgB,cAAc,CAAA"}
@@ -0,0 +1,2 @@
1
+ import{__esmMin as e}from"../_virtual/_rolldown/runtime.mjs";import{__decorate as t,init_decorate as n}from"../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorate.mjs";import{DOOM_TEAM_TYPES as r,init_types as i}from"../container/types.mjs";import{__decorateMetadata as a,init_decorateMetadata as o}from"../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateMetadata.mjs";import{__decorateParam as s,init_decorateParam as c}from"../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateParam.mjs";import{currentRunsDir as l,init_paths as u}from"../shared/paths.mjs";import{STATUS_FILE_NAME as d,init_statusWriter as f}from"../services/runs/background/statusWriter.mjs";import{parseAsyncRunStatus as p}from"./statusReader.mjs";import{init_statusReader as m}from"../services/runs/background/statusReader.mjs";import*as h from"node:fs";import*as g from"node:path";import{inject as _,injectable as v}from"inversify";function y(e,t){let n=e.list().map(e=>e.runId).filter(e=>e===t||e.startsWith(t)),r=n.find(e=>e===t);if(r)return r;if(n.length===1)return n[0];throw n.length===0?Error(`No current-session run found for '${t}'.`):Error(`Multiple current-session runs match '${t}'. Use a longer id.`)}function b(e){return g.join(l(),e,d)}function x(e){return typeof e==`object`&&e&&`code`in e?e.code:void 0}function S(e){return x(e)===`ENOENT`}function C(e){return typeof e==`string`&&k.has(e)?e:void 0}var w,T,E,D,O,k,A,j=e((()=>{i(),m(),f(),u(),o(),c(),n(),w=new Set([`complete`,`completed`,`failed`,`paused`,`stopped`]),T=1e4,E=250,D=`async-job-tracker`,O=`__unscoped__`,k=new Set([`starting`,`working`,`tool`,`waiting_for_reply`,`needs_attention`,`finalizing`,`active_long_running`]),A=class{constructor(e){this.scheduler=e}pollIntervalMs=E;retentionMs=T;now(){return Date.now()}readFile(e){try{return h.readFileSync(e,`utf-8`)}catch(e){if(S(e))return;throw e}}async readFileAsync(e){try{return await h.promises.readFile(e,`utf-8`)}catch(e){if(S(e))return;throw e}}sessions=new Map;unregisterPoll;session(e){let t=this.sessions.get(e);return t||(t={jobs:new Map,terminalAt:new Map},this.sessions.set(e,t)),t}forSession(e){if(!e.trim())throw Error(`Pi session identity is required to track subagent runs.`);return{track:t=>this.trackInSession(e,t),untrack:t=>this.untrackInSession(e,t),list:()=>this.listInSession(e),get:t=>this.getInSession(e,t),reset:()=>this.resetSession(e)}}parseStatus(e,t){if(t===void 0)return;let n=p(t,b(e));if(n.kind!==`ok`)return;let r=n.status;return{agent:r.agent,status:r.state,startedAt:r.startedAt,updatedAt:r.lastUpdate,error:r.error,activityState:C(r.activityState),attentionReason:r.attentionReason,runtime:r.runtime,tokens:r.tokens,currentTool:r.currentTool,toolCount:r.toolCount}}readStatus(e){return this.parseStatus(e,this.readFile(b(e)))}async readStatusAsync(e){return this.parseStatus(e,await this.readFileAsync(b(e)))}applyStatus(e,t,n){let r=this.session(e),i=r.jobs.get(t);if(n===void 0)return i||r.jobs.set(t,{runId:t,status:void 0}),!1;let a={runId:t,...n};r.jobs.set(t,a);let o=i?.status!==void 0&&w.has(i.status),s=a.status!==void 0&&w.has(a.status);return s&&!o&&r.terminalAt.set(t,this.now()),s||r.terminalAt.delete(t),!i||i.status!==a.status||i.updatedAt!==a.updatedAt||i.tokens!==a.tokens||i.currentTool!==a.currentTool||i.toolCount!==a.toolCount}refresh(e,t){return this.applyStatus(e,t,this.readStatus(t))}async refreshAsync(e,t){return this.applyStatus(e,t,await this.readStatusAsync(t))}async run(){let e=!1,t=this.now();for(let[n,r]of this.sessions){for(let t of r.jobs.keys())await this.refreshAsync(n,t)&&(e=!0);for(let[n,i]of r.terminalAt)t-i<=this.retentionMs||(r.jobs.delete(n),r.terminalAt.delete(n),e=!0);r.jobs.size===0&&this.sessions.delete(n)}return e}track(e){this.trackInSession(O,e)}untrack(e){this.untrackInSession(O,e)}list(){return this.listInSession(O)}get(e){return this.getInSession(O,e)}reset(){this.resetSession(O)}trackInSession(e,t){this.refresh(e,t)}untrackInSession(e,t){let n=this.sessions.get(e);n?.jobs.delete(t),n?.terminalAt.delete(t),n?.jobs.size===0&&this.sessions.delete(e)}listInSession(e){return[...this.sessions.get(e)?.jobs.values()??[]]}getInSession(e,t){return this.sessions.get(e)?.jobs.get(t)}resetSession(e){this.sessions.delete(e)}start(){this.stop(),this.unregisterPoll=this.scheduler.register({id:D,intervalMs:this.pollIntervalMs,run:()=>this.run()})}stop(){this.unregisterPoll?.(),this.unregisterPoll=void 0,this.sessions.clear()}},A=t([v(),s(0,_(r.PollScheduler)),a(`design:paramtypes`,[Object])],A)}));j();export{A as AsyncJobTracker,w as TERMINAL_ASYNC_JOB_STATES,j as init_asyncJobTracker,y as resolveTrackedRunId};
2
+ //# sourceMappingURL=asyncJobTracker.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asyncJobTracker.mjs","names":[],"sources":["../../src/adapters/asyncJobTracker.ts"],"sourcesContent":["/**\n * Live, in-memory registry of the async runs this session currently cares\n * about, refreshed from `status.json` on a `PollScheduler` tick.\n *\n * WHY THIS IS SMALLER THAN THE PREDECESSOR:\n * `doom-pi-subagents/src/runs/background/asyncJobTracker.ts` is 590 lines\n * doing four different jobs: this registry, TUI widget rendering\n * (`renderWidget`/`widgetRenderKey`/`ctx.ui.requestRender`), forwarding\n * control events and steering notices by byte-range-tailing each run's\n * `events.jsonl`, and projecting nested/parallel-group run trees. Only the\n * registry is ported. The other three have no consumer in this package yet:\n * TUI rendering is `G8` (slash commands + TUI), and nested/chain/parallel run\n * modes are `G7`+ (this package is currently single-run async-only - see\n * `spawnHandshake.ts`'s header). Porting rendering or event-tailing logic\n * with nothing to render to or forward to would be untested, unreachable\n * code; it is deferred to whichever later port actually needs it, not\n * dropped silently - this note is where to look for it.\n *\n * DESIGN PATTERNS:\n * - The in-memory map is a pure CACHE, never authoritative on its own:\n * `status.json` (owned by `CoalescedStatusWriter` elsewhere) is the only\n * source of truth. `track()` reads it synchronously immediately, so a\n * caller that already knows a run's id sees *something* right away rather\n * than waiting out the first poll\n * - Restart survivability follows from the point above rather than a second\n * persistence layer: this package has not built session-scoped run\n * ownership yet (which ids \"belong\" to a restarted session is not\n * something this module can determine on its own - see the AVOID entry),\n * so recovery is the caller re-`track()`-ing whatever ids it still cares\n * about from ITS OWN durable record. The very next poll tick repopulates\n * that job's status straight from disk. There is no separate store to keep\n * in sync, and therefore no window where memory could diverge from disk\n * that a restart would not immediately close\n * - Registered with `PollScheduler`, not a private timer: this polls\n * potentially many jobs' status files on an unbounded, periodic cadence\n * with no low-latency requirement - the exact shape `PollScheduler` exists\n * for. Contrast `completionBatcher.ts`/`spawnHandshake.ts`, which own\n * their own timers because they are short-lived, single-shot, and need\n * sub-200ms responsiveness `PollScheduler`'s floor cannot give them; this\n * registry needs neither\n * - Retention-then-eviction happens on the SAME poll tick as the status\n * refresh, rather than the predecessor's per-job `setTimeout`\n * (`scheduleCleanup`): a terminal job aged past `retentionMs` is simply\n * dropped the next time `run()` walks the map. One clock, not one timer per\n * job\n *\n * AVOID:\n * - Scanning `currentRunsDir()` to guess which run ids \"belong\" to this session on\n * startup. This package has no session-scoped run ownership concept yet;\n * inventing one here to answer \"what should I restore\" would be a guess,\n * not a fact this module has standing to assert. Restoration is the\n * caller's job (see the design note above)\n * - Growing `terminalStates` independently of `staleRunReconciler.ts`'s own\n * (unexported) copy; both must treat the same state strings as terminal,\n * or a job could be evicted here while the reconciler still thinks it is\n * in flight, or vice versa\n *\n * `activityState`/`attentionReason` (added for `subagentWait.ts`):\n * `DeliverableGuard.evaluate()` computes `activityState: 'needs_attention'`\n * and a `reason` (e.g. `'missing-deliverable'`), but returns it rather than\n * writing it anywhere - it has no standing to touch `status.json` itself (see\n * that module's header). Something upstream of this tracker - the run's own\n * runner main loop, not yet built - is responsible for folding that result\n * into `status.json` through `CoalescedStatusWriter`. This tracker's job is\n * only to read whatever ends up there, the same as every other field: it does\n * not compute attention, detect it, or decide when a run needs it.\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { inject, injectable } from 'inversify';\nimport { DOOM_TEAM_TYPES } from '../container/types.ts';\nimport { parseAsyncRunStatus } from '../services/runs/background/statusReader.ts';\nimport { STATUS_FILE_NAME } from '../services/runs/background/statusWriter.ts';\nimport { currentRunsDir } from '../shared/paths.ts';\nimport type { IPollScheduler } from '../shared/pollScheduler.ts';\nimport type { ActivityState } from '../types/index.ts';\n\n/**\n * States that mean \"already finished\"; matches `staleRunReconciler.ts`'s\n * own (unexported) set. Exported so a caller outside this module (the slash\n * layer's poll-until-terminal helper) can recognize the same terminal set\n * `TrackedAsyncJob.status` uses, rather than declaring a third copy of this\n * literal.\n */\nexport const TERMINAL_ASYNC_JOB_STATES = new Set(['complete', 'completed', 'failed', 'paused', 'stopped']);\n\n/** How long a terminal job stays queryable before eviction. */\nconst DEFAULT_RETENTION_MS = 10_000;\n/** How often tracked jobs' status is refreshed from disk. */\nconst DEFAULT_POLL_INTERVAL_MS = 250;\n\nconst POLL_SUBSCRIBER_ID = 'async-job-tracker';\n\n/**\n * The minimum shape this module reads. A run's actual `status.json` carries\n * far more (this package has no shared status type yet - see\n * `staleRunReconciler.ts`'s `ReconcilableStatus` for the same caveat);\n * everything else is simply not read here.\n */\nexport interface TrackedAsyncJob {\n runId: string;\n /** Named agent executing this run. Absent until the first readable status. */\n agent?: string;\n /** `status.json`'s `state` field. `undefined` until the first successful read. */\n status: string | undefined;\n startedAt?: number;\n updatedAt?: number;\n error?: string;\n /** `status.json`'s `activityState` field, e.g. `'needs_attention'`. See the module doc. */\n activityState?: ActivityState;\n /** `status.json`'s `reason` field, present alongside `activityState` (e.g. `'missing-deliverable'`). */\n attentionReason?: string;\n /** Which runtime is executing this run. Absent means the default `pi` path. */\n runtime?: string;\n tokens?: number;\n currentTool?: string;\n toolCount?: number;\n}\n\nexport interface ITrackedAsyncJobs {\n /**\n * Start tracking `runId`: reads its current status synchronously (so a\n * caller sees something immediately) and adds it to the poll rotation.\n * Calling this again for an id already tracked simply re-reads it now,\n * the same idempotent-refresh idiom as `CoalescedStatusWriter.open()`.\n */\n track(runId: string): void;\n /** Stop tracking `runId` immediately, without waiting out its retention window. */\n untrack(runId: string): void;\n /** Every currently tracked job (in-flight, or terminal within its retention window). */\n list(): TrackedAsyncJob[];\n get(runId: string): TrackedAsyncJob | undefined;\n /** Drop every tracked job. */\n reset(): void;\n}\n\nexport interface IAsyncJobTracker extends ITrackedAsyncJobs {\n /** Return the isolated run collection owned by one Pi session context. */\n forSession(sessionId: string): ITrackedAsyncJobs;\n /** Register with `PollScheduler`. Call once; a second call is a reset, same as `ResultWatcher.start()`. */\n start(): void;\n /** Unregister from `PollScheduler` and drop every tracked job. */\n stop(): void;\n}\n\n/** Resolve an exact id or unique prefix only inside one Pi session's run collection. */\nexport function resolveTrackedRunId(jobs: ITrackedAsyncJobs, id: string): string {\n const matches = jobs\n .list()\n .map((job) => job.runId)\n .filter((runId) => runId === id || runId.startsWith(id));\n const exact = matches.find((runId) => runId === id);\n if (exact) return exact;\n if (matches.length === 1) return matches[0]!;\n if (matches.length === 0) throw new Error(`No current-session run found for '${id}'.`);\n throw new Error(`Multiple current-session runs match '${id}'. Use a longer id.`);\n}\n\ninterface SessionJobs {\n jobs: Map<string, TrackedAsyncJob>;\n terminalAt: Map<string, number>;\n}\n\nconst UNSCOPED_SESSION = '__unscoped__';\n\nfunction statusPathFor(runId: string): string {\n return path.join(currentRunsDir(), runId, STATUS_FILE_NAME);\n}\n\nfunction errorCode(error: unknown): string | undefined {\n return typeof error === 'object' && error !== null && 'code' in error\n ? (error as NodeJS.ErrnoException).code\n : undefined;\n}\n\nfunction isNotFound(error: unknown): boolean {\n return errorCode(error) === 'ENOENT';\n}\n\ninterface ReadStatusResult {\n agent: string;\n status: string | undefined;\n startedAt?: number;\n updatedAt?: number;\n error?: string;\n activityState?: ActivityState;\n attentionReason?: string;\n runtime?: string;\n tokens?: number;\n currentTool?: string;\n toolCount?: number;\n}\n\nconst VALID_ACTIVITY_STATES: ReadonlySet<string> = new Set<ActivityState>([\n 'starting',\n 'working',\n 'tool',\n 'waiting_for_reply',\n 'needs_attention',\n 'finalizing',\n 'active_long_running',\n]);\n\nfunction asActivityState(value: unknown): ActivityState | undefined {\n return typeof value === 'string' && VALID_ACTIVITY_STATES.has(value) ? (value as ActivityState) : undefined;\n}\n\n@injectable()\nexport class AsyncJobTracker implements IAsyncJobTracker {\n constructor(@inject(DOOM_TEAM_TYPES.PollScheduler) private readonly scheduler: IPollScheduler) {}\n\n /**\n * Seams for tests, as protected members rather than constructor arguments:\n * inversify cannot resolve a primitive. See `pollScheduler.ts` and\n * `agents/discovery.ts` for the same pattern.\n */\n protected readonly pollIntervalMs: number = DEFAULT_POLL_INTERVAL_MS;\n protected readonly retentionMs: number = DEFAULT_RETENTION_MS;\n\n protected now(): number {\n return Date.now();\n }\n\n protected readFile(filePath: string): string | undefined {\n try {\n return fs.readFileSync(filePath, 'utf-8');\n } catch (error) {\n if (isNotFound(error)) return undefined;\n throw error;\n }\n }\n\n protected async readFileAsync(filePath: string): Promise<string | undefined> {\n try {\n return await fs.promises.readFile(filePath, 'utf-8');\n } catch (error) {\n if (isNotFound(error)) return undefined;\n throw error;\n }\n }\n\n private readonly sessions = new Map<string, SessionJobs>();\n private unregisterPoll: (() => void) | undefined;\n\n private session(sessionId: string): SessionJobs {\n let session = this.sessions.get(sessionId);\n if (!session) {\n session = { jobs: new Map(), terminalAt: new Map() };\n this.sessions.set(sessionId, session);\n }\n return session;\n }\n\n forSession(sessionId: string): ITrackedAsyncJobs {\n if (!sessionId.trim()) throw new Error('Pi session identity is required to track subagent runs.');\n return {\n track: (runId) => this.trackInSession(sessionId, runId),\n untrack: (runId) => this.untrackInSession(sessionId, runId),\n list: () => this.listInSession(sessionId),\n get: (runId) => this.getInSession(sessionId, runId),\n reset: () => this.resetSession(sessionId),\n };\n }\n\n private parseStatus(runId: string, raw: string | undefined): ReadStatusResult | undefined {\n if (raw === undefined) return undefined;\n const result = parseAsyncRunStatus(raw, statusPathFor(runId));\n if (result.kind !== 'ok') return undefined;\n const status = result.status;\n return {\n agent: status.agent,\n status: status.state,\n startedAt: status.startedAt,\n updatedAt: status.lastUpdate,\n error: status.error,\n activityState: asActivityState(status.activityState),\n attentionReason: status.attentionReason,\n runtime: status.runtime,\n tokens: status.tokens,\n currentTool: status.currentTool,\n toolCount: status.toolCount,\n };\n }\n\n private readStatus(runId: string): ReadStatusResult | undefined {\n return this.parseStatus(runId, this.readFile(statusPathFor(runId)));\n }\n\n private async readStatusAsync(runId: string): Promise<ReadStatusResult | undefined> {\n return this.parseStatus(runId, await this.readFileAsync(statusPathFor(runId)));\n }\n\n private applyStatus(sessionId: string, runId: string, read: ReadStatusResult | undefined): boolean {\n const session = this.session(sessionId);\n const existing = session.jobs.get(runId);\n if (read === undefined) {\n // A run may not have created its file yet, and a torn read must not blank\n // a previously known status for one polling pass.\n if (existing) return false;\n session.jobs.set(runId, { runId, status: undefined });\n return false;\n }\n\n const job: TrackedAsyncJob = { runId, ...read };\n session.jobs.set(runId, job);\n const wasTerminal = existing?.status !== undefined && TERMINAL_ASYNC_JOB_STATES.has(existing.status);\n const isTerminal = job.status !== undefined && TERMINAL_ASYNC_JOB_STATES.has(job.status);\n if (isTerminal && !wasTerminal) session.terminalAt.set(runId, this.now());\n if (!isTerminal) session.terminalAt.delete(runId);\n return (\n !existing ||\n existing.status !== job.status ||\n existing.updatedAt !== job.updatedAt ||\n existing.tokens !== job.tokens ||\n existing.currentTool !== job.currentTool ||\n existing.toolCount !== job.toolCount\n );\n }\n\n private refresh(sessionId: string, runId: string): boolean {\n return this.applyStatus(sessionId, runId, this.readStatus(runId));\n }\n\n private async refreshAsync(sessionId: string, runId: string): Promise<boolean> {\n return this.applyStatus(sessionId, runId, await this.readStatusAsync(runId));\n }\n\n /** One scheduler tick: asynchronously refresh every tracked status, then evict expired terminal jobs. */\n protected async run(): Promise<boolean> {\n let changed = false;\n const now = this.now();\n for (const [sessionId, session] of this.sessions) {\n for (const runId of session.jobs.keys()) {\n if (await this.refreshAsync(sessionId, runId)) changed = true;\n }\n for (const [runId, terminatedAt] of session.terminalAt) {\n if (now - terminatedAt <= this.retentionMs) continue;\n session.jobs.delete(runId);\n session.terminalAt.delete(runId);\n changed = true;\n }\n if (session.jobs.size === 0) this.sessions.delete(sessionId);\n }\n\n return changed;\n }\n\n track(runId: string): void {\n this.trackInSession(UNSCOPED_SESSION, runId);\n }\n\n untrack(runId: string): void {\n this.untrackInSession(UNSCOPED_SESSION, runId);\n }\n\n list(): TrackedAsyncJob[] {\n return this.listInSession(UNSCOPED_SESSION);\n }\n\n get(runId: string): TrackedAsyncJob | undefined {\n return this.getInSession(UNSCOPED_SESSION, runId);\n }\n\n reset(): void {\n this.resetSession(UNSCOPED_SESSION);\n }\n\n private trackInSession(sessionId: string, runId: string): void {\n this.refresh(sessionId, runId);\n }\n\n private untrackInSession(sessionId: string, runId: string): void {\n const session = this.sessions.get(sessionId);\n session?.jobs.delete(runId);\n session?.terminalAt.delete(runId);\n if (session?.jobs.size === 0) this.sessions.delete(sessionId);\n }\n\n private listInSession(sessionId: string): TrackedAsyncJob[] {\n return [...(this.sessions.get(sessionId)?.jobs.values() ?? [])];\n }\n\n private getInSession(sessionId: string, runId: string): TrackedAsyncJob | undefined {\n return this.sessions.get(sessionId)?.jobs.get(runId);\n }\n\n private resetSession(sessionId: string): void {\n this.sessions.delete(sessionId);\n }\n\n start(): void {\n this.stop();\n this.unregisterPoll = this.scheduler.register({\n id: POLL_SUBSCRIBER_ID,\n intervalMs: this.pollIntervalMs,\n run: () => this.run(),\n });\n }\n\n stop(): void {\n this.unregisterPoll?.();\n this.unregisterPoll = undefined;\n this.sessions.clear();\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ const e=require(`../_virtual/_rolldown/runtime.cjs`),t=require(`../shared/fileSystemRetry.cjs`);let n=require(`node:fs`);n=e.__toESM(n,1);let r=require(`node:path`);r=e.__toESM(r,1);function i(e={}){let i=e.fs??n,a=e.now??Date.now,o=e.pid??process.pid,s=e.random??Math.random,c=e.mode,l=e.retryRenameErrors??process.platform===`win32`,u=e.retryDirectoryErrors??l,d=e.retryDelaysMs??t.DEFAULT_FILE_SYSTEM_RETRY_DELAYS_MS,f=l?d:[],p=u?d:[],m=e.wait??t.waitForFileSystemRetry;return(e,n)=>{t.runFileSystemOperationWithRetry(()=>{i.mkdirSync(r.dirname(e),{recursive:!0})},{retryDelaysMs:p,wait:m});let l=r.join(r.dirname(e),`.${r.basename(e)}.${o}.${a()}.${s().toString(36).slice(2)}.tmp`);try{i.writeFileSync(l,JSON.stringify(n,null,2),c===void 0?`utf-8`:{encoding:`utf-8`,mode:c}),t.runFileSystemOperationWithRetry(()=>{i.renameSync(l,e)},{retryDelaysMs:f,wait:m})}finally{i.rmSync(l,{force:!0})}}}const a=i(),o=i({mode:384});async function s(e,i,a){let o=process.platform===`win32`?t.DEFAULT_FILE_SYSTEM_RETRY_DELAYS_MS:[];await t.runFileSystemOperationWithRetryAsync(()=>n.promises.mkdir(r.dirname(e),{recursive:!0}),{retryDelaysMs:o});let s=r.join(r.dirname(e),`.${r.basename(e)}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`);try{await n.promises.writeFile(s,JSON.stringify(i,null,2),a===void 0?`utf-8`:{encoding:`utf-8`,mode:a}),await t.runFileSystemOperationWithRetryAsync(()=>n.promises.rename(s,e),{retryDelaysMs:o})}finally{await n.promises.rm(s,{force:!0})}}exports.createAtomicJsonWriter=i,exports.writeAtomicJson=a,exports.writeAtomicJsonAsync=s,exports.writePrivateAtomicJson=o;
2
+ //# sourceMappingURL=atomicJson.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atomicJson.cjs","names":["fs","DEFAULT_FILE_SYSTEM_RETRY_DELAYS_MS","waitForFileSystemRetry","path","runFileSystemOperationWithRetryAsync"],"sources":["../../src/adapters/atomicJson.ts"],"sourcesContent":["/**\n * Atomic JSON writes.\n *\n * DESIGN PATTERNS:\n * - Write to a uniquely named temp file in the destination directory, then\n * rename onto the target. Rename is atomic within a filesystem, so a reader\n * sees either the previous file or the complete new one, never a partial write\n * - The temp name carries pid, timestamp and a random suffix so two processes\n * writing the same target never collide on the temp file\n *\n * WHAT THIS DOES NOT DO:\n * This prevents torn reads. It does NOT prevent lost updates: two writers doing\n * read-modify-write still clobber each other, because the rename only publishes\n * whatever the caller already computed. Anything needing mutual exclusion has to\n * take a lease or claim, not rely on atomic writes.\n *\n * AVOID:\n * - Treating this as a lock\n * - Using the plain writer for anything sensitive; prefer writePrivateAtomicJson,\n * which creates the file 0600 so a shared temp directory does not leak prompts\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport {\n DEFAULT_FILE_SYSTEM_RETRY_DELAYS_MS,\n runFileSystemOperationWithRetry,\n runFileSystemOperationWithRetryAsync,\n waitForFileSystemRetry,\n} from '../shared/fileSystemRetry.ts';\n\nconst PRIVATE_FILE_MODE = 0o600;\nconst JSON_INDENT = 2;\n\ntype AtomicJsonFs = Pick<typeof fs, 'mkdirSync' | 'writeFileSync' | 'renameSync' | 'rmSync'>;\n\ntype AtomicJsonWriterOptions = {\n fs?: AtomicJsonFs;\n now?: () => number;\n pid?: number;\n random?: () => number;\n mode?: number;\n retryRenameErrors?: boolean;\n retryDirectoryErrors?: boolean;\n retryDelaysMs?: readonly number[];\n wait?: (delayMs: number) => void;\n};\n\nexport function createAtomicJsonWriter(\n options: AtomicJsonWriterOptions = {},\n): (filePath: string, payload: object) => void {\n const fsImpl = options.fs ?? fs;\n const now = options.now ?? Date.now;\n const pid = options.pid ?? process.pid;\n const random = options.random ?? Math.random;\n const mode = options.mode;\n // Retries exist for Windows directory and rename locks; other platforms fail fast.\n const retryRenameErrors = options.retryRenameErrors ?? process.platform === 'win32';\n const retryDirectoryErrors = options.retryDirectoryErrors ?? retryRenameErrors;\n const retryDelaysMs = options.retryDelaysMs ?? DEFAULT_FILE_SYSTEM_RETRY_DELAYS_MS;\n const renameRetryDelaysMs = retryRenameErrors ? retryDelaysMs : [];\n const directoryRetryDelaysMs = retryDirectoryErrors ? retryDelaysMs : [];\n const wait = options.wait ?? waitForFileSystemRetry;\n\n return (filePath: string, payload: object): void => {\n runFileSystemOperationWithRetry(\n () => {\n fsImpl.mkdirSync(path.dirname(filePath), { recursive: true });\n },\n { retryDelaysMs: directoryRetryDelaysMs, wait },\n );\n const tempPath = path.join(\n path.dirname(filePath),\n `.${path.basename(filePath)}.${pid}.${now()}.${random().toString(36).slice(2)}.tmp`,\n );\n try {\n fsImpl.writeFileSync(\n tempPath,\n JSON.stringify(payload, null, JSON_INDENT),\n mode === undefined ? 'utf-8' : { encoding: 'utf-8', mode },\n );\n runFileSystemOperationWithRetry(\n () => {\n fsImpl.renameSync(tempPath, filePath);\n },\n { retryDelaysMs: renameRetryDelaysMs, wait },\n );\n } finally {\n // Best effort: on the happy path the rename already consumed the temp file.\n fsImpl.rmSync(tempPath, { force: true });\n }\n };\n}\n\nexport const writeAtomicJson = createAtomicJsonWriter();\nexport const writePrivateAtomicJson = createAtomicJsonWriter({ mode: PRIVATE_FILE_MODE });\n\n/** Promise-based atomic writer for startup, polling, and other non-critical paths. */\nexport async function writeAtomicJsonAsync(filePath: string, payload: object, mode?: number): Promise<void> {\n const retryDelaysMs = process.platform === 'win32' ? DEFAULT_FILE_SYSTEM_RETRY_DELAYS_MS : [];\n await runFileSystemOperationWithRetryAsync(() => fs.promises.mkdir(path.dirname(filePath), { recursive: true }), {\n retryDelaysMs,\n });\n const tempPath = path.join(\n path.dirname(filePath),\n `.${path.basename(filePath)}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`,\n );\n try {\n await fs.promises.writeFile(\n tempPath,\n JSON.stringify(payload, null, JSON_INDENT),\n mode === undefined ? 'utf-8' : { encoding: 'utf-8', mode },\n );\n await runFileSystemOperationWithRetryAsync(() => fs.promises.rename(tempPath, filePath), { retryDelaysMs });\n } finally {\n await fs.promises.rm(tempPath, { force: true });\n }\n}\n"],"mappings":"sLAgDA,SAAgB,EACd,EAAmC,EAAE,CACQ,CAC7C,IAAM,EAAS,EAAQ,IAAMA,EACvB,EAAM,EAAQ,KAAO,KAAK,IAC1B,EAAM,EAAQ,KAAO,QAAQ,IAC7B,EAAS,EAAQ,QAAU,KAAK,OAChC,EAAO,EAAQ,KAEf,EAAoB,EAAQ,mBAAqB,QAAQ,WAAa,QACtE,EAAuB,EAAQ,sBAAwB,EACvD,EAAgB,EAAQ,eAAiBC,EAAAA,oCACzC,EAAsB,EAAoB,EAAgB,EAAE,CAC5D,EAAyB,EAAuB,EAAgB,EAAE,CAClE,EAAO,EAAQ,MAAQC,EAAAA,uBAE7B,OAAQ,EAAkB,IAA0B,CAClD,EAAA,oCACQ,CACJ,EAAO,UAAUC,EAAK,QAAQ,EAAS,CAAE,CAAE,UAAW,GAAM,CAAC,EAE/D,CAAE,cAAe,EAAwB,OAAM,CAChD,CACD,IAAM,EAAWA,EAAK,KACpBA,EAAK,QAAQ,EAAS,CACtB,IAAIA,EAAK,SAAS,EAAS,CAAC,GAAG,EAAI,GAAG,GAAK,CAAC,GAAG,GAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE,CAAC,MAC/E,CACD,GAAI,CACF,EAAO,cACL,EACA,KAAK,UAAU,EAAS,KAAM,EAAY,CAC1C,IAAS,IAAA,GAAY,QAAU,CAAE,SAAU,QAAS,OAAM,CAC3D,CACD,EAAA,oCACQ,CACJ,EAAO,WAAW,EAAU,EAAS,EAEvC,CAAE,cAAe,EAAqB,OAAM,CAC7C,QACO,CAER,EAAO,OAAO,EAAU,CAAE,MAAO,GAAM,CAAC,GAK9C,MAAa,EAAkB,GAAwB,CAC1C,EAAyB,EAAuB,CAAE,KAAM,IAAmB,CAAC,CAGzF,eAAsB,EAAqB,EAAkB,EAAiB,EAA8B,CAC1G,IAAM,EAAgB,QAAQ,WAAa,QAAUF,EAAAA,oCAAsC,EAAE,CAC7F,MAAMG,EAAAA,yCAA2CJ,EAAG,SAAS,MAAMG,EAAK,QAAQ,EAAS,CAAE,CAAE,UAAW,GAAM,CAAC,CAAE,CAC/G,gBACD,CAAC,CACF,IAAM,EAAWA,EAAK,KACpBA,EAAK,QAAQ,EAAS,CACtB,IAAIA,EAAK,SAAS,EAAS,CAAC,GAAG,QAAQ,IAAI,GAAG,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE,CAAC,MACjG,CACD,GAAI,CACF,MAAMH,EAAG,SAAS,UAChB,EACA,KAAK,UAAU,EAAS,KAAM,EAAY,CAC1C,IAAS,IAAA,GAAY,QAAU,CAAE,SAAU,QAAS,OAAM,CAC3D,CACD,MAAMI,EAAAA,yCAA2CJ,EAAG,SAAS,OAAO,EAAU,EAAS,CAAE,CAAE,gBAAe,CAAC,QACnG,CACR,MAAMA,EAAG,SAAS,GAAG,EAAU,CAAE,MAAO,GAAM,CAAC"}
@@ -0,0 +1,2 @@
1
+ import{__esmMin as e}from"../_virtual/_rolldown/runtime.mjs";import{DEFAULT_FILE_SYSTEM_RETRY_DELAYS_MS as t,init_fileSystemRetry as n,runFileSystemOperationWithRetry as r,runFileSystemOperationWithRetryAsync as i,waitForFileSystemRetry as a}from"../shared/fileSystemRetry.mjs";import*as o from"node:fs";import*as s from"node:path";function c(e={}){let n=e.fs??o,i=e.now??Date.now,c=e.pid??process.pid,l=e.random??Math.random,u=e.mode,f=e.retryRenameErrors??process.platform===`win32`,p=e.retryDirectoryErrors??f,m=e.retryDelaysMs??t,h=f?m:[],g=p?m:[],_=e.wait??a;return(e,t)=>{r(()=>{n.mkdirSync(s.dirname(e),{recursive:!0})},{retryDelaysMs:g,wait:_});let a=s.join(s.dirname(e),`.${s.basename(e)}.${c}.${i()}.${l().toString(36).slice(2)}.tmp`);try{n.writeFileSync(a,JSON.stringify(t,null,d),u===void 0?`utf-8`:{encoding:`utf-8`,mode:u}),r(()=>{n.renameSync(a,e)},{retryDelaysMs:h,wait:_})}finally{n.rmSync(a,{force:!0})}}}async function l(e,n,r){let a=process.platform===`win32`?t:[];await i(()=>o.promises.mkdir(s.dirname(e),{recursive:!0}),{retryDelaysMs:a});let c=s.join(s.dirname(e),`.${s.basename(e)}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`);try{await o.promises.writeFile(c,JSON.stringify(n,null,d),r===void 0?`utf-8`:{encoding:`utf-8`,mode:r}),await i(()=>o.promises.rename(c,e),{retryDelaysMs:a})}finally{await o.promises.rm(c,{force:!0})}}var u,d,f,p,m=e((()=>{n(),u=384,d=2,f=c(),p=c({mode:u})}));m();export{c as createAtomicJsonWriter,m as init_atomicJson,f as writeAtomicJson,l as writeAtomicJsonAsync,p as writePrivateAtomicJson};
2
+ //# sourceMappingURL=atomicJson.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atomicJson.mjs","names":[],"sources":["../../src/adapters/atomicJson.ts"],"sourcesContent":["/**\n * Atomic JSON writes.\n *\n * DESIGN PATTERNS:\n * - Write to a uniquely named temp file in the destination directory, then\n * rename onto the target. Rename is atomic within a filesystem, so a reader\n * sees either the previous file or the complete new one, never a partial write\n * - The temp name carries pid, timestamp and a random suffix so two processes\n * writing the same target never collide on the temp file\n *\n * WHAT THIS DOES NOT DO:\n * This prevents torn reads. It does NOT prevent lost updates: two writers doing\n * read-modify-write still clobber each other, because the rename only publishes\n * whatever the caller already computed. Anything needing mutual exclusion has to\n * take a lease or claim, not rely on atomic writes.\n *\n * AVOID:\n * - Treating this as a lock\n * - Using the plain writer for anything sensitive; prefer writePrivateAtomicJson,\n * which creates the file 0600 so a shared temp directory does not leak prompts\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport {\n DEFAULT_FILE_SYSTEM_RETRY_DELAYS_MS,\n runFileSystemOperationWithRetry,\n runFileSystemOperationWithRetryAsync,\n waitForFileSystemRetry,\n} from '../shared/fileSystemRetry.ts';\n\nconst PRIVATE_FILE_MODE = 0o600;\nconst JSON_INDENT = 2;\n\ntype AtomicJsonFs = Pick<typeof fs, 'mkdirSync' | 'writeFileSync' | 'renameSync' | 'rmSync'>;\n\ntype AtomicJsonWriterOptions = {\n fs?: AtomicJsonFs;\n now?: () => number;\n pid?: number;\n random?: () => number;\n mode?: number;\n retryRenameErrors?: boolean;\n retryDirectoryErrors?: boolean;\n retryDelaysMs?: readonly number[];\n wait?: (delayMs: number) => void;\n};\n\nexport function createAtomicJsonWriter(\n options: AtomicJsonWriterOptions = {},\n): (filePath: string, payload: object) => void {\n const fsImpl = options.fs ?? fs;\n const now = options.now ?? Date.now;\n const pid = options.pid ?? process.pid;\n const random = options.random ?? Math.random;\n const mode = options.mode;\n // Retries exist for Windows directory and rename locks; other platforms fail fast.\n const retryRenameErrors = options.retryRenameErrors ?? process.platform === 'win32';\n const retryDirectoryErrors = options.retryDirectoryErrors ?? retryRenameErrors;\n const retryDelaysMs = options.retryDelaysMs ?? DEFAULT_FILE_SYSTEM_RETRY_DELAYS_MS;\n const renameRetryDelaysMs = retryRenameErrors ? retryDelaysMs : [];\n const directoryRetryDelaysMs = retryDirectoryErrors ? retryDelaysMs : [];\n const wait = options.wait ?? waitForFileSystemRetry;\n\n return (filePath: string, payload: object): void => {\n runFileSystemOperationWithRetry(\n () => {\n fsImpl.mkdirSync(path.dirname(filePath), { recursive: true });\n },\n { retryDelaysMs: directoryRetryDelaysMs, wait },\n );\n const tempPath = path.join(\n path.dirname(filePath),\n `.${path.basename(filePath)}.${pid}.${now()}.${random().toString(36).slice(2)}.tmp`,\n );\n try {\n fsImpl.writeFileSync(\n tempPath,\n JSON.stringify(payload, null, JSON_INDENT),\n mode === undefined ? 'utf-8' : { encoding: 'utf-8', mode },\n );\n runFileSystemOperationWithRetry(\n () => {\n fsImpl.renameSync(tempPath, filePath);\n },\n { retryDelaysMs: renameRetryDelaysMs, wait },\n );\n } finally {\n // Best effort: on the happy path the rename already consumed the temp file.\n fsImpl.rmSync(tempPath, { force: true });\n }\n };\n}\n\nexport const writeAtomicJson = createAtomicJsonWriter();\nexport const writePrivateAtomicJson = createAtomicJsonWriter({ mode: PRIVATE_FILE_MODE });\n\n/** Promise-based atomic writer for startup, polling, and other non-critical paths. */\nexport async function writeAtomicJsonAsync(filePath: string, payload: object, mode?: number): Promise<void> {\n const retryDelaysMs = process.platform === 'win32' ? DEFAULT_FILE_SYSTEM_RETRY_DELAYS_MS : [];\n await runFileSystemOperationWithRetryAsync(() => fs.promises.mkdir(path.dirname(filePath), { recursive: true }), {\n retryDelaysMs,\n });\n const tempPath = path.join(\n path.dirname(filePath),\n `.${path.basename(filePath)}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`,\n );\n try {\n await fs.promises.writeFile(\n tempPath,\n JSON.stringify(payload, null, JSON_INDENT),\n mode === undefined ? 'utf-8' : { encoding: 'utf-8', mode },\n );\n await runFileSystemOperationWithRetryAsync(() => fs.promises.rename(tempPath, filePath), { retryDelaysMs });\n } finally {\n await fs.promises.rm(tempPath, { force: true });\n }\n}\n"],"mappings":"4UAgDA,SAAgB,EACd,EAAmC,EAAE,CACQ,CAC7C,IAAM,EAAS,EAAQ,IAAM,EACvB,EAAM,EAAQ,KAAO,KAAK,IAC1B,EAAM,EAAQ,KAAO,QAAQ,IAC7B,EAAS,EAAQ,QAAU,KAAK,OAChC,EAAO,EAAQ,KAEf,EAAoB,EAAQ,mBAAqB,QAAQ,WAAa,QACtE,EAAuB,EAAQ,sBAAwB,EACvD,EAAgB,EAAQ,eAAiB,EACzC,EAAsB,EAAoB,EAAgB,EAAE,CAC5D,EAAyB,EAAuB,EAAgB,EAAE,CAClE,EAAO,EAAQ,MAAQ,EAE7B,OAAQ,EAAkB,IAA0B,CAClD,MACQ,CACJ,EAAO,UAAU,EAAK,QAAQ,EAAS,CAAE,CAAE,UAAW,GAAM,CAAC,EAE/D,CAAE,cAAe,EAAwB,OAAM,CAChD,CACD,IAAM,EAAW,EAAK,KACpB,EAAK,QAAQ,EAAS,CACtB,IAAI,EAAK,SAAS,EAAS,CAAC,GAAG,EAAI,GAAG,GAAK,CAAC,GAAG,GAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE,CAAC,MAC/E,CACD,GAAI,CACF,EAAO,cACL,EACA,KAAK,UAAU,EAAS,KAAM,EAAY,CAC1C,IAAS,IAAA,GAAY,QAAU,CAAE,SAAU,QAAS,OAAM,CAC3D,CACD,MACQ,CACJ,EAAO,WAAW,EAAU,EAAS,EAEvC,CAAE,cAAe,EAAqB,OAAM,CAC7C,QACO,CAER,EAAO,OAAO,EAAU,CAAE,MAAO,GAAM,CAAC,GAS9C,eAAsB,EAAqB,EAAkB,EAAiB,EAA8B,CAC1G,IAAM,EAAgB,QAAQ,WAAa,QAAU,EAAsC,EAAE,CAC7F,MAAM,MAA2C,EAAG,SAAS,MAAM,EAAK,QAAQ,EAAS,CAAE,CAAE,UAAW,GAAM,CAAC,CAAE,CAC/G,gBACD,CAAC,CACF,IAAM,EAAW,EAAK,KACpB,EAAK,QAAQ,EAAS,CACtB,IAAI,EAAK,SAAS,EAAS,CAAC,GAAG,QAAQ,IAAI,GAAG,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE,CAAC,MACjG,CACD,GAAI,CACF,MAAM,EAAG,SAAS,UAChB,EACA,KAAK,UAAU,EAAS,KAAM,EAAY,CAC1C,IAAS,IAAA,GAAY,QAAU,CAAE,SAAU,QAAS,OAAM,CAC3D,CACD,MAAM,MAA2C,EAAG,SAAS,OAAO,EAAU,EAAS,CAAE,CAAE,gBAAe,CAAC,QACnG,CACR,MAAM,EAAG,SAAS,GAAG,EAAU,CAAE,MAAO,GAAM,CAAC,2BAtFb,CAEhC,EAAoB,IACpB,EAAc,EA8DP,EAAkB,GAAwB,CAC1C,EAAyB,EAAuB,CAAE,KAAM,EAAmB,CAAC"}
@@ -0,0 +1,2 @@
1
+ require(`../../_virtual/_rolldown/runtime.cjs`);const e=require(`../../container/globalBridge.cjs`),t=require(`../../container/types.cjs`),n=require(`../../shared/paths.cjs`),r=require(`../../shared/modelResolution.cjs`),i=require(`../../services/runs/shared/modelFallback.cjs`),a=require(`../../extensions/spawnPlan.cjs`),o=require(`../asyncJobTracker.cjs`);require(`../../services/runs/background/asyncJobTracker.cjs`);const s=require(`../suspendedRuns.cjs`);require(`../../services/runs/registry/suspendedRuns.cjs`);const c=require(`../../extensions/config.cjs`),l=require(`../scopeOwner.cjs`),u=require(`../../container/index.cjs`),d=require(`../../commands/slash/slashCommands.cjs`),f=require(`../../extensions/delegationBridge.cjs`),p=require(`../../extensions/fablePlanBridge.cjs`),m=require(`../../extensions/orchestratorPrompt.cjs`),h=require(`../../services/runs/registry/sessionLifecycle.cjs`);require(`../../shared/scopeOwner.cjs`);const g=require(`../../tui/completionNotice.cjs`),_=require(`../../tui/register.cjs`);let v=require(`@agimon-ai/doompi-extension-contracts/child-process`),y=require(`@agimon-ai/doompi-extension-contracts/background-work`),b=require(`@agimon-ai/doompi-extension-contracts/delegation`),x=require(`@agimon-ai/doompi-extension-contracts/protocol`),S=require(`@agimon-ai/doompi-extension-contracts/subagent-policy`),C=require(`@agimon-ai/doompi-telemetry`);const w=`unknown`;function T(e,t,n,r,i,a){return{spawnPlanner:n,tracker:r,scheduler:i,discovery:e,skills:t,management:a,loadConfig:()=>c.loadConfig().config}}function E(E,D={}){let O=D.doomIntegrations??!0,k=new e.GlobalStateBridge,A,j=e=>(A??=(0,C.createDoomTelemetry)({serviceName:`doom-team`,packageName:`@agimon-ai/doompi-team`,cwd:e.cwd,env:process.env,enableLogs:!0,enableTraces:!0}),A),M=(e,t)=>{A?.recordEvent(e,t)},N=k.getDefaultContainer(),P=N??u.createExtensionContainer(M),F=N===void 0;F&&k.setDefaultContainer(P);let I=P.get(t.DOOM_TEAM_TYPES.SubagentToolService),L=P.get(t.DOOM_TEAM_TYPES.NativeTeamChannelService),R=P.get(t.DOOM_TEAM_TYPES.PollScheduler),z=P.get(t.DOOM_TEAM_TYPES.AsyncJobTracker),B=P.get(t.DOOM_TEAM_TYPES.SubagentWaiter),V=P.get(t.DOOM_TEAM_TYPES.AsyncSubagentSpawner),H=P.get(t.DOOM_TEAM_TYPES.AgentDiscoveryService),U=P.get(t.DOOM_TEAM_TYPES.SkillDiscoveryService),W=P.get(t.DOOM_TEAM_TYPES.SpawnPlanner),G=P.get(t.DOOM_TEAM_TYPES.CompletionNotifier),K=P.get(t.DOOM_TEAM_TYPES.ResultWatcher),q=P.get(t.DOOM_TEAM_TYPES.StaleRunReconciler),J=P.get(t.DOOM_TEAM_TYPES.ManagementActions),Y=P.get(t.DOOM_TEAM_TYPES.SubagentCapabilityPolicyStore);I.registerTool(E);let X=F&&O?_.registerSubagentLeaderContribution(E):void 0,Z=L.createRuntime(E);if(L.registerClient(E),G.attachHost(E),R.start(),z.start(),F){let e=[],t=[],u,C,w,D,O=f.createDelegationBridge({planner:W,management:J,waiter:B,scheduler:R,tracker:z,loadConfig:()=>c.loadConfig().config}),M=p.createFablePlanBridge({spawner:V,waiter:B,management:J,policies:Y,report:(e,t)=>{A?.recordEvent(e,t)}}),N=R.register({id:`stale-run-reconciler`,intervalMs:2e3,run:async()=>{let e=!1,t=!1;for(let n of w?.list()??[]){if(n.status&&o.TERMINAL_ASYNC_JOB_STATES.has(n.status))continue;t=!0;let{reconcile:r,sweep:i}=q.reconcileAndSweepAsync?await q.reconcileAndSweepAsync(n.runId):q.reconcileAndSweep(n.runId);r.repaired&&(w?.track(n.runId),e=!0),i.recovered.length>0&&(e=!0)}return e||t}});E.on(`before_agent_start`,e=>{if(m.shouldInjectOrchestratorPrompt(c.loadConfig().config))return{systemPrompt:m.appendOrchestratorPrompt(e.systemPrompt)}}),d.registerSlashCommands(E,{baseCwd:void 0},T(H,U,W,z,R,J)),_.registerAgentListCommand(E,{discovery:H,skills:U,policies:Y}),_.registerFleetCommand(E,{scheduler:R,tracker:z,management:J});let P=_.registerAgentStatus(E,{scheduler:R,tracker:z});g.registerCompletionRenderer(E),E.on(`session_start`,async(o,c)=>{let d=j(c);d.recordEvent(`doom_team.session_started`,{"team.root_session":(0,v.resolveRootSessionId)(c.sessionManager.getSessionId())===c.sessionManager.getSessionId()});let f=c.sessionManager.getSessionId(),p=n.createSessionScope((0,v.resolveRootSessionId)(f));n.setCurrentSessionScope(p),await l.writeScopeOwnerAsync(p);let m=await h.openScopeAsync(p,{readStatusAsync:async e=>J.statusAsync?(await J.statusAsync(e)).status:J.status(e).status});m.suspended.length>0&&c.hasUI&&c.ui.notify(await s.formatSuspendedRunsAsync(m.suspended),`info`),d.recordEvent(`doom_team.runs_restored`,{"team.suspended_count":m.suspended.length,"team.pruned_count":m.pruned.length,"team.reaped_count":m.reaped,outcome:`reported`}),w=z.forSession(f),D!==p.scopeKey&&(D=p.scopeKey,K.start(e=>w?.get(e.runId)?G.deliver(e):!1));for(let t of e)t();e=[];for(let e of t)e();t=[],Y.clear(),u?.dispose(),C?.dispose(),C=void 0,O.abandonAll(),M.abandonAll();let g=(0,x.createProtocolRuntime)({bus:E.events,source:_.SUBAGENT_LEADER_SOURCE,sessionId:c.sessionManager.getSessionId()});u=(0,y.provideBackgroundWorkRegistry)(g),C=M.bind({sessionId:f,cwd:c.cwd}),t.push(g.onNotification(S.SubagentPolicyRegistration,({policy:e,generation:t})=>{Y.register(e,t)}),g.onNotification(S.SubagentPolicyChanged,({policy:e,generation:t})=>{Y.update(e,t)}),g.onNotification(S.SubagentPolicyUnregistration,({owner:e,generation:t})=>{Y.remove(e,t)})),g.notify(S.SubagentPolicyDiscovery,{}),e.push(...O.bind(g,()=>{let e=i.normalizeParentModel(c.model);return{sessionId:c.sessionManager.getSessionId(),availableModels:r.authenticatedModelInfos(c.modelRegistry),...e?{parentModel:e}:{},forkSource:a.captureSessionForkSource(c.sessionManager,`tool`)}}),g.onNotification(b.DelegationRequested,e=>{d.recordEvent(`doom_team.delegation_requested`,{"agent.name":e.agent,"task.id":e.taskId,mode:e.runMode??`foreground`})}),g.onNotification(b.DelegationStarted,e=>{d.recordEvent(`doom_team.child_started`,{"run.id":e.runId,outcome:`started`})}),g.onNotification(b.DelegationUpdated,e=>{d.recordEvent(`doom_team.delegation_updated`,{"run.id":e.runId,"team.tool_count":e.toolCount??0,"team.duration_ms":e.durationMs??0,"team.token_count":e.tokens??0,outcome:e.status??`updated`})}),g.onNotification(b.DelegationFinished,e=>{d.recordEvent(`doom_team.delegation_finished`,{"run.id":e.runId,"team.tool_count":e.toolCount??0,"team.duration_ms":e.durationMs??0,outcome:e.status})}),g.onNotification(b.DelegationCancelled,()=>{d.recordEvent(`doom_team.delegation_cancelled`,{outcome:`cancelled`})})),Z.bindMainSession(f)}),k.setRuntimeCleanup(()=>{N();for(let t of e)t();e=[];for(let e of t)e();t=[],Y.clear(),u?.dispose(),u=void 0,C?.dispose(),C=void 0,O.abandonAll(),M.abandonAll(),X?.(),P(),Z.dispose(),K.stop(),D=void 0,G.dispose(),R.stop(),z.stop(),Z.dispose(),k.clearDefaultContainer()})}E.on(`session_shutdown`,async(e,t)=>{let r=n.tryCurrentSessionScope(),i=r?h.suspendScopeRuns({scope:r,reason:e.reason??w,readStatus:e=>J.status(e).status}):Promise.resolve(void 0);k.takeRuntimeCleanup()?.();let a;try{a=await i,await A?.recordEvent(`doom_team.session_finished`,{reason:e.reason??w,"team.suspended_count":a?.suspended.length??0,"team.unstoppable_count":a?.unstoppable.length??0,outcome:a?.unstoppable.length?`degraded`:`suspended`})}catch(t){await A?.recordError(`doom_team.session_shutdown_failed`,t,{reason:e.reason??w})}finally{await A?.shutdown(),A=void 0}})}exports.activateDoomTeamExtension=E;
2
+ //# sourceMappingURL=extension.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.cjs","names":["loadConfig","GlobalStateBridge","createExtensionContainer","DOOM_TEAM_TYPES","registerSubagentLeaderContribution","createDelegationBridge","createFablePlanBridge","TERMINAL_ASYNC_JOB_STATES","shouldInjectOrchestratorPrompt","appendOrchestratorPrompt","registerAgentStatus","createSessionScope","writeScopeOwnerAsync","openScopeAsync","formatSuspendedRunsAsync","SUBAGENT_LEADER_SOURCE","SubagentPolicyRegistration","SubagentPolicyChanged","SubagentPolicyUnregistration","SubagentPolicyDiscovery","normalizeParentModel","authenticatedModelInfos","captureSessionForkSource","DelegationRequested","DelegationStarted","DelegationUpdated","DelegationFinished","DelegationCancelled","tryCurrentSessionScope","suspendScopeRuns"],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["/**\n * The parent extension's implementation: everything `extensions/pi.ts` wires\n * into a Pi host, kept out of that adapter so it is testable without a host.\n *\n * `extensions/pi.ts` is a three-line re-export of this, matching every sibling\n * doom extension (`doom-task`, `doom-workflow`, `doom-file-edit`,\n * `doom-runner`) and the `thin-pi-adapter` rule they all satisfy.\n *\n * RELOAD SAFETY, AND WHY `GlobalStateBridge` OWNS IT:\n * The activation function below can run more than once against the SAME\n * `pi: ExtensionAPI` (a host reload re-invoking a still-cached module\n * instance). Building a SECOND `createExtensionContainer()` on a repeat\n * activation would produce two independent singleton sets in one process -\n * the exact split-brain shape flagged earlier in this package's history for\n * a similarly-shaped \"container per call instead of per process\" bug. Since\n * this file cannot be `@injectable()` (it IS the composition root; nothing\n * constructs it), it cannot hold instance state the way `SubagentToolService`\n * holds its own `WeakSet<ExtensionAPI>` registration guard. `GlobalStateBridge`\n * exists for exactly this: its `getDefaultContainer()`/`setDefaultContainer()`\n * pair (`container/globalBridge.ts`) is the one sanctioned place this\n * package is allowed to remember something across what would otherwise be\n * independent module instantiations, keyed through `globalThis` rather than\n * a module-level `let`. A repeat activation reuses the existing container, so\n * every already-idempotent per-service registration (`SubagentToolService`'s\n * own `WeakSet` guard,\n * `NativeTeamChannelService.createRuntime`'s `WeakMap` memo, `PollScheduler.\n * start()`'s own idempotent doc) stays correct. Registrations with NO internal\n * guard (`registerSlashCommands`, `registerAgentListCommand`, and\n * `registerFleetCommand`) are gated to run only on the activation that actually\n * built the container because `pi.registerCommand` has no documented\n * duplicate-name behavior or `hasCommand`-style helper in this package.\n *\n * DISPOSAL ON `session_shutdown`:\n * `GlobalStateBridge.setRuntimeCleanup()`/`takeRuntimeCleanup()` is a POP,\n * not a peek - the second call (a second shutdown event, or a defensive\n * double-registration of the handler across two activations) finds nothing\n * and no-ops, so the shutdown handler needs no separate idempotency guard of\n * its own. `SessionShutdownEvent.reason` covers `quit`/`reload`/`new`/\n * `resume`/`fork`, but its own doc says the event fires whenever \"an\n * extension runtime is torn down\" regardless of reason, so cleanup runs\n * unconditionally rather than branching on `reason`.\n *\n * SCOPE, STATED EXPLICITLY:\n * This wires the lifecycle services, starts `AsyncJobTracker`, and binds the\n * root session as intercom member `main`. Child membership is registered by\n * the child prompt runtime. It also drives\n * `StaleRunReconciler` from the shared poll scheduler for every tracked\n * non-terminal run. `ControlChannelWatcher` is child-runtime-owned, while\n * `AutoDrainService` remains outside this parent composition root.\n *\n */\n\nimport {\n type BackgroundWorkRegistryHandle,\n provideBackgroundWorkRegistry,\n} from '@agimon-ai/doompi-extension-contracts/background-work';\nimport { resolveRootSessionId } from '@agimon-ai/doompi-extension-contracts/child-process';\nimport {\n DelegationCancelled,\n DelegationFinished,\n DelegationRequested,\n DelegationStarted,\n DelegationUpdated,\n} from '@agimon-ai/doompi-extension-contracts/delegation';\nimport { createProtocolRuntime } from '@agimon-ai/doompi-extension-contracts/protocol';\nimport {\n SubagentPolicyChanged,\n SubagentPolicyDiscovery,\n SubagentPolicyRegistration,\n SubagentPolicyUnregistration,\n} from '@agimon-ai/doompi-extension-contracts/subagent-policy';\nimport { createDoomTelemetry, type DoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport {\n registerSlashCommands,\n type SlashCommandDeps,\n type SlashCommandState,\n} from '../../commands/slash/slashCommands.ts';\nimport { GlobalStateBridge } from '../../container/globalBridge.ts';\nimport { createExtensionContainer } from '../../container/index.ts';\nimport { DOOM_TEAM_TYPES } from '../../container/types.ts';\nimport { loadConfig } from '../../extensions/config.ts';\nimport { createDelegationBridge } from '../../extensions/delegationBridge.ts';\nimport { createFablePlanBridge } from '../../extensions/fablePlanBridge.ts';\nimport type { IManagementActions } from '../../extensions/managementActions.ts';\nimport { appendOrchestratorPrompt, shouldInjectOrchestratorPrompt } from '../../extensions/orchestratorPrompt.ts';\nimport { captureSessionForkSource, type ISpawnPlanner } from '../../extensions/spawnPlan.ts';\nimport type { ISubagentToolService } from '../../extensions/subagentTool.ts';\nimport { SubagentCapabilityPolicyStore } from '../../schemas/team/capabilityCeiling.ts';\nimport type { ISkillDiscoveryService } from '../../services/agents/skills.ts';\nimport type { IAgentDiscoveryService } from '../../services/agents/types.ts';\nimport type { INativeTeamChannelService } from '../../services/intercom/nativeTeamChannel.ts';\nimport type { IAsyncSubagentSpawner } from '../../services/runs/background/asyncExecution.ts';\nimport {\n type IAsyncJobTracker,\n type ITrackedAsyncJobs,\n TERMINAL_ASYNC_JOB_STATES,\n} from '../../services/runs/background/asyncJobTracker.ts';\nimport type { ICompletionNotifier } from '../../services/runs/background/notify.ts';\nimport type { IResultWatcher } from '../../services/runs/background/resultWatcher.ts';\nimport type { IStaleRunReconciler } from '../../services/runs/background/staleRunReconciler.ts';\nimport type { ISubagentWaiter } from '../../services/runs/background/subagentWait.ts';\nimport { openScopeAsync, suspendScopeRuns } from '../../services/runs/registry/sessionLifecycle.ts';\nimport { formatSuspendedRunsAsync } from '../../services/runs/registry/suspendedRuns.ts';\nimport { normalizeParentModel } from '../../services/runs/shared/modelFallback.ts';\nimport { authenticatedModelInfos } from '../../shared/modelResolution.ts';\nimport { createSessionScope, setCurrentSessionScope, tryCurrentSessionScope } from '../../shared/paths.ts';\nimport type { IPollScheduler } from '../../shared/pollScheduler.ts';\nimport { writeScopeOwnerAsync } from '../../shared/scopeOwner.ts';\nimport { registerCompletionRenderer } from '../../tui/completionNotice.ts';\nimport {\n registerAgentListCommand,\n registerAgentStatus,\n registerFleetCommand,\n registerSubagentLeaderContribution,\n SUBAGENT_LEADER_SOURCE,\n} from '../../tui/register.ts';\n\n/** See the subscriber's own comment for why crash detection does not need the 250ms floor. */\nconst STALE_RUN_RECONCILE_INTERVAL_MS = 2_000;\nconst SESSION_SHUTDOWN_REASON_FALLBACK = 'unknown';\n\nfunction buildSlashCommandDeps(\n discovery: IAgentDiscoveryService,\n skills: ISkillDiscoveryService,\n planner: ISpawnPlanner,\n tracker: IAsyncJobTracker,\n scheduler: IPollScheduler,\n management: IManagementActions,\n): SlashCommandDeps {\n return {\n spawnPlanner: planner,\n tracker,\n scheduler,\n discovery,\n skills,\n management,\n loadConfig: () => loadConfig().config,\n };\n}\n\n/**\n * The extension factory pi's loader calls, exported as the module default\n * (see the override this file carries in `vibe-lint.config.yaml`). This is an\n * ESM `.ts` module, so it CANNOT use the `export =` form that\n * `subagentPromptRuntimeEntry.cts` is required to use - that file is `.cts`\n * and is resolved by raw path, this one is resolved as a package subpath and\n * matches the `export default` convention every sibling extension in this repo\n * already uses (`doom-task`, `doom-file-edit`, `doom-pi-ui`).\n */\nexport interface DoomTeamExtensionOptions {\n doomIntegrations?: boolean;\n}\n\nexport function activateDoomTeamExtension(pi: ExtensionAPI, options: DoomTeamExtensionOptions = {}): void {\n const doomIntegrations = options.doomIntegrations ?? true;\n const bridge = new GlobalStateBridge();\n let telemetry: DoomTelemetry | undefined;\n const getTelemetry = (ctx: ExtensionContext): DoomTelemetry => {\n telemetry ??= createDoomTelemetry({\n serviceName: 'doom-team',\n packageName: '@agimon-ai/doompi-team',\n cwd: ctx.cwd,\n env: process.env,\n enableLogs: true,\n enableTraces: true,\n });\n return telemetry;\n };\n const reportConcurrencyEvent = (event: string, attributes: Record<string, unknown>): void => {\n void telemetry?.recordEvent(event, attributes);\n };\n const existingContainer = bridge.getDefaultContainer();\n const container = existingContainer ?? createExtensionContainer(reportConcurrencyEvent);\n const builtNewContainer = existingContainer === undefined;\n if (builtNewContainer) bridge.setDefaultContainer(container);\n\n const subagentTool = container.get<ISubagentToolService>(DOOM_TEAM_TYPES.SubagentToolService);\n const teamChannel = container.get<INativeTeamChannelService>(DOOM_TEAM_TYPES.NativeTeamChannelService);\n const pollScheduler = container.get<IPollScheduler>(DOOM_TEAM_TYPES.PollScheduler);\n const asyncJobTracker = container.get<IAsyncJobTracker>(DOOM_TEAM_TYPES.AsyncJobTracker);\n const subagentWaiter = container.get<ISubagentWaiter>(DOOM_TEAM_TYPES.SubagentWaiter);\n const asyncSubagentSpawner = container.get<IAsyncSubagentSpawner>(DOOM_TEAM_TYPES.AsyncSubagentSpawner);\n const discovery = container.get<IAgentDiscoveryService>(DOOM_TEAM_TYPES.AgentDiscoveryService);\n const skills = container.get<ISkillDiscoveryService>(DOOM_TEAM_TYPES.SkillDiscoveryService);\n const spawnPlanner = container.get<ISpawnPlanner>(DOOM_TEAM_TYPES.SpawnPlanner);\n const completionNotifier = container.get<ICompletionNotifier>(DOOM_TEAM_TYPES.CompletionNotifier);\n const resultWatcher = container.get<IResultWatcher>(DOOM_TEAM_TYPES.ResultWatcher);\n const staleRunReconciler = container.get<IStaleRunReconciler>(DOOM_TEAM_TYPES.StaleRunReconciler);\n const management = container.get<IManagementActions>(DOOM_TEAM_TYPES.ManagementActions);\n const capabilityPolicies = container.get<SubagentCapabilityPolicyStore>(\n DOOM_TEAM_TYPES.SubagentCapabilityPolicyStore,\n );\n\n // Each of these is idempotent on its own (own WeakSet/WeakMap guard, or\n // internally gated to no-op) - safe to redo on every activation, not just\n // the one that built the container.\n subagentTool.registerTool(pi);\n const disposeLeader = builtNewContainer && doomIntegrations ? registerSubagentLeaderContribution(pi) : undefined;\n const teamRuntime = teamChannel.createRuntime(pi);\n teamChannel.registerClient(pi);\n // Attach before `ResultWatcher.start()`, which `session_start` drives: a\n // result file left behind by a previous session is claimed on the watcher's\n // very first tick, and a notifier with no host yet would report\n // non-delivery for it and make the watcher retry a completion it could have\n // rendered immediately.\n completionNotifier.attachHost(pi);\n pollScheduler.start();\n asyncJobTracker.start();\n\n // No internal guard exists for these - see the module header. Gated to the\n // activation that actually built the container so a repeat activation does\n // not attempt to register the same command name twice.\n if (builtNewContainer) {\n let disposeDelegationProviders: Array<() => void> = [];\n let disposePolicyProviders: Array<() => void> = [];\n let backgroundWorkRegistry: BackgroundWorkRegistryHandle | undefined;\n let fableBrokerRegistration: { dispose(): void } | undefined;\n let currentSessionJobs: ITrackedAsyncJobs | undefined;\n // The scope `ResultWatcher` is currently watching. See its start site in\n // the `session_start` handler for why the watcher is latched on this\n // rather than started once.\n let watchedScopeKey: string | undefined;\n const delegationBridge = createDelegationBridge({\n planner: spawnPlanner,\n management,\n waiter: subagentWaiter,\n scheduler: pollScheduler,\n tracker: asyncJobTracker,\n loadConfig: () => loadConfig().config,\n });\n const fablePlanBridge = createFablePlanBridge({\n spawner: asyncSubagentSpawner,\n waiter: subagentWaiter,\n management,\n policies: capabilityPolicies,\n report: (event, attributes) => {\n void telemetry?.recordEvent(event, attributes);\n },\n });\n\n const unregisterStaleRunReconciler = pollScheduler.register({\n id: 'stale-run-reconciler',\n // Crash detection, not status freshness - `AsyncJobTracker` owns that and\n // polls on its own 250ms. This subscriber only ever acts on a run whose\n // process is provably dead, so noticing that 2s later is invisible, while\n // running it 4x/second per active run was not: each pass is a status read,\n // a run-id resolve and a pid probe that a healthy child always discards.\n intervalMs: STALE_RUN_RECONCILE_INTERVAL_MS,\n run: async () => {\n let repaired = false;\n let hasActiveRun = false;\n for (const job of currentSessionJobs?.list() ?? []) {\n if (job.status && TERMINAL_ASYNC_JOB_STATES.has(job.status)) continue;\n hasActiveRun = true;\n // One pass, one `inspect()`. Calling `reconcile` and\n // `sweepOrphanedClaims` separately probed the same pid twice for the\n // same answer - see `IStaleRunReconciler.reconcileAndSweep`.\n const { reconcile: outcome, sweep } = staleRunReconciler.reconcileAndSweepAsync\n ? await staleRunReconciler.reconcileAndSweepAsync(job.runId)\n : staleRunReconciler.reconcileAndSweep(job.runId);\n if (outcome.repaired) {\n currentSessionJobs?.track(job.runId);\n repaired = true;\n }\n if (sweep.recovered.length > 0) repaired = true;\n }\n // An active runner is useful work for scheduling purposes: keeping\n // the shared scheduler at its floor prevents crash detection from\n // inheriting the idle five-second backoff ceiling.\n return repaired || hasActiveRun;\n },\n });\n // The orchestration addendum. Registered here rather than inside the\n // `subagent` tool's description because it is behavioural guidance, and it\n // has to land before the model decides whether to reach for the tool at\n // all - see `orchestratorPrompt.ts`. Read config per turn so toggling it\n // does not need a session restart; `loadConfig` is memoized on the file's\n // own mtime, so this is a stat, not a read.\n pi.on('before_agent_start', (event: { systemPrompt?: string }) => {\n if (!shouldInjectOrchestratorPrompt(loadConfig().config)) return undefined;\n return { systemPrompt: appendOrchestratorPrompt(event.systemPrompt) };\n });\n\n const state: SlashCommandState = { baseCwd: undefined };\n registerSlashCommands(\n pi,\n state,\n buildSlashCommandDeps(discovery, skills, spawnPlanner, asyncJobTracker, pollScheduler, management),\n );\n registerAgentListCommand(pi, { discovery, skills, policies: capabilityPolicies });\n registerFleetCommand(pi, {\n scheduler: pollScheduler,\n tracker: asyncJobTracker,\n management,\n });\n const disposeAgentStatus = registerAgentStatus(pi, {\n scheduler: pollScheduler,\n tracker: asyncJobTracker,\n });\n registerCompletionRenderer(pi);\n\n // Bind the root session directly into the one intercom transport. Child\n // processes bind from the team environment written during spawn.\n pi.on('session_start', async (_event, ctx: ExtensionContext) => {\n const activeTelemetry = getTelemetry(ctx);\n void activeTelemetry.recordEvent('doom_team.session_started', {\n 'team.root_session':\n resolveRootSessionId(ctx.sessionManager.getSessionId()) === ctx.sessionManager.getSessionId(),\n });\n // Before anything else: every scoped path helper reads this. A child\n // keeps the root inherited from its spawn environment, while a top-level\n // session falls back to its own Pi session id.\n const sessionId = ctx.sessionManager.getSessionId();\n const scope = createSessionScope(resolveRootSessionId(sessionId));\n setCurrentSessionScope(scope);\n // Claim the scope for this process, so a later sweep can tell an\n // abandoned tree from a live one. Rewritten on every session_start\n // because /resume legitimately re-adopts a scope under a new process.\n await writeScopeOwnerAsync(scope);\n // Prune records whose process is gone, reap sibling scopes holding\n // nothing alive, and REPORT what is suspended. Nothing is restarted\n // here: reopening a session must not silently spawn agents and start\n // spending tokens on work that may be days stale.\n const opened = await openScopeAsync(scope, {\n readStatusAsync: async (runId) =>\n management.statusAsync ? (await management.statusAsync(runId)).status : management.status(runId).status,\n });\n if (opened.suspended.length > 0 && ctx.hasUI) {\n ctx.ui.notify(await formatSuspendedRunsAsync(opened.suspended), 'info');\n }\n void activeTelemetry.recordEvent('doom_team.runs_restored', {\n 'team.suspended_count': opened.suspended.length,\n 'team.pruned_count': opened.pruned.length,\n 'team.reaped_count': opened.reaped,\n outcome: 'reported',\n });\n currentSessionJobs = asyncJobTracker.forSession(sessionId);\n // Started HERE, not at activation: the first async tick scans\n // `currentRunsDir()` for lingering claims and puts an `fs.watch` on\n // `currentResultsDir()`, so it needs the scope that only exists from\n // this point on. Starting it\n // at activation threw outright, and would have pinned the watch to the\n // previous scope's directory after /new, /resume and /fork.\n //\n // Latched on the scope key because `start()`'s own contract says a\n // repeat call RESETS what it tracks: a reload that re-fires\n // `session_start` for the SAME session must not drop in-flight claims,\n // while a genuinely new scope has none to drop and needs the new watch.\n // `CompletionNotifier.deliver` matches `ResultConsumer` exactly, which\n // is what makes a completed run render in the parent's chat rather than\n // only land as a file nobody reads.\n if (watchedScopeKey !== scope.scopeKey) {\n watchedScopeKey = scope.scopeKey;\n resultWatcher.start((result) =>\n currentSessionJobs?.get(result.runId) ? completionNotifier.deliver(result) : false,\n );\n }\n for (const dispose of disposeDelegationProviders) dispose();\n disposeDelegationProviders = [];\n for (const dispose of disposePolicyProviders) dispose();\n disposePolicyProviders = [];\n capabilityPolicies.clear();\n backgroundWorkRegistry?.dispose();\n fableBrokerRegistration?.dispose();\n fableBrokerRegistration = undefined;\n delegationBridge.abandonAll();\n fablePlanBridge.abandonAll();\n const protocol = createProtocolRuntime({\n bus: pi.events,\n source: SUBAGENT_LEADER_SOURCE,\n sessionId: ctx.sessionManager.getSessionId(),\n });\n backgroundWorkRegistry = provideBackgroundWorkRegistry(protocol);\n fableBrokerRegistration = fablePlanBridge.bind({ sessionId, cwd: ctx.cwd });\n const registerPolicy = ({\n policy,\n generation,\n }: {\n policy: Parameters<typeof capabilityPolicies.update>[0];\n generation: string;\n }): void => {\n capabilityPolicies.register(policy, generation);\n };\n const updatePolicy: typeof registerPolicy = ({ policy, generation }): void => {\n capabilityPolicies.update(policy, generation);\n };\n disposePolicyProviders.push(\n protocol.onNotification(SubagentPolicyRegistration, registerPolicy),\n protocol.onNotification(SubagentPolicyChanged, updatePolicy),\n protocol.onNotification(SubagentPolicyUnregistration, ({ owner, generation }) => {\n capabilityPolicies.remove(owner, generation);\n }),\n );\n protocol.notify(SubagentPolicyDiscovery, {});\n disposeDelegationProviders.push(\n ...delegationBridge.bind(protocol, () => {\n const parentModel = normalizeParentModel(ctx.model);\n return {\n sessionId: ctx.sessionManager.getSessionId(),\n availableModels: authenticatedModelInfos(ctx.modelRegistry),\n ...(parentModel ? { parentModel } : {}),\n forkSource: captureSessionForkSource(ctx.sessionManager, 'tool'),\n };\n }),\n protocol.onNotification(DelegationRequested, (request) => {\n void activeTelemetry.recordEvent('doom_team.delegation_requested', {\n 'agent.name': request.agent,\n 'task.id': request.taskId,\n mode: request.runMode ?? 'foreground',\n });\n }),\n protocol.onNotification(DelegationStarted, (event) => {\n void activeTelemetry.recordEvent('doom_team.child_started', { 'run.id': event.runId, outcome: 'started' });\n }),\n protocol.onNotification(DelegationUpdated, (event) => {\n void activeTelemetry.recordEvent('doom_team.delegation_updated', {\n 'run.id': event.runId,\n 'team.tool_count': event.toolCount ?? 0,\n 'team.duration_ms': event.durationMs ?? 0,\n 'team.token_count': event.tokens ?? 0,\n outcome: event.status ?? 'updated',\n });\n }),\n protocol.onNotification(DelegationFinished, (event) => {\n void activeTelemetry.recordEvent('doom_team.delegation_finished', {\n 'run.id': event.runId,\n 'team.tool_count': event.toolCount ?? 0,\n 'team.duration_ms': event.durationMs ?? 0,\n outcome: event.status,\n });\n }),\n protocol.onNotification(DelegationCancelled, () => {\n void activeTelemetry.recordEvent('doom_team.delegation_cancelled', { outcome: 'cancelled' });\n }),\n );\n teamRuntime.bindMainSession(sessionId);\n });\n\n bridge.setRuntimeCleanup(() => {\n unregisterStaleRunReconciler();\n for (const dispose of disposeDelegationProviders) dispose();\n disposeDelegationProviders = [];\n for (const dispose of disposePolicyProviders) dispose();\n disposePolicyProviders = [];\n capabilityPolicies.clear();\n backgroundWorkRegistry?.dispose();\n backgroundWorkRegistry = undefined;\n fableBrokerRegistration?.dispose();\n fableBrokerRegistration = undefined;\n delegationBridge.abandonAll();\n fablePlanBridge.abandonAll();\n disposeLeader?.();\n disposeAgentStatus();\n teamRuntime.dispose();\n resultWatcher.stop();\n watchedScopeKey = undefined;\n completionNotifier.dispose();\n pollScheduler.stop();\n asyncJobTracker.stop();\n teamRuntime.dispose();\n bridge.clearDefaultContainer();\n });\n }\n\n /**\n * Every reason suspends, with no exception for `reload`.\n *\n * Pi emits this for `quit`, `reload`, `new`, `resume` and `fork`. Treating\n * `reload` differently - keeping children alive because `/domains`, `/major-mode`\n * and `/profile` only reload the extension - would be the one case someone\n * has to remember, and the one that silently misbehaves if Pi adds a sixth\n * reason. Suspending uniformly costs a respawn on reload; restore continues\n * the child's own transcript rather than restarting its task.\n */\n pi.on('session_shutdown', async (event: { reason?: string }, _ctx: ExtensionContext) => {\n const scope = tryCurrentSessionScope();\n const suspensionPromise = scope\n ? suspendScopeRuns({\n scope,\n reason: event.reason ?? SESSION_SHUTDOWN_REASON_FALLBACK,\n readStatus: (runId) => management.status(runId).status,\n })\n : Promise.resolve(undefined);\n bridge.takeRuntimeCleanup()?.();\n let suspension: Awaited<ReturnType<typeof suspendScopeRuns>> | undefined;\n try {\n suspension = await suspensionPromise;\n await telemetry?.recordEvent('doom_team.session_finished', {\n reason: event.reason ?? SESSION_SHUTDOWN_REASON_FALLBACK,\n 'team.suspended_count': suspension?.suspended.length ?? 0,\n 'team.unstoppable_count': suspension?.unstoppable.length ?? 0,\n outcome: suspension?.unstoppable.length ? 'degraded' : 'suspended',\n });\n } catch (error) {\n await telemetry?.recordError('doom_team.session_shutdown_failed', error, {\n reason: event.reason ?? SESSION_SHUTDOWN_REASON_FALLBACK,\n });\n } finally {\n await telemetry?.shutdown();\n telemetry = undefined;\n }\n });\n}\n"],"mappings":"o3CAuHA,MACM,EAAmC,UAEzC,SAAS,EACP,EACA,EACA,EACA,EACA,EACA,EACkB,CAClB,MAAO,CACL,aAAc,EACd,UACA,YACA,YACA,SACA,aACA,eAAkBA,EAAAA,YAAY,CAAC,OAChC,CAgBH,SAAgB,EAA0B,EAAkB,EAAoC,EAAE,CAAQ,CACxG,IAAM,EAAmB,EAAQ,kBAAoB,GAC/C,EAAS,IAAIC,EAAAA,kBACf,EACE,EAAgB,IACpB,KAAA,EAAA,EAAA,qBAAkC,CAChC,YAAa,YACb,YAAa,yBACb,IAAK,EAAI,IACT,IAAK,QAAQ,IACb,WAAY,GACZ,aAAc,GACf,CAAC,CACK,GAEH,GAA0B,EAAe,IAA8C,CACtF,GAAW,YAAY,EAAO,EAAW,EAE1C,EAAoB,EAAO,qBAAqB,CAChD,EAAY,GAAqBC,EAAAA,yBAAyB,EAAuB,CACjF,EAAoB,IAAsB,IAAA,GAC5C,GAAmB,EAAO,oBAAoB,EAAU,CAE5D,IAAM,EAAe,EAAU,IAA0BC,EAAAA,gBAAgB,oBAAoB,CACvF,EAAc,EAAU,IAA+BA,EAAAA,gBAAgB,yBAAyB,CAChG,EAAgB,EAAU,IAAoBA,EAAAA,gBAAgB,cAAc,CAC5E,EAAkB,EAAU,IAAsBA,EAAAA,gBAAgB,gBAAgB,CAClF,EAAiB,EAAU,IAAqBA,EAAAA,gBAAgB,eAAe,CAC/E,EAAuB,EAAU,IAA2BA,EAAAA,gBAAgB,qBAAqB,CACjG,EAAY,EAAU,IAA4BA,EAAAA,gBAAgB,sBAAsB,CACxF,EAAS,EAAU,IAA4BA,EAAAA,gBAAgB,sBAAsB,CACrF,EAAe,EAAU,IAAmBA,EAAAA,gBAAgB,aAAa,CACzE,EAAqB,EAAU,IAAyBA,EAAAA,gBAAgB,mBAAmB,CAC3F,EAAgB,EAAU,IAAoBA,EAAAA,gBAAgB,cAAc,CAC5E,EAAqB,EAAU,IAAyBA,EAAAA,gBAAgB,mBAAmB,CAC3F,EAAa,EAAU,IAAwBA,EAAAA,gBAAgB,kBAAkB,CACjF,EAAqB,EAAU,IACnCA,EAAAA,gBAAgB,8BACjB,CAKD,EAAa,aAAa,EAAG,CAC7B,IAAM,EAAgB,GAAqB,EAAmBC,EAAAA,mCAAmC,EAAG,CAAG,IAAA,GACjG,EAAc,EAAY,cAAc,EAAG,CAcjD,GAbA,EAAY,eAAe,EAAG,CAM9B,EAAmB,WAAW,EAAG,CACjC,EAAc,OAAO,CACrB,EAAgB,OAAO,CAKnB,EAAmB,CACrB,IAAI,EAAgD,EAAE,CAClD,EAA4C,EAAE,CAC9C,EACA,EACA,EAIA,EACE,EAAmBC,EAAAA,uBAAuB,CAC9C,QAAS,EACT,aACA,OAAQ,EACR,UAAW,EACX,QAAS,EACT,eAAkBL,EAAAA,YAAY,CAAC,OAChC,CAAC,CACI,EAAkBM,EAAAA,sBAAsB,CAC5C,QAAS,EACT,OAAQ,EACR,aACA,SAAU,EACV,QAAS,EAAO,IAAe,CACxB,GAAW,YAAY,EAAO,EAAW,EAEjD,CAAC,CAEI,EAA+B,EAAc,SAAS,CAC1D,GAAI,uBAMJ,WAAY,IACZ,IAAK,SAAY,CACf,IAAI,EAAW,GACX,EAAe,GACnB,IAAK,IAAM,KAAO,GAAoB,MAAM,EAAI,EAAE,CAAE,CAClD,GAAI,EAAI,QAAUC,EAAAA,0BAA0B,IAAI,EAAI,OAAO,CAAE,SAC7D,EAAe,GAIf,GAAM,CAAE,UAAW,EAAS,SAAU,EAAmB,uBACrD,MAAM,EAAmB,uBAAuB,EAAI,MAAM,CAC1D,EAAmB,kBAAkB,EAAI,MAAM,CAC/C,EAAQ,WACV,GAAoB,MAAM,EAAI,MAAM,CACpC,EAAW,IAET,EAAM,UAAU,OAAS,IAAG,EAAW,IAK7C,OAAO,GAAY,GAEtB,CAAC,CAOF,EAAG,GAAG,qBAAuB,GAAqC,CAC3DC,KAAAA,+BAA+BR,EAAAA,YAAY,CAAC,OAAO,CACxD,MAAO,CAAE,aAAcS,EAAAA,yBAAyB,EAAM,aAAa,CAAE,EACrE,CAGF,EAAA,sBACE,EACA,CAHiC,QAAS,IAAA,GAGrC,CACL,EAAsB,EAAW,EAAQ,EAAc,EAAiB,EAAe,EAAW,CACnG,CACD,EAAA,yBAAyB,EAAI,CAAE,YAAW,SAAQ,SAAU,EAAoB,CAAC,CACjF,EAAA,qBAAqB,EAAI,CACvB,UAAW,EACX,QAAS,EACT,aACD,CAAC,CACF,IAAM,EAAqBC,EAAAA,oBAAoB,EAAI,CACjD,UAAW,EACX,QAAS,EACV,CAAC,CACF,EAAA,2BAA2B,EAAG,CAI9B,EAAG,GAAG,gBAAiB,MAAO,EAAQ,IAA0B,CAC9D,IAAM,EAAkB,EAAa,EAAI,CACpC,EAAgB,YAAY,4BAA6B,CAC5D,qBAAA,EAAA,EAAA,sBACuB,EAAI,eAAe,cAAc,CAAC,GAAK,EAAI,eAAe,cAAc,CAChG,CAAC,CAIF,IAAM,EAAY,EAAI,eAAe,cAAc,CAC7C,EAAQC,EAAAA,oBAAAA,EAAAA,EAAAA,sBAAwC,EAAU,CAAC,CACjE,EAAA,uBAAuB,EAAM,CAI7B,MAAMC,EAAAA,qBAAqB,EAAM,CAKjC,IAAM,EAAS,MAAMC,EAAAA,eAAe,EAAO,CACzC,gBAAiB,KAAO,IACtB,EAAW,aAAe,MAAM,EAAW,YAAY,EAAM,EAAE,OAAS,EAAW,OAAO,EAAM,CAAC,OACpG,CAAC,CACE,EAAO,UAAU,OAAS,GAAK,EAAI,OACrC,EAAI,GAAG,OAAO,MAAMC,EAAAA,yBAAyB,EAAO,UAAU,CAAE,OAAO,CAEpE,EAAgB,YAAY,0BAA2B,CAC1D,uBAAwB,EAAO,UAAU,OACzC,oBAAqB,EAAO,OAAO,OACnC,oBAAqB,EAAO,OAC5B,QAAS,WACV,CAAC,CACF,EAAqB,EAAgB,WAAW,EAAU,CAetD,IAAoB,EAAM,WAC5B,EAAkB,EAAM,SACxB,EAAc,MAAO,GACnB,GAAoB,IAAI,EAAO,MAAM,CAAG,EAAmB,QAAQ,EAAO,CAAG,GAC9E,EAEH,IAAK,IAAM,KAAW,EAA4B,GAAS,CAC3D,EAA6B,EAAE,CAC/B,IAAK,IAAM,KAAW,EAAwB,GAAS,CACvD,EAAyB,EAAE,CAC3B,EAAmB,OAAO,CAC1B,GAAwB,SAAS,CACjC,GAAyB,SAAS,CAClC,EAA0B,IAAA,GAC1B,EAAiB,YAAY,CAC7B,EAAgB,YAAY,CAC5B,IAAM,GAAA,EAAA,EAAA,uBAAiC,CACrC,IAAK,EAAG,OACR,OAAQC,EAAAA,uBACR,UAAW,EAAI,eAAe,cAAc,CAC7C,CAAC,CACF,GAAA,EAAA,EAAA,+BAAuD,EAAS,CAChE,EAA0B,EAAgB,KAAK,CAAE,YAAW,IAAK,EAAI,IAAK,CAAC,CAa3E,EAAuB,KACrB,EAAS,eAAeC,EAAAA,4BAbF,CACtB,SACA,gBAIU,CACV,EAAmB,SAAS,EAAQ,EAAW,EAMoB,CACnE,EAAS,eAAeC,EAAAA,uBALmB,CAAE,SAAQ,gBAAuB,CAC5E,EAAmB,OAAO,EAAQ,EAAW,EAIe,CAC5D,EAAS,eAAeC,EAAAA,8BAA+B,CAAE,QAAO,gBAAiB,CAC/E,EAAmB,OAAO,EAAO,EAAW,EAC5C,CACH,CACD,EAAS,OAAOC,EAAAA,wBAAyB,EAAE,CAAC,CAC5C,EAA2B,KACzB,GAAG,EAAiB,KAAK,MAAgB,CACvC,IAAM,EAAcC,EAAAA,qBAAqB,EAAI,MAAM,CACnD,MAAO,CACL,UAAW,EAAI,eAAe,cAAc,CAC5C,gBAAiBC,EAAAA,wBAAwB,EAAI,cAAc,CAC3D,GAAI,EAAc,CAAE,cAAa,CAAG,EAAE,CACtC,WAAYC,EAAAA,yBAAyB,EAAI,eAAgB,OAAO,CACjE,EACD,CACF,EAAS,eAAeC,EAAAA,oBAAsB,GAAY,CACnD,EAAgB,YAAY,iCAAkC,CACjE,aAAc,EAAQ,MACtB,UAAW,EAAQ,OACnB,KAAM,EAAQ,SAAW,aAC1B,CAAC,EACF,CACF,EAAS,eAAeC,EAAAA,kBAAoB,GAAU,CAC/C,EAAgB,YAAY,0BAA2B,CAAE,SAAU,EAAM,MAAO,QAAS,UAAW,CAAC,EAC1G,CACF,EAAS,eAAeC,EAAAA,kBAAoB,GAAU,CAC/C,EAAgB,YAAY,+BAAgC,CAC/D,SAAU,EAAM,MAChB,kBAAmB,EAAM,WAAa,EACtC,mBAAoB,EAAM,YAAc,EACxC,mBAAoB,EAAM,QAAU,EACpC,QAAS,EAAM,QAAU,UAC1B,CAAC,EACF,CACF,EAAS,eAAeC,EAAAA,mBAAqB,GAAU,CAChD,EAAgB,YAAY,gCAAiC,CAChE,SAAU,EAAM,MAChB,kBAAmB,EAAM,WAAa,EACtC,mBAAoB,EAAM,YAAc,EACxC,QAAS,EAAM,OAChB,CAAC,EACF,CACF,EAAS,eAAeC,EAAAA,wBAA2B,CAC5C,EAAgB,YAAY,iCAAkC,CAAE,QAAS,YAAa,CAAC,EAC5F,CACH,CACD,EAAY,gBAAgB,EAAU,EACtC,CAEF,EAAO,sBAAwB,CAC7B,GAA8B,CAC9B,IAAK,IAAM,KAAW,EAA4B,GAAS,CAC3D,EAA6B,EAAE,CAC/B,IAAK,IAAM,KAAW,EAAwB,GAAS,CACvD,EAAyB,EAAE,CAC3B,EAAmB,OAAO,CAC1B,GAAwB,SAAS,CACjC,EAAyB,IAAA,GACzB,GAAyB,SAAS,CAClC,EAA0B,IAAA,GAC1B,EAAiB,YAAY,CAC7B,EAAgB,YAAY,CAC5B,KAAiB,CACjB,GAAoB,CACpB,EAAY,SAAS,CACrB,EAAc,MAAM,CACpB,EAAkB,IAAA,GAClB,EAAmB,SAAS,CAC5B,EAAc,MAAM,CACpB,EAAgB,MAAM,CACtB,EAAY,SAAS,CACrB,EAAO,uBAAuB,EAC9B,CAaJ,EAAG,GAAG,mBAAoB,MAAO,EAA4B,IAA2B,CACtF,IAAM,EAAQC,EAAAA,wBAAwB,CAChC,EAAoB,EACtBC,EAAAA,iBAAiB,CACf,QACA,OAAQ,EAAM,QAAU,EACxB,WAAa,GAAU,EAAW,OAAO,EAAM,CAAC,OACjD,CAAC,CACF,QAAQ,QAAQ,IAAA,GAAU,CAC9B,EAAO,oBAAoB,IAAI,CAC/B,IAAI,EACJ,GAAI,CACF,EAAa,MAAM,EACnB,MAAM,GAAW,YAAY,6BAA8B,CACzD,OAAQ,EAAM,QAAU,EACxB,uBAAwB,GAAY,UAAU,QAAU,EACxD,yBAA0B,GAAY,YAAY,QAAU,EAC5D,QAAS,GAAY,YAAY,OAAS,WAAa,YACxD,CAAC,OACK,EAAO,CACd,MAAM,GAAW,YAAY,oCAAqC,EAAO,CACvE,OAAQ,EAAM,QAAU,EACzB,CAAC,QACM,CACR,MAAM,GAAW,UAAU,CAC3B,EAAY,IAAA,KAEd"}
@@ -0,0 +1,2 @@
1
+ import{GlobalStateBridge as e,init_globalBridge as t}from"../../container/globalBridge.mjs";import{DOOM_TEAM_TYPES as n,init_types as r}from"../../container/types.mjs";import{createSessionScope as i,init_paths as a,setCurrentSessionScope as ee,tryCurrentSessionScope as o}from"../../shared/paths.mjs";import{authenticatedModelInfos as s,init_modelResolution as c}from"../../shared/modelResolution.mjs";import{init_modelFallback as l,normalizeParentModel as u}from"../../services/runs/shared/modelFallback.mjs";import{captureSessionForkSource as te,init_spawnPlan as d}from"../../extensions/spawnPlan.mjs";import{TERMINAL_ASYNC_JOB_STATES as f}from"../asyncJobTracker.mjs";import{init_asyncJobTracker as p}from"../../services/runs/background/asyncJobTracker.mjs";import{formatSuspendedRunsAsync as m}from"../suspendedRuns.mjs";import{init_suspendedRuns as h}from"../../services/runs/registry/suspendedRuns.mjs";import{init_config as g,loadConfig as _}from"../../extensions/config.mjs";import{writeScopeOwnerAsync as ne}from"../scopeOwner.mjs";import{createExtensionContainer as v,init_container as y}from"../../container/index.mjs";import{registerSlashCommands as b}from"../../commands/slash/slashCommands.mjs";import{createDelegationBridge as x}from"../../extensions/delegationBridge.mjs";import{createFablePlanBridge as S}from"../../extensions/fablePlanBridge.mjs";import{appendOrchestratorPrompt as C,shouldInjectOrchestratorPrompt as w}from"../../extensions/orchestratorPrompt.mjs";import{openScopeAsync as re,suspendScopeRuns as ie}from"../../services/runs/registry/sessionLifecycle.mjs";import"../../shared/scopeOwner.mjs";import{registerCompletionRenderer as ae}from"../../tui/completionNotice.mjs";import{SUBAGENT_LEADER_SOURCE as oe,registerAgentListCommand as se,registerAgentStatus as ce,registerFleetCommand as le,registerSubagentLeaderContribution as ue}from"../../tui/register.mjs";import{resolveRootSessionId as T}from"@agimon-ai/doompi-extension-contracts/child-process";import{provideBackgroundWorkRegistry as E}from"@agimon-ai/doompi-extension-contracts/background-work";import{DelegationCancelled as D,DelegationFinished as O,DelegationRequested as k,DelegationStarted as A,DelegationUpdated as j}from"@agimon-ai/doompi-extension-contracts/delegation";import{createProtocolRuntime as M}from"@agimon-ai/doompi-extension-contracts/protocol";import{SubagentPolicyChanged as N,SubagentPolicyDiscovery as P,SubagentPolicyRegistration as F,SubagentPolicyUnregistration as I}from"@agimon-ai/doompi-extension-contracts/subagent-policy";import{createDoomTelemetry as L}from"@agimon-ai/doompi-telemetry";t(),y(),r(),g(),d(),p(),h(),l(),c(),a();const R=`unknown`;function z(e,t,n,r,i,a){return{spawnPlanner:n,tracker:r,scheduler:i,discovery:e,skills:t,management:a,loadConfig:()=>_().config}}function B(t,r={}){let a=r.doomIntegrations??!0,c=new e,l,d=e=>(l??=L({serviceName:`doom-team`,packageName:`@agimon-ai/doompi-team`,cwd:e.cwd,env:process.env,enableLogs:!0,enableTraces:!0}),l),p=(e,t)=>{l?.recordEvent(e,t)},h=c.getDefaultContainer(),g=h??v(p),y=h===void 0;y&&c.setDefaultContainer(g);let B=g.get(n.SubagentToolService),V=g.get(n.NativeTeamChannelService),H=g.get(n.PollScheduler),U=g.get(n.AsyncJobTracker),W=g.get(n.SubagentWaiter),de=g.get(n.AsyncSubagentSpawner),G=g.get(n.AgentDiscoveryService),K=g.get(n.SkillDiscoveryService),q=g.get(n.SpawnPlanner),J=g.get(n.CompletionNotifier),Y=g.get(n.ResultWatcher),X=g.get(n.StaleRunReconciler),Z=g.get(n.ManagementActions),Q=g.get(n.SubagentCapabilityPolicyStore);B.registerTool(t);let fe=y&&a?ue(t):void 0,$=V.createRuntime(t);if(V.registerClient(t),J.attachHost(t),H.start(),U.start(),y){let e=[],n=[],r,a,o,p,h=x({planner:q,management:Z,waiter:W,scheduler:H,tracker:U,loadConfig:()=>_().config}),g=S({spawner:de,waiter:W,management:Z,policies:Q,report:(e,t)=>{l?.recordEvent(e,t)}}),v=H.register({id:`stale-run-reconciler`,intervalMs:2e3,run:async()=>{let e=!1,t=!1;for(let n of o?.list()??[]){if(n.status&&f.has(n.status))continue;t=!0;let{reconcile:r,sweep:i}=X.reconcileAndSweepAsync?await X.reconcileAndSweepAsync(n.runId):X.reconcileAndSweep(n.runId);r.repaired&&(o?.track(n.runId),e=!0),i.recovered.length>0&&(e=!0)}return e||t}});t.on(`before_agent_start`,e=>{if(w(_().config))return{systemPrompt:C(e.systemPrompt)}}),b(t,{baseCwd:void 0},z(G,K,q,U,H,Z)),se(t,{discovery:G,skills:K,policies:Q}),le(t,{scheduler:H,tracker:U,management:Z});let y=ce(t,{scheduler:H,tracker:U});ae(t),t.on(`session_start`,async(c,l)=>{let f=d(l);f.recordEvent(`doom_team.session_started`,{"team.root_session":T(l.sessionManager.getSessionId())===l.sessionManager.getSessionId()});let _=l.sessionManager.getSessionId(),v=i(T(_));ee(v),await ne(v);let y=await re(v,{readStatusAsync:async e=>Z.statusAsync?(await Z.statusAsync(e)).status:Z.status(e).status});y.suspended.length>0&&l.hasUI&&l.ui.notify(await m(y.suspended),`info`),f.recordEvent(`doom_team.runs_restored`,{"team.suspended_count":y.suspended.length,"team.pruned_count":y.pruned.length,"team.reaped_count":y.reaped,outcome:`reported`}),o=U.forSession(_),p!==v.scopeKey&&(p=v.scopeKey,Y.start(e=>o?.get(e.runId)?J.deliver(e):!1));for(let t of e)t();e=[];for(let e of n)e();n=[],Q.clear(),r?.dispose(),a?.dispose(),a=void 0,h.abandonAll(),g.abandonAll();let b=M({bus:t.events,source:oe,sessionId:l.sessionManager.getSessionId()});r=E(b),a=g.bind({sessionId:_,cwd:l.cwd}),n.push(b.onNotification(F,({policy:e,generation:t})=>{Q.register(e,t)}),b.onNotification(N,({policy:e,generation:t})=>{Q.update(e,t)}),b.onNotification(I,({owner:e,generation:t})=>{Q.remove(e,t)})),b.notify(P,{}),e.push(...h.bind(b,()=>{let e=u(l.model);return{sessionId:l.sessionManager.getSessionId(),availableModels:s(l.modelRegistry),...e?{parentModel:e}:{},forkSource:te(l.sessionManager,`tool`)}}),b.onNotification(k,e=>{f.recordEvent(`doom_team.delegation_requested`,{"agent.name":e.agent,"task.id":e.taskId,mode:e.runMode??`foreground`})}),b.onNotification(A,e=>{f.recordEvent(`doom_team.child_started`,{"run.id":e.runId,outcome:`started`})}),b.onNotification(j,e=>{f.recordEvent(`doom_team.delegation_updated`,{"run.id":e.runId,"team.tool_count":e.toolCount??0,"team.duration_ms":e.durationMs??0,"team.token_count":e.tokens??0,outcome:e.status??`updated`})}),b.onNotification(O,e=>{f.recordEvent(`doom_team.delegation_finished`,{"run.id":e.runId,"team.tool_count":e.toolCount??0,"team.duration_ms":e.durationMs??0,outcome:e.status})}),b.onNotification(D,()=>{f.recordEvent(`doom_team.delegation_cancelled`,{outcome:`cancelled`})})),$.bindMainSession(_)}),c.setRuntimeCleanup(()=>{v();for(let t of e)t();e=[];for(let e of n)e();n=[],Q.clear(),r?.dispose(),r=void 0,a?.dispose(),a=void 0,h.abandonAll(),g.abandonAll(),fe?.(),y(),$.dispose(),Y.stop(),p=void 0,J.dispose(),H.stop(),U.stop(),$.dispose(),c.clearDefaultContainer()})}t.on(`session_shutdown`,async(e,t)=>{let n=o(),r=n?ie({scope:n,reason:e.reason??R,readStatus:e=>Z.status(e).status}):Promise.resolve(void 0);c.takeRuntimeCleanup()?.();let i;try{i=await r,await l?.recordEvent(`doom_team.session_finished`,{reason:e.reason??R,"team.suspended_count":i?.suspended.length??0,"team.unstoppable_count":i?.unstoppable.length??0,outcome:i?.unstoppable.length?`degraded`:`suspended`})}catch(t){await l?.recordError(`doom_team.session_shutdown_failed`,t,{reason:e.reason??R})}finally{await l?.shutdown(),l=void 0}})}export{B as activateDoomTeamExtension};
2
+ //# sourceMappingURL=extension.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.mjs","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["/**\n * The parent extension's implementation: everything `extensions/pi.ts` wires\n * into a Pi host, kept out of that adapter so it is testable without a host.\n *\n * `extensions/pi.ts` is a three-line re-export of this, matching every sibling\n * doom extension (`doom-task`, `doom-workflow`, `doom-file-edit`,\n * `doom-runner`) and the `thin-pi-adapter` rule they all satisfy.\n *\n * RELOAD SAFETY, AND WHY `GlobalStateBridge` OWNS IT:\n * The activation function below can run more than once against the SAME\n * `pi: ExtensionAPI` (a host reload re-invoking a still-cached module\n * instance). Building a SECOND `createExtensionContainer()` on a repeat\n * activation would produce two independent singleton sets in one process -\n * the exact split-brain shape flagged earlier in this package's history for\n * a similarly-shaped \"container per call instead of per process\" bug. Since\n * this file cannot be `@injectable()` (it IS the composition root; nothing\n * constructs it), it cannot hold instance state the way `SubagentToolService`\n * holds its own `WeakSet<ExtensionAPI>` registration guard. `GlobalStateBridge`\n * exists for exactly this: its `getDefaultContainer()`/`setDefaultContainer()`\n * pair (`container/globalBridge.ts`) is the one sanctioned place this\n * package is allowed to remember something across what would otherwise be\n * independent module instantiations, keyed through `globalThis` rather than\n * a module-level `let`. A repeat activation reuses the existing container, so\n * every already-idempotent per-service registration (`SubagentToolService`'s\n * own `WeakSet` guard,\n * `NativeTeamChannelService.createRuntime`'s `WeakMap` memo, `PollScheduler.\n * start()`'s own idempotent doc) stays correct. Registrations with NO internal\n * guard (`registerSlashCommands`, `registerAgentListCommand`, and\n * `registerFleetCommand`) are gated to run only on the activation that actually\n * built the container because `pi.registerCommand` has no documented\n * duplicate-name behavior or `hasCommand`-style helper in this package.\n *\n * DISPOSAL ON `session_shutdown`:\n * `GlobalStateBridge.setRuntimeCleanup()`/`takeRuntimeCleanup()` is a POP,\n * not a peek - the second call (a second shutdown event, or a defensive\n * double-registration of the handler across two activations) finds nothing\n * and no-ops, so the shutdown handler needs no separate idempotency guard of\n * its own. `SessionShutdownEvent.reason` covers `quit`/`reload`/`new`/\n * `resume`/`fork`, but its own doc says the event fires whenever \"an\n * extension runtime is torn down\" regardless of reason, so cleanup runs\n * unconditionally rather than branching on `reason`.\n *\n * SCOPE, STATED EXPLICITLY:\n * This wires the lifecycle services, starts `AsyncJobTracker`, and binds the\n * root session as intercom member `main`. Child membership is registered by\n * the child prompt runtime. It also drives\n * `StaleRunReconciler` from the shared poll scheduler for every tracked\n * non-terminal run. `ControlChannelWatcher` is child-runtime-owned, while\n * `AutoDrainService` remains outside this parent composition root.\n *\n */\n\nimport {\n type BackgroundWorkRegistryHandle,\n provideBackgroundWorkRegistry,\n} from '@agimon-ai/doompi-extension-contracts/background-work';\nimport { resolveRootSessionId } from '@agimon-ai/doompi-extension-contracts/child-process';\nimport {\n DelegationCancelled,\n DelegationFinished,\n DelegationRequested,\n DelegationStarted,\n DelegationUpdated,\n} from '@agimon-ai/doompi-extension-contracts/delegation';\nimport { createProtocolRuntime } from '@agimon-ai/doompi-extension-contracts/protocol';\nimport {\n SubagentPolicyChanged,\n SubagentPolicyDiscovery,\n SubagentPolicyRegistration,\n SubagentPolicyUnregistration,\n} from '@agimon-ai/doompi-extension-contracts/subagent-policy';\nimport { createDoomTelemetry, type DoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';\nimport {\n registerSlashCommands,\n type SlashCommandDeps,\n type SlashCommandState,\n} from '../../commands/slash/slashCommands.ts';\nimport { GlobalStateBridge } from '../../container/globalBridge.ts';\nimport { createExtensionContainer } from '../../container/index.ts';\nimport { DOOM_TEAM_TYPES } from '../../container/types.ts';\nimport { loadConfig } from '../../extensions/config.ts';\nimport { createDelegationBridge } from '../../extensions/delegationBridge.ts';\nimport { createFablePlanBridge } from '../../extensions/fablePlanBridge.ts';\nimport type { IManagementActions } from '../../extensions/managementActions.ts';\nimport { appendOrchestratorPrompt, shouldInjectOrchestratorPrompt } from '../../extensions/orchestratorPrompt.ts';\nimport { captureSessionForkSource, type ISpawnPlanner } from '../../extensions/spawnPlan.ts';\nimport type { ISubagentToolService } from '../../extensions/subagentTool.ts';\nimport { SubagentCapabilityPolicyStore } from '../../schemas/team/capabilityCeiling.ts';\nimport type { ISkillDiscoveryService } from '../../services/agents/skills.ts';\nimport type { IAgentDiscoveryService } from '../../services/agents/types.ts';\nimport type { INativeTeamChannelService } from '../../services/intercom/nativeTeamChannel.ts';\nimport type { IAsyncSubagentSpawner } from '../../services/runs/background/asyncExecution.ts';\nimport {\n type IAsyncJobTracker,\n type ITrackedAsyncJobs,\n TERMINAL_ASYNC_JOB_STATES,\n} from '../../services/runs/background/asyncJobTracker.ts';\nimport type { ICompletionNotifier } from '../../services/runs/background/notify.ts';\nimport type { IResultWatcher } from '../../services/runs/background/resultWatcher.ts';\nimport type { IStaleRunReconciler } from '../../services/runs/background/staleRunReconciler.ts';\nimport type { ISubagentWaiter } from '../../services/runs/background/subagentWait.ts';\nimport { openScopeAsync, suspendScopeRuns } from '../../services/runs/registry/sessionLifecycle.ts';\nimport { formatSuspendedRunsAsync } from '../../services/runs/registry/suspendedRuns.ts';\nimport { normalizeParentModel } from '../../services/runs/shared/modelFallback.ts';\nimport { authenticatedModelInfos } from '../../shared/modelResolution.ts';\nimport { createSessionScope, setCurrentSessionScope, tryCurrentSessionScope } from '../../shared/paths.ts';\nimport type { IPollScheduler } from '../../shared/pollScheduler.ts';\nimport { writeScopeOwnerAsync } from '../../shared/scopeOwner.ts';\nimport { registerCompletionRenderer } from '../../tui/completionNotice.ts';\nimport {\n registerAgentListCommand,\n registerAgentStatus,\n registerFleetCommand,\n registerSubagentLeaderContribution,\n SUBAGENT_LEADER_SOURCE,\n} from '../../tui/register.ts';\n\n/** See the subscriber's own comment for why crash detection does not need the 250ms floor. */\nconst STALE_RUN_RECONCILE_INTERVAL_MS = 2_000;\nconst SESSION_SHUTDOWN_REASON_FALLBACK = 'unknown';\n\nfunction buildSlashCommandDeps(\n discovery: IAgentDiscoveryService,\n skills: ISkillDiscoveryService,\n planner: ISpawnPlanner,\n tracker: IAsyncJobTracker,\n scheduler: IPollScheduler,\n management: IManagementActions,\n): SlashCommandDeps {\n return {\n spawnPlanner: planner,\n tracker,\n scheduler,\n discovery,\n skills,\n management,\n loadConfig: () => loadConfig().config,\n };\n}\n\n/**\n * The extension factory pi's loader calls, exported as the module default\n * (see the override this file carries in `vibe-lint.config.yaml`). This is an\n * ESM `.ts` module, so it CANNOT use the `export =` form that\n * `subagentPromptRuntimeEntry.cts` is required to use - that file is `.cts`\n * and is resolved by raw path, this one is resolved as a package subpath and\n * matches the `export default` convention every sibling extension in this repo\n * already uses (`doom-task`, `doom-file-edit`, `doom-pi-ui`).\n */\nexport interface DoomTeamExtensionOptions {\n doomIntegrations?: boolean;\n}\n\nexport function activateDoomTeamExtension(pi: ExtensionAPI, options: DoomTeamExtensionOptions = {}): void {\n const doomIntegrations = options.doomIntegrations ?? true;\n const bridge = new GlobalStateBridge();\n let telemetry: DoomTelemetry | undefined;\n const getTelemetry = (ctx: ExtensionContext): DoomTelemetry => {\n telemetry ??= createDoomTelemetry({\n serviceName: 'doom-team',\n packageName: '@agimon-ai/doompi-team',\n cwd: ctx.cwd,\n env: process.env,\n enableLogs: true,\n enableTraces: true,\n });\n return telemetry;\n };\n const reportConcurrencyEvent = (event: string, attributes: Record<string, unknown>): void => {\n void telemetry?.recordEvent(event, attributes);\n };\n const existingContainer = bridge.getDefaultContainer();\n const container = existingContainer ?? createExtensionContainer(reportConcurrencyEvent);\n const builtNewContainer = existingContainer === undefined;\n if (builtNewContainer) bridge.setDefaultContainer(container);\n\n const subagentTool = container.get<ISubagentToolService>(DOOM_TEAM_TYPES.SubagentToolService);\n const teamChannel = container.get<INativeTeamChannelService>(DOOM_TEAM_TYPES.NativeTeamChannelService);\n const pollScheduler = container.get<IPollScheduler>(DOOM_TEAM_TYPES.PollScheduler);\n const asyncJobTracker = container.get<IAsyncJobTracker>(DOOM_TEAM_TYPES.AsyncJobTracker);\n const subagentWaiter = container.get<ISubagentWaiter>(DOOM_TEAM_TYPES.SubagentWaiter);\n const asyncSubagentSpawner = container.get<IAsyncSubagentSpawner>(DOOM_TEAM_TYPES.AsyncSubagentSpawner);\n const discovery = container.get<IAgentDiscoveryService>(DOOM_TEAM_TYPES.AgentDiscoveryService);\n const skills = container.get<ISkillDiscoveryService>(DOOM_TEAM_TYPES.SkillDiscoveryService);\n const spawnPlanner = container.get<ISpawnPlanner>(DOOM_TEAM_TYPES.SpawnPlanner);\n const completionNotifier = container.get<ICompletionNotifier>(DOOM_TEAM_TYPES.CompletionNotifier);\n const resultWatcher = container.get<IResultWatcher>(DOOM_TEAM_TYPES.ResultWatcher);\n const staleRunReconciler = container.get<IStaleRunReconciler>(DOOM_TEAM_TYPES.StaleRunReconciler);\n const management = container.get<IManagementActions>(DOOM_TEAM_TYPES.ManagementActions);\n const capabilityPolicies = container.get<SubagentCapabilityPolicyStore>(\n DOOM_TEAM_TYPES.SubagentCapabilityPolicyStore,\n );\n\n // Each of these is idempotent on its own (own WeakSet/WeakMap guard, or\n // internally gated to no-op) - safe to redo on every activation, not just\n // the one that built the container.\n subagentTool.registerTool(pi);\n const disposeLeader = builtNewContainer && doomIntegrations ? registerSubagentLeaderContribution(pi) : undefined;\n const teamRuntime = teamChannel.createRuntime(pi);\n teamChannel.registerClient(pi);\n // Attach before `ResultWatcher.start()`, which `session_start` drives: a\n // result file left behind by a previous session is claimed on the watcher's\n // very first tick, and a notifier with no host yet would report\n // non-delivery for it and make the watcher retry a completion it could have\n // rendered immediately.\n completionNotifier.attachHost(pi);\n pollScheduler.start();\n asyncJobTracker.start();\n\n // No internal guard exists for these - see the module header. Gated to the\n // activation that actually built the container so a repeat activation does\n // not attempt to register the same command name twice.\n if (builtNewContainer) {\n let disposeDelegationProviders: Array<() => void> = [];\n let disposePolicyProviders: Array<() => void> = [];\n let backgroundWorkRegistry: BackgroundWorkRegistryHandle | undefined;\n let fableBrokerRegistration: { dispose(): void } | undefined;\n let currentSessionJobs: ITrackedAsyncJobs | undefined;\n // The scope `ResultWatcher` is currently watching. See its start site in\n // the `session_start` handler for why the watcher is latched on this\n // rather than started once.\n let watchedScopeKey: string | undefined;\n const delegationBridge = createDelegationBridge({\n planner: spawnPlanner,\n management,\n waiter: subagentWaiter,\n scheduler: pollScheduler,\n tracker: asyncJobTracker,\n loadConfig: () => loadConfig().config,\n });\n const fablePlanBridge = createFablePlanBridge({\n spawner: asyncSubagentSpawner,\n waiter: subagentWaiter,\n management,\n policies: capabilityPolicies,\n report: (event, attributes) => {\n void telemetry?.recordEvent(event, attributes);\n },\n });\n\n const unregisterStaleRunReconciler = pollScheduler.register({\n id: 'stale-run-reconciler',\n // Crash detection, not status freshness - `AsyncJobTracker` owns that and\n // polls on its own 250ms. This subscriber only ever acts on a run whose\n // process is provably dead, so noticing that 2s later is invisible, while\n // running it 4x/second per active run was not: each pass is a status read,\n // a run-id resolve and a pid probe that a healthy child always discards.\n intervalMs: STALE_RUN_RECONCILE_INTERVAL_MS,\n run: async () => {\n let repaired = false;\n let hasActiveRun = false;\n for (const job of currentSessionJobs?.list() ?? []) {\n if (job.status && TERMINAL_ASYNC_JOB_STATES.has(job.status)) continue;\n hasActiveRun = true;\n // One pass, one `inspect()`. Calling `reconcile` and\n // `sweepOrphanedClaims` separately probed the same pid twice for the\n // same answer - see `IStaleRunReconciler.reconcileAndSweep`.\n const { reconcile: outcome, sweep } = staleRunReconciler.reconcileAndSweepAsync\n ? await staleRunReconciler.reconcileAndSweepAsync(job.runId)\n : staleRunReconciler.reconcileAndSweep(job.runId);\n if (outcome.repaired) {\n currentSessionJobs?.track(job.runId);\n repaired = true;\n }\n if (sweep.recovered.length > 0) repaired = true;\n }\n // An active runner is useful work for scheduling purposes: keeping\n // the shared scheduler at its floor prevents crash detection from\n // inheriting the idle five-second backoff ceiling.\n return repaired || hasActiveRun;\n },\n });\n // The orchestration addendum. Registered here rather than inside the\n // `subagent` tool's description because it is behavioural guidance, and it\n // has to land before the model decides whether to reach for the tool at\n // all - see `orchestratorPrompt.ts`. Read config per turn so toggling it\n // does not need a session restart; `loadConfig` is memoized on the file's\n // own mtime, so this is a stat, not a read.\n pi.on('before_agent_start', (event: { systemPrompt?: string }) => {\n if (!shouldInjectOrchestratorPrompt(loadConfig().config)) return undefined;\n return { systemPrompt: appendOrchestratorPrompt(event.systemPrompt) };\n });\n\n const state: SlashCommandState = { baseCwd: undefined };\n registerSlashCommands(\n pi,\n state,\n buildSlashCommandDeps(discovery, skills, spawnPlanner, asyncJobTracker, pollScheduler, management),\n );\n registerAgentListCommand(pi, { discovery, skills, policies: capabilityPolicies });\n registerFleetCommand(pi, {\n scheduler: pollScheduler,\n tracker: asyncJobTracker,\n management,\n });\n const disposeAgentStatus = registerAgentStatus(pi, {\n scheduler: pollScheduler,\n tracker: asyncJobTracker,\n });\n registerCompletionRenderer(pi);\n\n // Bind the root session directly into the one intercom transport. Child\n // processes bind from the team environment written during spawn.\n pi.on('session_start', async (_event, ctx: ExtensionContext) => {\n const activeTelemetry = getTelemetry(ctx);\n void activeTelemetry.recordEvent('doom_team.session_started', {\n 'team.root_session':\n resolveRootSessionId(ctx.sessionManager.getSessionId()) === ctx.sessionManager.getSessionId(),\n });\n // Before anything else: every scoped path helper reads this. A child\n // keeps the root inherited from its spawn environment, while a top-level\n // session falls back to its own Pi session id.\n const sessionId = ctx.sessionManager.getSessionId();\n const scope = createSessionScope(resolveRootSessionId(sessionId));\n setCurrentSessionScope(scope);\n // Claim the scope for this process, so a later sweep can tell an\n // abandoned tree from a live one. Rewritten on every session_start\n // because /resume legitimately re-adopts a scope under a new process.\n await writeScopeOwnerAsync(scope);\n // Prune records whose process is gone, reap sibling scopes holding\n // nothing alive, and REPORT what is suspended. Nothing is restarted\n // here: reopening a session must not silently spawn agents and start\n // spending tokens on work that may be days stale.\n const opened = await openScopeAsync(scope, {\n readStatusAsync: async (runId) =>\n management.statusAsync ? (await management.statusAsync(runId)).status : management.status(runId).status,\n });\n if (opened.suspended.length > 0 && ctx.hasUI) {\n ctx.ui.notify(await formatSuspendedRunsAsync(opened.suspended), 'info');\n }\n void activeTelemetry.recordEvent('doom_team.runs_restored', {\n 'team.suspended_count': opened.suspended.length,\n 'team.pruned_count': opened.pruned.length,\n 'team.reaped_count': opened.reaped,\n outcome: 'reported',\n });\n currentSessionJobs = asyncJobTracker.forSession(sessionId);\n // Started HERE, not at activation: the first async tick scans\n // `currentRunsDir()` for lingering claims and puts an `fs.watch` on\n // `currentResultsDir()`, so it needs the scope that only exists from\n // this point on. Starting it\n // at activation threw outright, and would have pinned the watch to the\n // previous scope's directory after /new, /resume and /fork.\n //\n // Latched on the scope key because `start()`'s own contract says a\n // repeat call RESETS what it tracks: a reload that re-fires\n // `session_start` for the SAME session must not drop in-flight claims,\n // while a genuinely new scope has none to drop and needs the new watch.\n // `CompletionNotifier.deliver` matches `ResultConsumer` exactly, which\n // is what makes a completed run render in the parent's chat rather than\n // only land as a file nobody reads.\n if (watchedScopeKey !== scope.scopeKey) {\n watchedScopeKey = scope.scopeKey;\n resultWatcher.start((result) =>\n currentSessionJobs?.get(result.runId) ? completionNotifier.deliver(result) : false,\n );\n }\n for (const dispose of disposeDelegationProviders) dispose();\n disposeDelegationProviders = [];\n for (const dispose of disposePolicyProviders) dispose();\n disposePolicyProviders = [];\n capabilityPolicies.clear();\n backgroundWorkRegistry?.dispose();\n fableBrokerRegistration?.dispose();\n fableBrokerRegistration = undefined;\n delegationBridge.abandonAll();\n fablePlanBridge.abandonAll();\n const protocol = createProtocolRuntime({\n bus: pi.events,\n source: SUBAGENT_LEADER_SOURCE,\n sessionId: ctx.sessionManager.getSessionId(),\n });\n backgroundWorkRegistry = provideBackgroundWorkRegistry(protocol);\n fableBrokerRegistration = fablePlanBridge.bind({ sessionId, cwd: ctx.cwd });\n const registerPolicy = ({\n policy,\n generation,\n }: {\n policy: Parameters<typeof capabilityPolicies.update>[0];\n generation: string;\n }): void => {\n capabilityPolicies.register(policy, generation);\n };\n const updatePolicy: typeof registerPolicy = ({ policy, generation }): void => {\n capabilityPolicies.update(policy, generation);\n };\n disposePolicyProviders.push(\n protocol.onNotification(SubagentPolicyRegistration, registerPolicy),\n protocol.onNotification(SubagentPolicyChanged, updatePolicy),\n protocol.onNotification(SubagentPolicyUnregistration, ({ owner, generation }) => {\n capabilityPolicies.remove(owner, generation);\n }),\n );\n protocol.notify(SubagentPolicyDiscovery, {});\n disposeDelegationProviders.push(\n ...delegationBridge.bind(protocol, () => {\n const parentModel = normalizeParentModel(ctx.model);\n return {\n sessionId: ctx.sessionManager.getSessionId(),\n availableModels: authenticatedModelInfos(ctx.modelRegistry),\n ...(parentModel ? { parentModel } : {}),\n forkSource: captureSessionForkSource(ctx.sessionManager, 'tool'),\n };\n }),\n protocol.onNotification(DelegationRequested, (request) => {\n void activeTelemetry.recordEvent('doom_team.delegation_requested', {\n 'agent.name': request.agent,\n 'task.id': request.taskId,\n mode: request.runMode ?? 'foreground',\n });\n }),\n protocol.onNotification(DelegationStarted, (event) => {\n void activeTelemetry.recordEvent('doom_team.child_started', { 'run.id': event.runId, outcome: 'started' });\n }),\n protocol.onNotification(DelegationUpdated, (event) => {\n void activeTelemetry.recordEvent('doom_team.delegation_updated', {\n 'run.id': event.runId,\n 'team.tool_count': event.toolCount ?? 0,\n 'team.duration_ms': event.durationMs ?? 0,\n 'team.token_count': event.tokens ?? 0,\n outcome: event.status ?? 'updated',\n });\n }),\n protocol.onNotification(DelegationFinished, (event) => {\n void activeTelemetry.recordEvent('doom_team.delegation_finished', {\n 'run.id': event.runId,\n 'team.tool_count': event.toolCount ?? 0,\n 'team.duration_ms': event.durationMs ?? 0,\n outcome: event.status,\n });\n }),\n protocol.onNotification(DelegationCancelled, () => {\n void activeTelemetry.recordEvent('doom_team.delegation_cancelled', { outcome: 'cancelled' });\n }),\n );\n teamRuntime.bindMainSession(sessionId);\n });\n\n bridge.setRuntimeCleanup(() => {\n unregisterStaleRunReconciler();\n for (const dispose of disposeDelegationProviders) dispose();\n disposeDelegationProviders = [];\n for (const dispose of disposePolicyProviders) dispose();\n disposePolicyProviders = [];\n capabilityPolicies.clear();\n backgroundWorkRegistry?.dispose();\n backgroundWorkRegistry = undefined;\n fableBrokerRegistration?.dispose();\n fableBrokerRegistration = undefined;\n delegationBridge.abandonAll();\n fablePlanBridge.abandonAll();\n disposeLeader?.();\n disposeAgentStatus();\n teamRuntime.dispose();\n resultWatcher.stop();\n watchedScopeKey = undefined;\n completionNotifier.dispose();\n pollScheduler.stop();\n asyncJobTracker.stop();\n teamRuntime.dispose();\n bridge.clearDefaultContainer();\n });\n }\n\n /**\n * Every reason suspends, with no exception for `reload`.\n *\n * Pi emits this for `quit`, `reload`, `new`, `resume` and `fork`. Treating\n * `reload` differently - keeping children alive because `/domains`, `/major-mode`\n * and `/profile` only reload the extension - would be the one case someone\n * has to remember, and the one that silently misbehaves if Pi adds a sixth\n * reason. Suspending uniformly costs a respawn on reload; restore continues\n * the child's own transcript rather than restarting its task.\n */\n pi.on('session_shutdown', async (event: { reason?: string }, _ctx: ExtensionContext) => {\n const scope = tryCurrentSessionScope();\n const suspensionPromise = scope\n ? suspendScopeRuns({\n scope,\n reason: event.reason ?? SESSION_SHUTDOWN_REASON_FALLBACK,\n readStatus: (runId) => management.status(runId).status,\n })\n : Promise.resolve(undefined);\n bridge.takeRuntimeCleanup()?.();\n let suspension: Awaited<ReturnType<typeof suspendScopeRuns>> | undefined;\n try {\n suspension = await suspensionPromise;\n await telemetry?.recordEvent('doom_team.session_finished', {\n reason: event.reason ?? SESSION_SHUTDOWN_REASON_FALLBACK,\n 'team.suspended_count': suspension?.suspended.length ?? 0,\n 'team.unstoppable_count': suspension?.unstoppable.length ?? 0,\n outcome: suspension?.unstoppable.length ? 'degraded' : 'suspended',\n });\n } catch (error) {\n await telemetry?.recordError('doom_team.session_shutdown_failed', error, {\n reason: event.reason ?? SESSION_SHUTDOWN_REASON_FALLBACK,\n });\n } finally {\n await telemetry?.shutdown();\n telemetry = undefined;\n }\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorate.cjs`);let t=require(`inversify`),n=class{floorMs=200;ceilingMs=5e3;backoffMultiplier=2;now(){return Date.now()}onSubscriberError(e,t){this.lastSubscriberError={id:e,error:t,at:this.now()},this.subscriberErrorCount+=1}lastSubscriberError;subscriberErrorCount=0;subscribers=new Map;nextSubscriberKey=0;timer;currentIntervalMs;running=!1;tickRunning=!1;forcedTickQueued=!1;generation=0;register(e){if(!(e.intervalMs>0))throw Error(`Poll subscriber "${e.id}" must have a positive intervalMs.`);let t=this.nextSubscriberKey++;return this.subscribers.set(t,{...e,lastRunAt:void 0}),()=>{this.subscribers.delete(t)}}start(){this.running||(this.running=!0,this.generation+=1,this.currentIntervalMs=this.floorMs,this.tick(!1))}stop(){this.running=!1,this.generation+=1,this.forcedTickQueued=!1,this.timer&&clearTimeout(this.timer),this.timer=void 0}wake(){this.running&&(this.timer&&clearTimeout(this.timer),this.timer=void 0,this.tick(!0))}tick(e){if(this.tickRunning){this.forcedTickQueued||=e;return}this.tickRunning=!0;let t=this.generation,n=this.now(),r=[...this.subscribers.values()],i=!1,a=!1,o=()=>{if(t===this.generation&&a){let e=this.currentIntervalMs??this.floorMs;this.currentIntervalMs=i?this.floorMs:Math.min(e*this.backoffMultiplier,this.ceilingMs)}if(this.tickRunning=!1,this.running){if(this.forcedTickQueued||t!==this.generation){this.forcedTickQueued=!1,this.tick(!0);return}this.scheduleNext()}},s=c=>{if(t!==this.generation){o();return}for(let t=c;t<r.length;t+=1){let o=r[t];if(o&&(e||o.lastRunAt===void 0||n-o.lastRunAt>=o.intervalMs)){o.lastRunAt=n,a=!0;try{let e=o.run();if(e instanceof Promise){e.then(e=>{e&&(i=!0),s(t+1)},e=>{this.onSubscriberError(o.id,e),s(t+1)});return}e&&(i=!0)}catch(e){this.onSubscriberError(o.id,e)}}}o()};s(0)}scheduleNext(){if(!this.running)return;let e=this.currentIntervalMs??this.floorMs;this.timer=setTimeout(()=>this.tick(!1),e),this.timer.unref?.()}};n=e.__decorate([(0,t.injectable)()],n),Object.defineProperty(exports,`PollScheduler`,{enumerable:!0,get:function(){return n}});
2
+ //# sourceMappingURL=pollScheduler.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pollScheduler.cjs","names":[],"sources":["../../src/adapters/pollScheduler.ts"],"sourcesContent":["/**\n * One master tick that drives every background subscriber in the runner\n * process: channels, watchers, inspectors, anything that used to own its own\n * `setInterval`.\n *\n * WHY ONE TICK AND NOT ONE TIMER PER SUBSCRIBER:\n * The predecessor package (`doom-pi-subagents`) gave every channel, watcher\n * and inspector its own independent interval. None of them coordinated, all of\n * them kept firing when nothing was happening, and the parent process burned\n * CPU while completely idle. A single scheduler that every subscriber reports\n * to can decide, once, whether there is any reason to keep ticking quickly.\n *\n * IDLE BACKOFF:\n * The tick interval starts at `floorMs`. A tick where nothing reported work\n * multiplies the interval by `backoffMultiplier`, capped at `ceilingMs`. A tick\n * where anything reported work resets it straight back to `floorMs`. \"Reported\n * work\" means a subscriber's `run()` returned `true`; returning `false` or\n * `void` means it checked and found nothing to do.\n *\n * WATCH-FIRST, POLL AS A SAFETY NET:\n * The intended pattern is: a subscriber's own `intervalMs` is set generously\n * (roughly 4x looser than how quickly you actually want it checked), and a\n * filesystem watch is the fast path. When the watch fires, its handler calls\n * `wake()`, which runs every subscriber immediately regardless of backoff.\n * Polling on `intervalMs` only exists to cover the platforms and mount types\n * where filesystem watches are unreliable or simply do not fire. Neither path\n * is trusted alone: the watch gives latency, the poll interval gives a bound\n * on how late a check can ever be.\n *\n * DESIGN PATTERNS:\n * - Subscribers are checked for both \"due\" (their own `intervalMs` has\n * elapsed) and \"forced\" (a `wake()` call), so a fast-changing subscriber and\n * a rarely-changing one can share one clock without either starving\n * - A subscriber's key is internal and never the caller-supplied `id`, so two\n * subscribers that reuse the same `id` string (a plausible mistake with\n * per-run subscriber names) cannot make one's `unregister()` delete the\n * other's registration\n * - Synchronous subscribers still complete in the same tick. Async subscribers\n * are awaited sequentially, and forced wakes coalesce behind the active tick,\n * so slow filesystem work never creates overlapping scans\n *\n * AVOID:\n * - Reading `this.floorMs` (or the other seam fields) from the constructor:\n * field initializer order runs the base class's defaults before a test\n * subclass's overrides are applied, so a value read in the constructor would\n * see the base default even when a subclass overrides it. Everything that\n * needs these values reads them lazily, from `start()` or `tick()`, which run\n * after construction is complete\n * - Letting a subscriber's thrown error escape `tick()`; it must not stop the\n * tick or affect its peers. It is recorded rather than discarded, since a\n * subscriber that throws every tick otherwise looks identical to an idle one\n */\n\nimport { injectable } from 'inversify';\n\n/** Minimum spacing between ticks once nothing has reported work in a while. */\nconst DEFAULT_FLOOR_MS = 200;\n/** Ceiling the backoff grows toward while idle. */\nconst DEFAULT_CEILING_MS = 5_000;\n/** Growth factor applied to the tick interval on every idle tick. */\nconst DEFAULT_BACKOFF_MULTIPLIER = 2;\n\nexport interface PollSubscription {\n /** For readability in logs and error messages only; not used as a map key. */\n id: string;\n /** How often this subscriber is checked, in milliseconds. Must be positive. */\n intervalMs: number;\n /**\n * Called when due. Return `true` when it did real work, which resets the\n * scheduler's backoff to the floor. Return `false` or nothing when there was\n * nothing to do, which lets idle backoff continue growing.\n */\n run: () => boolean | void | Promise<boolean | undefined>;\n}\n\nexport interface IPollScheduler {\n /** Register a subscriber. Call the returned function to unregister it. */\n register(subscription: PollSubscription): () => void;\n /** Run every subscriber immediately, bypassing backoff and due-checks. */\n wake(): void;\n /** Begin ticking. Idempotent: a second call while running does nothing. */\n start(): void;\n /** Stop ticking and clear the pending timer. Idempotent. */\n stop(): void;\n}\n\ninterface InternalSubscriber extends PollSubscription {\n /** `undefined` until the first tick runs it; never `0`, which a test clock may legitimately start at. */\n lastRunAt: number | undefined;\n}\n\n@injectable()\nexport class PollScheduler implements IPollScheduler {\n /**\n * Seams for tests, as protected members rather than constructor arguments.\n * The container resolves this service by type, and inversify cannot supply a\n * primitive like a backoff curve, so a test subclass overrides these instead.\n */\n protected readonly floorMs: number = DEFAULT_FLOOR_MS;\n protected readonly ceilingMs: number = DEFAULT_CEILING_MS;\n protected readonly backoffMultiplier: number = DEFAULT_BACKOFF_MULTIPLIER;\n\n protected now(): number {\n return Date.now();\n }\n\n /**\n * Records a subscriber that threw. Overridable, and deliberately not a\n * stdio write: this runs inside a detached runner whose stdout is the child's\n * captured transcript. The composition root routes these into that process's\n * own diagnostics; the default keeps the most recent one queryable so a\n * failing subscriber can still be found after the fact.\n */\n protected onSubscriberError(id: string, error: unknown): void {\n this.lastSubscriberError = { id, error, at: this.now() };\n this.subscriberErrorCount += 1;\n }\n\n /** The most recent subscriber failure, for diagnostics. */\n lastSubscriberError: { id: string; error: unknown; at: number } | undefined;\n /** How many subscriber failures this scheduler has absorbed. */\n subscriberErrorCount = 0;\n\n private readonly subscribers = new Map<number, InternalSubscriber>();\n private nextSubscriberKey = 0;\n private timer: ReturnType<typeof setTimeout> | undefined;\n private currentIntervalMs: number | undefined;\n private running = false;\n private tickRunning = false;\n private forcedTickQueued = false;\n private generation = 0;\n\n register(subscription: PollSubscription): () => void {\n if (!(subscription.intervalMs > 0)) {\n throw new Error(`Poll subscriber \"${subscription.id}\" must have a positive intervalMs.`);\n }\n const key = this.nextSubscriberKey++;\n this.subscribers.set(key, { ...subscription, lastRunAt: undefined });\n return () => {\n this.subscribers.delete(key);\n };\n }\n\n start(): void {\n if (this.running) return;\n this.running = true;\n this.generation += 1;\n this.currentIntervalMs = this.floorMs;\n this.tick(false);\n }\n\n stop(): void {\n this.running = false;\n this.generation += 1;\n this.forcedTickQueued = false;\n if (this.timer) clearTimeout(this.timer);\n this.timer = undefined;\n }\n\n wake(): void {\n if (!this.running) return;\n if (this.timer) clearTimeout(this.timer);\n this.timer = undefined;\n this.tick(true);\n }\n\n /**\n * Run every due subscriber (or, when `forced`, every subscriber), fold the\n * outcome into the backoff curve, and schedule the next tick.\n */\n private tick(forced: boolean): void {\n if (this.tickRunning) {\n this.forcedTickQueued ||= forced;\n return;\n }\n\n this.tickRunning = true;\n const generation = this.generation;\n const timestamp = this.now();\n const subscribers = [...this.subscribers.values()];\n let workHappened = false;\n let anySubscriberRan = false;\n\n const finish = (): void => {\n if (generation === this.generation && anySubscriberRan) {\n const previousIntervalMs = this.currentIntervalMs ?? this.floorMs;\n this.currentIntervalMs = workHappened\n ? this.floorMs\n : Math.min(previousIntervalMs * this.backoffMultiplier, this.ceilingMs);\n }\n this.tickRunning = false;\n if (!this.running) return;\n if (this.forcedTickQueued || generation !== this.generation) {\n this.forcedTickQueued = false;\n this.tick(true);\n return;\n }\n this.scheduleNext();\n };\n\n const visit = (index: number): void => {\n if (generation !== this.generation) {\n finish();\n return;\n }\n for (let current = index; current < subscribers.length; current += 1) {\n const subscriber = subscribers[current];\n if (!subscriber) continue;\n const due =\n forced || subscriber.lastRunAt === undefined || timestamp - subscriber.lastRunAt >= subscriber.intervalMs;\n if (!due) continue;\n subscriber.lastRunAt = timestamp;\n anySubscriberRan = true;\n try {\n const result = subscriber.run();\n if (result instanceof Promise) {\n void result.then(\n (worked) => {\n if (worked) workHappened = true;\n visit(current + 1);\n },\n (error: unknown) => {\n this.onSubscriberError(subscriber.id, error);\n visit(current + 1);\n },\n );\n return;\n }\n if (result) workHappened = true;\n } catch (error) {\n this.onSubscriberError(subscriber.id, error);\n }\n }\n finish();\n };\n\n visit(0);\n }\n\n private scheduleNext(): void {\n if (!this.running) return;\n const delayMs = this.currentIntervalMs ?? this.floorMs;\n this.timer = setTimeout(() => this.tick(false), delayMs);\n // A pending background poll must never be the reason the process stays\n // alive; `unref` is optional only because some test timer shims omit it.\n this.timer.unref?.();\n }\n}\n"],"mappings":"0JA4FO,EAAA,KAA8C,CAMnD,QAAqC,IACrC,UAAuC,IACvC,kBAA+C,EAE/C,KAAwB,CACtB,OAAO,KAAK,KAAK,CAUnB,kBAA4B,EAAY,EAAsB,CAC5D,KAAK,oBAAsB,CAAE,KAAI,QAAO,GAAI,KAAK,KAAK,CAAE,CACxD,KAAK,sBAAwB,EAI/B,oBAEA,qBAAuB,EAEvB,YAA+B,IAAI,IACnC,kBAA4B,EAC5B,MACA,kBACA,QAAkB,GAClB,YAAsB,GACtB,iBAA2B,GAC3B,WAAqB,EAErB,SAAS,EAA4C,CACnD,GAAI,EAAE,EAAa,WAAa,GAC9B,MAAU,MAAM,oBAAoB,EAAa,GAAG,oCAAoC,CAE1F,IAAM,EAAM,KAAK,oBAEjB,OADA,KAAK,YAAY,IAAI,EAAK,CAAE,GAAG,EAAc,UAAW,IAAA,GAAW,CAAC,KACvD,CACX,KAAK,YAAY,OAAO,EAAI,EAIhC,OAAc,CACR,KAAK,UACT,KAAK,QAAU,GACf,KAAK,YAAc,EACnB,KAAK,kBAAoB,KAAK,QAC9B,KAAK,KAAK,GAAM,EAGlB,MAAa,CACX,KAAK,QAAU,GACf,KAAK,YAAc,EACnB,KAAK,iBAAmB,GACpB,KAAK,OAAO,aAAa,KAAK,MAAM,CACxC,KAAK,MAAQ,IAAA,GAGf,MAAa,CACN,KAAK,UACN,KAAK,OAAO,aAAa,KAAK,MAAM,CACxC,KAAK,MAAQ,IAAA,GACb,KAAK,KAAK,GAAK,EAOjB,KAAa,EAAuB,CAClC,GAAI,KAAK,YAAa,CACpB,KAAK,mBAAqB,EAC1B,OAGF,KAAK,YAAc,GACnB,IAAM,EAAa,KAAK,WAClB,EAAY,KAAK,KAAK,CACtB,EAAc,CAAC,GAAG,KAAK,YAAY,QAAQ,CAAC,CAC9C,EAAe,GACf,EAAmB,GAEjB,MAAqB,CACzB,GAAI,IAAe,KAAK,YAAc,EAAkB,CACtD,IAAM,EAAqB,KAAK,mBAAqB,KAAK,QAC1D,KAAK,kBAAoB,EACrB,KAAK,QACL,KAAK,IAAI,EAAqB,KAAK,kBAAmB,KAAK,UAAU,CAE3E,QAAK,YAAc,GACd,KAAK,QACV,IAAI,KAAK,kBAAoB,IAAe,KAAK,WAAY,CAC3D,KAAK,iBAAmB,GACxB,KAAK,KAAK,GAAK,CACf,OAEF,KAAK,cAAc,GAGf,EAAS,GAAwB,CACrC,GAAI,IAAe,KAAK,WAAY,CAClC,GAAQ,CACR,OAEF,IAAK,IAAI,EAAU,EAAO,EAAU,EAAY,OAAQ,GAAW,EAAG,CACpE,IAAM,EAAa,EAAY,GAC1B,OAEH,GAAU,EAAW,YAAc,IAAA,IAAa,EAAY,EAAW,WAAa,EAAW,YAGjG,CADA,EAAW,UAAY,EACvB,EAAmB,GACnB,GAAI,CACF,IAAM,EAAS,EAAW,KAAK,CAC/B,GAAI,aAAkB,QAAS,CACxB,EAAO,KACT,GAAW,CACN,IAAQ,EAAe,IAC3B,EAAM,EAAU,EAAE,EAEnB,GAAmB,CAClB,KAAK,kBAAkB,EAAW,GAAI,EAAM,CAC5C,EAAM,EAAU,EAAE,EAErB,CACD,OAEE,IAAQ,EAAe,UACpB,EAAO,CACd,KAAK,kBAAkB,EAAW,GAAI,EAAM,GAGhD,GAAQ,EAGV,EAAM,EAAE,CAGV,cAA6B,CAC3B,GAAI,CAAC,KAAK,QAAS,OACnB,IAAM,EAAU,KAAK,mBAAqB,KAAK,QAC/C,KAAK,MAAQ,eAAiB,KAAK,KAAK,GAAM,CAAE,EAAQ,CAGxD,KAAK,MAAM,SAAS,qCA1JX,CAAA,CAAA,EAAA"}
@@ -0,0 +1,2 @@
1
+ import{__esmMin as e}from"../_virtual/_rolldown/runtime.mjs";import{__decorate as t,init_decorate as n}from"../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorate.mjs";import{injectable as r}from"inversify";var i,a,o,s,c=e((()=>{n(),i=200,a=5e3,o=2,s=class{floorMs=i;ceilingMs=a;backoffMultiplier=o;now(){return Date.now()}onSubscriberError(e,t){this.lastSubscriberError={id:e,error:t,at:this.now()},this.subscriberErrorCount+=1}lastSubscriberError;subscriberErrorCount=0;subscribers=new Map;nextSubscriberKey=0;timer;currentIntervalMs;running=!1;tickRunning=!1;forcedTickQueued=!1;generation=0;register(e){if(!(e.intervalMs>0))throw Error(`Poll subscriber "${e.id}" must have a positive intervalMs.`);let t=this.nextSubscriberKey++;return this.subscribers.set(t,{...e,lastRunAt:void 0}),()=>{this.subscribers.delete(t)}}start(){this.running||(this.running=!0,this.generation+=1,this.currentIntervalMs=this.floorMs,this.tick(!1))}stop(){this.running=!1,this.generation+=1,this.forcedTickQueued=!1,this.timer&&clearTimeout(this.timer),this.timer=void 0}wake(){this.running&&(this.timer&&clearTimeout(this.timer),this.timer=void 0,this.tick(!0))}tick(e){if(this.tickRunning){this.forcedTickQueued||=e;return}this.tickRunning=!0;let t=this.generation,n=this.now(),r=[...this.subscribers.values()],i=!1,a=!1,o=()=>{if(t===this.generation&&a){let e=this.currentIntervalMs??this.floorMs;this.currentIntervalMs=i?this.floorMs:Math.min(e*this.backoffMultiplier,this.ceilingMs)}if(this.tickRunning=!1,this.running){if(this.forcedTickQueued||t!==this.generation){this.forcedTickQueued=!1,this.tick(!0);return}this.scheduleNext()}},s=c=>{if(t!==this.generation){o();return}for(let t=c;t<r.length;t+=1){let o=r[t];if(o&&(e||o.lastRunAt===void 0||n-o.lastRunAt>=o.intervalMs)){o.lastRunAt=n,a=!0;try{let e=o.run();if(e instanceof Promise){e.then(e=>{e&&(i=!0),s(t+1)},e=>{this.onSubscriberError(o.id,e),s(t+1)});return}e&&(i=!0)}catch(e){this.onSubscriberError(o.id,e)}}}o()};s(0)}scheduleNext(){if(!this.running)return;let e=this.currentIntervalMs??this.floorMs;this.timer=setTimeout(()=>this.tick(!1),e),this.timer.unref?.()}},s=t([r()],s)}));c();export{s as PollScheduler,c as init_pollScheduler};
2
+ //# sourceMappingURL=pollScheduler.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pollScheduler.mjs","names":[],"sources":["../../src/adapters/pollScheduler.ts"],"sourcesContent":["/**\n * One master tick that drives every background subscriber in the runner\n * process: channels, watchers, inspectors, anything that used to own its own\n * `setInterval`.\n *\n * WHY ONE TICK AND NOT ONE TIMER PER SUBSCRIBER:\n * The predecessor package (`doom-pi-subagents`) gave every channel, watcher\n * and inspector its own independent interval. None of them coordinated, all of\n * them kept firing when nothing was happening, and the parent process burned\n * CPU while completely idle. A single scheduler that every subscriber reports\n * to can decide, once, whether there is any reason to keep ticking quickly.\n *\n * IDLE BACKOFF:\n * The tick interval starts at `floorMs`. A tick where nothing reported work\n * multiplies the interval by `backoffMultiplier`, capped at `ceilingMs`. A tick\n * where anything reported work resets it straight back to `floorMs`. \"Reported\n * work\" means a subscriber's `run()` returned `true`; returning `false` or\n * `void` means it checked and found nothing to do.\n *\n * WATCH-FIRST, POLL AS A SAFETY NET:\n * The intended pattern is: a subscriber's own `intervalMs` is set generously\n * (roughly 4x looser than how quickly you actually want it checked), and a\n * filesystem watch is the fast path. When the watch fires, its handler calls\n * `wake()`, which runs every subscriber immediately regardless of backoff.\n * Polling on `intervalMs` only exists to cover the platforms and mount types\n * where filesystem watches are unreliable or simply do not fire. Neither path\n * is trusted alone: the watch gives latency, the poll interval gives a bound\n * on how late a check can ever be.\n *\n * DESIGN PATTERNS:\n * - Subscribers are checked for both \"due\" (their own `intervalMs` has\n * elapsed) and \"forced\" (a `wake()` call), so a fast-changing subscriber and\n * a rarely-changing one can share one clock without either starving\n * - A subscriber's key is internal and never the caller-supplied `id`, so two\n * subscribers that reuse the same `id` string (a plausible mistake with\n * per-run subscriber names) cannot make one's `unregister()` delete the\n * other's registration\n * - Synchronous subscribers still complete in the same tick. Async subscribers\n * are awaited sequentially, and forced wakes coalesce behind the active tick,\n * so slow filesystem work never creates overlapping scans\n *\n * AVOID:\n * - Reading `this.floorMs` (or the other seam fields) from the constructor:\n * field initializer order runs the base class's defaults before a test\n * subclass's overrides are applied, so a value read in the constructor would\n * see the base default even when a subclass overrides it. Everything that\n * needs these values reads them lazily, from `start()` or `tick()`, which run\n * after construction is complete\n * - Letting a subscriber's thrown error escape `tick()`; it must not stop the\n * tick or affect its peers. It is recorded rather than discarded, since a\n * subscriber that throws every tick otherwise looks identical to an idle one\n */\n\nimport { injectable } from 'inversify';\n\n/** Minimum spacing between ticks once nothing has reported work in a while. */\nconst DEFAULT_FLOOR_MS = 200;\n/** Ceiling the backoff grows toward while idle. */\nconst DEFAULT_CEILING_MS = 5_000;\n/** Growth factor applied to the tick interval on every idle tick. */\nconst DEFAULT_BACKOFF_MULTIPLIER = 2;\n\nexport interface PollSubscription {\n /** For readability in logs and error messages only; not used as a map key. */\n id: string;\n /** How often this subscriber is checked, in milliseconds. Must be positive. */\n intervalMs: number;\n /**\n * Called when due. Return `true` when it did real work, which resets the\n * scheduler's backoff to the floor. Return `false` or nothing when there was\n * nothing to do, which lets idle backoff continue growing.\n */\n run: () => boolean | void | Promise<boolean | undefined>;\n}\n\nexport interface IPollScheduler {\n /** Register a subscriber. Call the returned function to unregister it. */\n register(subscription: PollSubscription): () => void;\n /** Run every subscriber immediately, bypassing backoff and due-checks. */\n wake(): void;\n /** Begin ticking. Idempotent: a second call while running does nothing. */\n start(): void;\n /** Stop ticking and clear the pending timer. Idempotent. */\n stop(): void;\n}\n\ninterface InternalSubscriber extends PollSubscription {\n /** `undefined` until the first tick runs it; never `0`, which a test clock may legitimately start at. */\n lastRunAt: number | undefined;\n}\n\n@injectable()\nexport class PollScheduler implements IPollScheduler {\n /**\n * Seams for tests, as protected members rather than constructor arguments.\n * The container resolves this service by type, and inversify cannot supply a\n * primitive like a backoff curve, so a test subclass overrides these instead.\n */\n protected readonly floorMs: number = DEFAULT_FLOOR_MS;\n protected readonly ceilingMs: number = DEFAULT_CEILING_MS;\n protected readonly backoffMultiplier: number = DEFAULT_BACKOFF_MULTIPLIER;\n\n protected now(): number {\n return Date.now();\n }\n\n /**\n * Records a subscriber that threw. Overridable, and deliberately not a\n * stdio write: this runs inside a detached runner whose stdout is the child's\n * captured transcript. The composition root routes these into that process's\n * own diagnostics; the default keeps the most recent one queryable so a\n * failing subscriber can still be found after the fact.\n */\n protected onSubscriberError(id: string, error: unknown): void {\n this.lastSubscriberError = { id, error, at: this.now() };\n this.subscriberErrorCount += 1;\n }\n\n /** The most recent subscriber failure, for diagnostics. */\n lastSubscriberError: { id: string; error: unknown; at: number } | undefined;\n /** How many subscriber failures this scheduler has absorbed. */\n subscriberErrorCount = 0;\n\n private readonly subscribers = new Map<number, InternalSubscriber>();\n private nextSubscriberKey = 0;\n private timer: ReturnType<typeof setTimeout> | undefined;\n private currentIntervalMs: number | undefined;\n private running = false;\n private tickRunning = false;\n private forcedTickQueued = false;\n private generation = 0;\n\n register(subscription: PollSubscription): () => void {\n if (!(subscription.intervalMs > 0)) {\n throw new Error(`Poll subscriber \"${subscription.id}\" must have a positive intervalMs.`);\n }\n const key = this.nextSubscriberKey++;\n this.subscribers.set(key, { ...subscription, lastRunAt: undefined });\n return () => {\n this.subscribers.delete(key);\n };\n }\n\n start(): void {\n if (this.running) return;\n this.running = true;\n this.generation += 1;\n this.currentIntervalMs = this.floorMs;\n this.tick(false);\n }\n\n stop(): void {\n this.running = false;\n this.generation += 1;\n this.forcedTickQueued = false;\n if (this.timer) clearTimeout(this.timer);\n this.timer = undefined;\n }\n\n wake(): void {\n if (!this.running) return;\n if (this.timer) clearTimeout(this.timer);\n this.timer = undefined;\n this.tick(true);\n }\n\n /**\n * Run every due subscriber (or, when `forced`, every subscriber), fold the\n * outcome into the backoff curve, and schedule the next tick.\n */\n private tick(forced: boolean): void {\n if (this.tickRunning) {\n this.forcedTickQueued ||= forced;\n return;\n }\n\n this.tickRunning = true;\n const generation = this.generation;\n const timestamp = this.now();\n const subscribers = [...this.subscribers.values()];\n let workHappened = false;\n let anySubscriberRan = false;\n\n const finish = (): void => {\n if (generation === this.generation && anySubscriberRan) {\n const previousIntervalMs = this.currentIntervalMs ?? this.floorMs;\n this.currentIntervalMs = workHappened\n ? this.floorMs\n : Math.min(previousIntervalMs * this.backoffMultiplier, this.ceilingMs);\n }\n this.tickRunning = false;\n if (!this.running) return;\n if (this.forcedTickQueued || generation !== this.generation) {\n this.forcedTickQueued = false;\n this.tick(true);\n return;\n }\n this.scheduleNext();\n };\n\n const visit = (index: number): void => {\n if (generation !== this.generation) {\n finish();\n return;\n }\n for (let current = index; current < subscribers.length; current += 1) {\n const subscriber = subscribers[current];\n if (!subscriber) continue;\n const due =\n forced || subscriber.lastRunAt === undefined || timestamp - subscriber.lastRunAt >= subscriber.intervalMs;\n if (!due) continue;\n subscriber.lastRunAt = timestamp;\n anySubscriberRan = true;\n try {\n const result = subscriber.run();\n if (result instanceof Promise) {\n void result.then(\n (worked) => {\n if (worked) workHappened = true;\n visit(current + 1);\n },\n (error: unknown) => {\n this.onSubscriberError(subscriber.id, error);\n visit(current + 1);\n },\n );\n return;\n }\n if (result) workHappened = true;\n } catch (error) {\n this.onSubscriberError(subscriber.id, error);\n }\n }\n finish();\n };\n\n visit(0);\n }\n\n private scheduleNext(): void {\n if (!this.running) return;\n const delayMs = this.currentIntervalMs ?? this.floorMs;\n this.timer = setTimeout(() => this.tick(false), delayMs);\n // A pending background poll must never be the reason the process stays\n // alive; `unref` is optional only because some test timer shims omit it.\n this.timer.unref?.();\n }\n}\n"],"mappings":"6OAwDM,EAAmB,IAEnB,EAAqB,IAErB,EAA6B,IAgC5B,KAA8C,CAMnD,QAAqC,EACrC,UAAuC,EACvC,kBAA+C,EAE/C,KAAwB,CACtB,OAAO,KAAK,KAAK,CAUnB,kBAA4B,EAAY,EAAsB,CAC5D,KAAK,oBAAsB,CAAE,KAAI,QAAO,GAAI,KAAK,KAAK,CAAE,CACxD,KAAK,sBAAwB,EAI/B,oBAEA,qBAAuB,EAEvB,YAA+B,IAAI,IACnC,kBAA4B,EAC5B,MACA,kBACA,QAAkB,GAClB,YAAsB,GACtB,iBAA2B,GAC3B,WAAqB,EAErB,SAAS,EAA4C,CACnD,GAAI,EAAE,EAAa,WAAa,GAC9B,MAAU,MAAM,oBAAoB,EAAa,GAAG,oCAAoC,CAE1F,IAAM,EAAM,KAAK,oBAEjB,OADA,KAAK,YAAY,IAAI,EAAK,CAAE,GAAG,EAAc,UAAW,IAAA,GAAW,CAAC,KACvD,CACX,KAAK,YAAY,OAAO,EAAI,EAIhC,OAAc,CACR,KAAK,UACT,KAAK,QAAU,GACf,KAAK,YAAc,EACnB,KAAK,kBAAoB,KAAK,QAC9B,KAAK,KAAK,GAAM,EAGlB,MAAa,CACX,KAAK,QAAU,GACf,KAAK,YAAc,EACnB,KAAK,iBAAmB,GACpB,KAAK,OAAO,aAAa,KAAK,MAAM,CACxC,KAAK,MAAQ,IAAA,GAGf,MAAa,CACN,KAAK,UACN,KAAK,OAAO,aAAa,KAAK,MAAM,CACxC,KAAK,MAAQ,IAAA,GACb,KAAK,KAAK,GAAK,EAOjB,KAAa,EAAuB,CAClC,GAAI,KAAK,YAAa,CACpB,KAAK,mBAAqB,EAC1B,OAGF,KAAK,YAAc,GACnB,IAAM,EAAa,KAAK,WAClB,EAAY,KAAK,KAAK,CACtB,EAAc,CAAC,GAAG,KAAK,YAAY,QAAQ,CAAC,CAC9C,EAAe,GACf,EAAmB,GAEjB,MAAqB,CACzB,GAAI,IAAe,KAAK,YAAc,EAAkB,CACtD,IAAM,EAAqB,KAAK,mBAAqB,KAAK,QAC1D,KAAK,kBAAoB,EACrB,KAAK,QACL,KAAK,IAAI,EAAqB,KAAK,kBAAmB,KAAK,UAAU,CAE3E,QAAK,YAAc,GACd,KAAK,QACV,IAAI,KAAK,kBAAoB,IAAe,KAAK,WAAY,CAC3D,KAAK,iBAAmB,GACxB,KAAK,KAAK,GAAK,CACf,OAEF,KAAK,cAAc,GAGf,EAAS,GAAwB,CACrC,GAAI,IAAe,KAAK,WAAY,CAClC,GAAQ,CACR,OAEF,IAAK,IAAI,EAAU,EAAO,EAAU,EAAY,OAAQ,GAAW,EAAG,CACpE,IAAM,EAAa,EAAY,GAC1B,OAEH,GAAU,EAAW,YAAc,IAAA,IAAa,EAAY,EAAW,WAAa,EAAW,YAGjG,CADA,EAAW,UAAY,EACvB,EAAmB,GACnB,GAAI,CACF,IAAM,EAAS,EAAW,KAAK,CAC/B,GAAI,aAAkB,QAAS,CACxB,EAAO,KACT,GAAW,CACN,IAAQ,EAAe,IAC3B,EAAM,EAAU,EAAE,EAEnB,GAAmB,CAClB,KAAK,kBAAkB,EAAW,GAAI,EAAM,CAC5C,EAAM,EAAU,EAAE,EAErB,CACD,OAEE,IAAQ,EAAe,UACpB,EAAO,CACd,KAAK,kBAAkB,EAAW,GAAI,EAAM,GAGhD,GAAQ,EAGV,EAAM,EAAE,CAGV,cAA6B,CAC3B,GAAI,CAAC,KAAK,QAAS,OACnB,IAAM,EAAU,KAAK,mBAAqB,KAAK,QAC/C,KAAK,MAAQ,eAAiB,KAAK,KAAK,GAAM,CAAE,EAAQ,CAGxD,KAAK,MAAM,SAAS,QA1JvB,GAAY,CAAA,CAAA,EAAA"}
@@ -0,0 +1,5 @@
1
+ const e=require(`../../_virtual/_rolldown/runtime.cjs`);let t=require(`node:fs`);t=e.__toESM(t,1);let n=require(`node:path`);n=e.__toESM(n,1);const r=1024;1024*r,32*r;const i=`
2
+
3
+ … payload truncated`,a=[`command`,`path`,`file_path`,`pattern`,`query`,`url`,`task`,`describe`,`search`];function o(e){return e instanceof Error?e.message:String(e)}function s(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function c(e,t=32768){let n;if(typeof e==`string`)n=e;else try{let t=JSON.stringify(e,null,2);if(t===void 0)return;n=t}catch{return}if(!n.trim())return;let r=Buffer.from(n,`utf-8`);if(r.length<=t)return{text:n,truncated:!1};let a=Buffer.byteLength(i,`utf-8`),o=Math.max(0,t-a);for(;o>0&&((r[o]??0)&192)==128;)o--;return{text:`${r.subarray(0,o).toString(`utf-8`)}${i}`,truncated:!0}}function l(e){if(!e||typeof e!=`object`)return;let t=e,n=t.cost,r=n&&typeof n==`object`?s(n.total)??0:s(n)??0;return{input:s(t.input)??s(t.inputTokens)??0,output:s(t.output)??s(t.outputTokens)??0,cacheRead:s(t.cacheRead)??0,cacheWrite:s(t.cacheWrite)??0,cost:r}}function u(e){if(e.role!==`assistant`||!e.usage||typeof e.usage!=`object`)return;let t=e.usage,n=s(t.totalTokens);if(n!==void 0)return n;let r=l(e.usage);if(r)return r.input+r.output+r.cacheRead+r.cacheWrite}function d(e){if(!(e.role!==`assistant`||!Array.isArray(e.content)))for(let t=e.content.length-1;t>=0;--t){let n=e.content[t];if(!n||typeof n!=`object`)continue;let r=n,i=(r.type===`thinking`&&typeof r.thinking==`string`?r.thinking:typeof r.text==`string`?r.text:void 0)?.replace(/\s+/g,` `).trim();if(i)return i.length<=72?`working: ${i}`:`working: …${i.slice(-71)}`}}function f(e,t){return e.length>t?`${e.slice(0,t-3)}...`:e}function p(e){if(typeof e==`string`&&e.trim().length>0)return e;if(typeof e==`number`||typeof e==`boolean`)return String(e)}function m(e){if(!Array.isArray(e)||e.length===0)return;let t=p(e[0]);if(t)return`${t}${e.length>1?` (+${e.length-1} more)`:``}`}function h(e){if(typeof e.tool==`string`&&e.tool){let t=typeof e.server==`string`&&e.server?`${e.server}/`:``,n=typeof e.args==`string`&&e.args?` ${e.args.slice(0,40)}`:``;return`${t}${e.tool}${n}`}let t=m(e.queries);if(t)return f(t,60);if(typeof e.query==`string`&&e.query.trim().length>0)return f(e.query,60);if(typeof e.workflow==`string`&&e.workflow.trim().length>0)return`workflow=${f(e.workflow,48)}`;if(typeof e.url==`string`&&e.url.trim().length>0)return f(e.url,60);let n=m(e.urls);if(n)return f(n,60);if(typeof e.prompt==`string`&&e.prompt.trim().length>0)return f(e.prompt,60);for(let t of a){let n=e[t];if(typeof n==`string`&&n.length>0)return f(n,60)}for(let[t,n]of Object.entries(e)){let e=m(n);if(e)return`${t}=${f(e,50)}`;if(typeof n==`string`&&n.length>0)return`${t}=${f(n,50)}`}return``}function g(e,t){if(!t||typeof t!=`object`||Array.isArray(t))return e;let n=h(t);return n?`${e} (${n})`:e}function _(e){if(!e)return``;if(typeof e==`string`)return e;if(!Array.isArray(e))return``;let t=[];for(let n of e){if(!n||typeof n!=`object`)continue;let e=n;if(e.type===`text`&&`text`in e)t.push(String(e.text));else if(e.type===`tool_result`&&`content`in e){let n=_(e.content);n&&t.push(n)}else `text`in e&&t.push(String(e.text))}return t.join(`
4
+ `)}function v(e){return e.args&&typeof e.args==`object`&&!Array.isArray(e.args)?e.args:{}}function y(e){let r=0,i,a=!1,s=e.maxBytes??52428800,u=t=>{let n=Date.now();return{version:1,recordType:t,source:e.source,runId:e.runId,agent:e.agent,...e.childIndex===void 0?{}:{childIndex:e.childIndex},cwd:e.cwd,ts:n,timestamp:new Date(n).toISOString()}},d=()=>`${JSON.stringify({...u(`truncated`),maxBytes:s,message:`Child transcript exceeded ${s} bytes; further records were omitted.`})}\n`,f=Buffer.byteLength(d(),`utf-8`),p=()=>{a=!0;let n=d(),c=Buffer.byteLength(n,`utf-8`);if(!(r+c>s))try{t.appendFileSync(e.transcriptPath,n,`utf-8`),r+=c}catch(t){i=`Failed to write child transcript '${e.transcriptPath}': ${o(t)}`}},m=n=>{if(i||a)return;let c=`${JSON.stringify(n)}\n`,l=Buffer.byteLength(c,`utf-8`);if(r+l+f>s){p();return}try{t.appendFileSync(e.transcriptPath,c,`utf-8`),r+=l}catch(t){i=`Failed to write child transcript '${e.transcriptPath}': ${o(t)}`}};try{t.mkdirSync(n.dirname(e.transcriptPath),{recursive:!0}),t.writeFileSync(e.transcriptPath,``,`utf-8`)}catch(t){i=`Failed to initialize child transcript '${e.transcriptPath}': ${o(t)}`}let g=(e,t)=>{let n=_(t.content),r=l(t.usage);if(t.role===`toolResult`){let r=c(n);m({...u(`message`),sourceEventType:e,role:t.role,toolCallId:t.toolCallId,toolName:t.toolName,isError:t.isError,...r?{text:r.text,outputTruncated:r.truncated}:{},message:{role:t.role,toolCallId:t.toolCallId,toolName:t.toolName,isError:t.isError,content:r?[{type:`text`,text:r.text}]:[],...t.timestamp===void 0?{}:{timestamp:t.timestamp}}});return}m({...u(`message`),sourceEventType:e,role:t.role,...n?{text:n}:{},...t.model?{model:t.model}:{},...t.stopReason?{stopReason:t.stopReason}:{},...t.errorMessage?{errorMessage:t.errorMessage}:{},...r?{usage:r}:{},message:t})},y=e=>{e.trim()&&m({...u(`stderr`),text:e})};return{path:e.transcriptPath,writeInitialUserMessage(e){m({...u(`message`),sourceEventType:`initial_prompt`,role:`user`,text:e,message:{role:`user`,content:[{type:`text`,text:e}]}})},writeChildEvent(e){if((e.type===`message_end`||e.type===`tool_result_end`)&&e.message){g(e.type,e.message);return}if(e.type===`tool_execution_start`&&e.toolName){let t=v(e),n=c(t);m({...u(`tool_start`),sourceEventType:e.type,...e.toolCallId?{toolCallId:e.toolCallId}:{},toolName:e.toolName,...Object.keys(t).length>0?{argsPreview:h(t)}:{},...n?{argsPayload:n.text}:{}});return}e.type===`tool_execution_end`&&m({...u(`tool_end`),sourceEventType:e.type,...e.toolCallId?{toolCallId:e.toolCallId}:{},...e.toolName?{toolName:e.toolName}:{},...typeof e.isError==`boolean`?{isError:e.isError}:{}})},writeStdoutLine(e){e.trim()&&m({...u(`stdout`),text:e})},writeStderrLine:y,writeStderrText(e){for(let t of e.split(/\r?\n/))y(t)},getError(){return i}}}exports.createChildTranscriptWriter=y,exports.extractToolArgsPreview=h,exports.formatToolActivity=g,exports.getMessageActivity=d,exports.getMessageUsageTokens=u;
5
+ //# sourceMappingURL=childTranscript.cjs.map