@agimon-ai/po-runner 0.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +257 -0
  3. package/dist/ansiScrub-CsqTSaVT.mjs +71 -0
  4. package/dist/ansiScrub-CsqTSaVT.mjs.map +1 -0
  5. package/dist/ansiScrub-D5gpHDch.cjs +100 -0
  6. package/dist/ansiScrub-D5gpHDch.cjs.map +1 -0
  7. package/dist/ansiScrub.cjs +7 -0
  8. package/dist/ansiScrub.d.mts +26 -0
  9. package/dist/ansiScrub.d.mts.map +1 -0
  10. package/dist/ansiScrub.mjs +2 -0
  11. package/dist/apiContracts.cjs +162 -0
  12. package/dist/apiContracts.cjs.map +1 -0
  13. package/dist/apiContracts.d.mts +53 -0
  14. package/dist/apiContracts.d.mts.map +1 -0
  15. package/dist/apiContracts.mjs +157 -0
  16. package/dist/apiContracts.mjs.map +1 -0
  17. package/dist/bashResult-DNgtahGR.cjs +629 -0
  18. package/dist/bashResult-DNgtahGR.cjs.map +1 -0
  19. package/dist/bashResult-DcrRaBLv.d.mts +49 -0
  20. package/dist/bashResult-DcrRaBLv.d.mts.map +1 -0
  21. package/dist/bashResult-bIVSzoj-.mjs +546 -0
  22. package/dist/bashResult-bIVSzoj-.mjs.map +1 -0
  23. package/dist/bashRunService-CJ02XaAq.mjs +440 -0
  24. package/dist/bashRunService-CJ02XaAq.mjs.map +1 -0
  25. package/dist/bashRunService-Ci0cGdYO.d.mts +71 -0
  26. package/dist/bashRunService-Ci0cGdYO.d.mts.map +1 -0
  27. package/dist/bashRunService-DyqxOSlx.cjs +445 -0
  28. package/dist/bashRunService-DyqxOSlx.cjs.map +1 -0
  29. package/dist/bashRunService.cjs +3 -0
  30. package/dist/bashRunService.d.mts +36 -0
  31. package/dist/bashRunService.d.mts.map +1 -0
  32. package/dist/bashRunService.mjs +2 -0
  33. package/dist/bashSchema.cjs +5 -0
  34. package/dist/bashSchema.d.mts +7 -0
  35. package/dist/bashSchema.d.mts.map +1 -0
  36. package/dist/bashSchema.mjs +2 -0
  37. package/dist/bashTool-B1EwZLo_.d.mts +20 -0
  38. package/dist/bashTool-B1EwZLo_.d.mts.map +1 -0
  39. package/dist/bashTool-C-k7fmyh.mjs +24 -0
  40. package/dist/bashTool-C-k7fmyh.mjs.map +1 -0
  41. package/dist/bashTool-CdgtqVFD.cjs +41 -0
  42. package/dist/bashTool-CdgtqVFD.cjs.map +1 -0
  43. package/dist/bashTool.cjs +13 -0
  44. package/dist/bashTool.cjs.map +1 -0
  45. package/dist/bashTool.d.mts +8 -0
  46. package/dist/bashTool.d.mts.map +1 -0
  47. package/dist/bashTool.mjs +11 -0
  48. package/dist/bashTool.mjs.map +1 -0
  49. package/dist/bin/cli.cjs +78 -0
  50. package/dist/bin/cli.cjs.map +1 -0
  51. package/dist/bin/cli.d.mts +4 -0
  52. package/dist/bin/cli.d.mts.map +1 -0
  53. package/dist/bin/cli.mjs +77 -0
  54. package/dist/bin/cli.mjs.map +1 -0
  55. package/dist/bin/logSink.cjs +102 -0
  56. package/dist/bin/logSink.cjs.map +1 -0
  57. package/dist/bin/logSink.d.mts +4 -0
  58. package/dist/bin/logSink.d.mts.map +1 -0
  59. package/dist/bin/logSink.mjs +99 -0
  60. package/dist/bin/logSink.mjs.map +1 -0
  61. package/dist/bin/runnerHost.cjs +131 -0
  62. package/dist/bin/runnerHost.cjs.map +1 -0
  63. package/dist/bin/runnerHost.d.mts +4 -0
  64. package/dist/bin/runnerHost.d.mts.map +1 -0
  65. package/dist/bin/runnerHost.mjs +127 -0
  66. package/dist/bin/runnerHost.mjs.map +1 -0
  67. package/dist/cliApp-Dj9nwaOv.cjs +244 -0
  68. package/dist/cliApp-Dj9nwaOv.cjs.map +1 -0
  69. package/dist/cliApp-v8Z3rMCi.mjs +237 -0
  70. package/dist/cliApp-v8Z3rMCi.mjs.map +1 -0
  71. package/dist/cliApp.cjs +3 -0
  72. package/dist/cliApp.d.mts +18 -0
  73. package/dist/cliApp.d.mts.map +1 -0
  74. package/dist/cliApp.mjs +2 -0
  75. package/dist/clock-Cv2pddgo.mjs +16 -0
  76. package/dist/clock-Cv2pddgo.mjs.map +1 -0
  77. package/dist/clock-euJkweLq.d.mts +11 -0
  78. package/dist/clock-euJkweLq.d.mts.map +1 -0
  79. package/dist/clock-jqnLWziT.cjs +21 -0
  80. package/dist/clock-jqnLWziT.cjs.map +1 -0
  81. package/dist/clock.cjs +3 -0
  82. package/dist/clock.d.mts +10 -0
  83. package/dist/clock.d.mts.map +1 -0
  84. package/dist/clock.mjs +2 -0
  85. package/dist/compaction-4QSUsBxq.cjs +40 -0
  86. package/dist/compaction-4QSUsBxq.cjs.map +1 -0
  87. package/dist/compaction-DCw80VZj.mjs +29 -0
  88. package/dist/compaction-DCw80VZj.mjs.map +1 -0
  89. package/dist/compaction.cjs +4 -0
  90. package/dist/compaction.d.mts +10 -0
  91. package/dist/compaction.d.mts.map +1 -0
  92. package/dist/compaction.mjs +2 -0
  93. package/dist/config.cjs +41 -0
  94. package/dist/config.d.mts +2 -0
  95. package/dist/config.mjs +2 -0
  96. package/dist/extensions/mcp-ui.mjs +23 -0
  97. package/dist/extensions/mcp-ui.mjs.map +1 -0
  98. package/dist/extensions/mcp.cjs +142 -0
  99. package/dist/extensions/mcp.cjs.map +1 -0
  100. package/dist/extensions/mcp.d.mts +5 -0
  101. package/dist/extensions/mcp.d.mts.map +1 -0
  102. package/dist/extensions/mcp.mjs +114 -0
  103. package/dist/extensions/mcp.mjs.map +1 -0
  104. package/dist/extensions/server.cjs +1156 -0
  105. package/dist/extensions/server.cjs.map +1 -0
  106. package/dist/extensions/server.d.mts +5 -0
  107. package/dist/extensions/server.d.mts.map +1 -0
  108. package/dist/extensions/server.mjs +1146 -0
  109. package/dist/extensions/server.mjs.map +1 -0
  110. package/dist/extensions/web.mjs +1785 -0
  111. package/dist/extensions/web.mjs.map +1 -0
  112. package/dist/headless-BGYfIlNk.mjs +169 -0
  113. package/dist/headless-BGYfIlNk.mjs.map +1 -0
  114. package/dist/headless-CHUsBGhg.cjs +180 -0
  115. package/dist/headless-CHUsBGhg.cjs.map +1 -0
  116. package/dist/index-BZL7keVW.d.mts +31 -0
  117. package/dist/index-BZL7keVW.d.mts.map +1 -0
  118. package/dist/index-BwB_jTI9.d.mts +12 -0
  119. package/dist/index-BwB_jTI9.d.mts.map +1 -0
  120. package/dist/index-D9-IXax4.d.mts +43 -0
  121. package/dist/index-D9-IXax4.d.mts.map +1 -0
  122. package/dist/index-DBz0DxnL.d.mts +39 -0
  123. package/dist/index-DBz0DxnL.d.mts.map +1 -0
  124. package/dist/index-DM7yJpMs.d.mts +25 -0
  125. package/dist/index-DM7yJpMs.d.mts.map +1 -0
  126. package/dist/index-Dhi8asLH.d.mts +22 -0
  127. package/dist/index-Dhi8asLH.d.mts.map +1 -0
  128. package/dist/index.cjs +19 -0
  129. package/dist/index.d.mts +7 -0
  130. package/dist/index.mjs +6 -0
  131. package/dist/launcher-BDm6-DiQ.mjs +150 -0
  132. package/dist/launcher-BDm6-DiQ.mjs.map +1 -0
  133. package/dist/launcher-BG5t9nvG.d.mts +39 -0
  134. package/dist/launcher-BG5t9nvG.d.mts.map +1 -0
  135. package/dist/launcher-SlyE8R3b.cjs +157 -0
  136. package/dist/launcher-SlyE8R3b.cjs.map +1 -0
  137. package/dist/launcher.cjs +3 -0
  138. package/dist/launcher.d.mts +33 -0
  139. package/dist/launcher.d.mts.map +1 -0
  140. package/dist/launcher.mjs +2 -0
  141. package/dist/lifeline-BZaQA0rm.mjs +88 -0
  142. package/dist/lifeline-BZaQA0rm.mjs.map +1 -0
  143. package/dist/lifeline-BuV_erib.cjs +98 -0
  144. package/dist/lifeline-BuV_erib.cjs.map +1 -0
  145. package/dist/lifeline-eJdZV0nN.d.mts +19 -0
  146. package/dist/lifeline-eJdZV0nN.d.mts.map +1 -0
  147. package/dist/lifeline.cjs +6 -0
  148. package/dist/lifeline.d.mts +21 -0
  149. package/dist/lifeline.d.mts.map +1 -0
  150. package/dist/lifeline.mjs +3 -0
  151. package/dist/logFile-C7oQ_v-g.d.mts +16 -0
  152. package/dist/logFile-C7oQ_v-g.d.mts.map +1 -0
  153. package/dist/logFile-CNvepZh0.cjs +67 -0
  154. package/dist/logFile-CNvepZh0.cjs.map +1 -0
  155. package/dist/logFile-KKPbkC-a.mjs +60 -0
  156. package/dist/logFile-KKPbkC-a.mjs.map +1 -0
  157. package/dist/logFile.cjs +3 -0
  158. package/dist/logFile.d.mts +11 -0
  159. package/dist/logFile.d.mts.map +1 -0
  160. package/dist/logFile.mjs +2 -0
  161. package/dist/logReader-B6J7L7Ua.cjs +282 -0
  162. package/dist/logReader-B6J7L7Ua.cjs.map +1 -0
  163. package/dist/logReader-MdW9ffvV.d.mts +43 -0
  164. package/dist/logReader-MdW9ffvV.d.mts.map +1 -0
  165. package/dist/logReader-UfbDbwQl.mjs +257 -0
  166. package/dist/logReader-UfbDbwQl.mjs.map +1 -0
  167. package/dist/logReader.cjs +4 -0
  168. package/dist/logReader.d.mts +3 -0
  169. package/dist/logReader.mjs +2 -0
  170. package/dist/processControl-BAOa3oo_.d.mts +14 -0
  171. package/dist/processControl-BAOa3oo_.d.mts.map +1 -0
  172. package/dist/processControl-DApTpV16.mjs +26 -0
  173. package/dist/processControl-DApTpV16.mjs.map +1 -0
  174. package/dist/processControl-DNJ1WZ9N.cjs +31 -0
  175. package/dist/processControl-DNJ1WZ9N.cjs.map +1 -0
  176. package/dist/processControl.cjs +3 -0
  177. package/dist/processControl.d.mts +10 -0
  178. package/dist/processControl.d.mts.map +1 -0
  179. package/dist/processControl.mjs +2 -0
  180. package/dist/ptyHost-DWWtRrGn.d.mts +38 -0
  181. package/dist/ptyHost-DWWtRrGn.d.mts.map +1 -0
  182. package/dist/ptyHost-DlQtTB8F.mjs +150 -0
  183. package/dist/ptyHost-DlQtTB8F.mjs.map +1 -0
  184. package/dist/ptyHost-MI2Z6WTG.cjs +157 -0
  185. package/dist/ptyHost-MI2Z6WTG.cjs.map +1 -0
  186. package/dist/ptyHost.cjs +3 -0
  187. package/dist/ptyHost.d.mts +26 -0
  188. package/dist/ptyHost.d.mts.map +1 -0
  189. package/dist/ptyHost.mjs +2 -0
  190. package/dist/ptySpawner-B6GsueZd.d.mts +28 -0
  191. package/dist/ptySpawner-B6GsueZd.d.mts.map +1 -0
  192. package/dist/ptySpawner-DEi1KOnd.mjs +17 -0
  193. package/dist/ptySpawner-DEi1KOnd.mjs.map +1 -0
  194. package/dist/ptySpawner-ijw0g5_T.cjs +22 -0
  195. package/dist/ptySpawner-ijw0g5_T.cjs.map +1 -0
  196. package/dist/ptySpawner.cjs +3 -0
  197. package/dist/ptySpawner.d.mts +14 -0
  198. package/dist/ptySpawner.d.mts.map +1 -0
  199. package/dist/ptySpawner.mjs +2 -0
  200. package/dist/reconcile-BugwYFbV.cjs +133 -0
  201. package/dist/reconcile-BugwYFbV.cjs.map +1 -0
  202. package/dist/reconcile-DMeNSxwn.mjs +114 -0
  203. package/dist/reconcile-DMeNSxwn.mjs.map +1 -0
  204. package/dist/reconcile.cjs +5 -0
  205. package/dist/reconcile.d.mts +36 -0
  206. package/dist/reconcile.d.mts.map +1 -0
  207. package/dist/reconcile.mjs +2 -0
  208. package/dist/responseEnvelope.cjs +19 -0
  209. package/dist/responseEnvelope.d.mts +50 -0
  210. package/dist/responseEnvelope.d.mts.map +1 -0
  211. package/dist/responseEnvelope.mjs +3 -0
  212. package/dist/rmuxBackend-CaEWooWn.d.mts +36 -0
  213. package/dist/rmuxBackend-CaEWooWn.d.mts.map +1 -0
  214. package/dist/rmuxBackend-DfyQwJrc.mjs +509 -0
  215. package/dist/rmuxBackend-DfyQwJrc.mjs.map +1 -0
  216. package/dist/rmuxBackend-DlxgqRZ1.cjs +523 -0
  217. package/dist/rmuxBackend-DlxgqRZ1.cjs.map +1 -0
  218. package/dist/rmuxBackend.cjs +4 -0
  219. package/dist/rmuxBackend.d.mts +3 -0
  220. package/dist/rmuxBackend.mjs +2 -0
  221. package/dist/rolldown-runtime-VH7oDXx4.cjs +28 -0
  222. package/dist/rtkProcessor-B4_urXQr.mjs +10 -0
  223. package/dist/rtkProcessor-B4_urXQr.mjs.map +1 -0
  224. package/dist/rtkProcessor-B9KPdyzr.mjs +309 -0
  225. package/dist/rtkProcessor-B9KPdyzr.mjs.map +1 -0
  226. package/dist/rtkProcessor-Bc4L4o_8.cjs +335 -0
  227. package/dist/rtkProcessor-Bc4L4o_8.cjs.map +1 -0
  228. package/dist/rtkProcessor-CVZvNhkJ.d.mts +35 -0
  229. package/dist/rtkProcessor-CVZvNhkJ.d.mts.map +1 -0
  230. package/dist/rtkProcessor-CsrCPyTQ.cjs +33 -0
  231. package/dist/rtkProcessor-CsrCPyTQ.cjs.map +1 -0
  232. package/dist/rtkProcessor.cjs +11 -0
  233. package/dist/rtkProcessor.d.mts +7 -0
  234. package/dist/rtkProcessor.d.mts.map +1 -0
  235. package/dist/rtkProcessor.mjs +3 -0
  236. package/dist/runnerConfig-BQBlVAXn.mjs +134 -0
  237. package/dist/runnerConfig-BQBlVAXn.mjs.map +1 -0
  238. package/dist/runnerConfig-BjtulXBI.d.mts +57 -0
  239. package/dist/runnerConfig-BjtulXBI.d.mts.map +1 -0
  240. package/dist/runnerConfig-D2tGq5ZM.cjs +367 -0
  241. package/dist/runnerConfig-D2tGq5ZM.cjs.map +1 -0
  242. package/dist/runnerDependencies-DruByBGS.mjs +647 -0
  243. package/dist/runnerDependencies-DruByBGS.mjs.map +1 -0
  244. package/dist/runnerDependencies-KMZigIxB.cjs +667 -0
  245. package/dist/runnerDependencies-KMZigIxB.cjs.map +1 -0
  246. package/dist/runnerDependencies.cjs +3 -0
  247. package/dist/runnerDependencies.d.mts +2 -0
  248. package/dist/runnerDependencies.mjs +2 -0
  249. package/dist/runnerNamer-B8FH7n2v.mjs +44 -0
  250. package/dist/runnerNamer-B8FH7n2v.mjs.map +1 -0
  251. package/dist/runnerNamer-we1XVYfM.cjs +49 -0
  252. package/dist/runnerNamer-we1XVYfM.cjs.map +1 -0
  253. package/dist/runnerNamer.cjs +3 -0
  254. package/dist/runnerNamer.d.mts +11 -0
  255. package/dist/runnerNamer.d.mts.map +1 -0
  256. package/dist/runnerNamer.mjs +2 -0
  257. package/dist/runnerPaths-BTEuzxw0.cjs +471 -0
  258. package/dist/runnerPaths-BTEuzxw0.cjs.map +1 -0
  259. package/dist/runnerPaths-B_dAAeco.mjs +451 -0
  260. package/dist/runnerPaths-B_dAAeco.mjs.map +1 -0
  261. package/dist/runnerPaths.cjs +3 -0
  262. package/dist/runnerPaths.d.mts +50 -0
  263. package/dist/runnerPaths.d.mts.map +1 -0
  264. package/dist/runnerPaths.mjs +2 -0
  265. package/dist/runnerRegistry-BmkZTJHi.cjs +371 -0
  266. package/dist/runnerRegistry-BmkZTJHi.cjs.map +1 -0
  267. package/dist/runnerRegistry-CeOHEjBv.mjs +339 -0
  268. package/dist/runnerRegistry-CeOHEjBv.mjs.map +1 -0
  269. package/dist/runnerRegistry-CtJiD02R.d.mts +88 -0
  270. package/dist/runnerRegistry-CtJiD02R.d.mts.map +1 -0
  271. package/dist/runnerRegistry.cjs +4 -0
  272. package/dist/runnerRegistry.d.mts +3 -0
  273. package/dist/runnerRegistry.mjs +2 -0
  274. package/dist/runnerSettings-DiV1lvzx.d.mts +34 -0
  275. package/dist/runnerSettings-DiV1lvzx.d.mts.map +1 -0
  276. package/dist/services/lifeline/client.cjs +52 -0
  277. package/dist/services/lifeline/client.cjs.map +1 -0
  278. package/dist/services/lifeline/client.d.mts +22 -0
  279. package/dist/services/lifeline/client.d.mts.map +1 -0
  280. package/dist/services/lifeline/client.mjs +48 -0
  281. package/dist/services/lifeline/client.mjs.map +1 -0
  282. package/dist/services/runnerSupervisor/index.cjs +207 -0
  283. package/dist/services/runnerSupervisor/index.cjs.map +1 -0
  284. package/dist/services/runnerSupervisor/index.d.mts +71 -0
  285. package/dist/services/runnerSupervisor/index.d.mts.map +1 -0
  286. package/dist/services/runnerSupervisor/index.mjs +195 -0
  287. package/dist/services/runnerSupervisor/index.mjs.map +1 -0
  288. package/dist/session-BC43uEyG.cjs +29 -0
  289. package/dist/session-BC43uEyG.cjs.map +1 -0
  290. package/dist/session-Chsb_Nh2.mjs +18 -0
  291. package/dist/session-Chsb_Nh2.mjs.map +1 -0
  292. package/dist/session-DE2Acesp.mjs +6 -0
  293. package/dist/session-DE2Acesp.mjs.map +1 -0
  294. package/dist/session-SfIPtdZO.cjs +11 -0
  295. package/dist/session-SfIPtdZO.cjs.map +1 -0
  296. package/dist/session.cjs +6 -0
  297. package/dist/session.d.mts +11 -0
  298. package/dist/session.d.mts.map +1 -0
  299. package/dist/session.mjs +3 -0
  300. package/dist/spawner-BxFsINXP.cjs +68 -0
  301. package/dist/spawner-BxFsINXP.cjs.map +1 -0
  302. package/dist/spawner-CdrN_HNk.d.mts +35 -0
  303. package/dist/spawner-CdrN_HNk.d.mts.map +1 -0
  304. package/dist/spawner-LoVsn55-.mjs +63 -0
  305. package/dist/spawner-LoVsn55-.mjs.map +1 -0
  306. package/dist/spawner.cjs +3 -0
  307. package/dist/spawner.d.mts +9 -0
  308. package/dist/spawner.d.mts.map +1 -0
  309. package/dist/spawner.mjs +2 -0
  310. package/dist/type-BXM03qSw.d.mts +44 -0
  311. package/dist/type-BXM03qSw.d.mts.map +1 -0
  312. package/dist/type-C31e1gla.d.mts +43 -0
  313. package/dist/type-C31e1gla.d.mts.map +1 -0
  314. package/dist/type-vWQNTahw.d.mts +12 -0
  315. package/dist/type-vWQNTahw.d.mts.map +1 -0
  316. package/dist/types.cjs +0 -0
  317. package/dist/types.d.mts +3 -0
  318. package/dist/types.mjs +1 -0
  319. package/llms.txt +9 -0
  320. package/package.json +303 -0
  321. package/skills/doom-runner/SKILL.md +78 -0
  322. package/src/prompts/po-use-runner/SKILL.md +47 -0
@@ -0,0 +1,1146 @@
1
+ import { c as getLogTtlMs } from "../runnerConfig-BQBlVAXn.mjs";
2
+ import { r as summarizeLog, t as LogReader } from "../logReader-UfbDbwQl.mjs";
3
+ import { n as createHeadlessRunnersCommand, t as createHeadlessBashTool } from "../headless-BGYfIlNk.mjs";
4
+ import { n as reconcileActiveRunners, r as stopRunnerProcess, t as cleanupLegacyRunnerStore } from "../reconcile-DMeNSxwn.mjs";
5
+ import { t as activeRunnerRecovery } from "../compaction-DCw80VZj.mjs";
6
+ import { t as RmuxBackend } from "../rmuxBackend-DfyQwJrc.mjs";
7
+ import { n as TmuxBackend, r as PtyBackendChain, t as createRunnerDependencies } from "../runnerDependencies-DruByBGS.mjs";
8
+ import { n as resolveRunnerStoreDirectory, r as runnerStateDirFor, t as RunnerPaths } from "../runnerPaths-B_dAAeco.mjs";
9
+ import { a as isRunnerRecord, i as formatRunnerStatus, r as formatRunnerFinished } from "../runnerRegistry-CeOHEjBv.mjs";
10
+ import fs from "node:fs";
11
+ import path from "node:path";
12
+ import { resolveRootSessionId } from "@agimon-ai/po-core/childProcess";
13
+ import { composeServerProviderOverrides, defineServerPlugin, packageResourcePath, readPackageResource } from "@agimon-ai/po-core/serverFacet";
14
+ import { composeRootHooks, defineChannel, defineHook, defineResource, defineRoot, defineRoute, defineServerCommand, defineServerTool } from "@agimon-ai/po-core/extensionFile";
15
+ import { DOOM_BACKGROUND_WORK_SERVICE, readDoomBackgroundWorkService } from "@agimon-ai/po-core/backgroundWork";
16
+ import { createDoomTelemetry } from "@agimon-ai/po-telemetry";
17
+ import { CONFIG_DIR_NAME } from "@earendil-works/pi-coding-agent";
18
+ import { Hono } from "hono";
19
+ import { streamSSE } from "hono/streaming";
20
+ import { apiResponse, defineApiRoutes } from "@agimon-ai/po-core/web";
21
+ import { DOOM_HELP_WHEN } from "@agimon-ai/po-core/help";
22
+ //#region src/constants/runnerSettings.ts
23
+ const RUNNER_SETTINGS_FILE = "po-runner.json";
24
+ const RATIO_KEYS = ["headRatio", "errorBudgetRatio"];
25
+ const MAX_RESULT_BYTES_CEILING = 262144;
26
+ const MAX_RESULT_LINES_CEILING = 5e3;
27
+ const MAX_RESULT_TOKENS_CEILING = 1e5;
28
+ //#endregion
29
+ //#region src/constants/runnerRuntime.ts
30
+ const RUNNER_STATUS_KEY = "doom-runner-runners";
31
+ const BACKGROUND_WORK_PROVIDER = "doom-runner";
32
+ const HISTORY_SWEEP_INTERVAL_MS = 6e5;
33
+ //#endregion
34
+ //#region src/constants/webRunners.ts
35
+ const RUNNER_RUNS_TYPE = "runner_runs";
36
+ //#endregion
37
+ //#region src/services/webRunnerRuns/index.ts
38
+ /** How long a finished runner stays in the cockpit's feed after it exited. */
39
+ /** One on-disk metadata record, or undefined when the text is not a runner record. */
40
+ function parseRunnerRecord(raw) {
41
+ try {
42
+ const parsed = JSON.parse(raw);
43
+ return isRunnerRecord(parsed) ? parsed : void 0;
44
+ } catch {
45
+ return;
46
+ }
47
+ }
48
+ function toRunnerRunView(record) {
49
+ return {
50
+ id: record.id,
51
+ name: record.name,
52
+ pid: record.pid,
53
+ command: record.command,
54
+ cwd: record.cwd,
55
+ interactive: record.interactive,
56
+ backend: record.backend,
57
+ state: record.state,
58
+ promoted: record.promoted,
59
+ startedAt: record.startedAt,
60
+ logPath: record.logPath,
61
+ ...record.exit ? { exit: {
62
+ reason: record.exit.reason,
63
+ code: record.exit.code,
64
+ signal: record.exit.signal,
65
+ ...record.exit.terminationReason === void 0 ? {} : { terminationReason: record.exit.terminationReason },
66
+ ...record.exit.stopReason === void 0 ? {} : { stopReason: record.exit.stopReason },
67
+ finishedAt: record.exit.finishedAt
68
+ } } : {}
69
+ };
70
+ }
71
+ function finishedAt(record) {
72
+ const parsed = record.exit === void 0 ? NaN : Date.parse(record.exit.finishedAt);
73
+ return Number.isFinite(parsed) ? parsed : Date.parse(record.startedAt);
74
+ }
75
+ /**
76
+ * The feed the cockpit shows: running runners first, newest start first, then
77
+ * the recently finished ones, newest exit first. Finished runners older than
78
+ * the retention window are left out; the registry keeps them for the CLI.
79
+ */
80
+ function presentRunnerRuns(records, now) {
81
+ const running = records.filter((record) => record.state === "running").sort((left, right) => right.startedAt.localeCompare(left.startedAt));
82
+ const finished = records.filter((record) => record.state === "completed" && now - finishedAt(record) <= 6e5).sort((left, right) => finishedAt(right) - finishedAt(left));
83
+ return [...running, ...finished].map(toRunnerRunView);
84
+ }
85
+ //#endregion
86
+ //#region src/services/runnerServerRuntime/index.ts
87
+ const COMPLETION_RETRY_MS = 1e3;
88
+ function createRunnerServerRuntime(container, directEvents, wakeAgent, execution) {
89
+ const telemetry = execution ? createDoomTelemetry({
90
+ serviceName: "doom-runner",
91
+ packageName: "@agimon-ai/po-runner",
92
+ cwd: execution.cwd,
93
+ env: execution.environment,
94
+ enableLogs: true,
95
+ enableTraces: true
96
+ }) : void 0;
97
+ let sessionId;
98
+ let recoveredCompactionId;
99
+ let supervision;
100
+ let runtimeDisposal;
101
+ let disposal;
102
+ let backgroundWorkItems = [];
103
+ let backgroundWorkProvider;
104
+ const watched = /* @__PURE__ */ new Set();
105
+ let unsubscribeWatched;
106
+ let wakes = Promise.resolve();
107
+ let closing = false;
108
+ let retryTimer;
109
+ let statusTimer;
110
+ let historyTimer;
111
+ let historySweep;
112
+ const sweepHistory = () => {
113
+ if (closing) return Promise.resolve();
114
+ historySweep ??= (async () => {
115
+ const ttl = getLogTtlMs(container.environment);
116
+ const result = container.paths.sweepHistoryAsync ? await container.paths.sweepHistoryAsync(ttl) : container.paths.sweepHistory(ttl);
117
+ for (const error of result.errors) process.emitWarning(error);
118
+ })().catch((error) => process.emitWarning(`Could not sweep doom-runner history: ${String(error)}`)).finally(() => {
119
+ historySweep = void 0;
120
+ });
121
+ return historySweep;
122
+ };
123
+ const ensureSession = (requestedSessionId) => {
124
+ if (closing) return Promise.reject(/* @__PURE__ */ new Error("Runner runtime is closing."));
125
+ if (sessionId !== void 0 && sessionId !== requestedSessionId) throw new Error(`Runner runtime belongs to session ${sessionId}.`);
126
+ sessionId ??= requestedSessionId;
127
+ supervision ??= (async () => {
128
+ await telemetry?.recordEvent("doom_runner.session_started", { outcome: "started" });
129
+ if (closing) return;
130
+ container.paths.setSessionId(requestedSessionId);
131
+ if (await container.lifeline.arm(requestedSessionId) === void 0) throw new Error("Could not arm runner supervision lifeline.");
132
+ if (closing) return;
133
+ const promotedIds = (await container.runnerRegistry.listAll(requestedSessionId)).filter((record) => record.state === "running" && record.promoted).map((record) => record.id);
134
+ const legacy = await cleanupLegacyRunnerStore({
135
+ registry: container.runnerRegistry,
136
+ launcher: container.launcher,
137
+ rmuxBackend: container.rmuxBackend,
138
+ processControl: container.processControl,
139
+ currentHostPid: process.pid,
140
+ paths: container.paths
141
+ });
142
+ for (const error of legacy.errors) process.emitWarning(error);
143
+ if (closing) return;
144
+ const reconciled = await reconcileActiveRunners({
145
+ registry: container.runnerRegistry,
146
+ launcher: container.launcher,
147
+ rmuxBackend: container.rmuxBackend,
148
+ processControl: container.processControl,
149
+ currentHostPid: process.pid,
150
+ startup: true,
151
+ startupSessionId: requestedSessionId
152
+ });
153
+ for (const error of reconciled.errors) process.emitWarning(error);
154
+ await telemetry?.recordEvent("doom_runner.reconciled", {
155
+ "runner.reclaimed_count": legacy.reclaimed.length + reconciled.reclaimed.length,
156
+ "runner.error_count": legacy.errors.length + reconciled.errors.length,
157
+ outcome: legacy.errors.length + reconciled.errors.length === 0 ? "completed" : "degraded"
158
+ });
159
+ if (!closing) {
160
+ unsubscribeRunnerUpdates ??= container.runnerRegistry.subscribe(() => requestPublish(requestedSessionId), requestedSessionId);
161
+ for (const id of promotedIds) watchRunner(id);
162
+ requestPublish(requestedSessionId);
163
+ await sweepHistory();
164
+ if (closing) return;
165
+ statusTimer ??= setInterval(() => {
166
+ refreshSession(requestedSessionId);
167
+ }, 500);
168
+ statusTimer.unref?.();
169
+ historyTimer ??= setInterval(() => {
170
+ sweepHistory();
171
+ }, HISTORY_SWEEP_INTERVAL_MS);
172
+ historyTimer.unref?.();
173
+ }
174
+ })().catch((error) => {
175
+ supervision = void 0;
176
+ throw error;
177
+ });
178
+ return supervision;
179
+ };
180
+ const disposeRuntime = () => {
181
+ runtimeDisposal ??= (async () => {
182
+ await supervision?.catch((error) => process.emitWarning(`Could not initialize headless runner supervision: ${String(error)}`));
183
+ const ownedSessionId = sessionId;
184
+ if (ownedSessionId === void 0) return;
185
+ const records = await container.runnerRegistry.listBySession(ownedSessionId).catch(() => []);
186
+ await Promise.all(records.map(async (record) => {
187
+ try {
188
+ if (!await stopRunnerProcess(record, container.launcher, container.rmuxBackend, {
189
+ registry: container.runnerRegistry,
190
+ intent: {
191
+ reason: "stopped",
192
+ terminationReason: "parent_session_cleanup",
193
+ stopReason: "session ended"
194
+ }
195
+ }) && container.processControl.isAlive(record.pid)) {
196
+ process.emitWarning(`Could not stop runner ${record.id} during session shutdown`);
197
+ return;
198
+ }
199
+ await container.runnerRegistry.complete(record.id, {
200
+ reason: "stopped",
201
+ code: null,
202
+ signal: null,
203
+ stopReason: "session ended"
204
+ }, ownedSessionId);
205
+ } catch (error) {
206
+ process.emitWarning(`Could not clean up runner ${record.id}: ${String(error)}`);
207
+ }
208
+ }));
209
+ try {
210
+ await container.ptyHost.disposeAll();
211
+ } finally {
212
+ container.lifeline.dispose();
213
+ container.runnerRegistry.close();
214
+ }
215
+ })();
216
+ return runtimeDisposal;
217
+ };
218
+ let refreshInFlight;
219
+ const refreshSession = (ownedSessionId) => {
220
+ if (closing) return Promise.resolve();
221
+ refreshInFlight ??= refreshNow(ownedSessionId).finally(() => {
222
+ refreshInFlight = void 0;
223
+ });
224
+ return refreshInFlight;
225
+ };
226
+ const refreshNow = async (ownedSessionId) => {
227
+ if (closing) return;
228
+ try {
229
+ const reconciled = await reconcileActiveRunners({
230
+ registry: container.runnerRegistry,
231
+ launcher: container.launcher,
232
+ rmuxBackend: container.rmuxBackend,
233
+ processControl: container.processControl,
234
+ currentHostPid: process.pid,
235
+ startup: false,
236
+ active: await container.runnerRegistry.listBySession(ownedSessionId)
237
+ });
238
+ for (const error of reconciled.errors) process.emitWarning(error);
239
+ if (!closing) {
240
+ requestPublish(ownedSessionId);
241
+ wakeForFinished(ownedSessionId);
242
+ }
243
+ } catch (error) {
244
+ process.emitWarning(`Could not refresh doom-runner: ${String(error)}`);
245
+ }
246
+ };
247
+ const publishRuns = async (ownedSessionId) => {
248
+ try {
249
+ const records = await container.runnerRegistry.listAll(ownedSessionId);
250
+ if (closing) return;
251
+ if (execution) {
252
+ const root = resolveRootSessionId(ownedSessionId, container.environment);
253
+ const count = (await container.runnerRegistry.list()).filter((record) => (record.rootSessionId ?? record.sessionId) === root).length;
254
+ if (closing) return;
255
+ execution.client.setStatus(RUNNER_STATUS_KEY, formatRunnerStatus(count));
256
+ }
257
+ if (closing) return;
258
+ const nextBackgroundWork = records.filter((record) => record.state === "running" || watched.has(record.id)).map((record) => ({
259
+ id: record.id,
260
+ sessionId: record.sessionId,
261
+ label: record.name,
262
+ ...record.state === "running" ? { status: record.state } : {}
263
+ }));
264
+ if (JSON.stringify(nextBackgroundWork) !== JSON.stringify(backgroundWorkItems)) {
265
+ backgroundWorkItems = nextBackgroundWork;
266
+ backgroundWorkProvider?.update();
267
+ }
268
+ directEvents.publish(RUNNER_RUNS_TYPE, ownedSessionId, { runs: presentRunnerRuns(records, Date.now()) });
269
+ } catch (error) {
270
+ process.emitWarning(`Could not publish runner state: ${String(error)}`);
271
+ }
272
+ };
273
+ let publishInFlight;
274
+ let publishAgain = false;
275
+ let unsubscribeRunnerUpdates;
276
+ const requestPublish = (ownedSessionId) => {
277
+ if (closing) return;
278
+ publishAgain = true;
279
+ if (publishInFlight !== void 0) return;
280
+ publishInFlight = (async () => {
281
+ do {
282
+ publishAgain = false;
283
+ await publishRuns(ownedSessionId);
284
+ } while (publishAgain && !closing);
285
+ })().catch((error) => {
286
+ process.emitWarning(`Could not schedule runner state publication: ${String(error)}`);
287
+ }).finally(() => {
288
+ publishInFlight = void 0;
289
+ if (publishAgain) requestPublish(ownedSessionId);
290
+ });
291
+ };
292
+ const wakeForFinished = (ownedSessionId) => {
293
+ if (closing) return;
294
+ wakes = wakes.then(async () => {
295
+ if (closing) return;
296
+ let retry = false;
297
+ for (const id of watched) {
298
+ if (closing) return;
299
+ try {
300
+ const record = await container.runnerRegistry.get(id, ownedSessionId);
301
+ if (closing) return;
302
+ if (record?.state === "running") continue;
303
+ if (record) await wakeAgent?.(formatRunnerFinished(record), `runner-finished:${JSON.stringify([ownedSessionId, id])}`);
304
+ if (record) await telemetry?.recordEvent("doom_runner.process_finished", {
305
+ outcome: "completed",
306
+ "runner.exit_code": record.exit?.code ?? 0,
307
+ "runner.backend": record.backend
308
+ });
309
+ watched.delete(id);
310
+ requestPublish(ownedSessionId);
311
+ } catch (error) {
312
+ retry = true;
313
+ process.emitWarning(`Could not report finished runner ${id}: ${String(error)}`);
314
+ }
315
+ }
316
+ if (retry && !closing && retryTimer === void 0) {
317
+ retryTimer = setTimeout(() => {
318
+ retryTimer = void 0;
319
+ wakeForFinished(ownedSessionId);
320
+ }, COMPLETION_RETRY_MS);
321
+ retryTimer.unref?.();
322
+ }
323
+ if (watched.size === 0) {
324
+ clearTimeout(retryTimer);
325
+ retryTimer = void 0;
326
+ unsubscribeWatched?.();
327
+ unsubscribeWatched = void 0;
328
+ }
329
+ }).catch((error) => {
330
+ process.emitWarning(`Could not report a finished runner: ${String(error)}`);
331
+ });
332
+ };
333
+ const watchRunner = (id) => {
334
+ const ownedSessionId = sessionId;
335
+ if (!wakeAgent || closing || ownedSessionId === void 0) return;
336
+ watched.add(id);
337
+ requestPublish(ownedSessionId);
338
+ unsubscribeWatched ??= container.runnerRegistry.subscribe(() => wakeForFinished(ownedSessionId), ownedSessionId);
339
+ wakeForFinished(ownedSessionId);
340
+ };
341
+ return {
342
+ container,
343
+ activity: {
344
+ name: "runner",
345
+ start: async (executionContext) => {
346
+ await ensureSession(executionContext.sessionId);
347
+ requestPublish(executionContext.sessionId);
348
+ return () => {};
349
+ }
350
+ },
351
+ ensureSession,
352
+ watchRunner,
353
+ async recoverCompaction(event) {
354
+ if (event.status !== "completed" || closing || !execution || typeof event.entryId !== "string" || event.entryId === recoveredCompactionId) return;
355
+ const compacted = (await execution.session.entries()).findLast((entry) => entry.type === "compaction");
356
+ if (closing || compacted?.id !== event.entryId) return;
357
+ await ensureSession(execution.sessionId);
358
+ let records;
359
+ try {
360
+ records = await container.runnerRegistry.listBySession(execution.sessionId);
361
+ } catch {
362
+ return;
363
+ }
364
+ if (closing) return;
365
+ const active = records.filter((record) => record.state === "running");
366
+ const text = activeRunnerRecovery(active);
367
+ if (!text) return;
368
+ await execution.session.appendMessage?.({
369
+ type: "doom-runner-compaction",
370
+ text,
371
+ display: false,
372
+ details: {
373
+ sessionId: execution.sessionId,
374
+ runnerIds: active.map((record) => record.id)
375
+ }
376
+ });
377
+ if (!closing) recoveredCompactionId = event.entryId;
378
+ },
379
+ backgroundWorkPlugin: (context) => {
380
+ context.inject([DOOM_BACKGROUND_WORK_SERVICE], (serviceContext) => {
381
+ const service = readDoomBackgroundWorkService(serviceContext);
382
+ if (!service) return void 0;
383
+ const registration = service.register({
384
+ provider: BACKGROUND_WORK_PROVIDER,
385
+ listActiveWork: () => backgroundWorkItems
386
+ });
387
+ backgroundWorkProvider = registration;
388
+ return () => {
389
+ registration.dispose();
390
+ if (backgroundWorkProvider === registration) backgroundWorkProvider = void 0;
391
+ };
392
+ });
393
+ },
394
+ dispose() {
395
+ if (disposal) return disposal;
396
+ closing = true;
397
+ disposal = (async () => {
398
+ closing = true;
399
+ clearInterval(statusTimer);
400
+ clearInterval(historyTimer);
401
+ clearTimeout(retryTimer);
402
+ retryTimer = void 0;
403
+ watched.clear();
404
+ unsubscribeWatched?.();
405
+ unsubscribeWatched = void 0;
406
+ unsubscribeRunnerUpdates?.();
407
+ unsubscribeRunnerUpdates = void 0;
408
+ await wakes;
409
+ await publishInFlight;
410
+ await historySweep;
411
+ await refreshInFlight;
412
+ try {
413
+ execution?.client.setStatus(RUNNER_STATUS_KEY, void 0);
414
+ } catch (error) {
415
+ process.emitWarning(`Could not clear runner status: ${String(error)}`);
416
+ }
417
+ await disposeRuntime();
418
+ await telemetry?.recordEvent("doom_runner.session_finished", { outcome: "stopped" });
419
+ await telemetry?.shutdown();
420
+ })();
421
+ return disposal;
422
+ }
423
+ };
424
+ }
425
+ //#endregion
426
+ //#region src/services/runnerSettings/index.ts
427
+ /** Pi's convention is one JSON file per extension under the config directory. */
428
+ const EMPTY = {
429
+ settings: {},
430
+ issues: []
431
+ };
432
+ const COUNT_KEYS = [
433
+ "maxResultBytes",
434
+ "maxResultLines",
435
+ "successMaxResultBytes",
436
+ "maxResultTokens",
437
+ "successMaxResultTokens",
438
+ "errorMaxEntries",
439
+ "errorMaxVariantsJoined"
440
+ ];
441
+ const KNOWN_KEYS = /* @__PURE__ */ new Set([
442
+ ...RATIO_KEYS,
443
+ ...COUNT_KEYS,
444
+ "errorPatterns"
445
+ ]);
446
+ /** Ceilings so a project file cannot flood the model's context. */
447
+ const CEILINGS = {
448
+ maxResultBytes: MAX_RESULT_BYTES_CEILING,
449
+ successMaxResultBytes: MAX_RESULT_BYTES_CEILING,
450
+ maxResultTokens: MAX_RESULT_TOKENS_CEILING,
451
+ successMaxResultTokens: MAX_RESULT_TOKENS_CEILING,
452
+ maxResultLines: MAX_RESULT_LINES_CEILING,
453
+ errorMaxEntries: 100,
454
+ errorMaxVariantsJoined: 100
455
+ };
456
+ var RunnerSettingsLoader = class {
457
+ load(cwd, trusted) {
458
+ if (!trusted) return EMPTY;
459
+ let raw;
460
+ try {
461
+ raw = fs.readFileSync(path.join(cwd, CONFIG_DIR_NAME, RUNNER_SETTINGS_FILE), "utf8");
462
+ } catch (error) {
463
+ if (error.code === "ENOENT") return EMPTY;
464
+ return {
465
+ settings: {},
466
+ issues: [`${RUNNER_SETTINGS_FILE} could not be read`]
467
+ };
468
+ }
469
+ let parsed;
470
+ try {
471
+ parsed = JSON.parse(raw);
472
+ } catch {
473
+ return {
474
+ settings: {},
475
+ issues: [`${RUNNER_SETTINGS_FILE} is not valid JSON`]
476
+ };
477
+ }
478
+ return validate(parsed);
479
+ }
480
+ };
481
+ function validate(parsed) {
482
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return {
483
+ settings: {},
484
+ issues: [`${RUNNER_SETTINGS_FILE} must contain a JSON object`]
485
+ };
486
+ const source = parsed;
487
+ const settings = {};
488
+ const issues = [];
489
+ for (const key of Object.keys(source)) if (!KNOWN_KEYS.has(key)) issues.push(`unknown key ${key}`);
490
+ for (const key of COUNT_KEYS) {
491
+ const value = source[key];
492
+ if (value === void 0) continue;
493
+ if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
494
+ issues.push(`${key} must be a positive integer`);
495
+ continue;
496
+ }
497
+ settings[key] = Math.min(value, CEILINGS[key] ?? value);
498
+ }
499
+ for (const key of RATIO_KEYS) {
500
+ const value = source[key];
501
+ if (value === void 0) continue;
502
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0 || value >= 1) {
503
+ issues.push(`${key} must be a number above 0 and below 1`);
504
+ continue;
505
+ }
506
+ settings[key] = value;
507
+ }
508
+ const patterns = source.errorPatterns;
509
+ if (patterns !== void 0) {
510
+ if (!Array.isArray(patterns) || patterns.some((entry) => typeof entry !== "string")) issues.push("errorPatterns must be an array of strings");
511
+ else {
512
+ const accepted = [];
513
+ for (const pattern of patterns.slice(0, 32)) {
514
+ if (pattern.length > 512) {
515
+ issues.push("errorPatterns entry is too long");
516
+ continue;
517
+ }
518
+ try {
519
+ new RegExp(pattern, "iu");
520
+ accepted.push(pattern);
521
+ } catch {
522
+ issues.push(`errorPatterns entry is not a valid regular expression: ${pattern}`);
523
+ }
524
+ }
525
+ if (accepted.length > 0) settings.errorPatterns = accepted;
526
+ }
527
+ }
528
+ return {
529
+ settings,
530
+ issues
531
+ };
532
+ }
533
+ //#endregion
534
+ //#region src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.ts
535
+ const RUNNER_SERVER_SCOPE_SERVICE = "doom/runner-server-scope";
536
+ const createRunnerServerRoot = ({ host, agent, signal }) => {
537
+ if (!host.context.directEvents) throw new Error("Runner headless facet requires the session direct event bus.");
538
+ if (!host.context.cwd || !host.context.environment) throw new Error("Runner headless facet requires session cwd and environment.");
539
+ const loaded = new RunnerSettingsLoader().load(host.context.cwd, true);
540
+ const settings = Object.freeze({
541
+ ...loaded.settings,
542
+ ...loaded.settings.errorPatterns ? { errorPatterns: Object.freeze([...loaded.settings.errorPatterns]) } : {}
543
+ });
544
+ for (const issue of loaded.issues) process.emitWarning(`${RUNNER_SETTINGS_FILE}: ${issue}`);
545
+ const dependencies = createRunnerDependencies({
546
+ settings,
547
+ cwd: host.context.cwd,
548
+ environment: host.context.environment,
549
+ ...host.context.executionBudget === void 0 ? {} : { executionBudget: host.context.executionBudget }
550
+ });
551
+ const execution = agent?.context;
552
+ const wakeAgent = execution && (async (content, requestId) => {
553
+ try {
554
+ if (!execution.session.admitPrompt) throw new Error("The session cannot admit a runner notification.");
555
+ await execution.session.admitPrompt(content, "steer", void 0, requestId);
556
+ } catch (error) {
557
+ await Promise.resolve().then(() => execution.client.notify({
558
+ body: String(error),
559
+ level: "warning"
560
+ })).catch(() => void 0);
561
+ throw error;
562
+ }
563
+ });
564
+ const runtime = createRunnerServerRuntime(dependencies, host.context.directEvents, wakeAgent, execution);
565
+ const bash = (wakeOnExit) => createHeadlessBashTool({ run: async (request) => {
566
+ await runtime.ensureSession(request.sessionId);
567
+ const result = await dependencies.bashRunService.run({
568
+ ...request,
569
+ ...signal ? { signal: request.signal ? AbortSignal.any([signal, request.signal]) : signal } : {}
570
+ });
571
+ if (wakeOnExit && result.kind === "promoted") runtime.watchRunner(result.id);
572
+ return result;
573
+ } }, (path, lines, bytes, tokens) => summarizeLog(path, lines, bytes, tokens, settings), settings, dependencies.environment);
574
+ const value = {
575
+ tool: bash(true),
576
+ remoteTool: bash(false),
577
+ command: createHeadlessRunnersCommand(dependencies),
578
+ recoverCompaction: runtime.recoverCompaction
579
+ };
580
+ return {
581
+ value,
582
+ services: [runtime.backgroundWorkPlugin, (context) => {
583
+ context.plugin((providerContext) => providerContext.provide(RUNNER_SERVER_SCOPE_SERVICE, value));
584
+ }],
585
+ activities: [runtime.activity],
586
+ onStart: execution ? () => runtime.ensureSession(execution.sessionId) : void 0,
587
+ onStop: runtime.dispose
588
+ };
589
+ };
590
+ //#endregion
591
+ //#region src/extensions/workspaces/sessions/(backend)/root.server.ts
592
+ var root_server_default = defineRoot(createRunnerServerRoot);
593
+ //#endregion
594
+ //#region src/services/runnersChannel/index.ts
595
+ function runnerPayload(value) {
596
+ return typeof value === "object" && value !== null && Array.isArray(value.runs);
597
+ }
598
+ /**
599
+ * The runners data channel consumes lifecycle-owned snapshots from the session
600
+ * server. Durable registry files are read by the owning session only, never by
601
+ * this hub channel.
602
+ */
603
+ function createRunnersChannel() {
604
+ return {
605
+ frameType: RUNNER_RUNS_TYPE,
606
+ start(host) {
607
+ const latest = /* @__PURE__ */ new Map();
608
+ const subscriptions = /* @__PURE__ */ new Map();
609
+ return {
610
+ payloadFor(scope) {
611
+ const runs = latest.get(scope.sessionId);
612
+ return runs === void 0 ? void 0 : { runs };
613
+ },
614
+ sessionAdded(scope) {
615
+ subscriptions.get(scope.sessionId)?.();
616
+ latest.delete(scope.sessionId);
617
+ const unsubscribe = host.directEvents.subscribe(RUNNER_RUNS_TYPE, scope.sessionId, (payload) => {
618
+ if (!runnerPayload(payload)) return;
619
+ latest.set(scope.sessionId, payload.runs);
620
+ host.publish(scope.sessionId, payload);
621
+ }, { replayLatest: true });
622
+ subscriptions.set(scope.sessionId, unsubscribe);
623
+ },
624
+ sessionRemoved(sessionId) {
625
+ subscriptions.get(sessionId)?.();
626
+ subscriptions.delete(sessionId);
627
+ latest.delete(sessionId);
628
+ },
629
+ close() {
630
+ for (const unsubscribe of subscriptions.values()) unsubscribe();
631
+ subscriptions.clear();
632
+ latest.clear();
633
+ }
634
+ };
635
+ }
636
+ };
637
+ }
638
+ //#endregion
639
+ //#region src/extensions/(backend)/channel/runnerRuns.server.ts
640
+ var runnerRuns_server_default = defineChannel(function runnerRunsChannel() {
641
+ return createRunnersChannel();
642
+ });
643
+ //#endregion
644
+ //#region src/constants/runnerLogApi.ts
645
+ const LOG_DIR_NAME = "logs";
646
+ const STATE_EXTENSION = ".json";
647
+ const RUNNING_STATE = "running";
648
+ const STATE_POLL_MS = 1e3;
649
+ const HEARTBEAT_MS = 15e3;
650
+ const MAX_LINES = 5e3;
651
+ const SAFE_SEGMENT = /^[\w.@-]+$/;
652
+ const RAW_LOG_SUFFIX = ".raw";
653
+ const NOT_ATTACHABLE = "No attachable runner by that name in this session.";
654
+ //#endregion
655
+ //#region src/constants/webRunnerLog.ts
656
+ const RUNNER_API_BASE_PATH = "runner";
657
+ const RUN_ID_PARAM = "runId";
658
+ const RUNNER_SCREEN_EVENT = "screen";
659
+ const RUNNER_LOG_STREAM_EVENT = "append";
660
+ const RUNNER_LOG_PING_EVENT = "ping";
661
+ //#endregion
662
+ //#region src/services/logTail/index.ts
663
+ /** How often the tail restats the file; the same cadence the CLI's --follow uses. */
664
+ /**
665
+ * Polling tail: read the delta between the last offset and the file's current
666
+ * size, and hand back only complete lines.
667
+ *
668
+ * Same reliability posture as this package's runner watcher: the poll is the
669
+ * mechanism, not an accelerator for a change notification. fs.watchFile only
670
+ * fires when it observes a difference from a baseline it took itself, so a
671
+ * write that lands before its first stat is a change it never reports; a
672
+ * restat every tick has no such window.
673
+ *
674
+ * A write that lands mid-line is common, so the trailing fragment is held
675
+ * until its newline arrives rather than emitted as a line that will change.
676
+ */
677
+ var LogTail = class {
678
+ follow(logPath, options) {
679
+ let offset = options.from;
680
+ let pending = "";
681
+ let closed = false;
682
+ const drain = (size) => {
683
+ if (size < offset) {
684
+ offset = 0;
685
+ pending = "";
686
+ }
687
+ if (size === offset) return;
688
+ const length = size - offset;
689
+ const buffer = Buffer.alloc(length);
690
+ const descriptor = fs.openSync(logPath, "r");
691
+ let bytesRead;
692
+ try {
693
+ bytesRead = fs.readSync(descriptor, buffer, 0, length, offset);
694
+ } finally {
695
+ fs.closeSync(descriptor);
696
+ }
697
+ offset = size;
698
+ if (bytesRead <= 0) return;
699
+ pending += buffer.subarray(0, bytesRead).toString("utf8");
700
+ const lines = pending.split("\n");
701
+ pending = lines.pop() ?? "";
702
+ if (lines.length > 0) options.onLines(lines, offset - Buffer.byteLength(pending, "utf8"));
703
+ };
704
+ const tick = () => {
705
+ if (closed) return;
706
+ try {
707
+ drain(fs.statSync(logPath).size);
708
+ } catch (error) {
709
+ if (error.code === "ENOENT") return;
710
+ options.onError(error instanceof Error ? error : new Error(String(error)));
711
+ }
712
+ };
713
+ const timer = setInterval(tick, 250);
714
+ timer.unref?.();
715
+ return { close() {
716
+ if (closed) return;
717
+ closed = true;
718
+ clearInterval(timer);
719
+ } };
720
+ }
721
+ };
722
+ //#endregion
723
+ //#region src/types/webRunnerLog.ts
724
+ /** The named SSE event carrying a RunnerLogStreamEvent payload. */
725
+ /**
726
+ * The named SSE event that carries nothing.
727
+ *
728
+ * A runner can be alive and silent for minutes, which on the wire is
729
+ * indistinguishable from a connection that died. This is sent on a timer so
730
+ * the socket keeps proving itself. Readers that only listen for `append`
731
+ * ignore it, which is what makes it safe to add.
732
+ */
733
+ /** Query parameter names, shared so the page and the route cannot drift apart. */
734
+ const RUNNER_LOG_PARAMS = {
735
+ lines: "lines",
736
+ grep: "grep",
737
+ ignoreCase: "ignoreCase",
738
+ contextLines: "contextLines",
739
+ from: "from"
740
+ };
741
+ //#endregion
742
+ //#region src/types/apiRoutes.ts
743
+ /**
744
+ * This package's routes, as data.
745
+ *
746
+ * No scope and no base path: the build reads both off
747
+ * `src/extensions/workspaces/sessions/(backend)/api/runner/`, so the mount is
748
+ * stated once, by the folder that creates it. This package stated it four times
749
+ * before, once per URL builder, each of them re-spelling `/plugins/` and the
750
+ * session prefix by hand.
751
+ *
752
+ * The Hono app registers these paths verbatim and the browser addresses them,
753
+ * so a path cannot move on one side alone. `:runId` is Hono's own parameter
754
+ * syntax for that reason; a caller supplies the value as `params`, and the
755
+ * client encodes the segment.
756
+ */
757
+ var apiRoutes_default = defineApiRoutes({
758
+ log: {
759
+ method: "GET",
760
+ path: `/runners/:${RUN_ID_PARAM}/log`,
761
+ query: [
762
+ RUNNER_LOG_PARAMS.lines,
763
+ RUNNER_LOG_PARAMS.grep,
764
+ RUNNER_LOG_PARAMS.ignoreCase,
765
+ RUNNER_LOG_PARAMS.contextLines
766
+ ],
767
+ response: apiResponse()
768
+ },
769
+ /**
770
+ * The live tail of that same log.
771
+ *
772
+ * `stream: true`, so the client exposes a URL and no call method: the
773
+ * consumer is the browser's own `EventSource`, and a relayed call would
774
+ * buffer a stream that never ends.
775
+ */
776
+ logStream: {
777
+ method: "GET",
778
+ path: `/runners/:${RUN_ID_PARAM}/log/stream`,
779
+ query: [RUNNER_LOG_PARAMS.from],
780
+ stream: true
781
+ },
782
+ /** The unscrubbed pane bytes, for a terminal emulator rather than a reader. */
783
+ screenStream: {
784
+ method: "GET",
785
+ path: `/runners/:${RUN_ID_PARAM}/screen/stream`,
786
+ query: [RUNNER_LOG_PARAMS.from],
787
+ stream: true
788
+ },
789
+ input: {
790
+ method: "POST",
791
+ path: `/runners/:${RUN_ID_PARAM}/screen/input`
792
+ }
793
+ });
794
+ //#endregion
795
+ //#region src/services/runnerLogApi/index.ts
796
+ /** How often a follow re-reads the record to notice the runner exiting. */
797
+ /**
798
+ * How often a silent but living stream proves it is still there. Short enough
799
+ * that an idle proxy does not reap the socket, long enough to cost nothing.
800
+ */
801
+ /** Kept in step with LogQuery's own default, so an unasked-for tail is the same size everywhere. */
802
+ /** A page that asks for more than this gets this; the whole point of the route is a bounded read. */
803
+ /** Path segments the client supplies are names, never paths. */
804
+ /** Backends that expose a pane another process can read and write. */
805
+ const MULTIPLEXER_BACKENDS = /* @__PURE__ */ new Set(["rmux", "tmux"]);
806
+ /** Rejects anything that could climb out of the session's own directory before a path is built. */
807
+ function isSafeSegment(value) {
808
+ return value !== "" && value !== "." && value !== ".." && SAFE_SEGMENT.test(value);
809
+ }
810
+ /**
811
+ * The log file a run wrote, or undefined when there is no such run or its
812
+ * record points somewhere it has no business pointing.
813
+ *
814
+ * The record names its own log path, and that record is written by another
815
+ * process, so the path is checked rather than trusted: it must sit inside this
816
+ * session's own logs directory. Without that check a doctored record would
817
+ * turn this route into an arbitrary file read.
818
+ */
819
+ function resolveLogFile(stateDir, logsDir, sessionId, runId) {
820
+ const statePath = path.join(stateDir, `${runId}${STATE_EXTENSION}`);
821
+ let raw;
822
+ try {
823
+ raw = fs.readFileSync(statePath, "utf8");
824
+ } catch {
825
+ return;
826
+ }
827
+ const record = parseRunnerRecord(raw);
828
+ if (record === void 0 || record.id !== runId || record.sessionId !== sessionId) return void 0;
829
+ const resolved = path.resolve(record.logPath);
830
+ if (resolved !== logsDir && !resolved.startsWith(`${logsDir}${path.sep}`)) return void 0;
831
+ return record;
832
+ }
833
+ function isRecord(value) {
834
+ return typeof value === "object" && value !== null && !Array.isArray(value);
835
+ }
836
+ function numberParam(value, fallback, max) {
837
+ const parsed = value === void 0 ? NaN : Number.parseInt(value, 10);
838
+ if (!Number.isFinite(parsed) || parsed < 0) return fallback;
839
+ return Math.min(parsed, max);
840
+ }
841
+ function logQueryOf(url) {
842
+ const grep = url.searchParams.get(RUNNER_LOG_PARAMS.grep) ?? void 0;
843
+ return {
844
+ lines: numberParam(url.searchParams.get(RUNNER_LOG_PARAMS.lines) ?? void 0, 200, MAX_LINES),
845
+ ...grep === void 0 || grep === "" ? {} : { grep },
846
+ ignoreCase: url.searchParams.get(RUNNER_LOG_PARAMS.ignoreCase) === "true",
847
+ contextLines: numberParam(url.searchParams.get(RUNNER_LOG_PARAMS.contextLines) ?? void 0, 0, MAX_LINES)
848
+ };
849
+ }
850
+ /**
851
+ * This package's HTTP surface: one runner's log, as a bounded slice and as a
852
+ * live tail.
853
+ *
854
+ * The routes are mounted inside one session's own server, so they name a runner
855
+ * and nothing else; the session is the host, not a parameter. The reader only
856
+ * ever returns the last N lines of what matched, so both routes stay bounded no
857
+ * matter how large the file on disk is.
858
+ *
859
+ * Paths come from src/types/apiRoutes, the one table the browser's generated
860
+ * client reads too, so this app and the cockpit cannot disagree about where a
861
+ * route lives. They stay relative to the mount the host strips.
862
+ */
863
+ function createRunnerLogApi(options) {
864
+ const logReader = options.logReader ?? new LogReader();
865
+ const logTail = options.logTail ?? new LogTail();
866
+ const sessionId = options.sessionId;
867
+ const paths = new RunnerPaths(options.cwd, options.environment);
868
+ const storeDir = options.storeDir ?? resolveRunnerStoreDirectory(options.environment ?? process.env);
869
+ const stateDir = options.storeDir === void 0 ? paths.stateDirectory(sessionId) : runnerStateDirFor(storeDir, sessionId);
870
+ const logsDir = options.storeDir === void 0 ? paths.logDirectory(sessionId) : path.join(storeDir, sessionId, LOG_DIR_NAME);
871
+ const app = new Hono();
872
+ let paneBackend = options.pane;
873
+ const pane = () => {
874
+ paneBackend ??= (() => {
875
+ const paths = new RunnerPaths(options.cwd, options.environment);
876
+ return new PtyBackendChain(new RmuxBackend(paths), new TmuxBackend(paths));
877
+ })();
878
+ return paneBackend;
879
+ };
880
+ /** The record behind a request, or undefined when this session has no such run. */
881
+ const runnerOf = (runId) => isSafeSegment(runId) ? resolveLogFile(stateDir, logsDir, sessionId, runId) : void 0;
882
+ /**
883
+ * The pane a request may attach to.
884
+ *
885
+ * Same posture as the log routes: the record is written by another process,
886
+ * so nothing on it is trusted until it is checked. The target must be one
887
+ * this package owns, the run must still be up, and it must have been started
888
+ * interactive. A non-interactive run has no terminal to type into, and a
889
+ * subprocess-backed run has no pane at all.
890
+ */
891
+ const attachableOf = (runId) => {
892
+ const record = runnerOf(runId);
893
+ if (record === void 0 || record.state !== "running" || record.interactive !== true) return void 0;
894
+ const target = record.backendTarget;
895
+ if (target === void 0 || !MULTIPLEXER_BACKENDS.has(record.backend) || !isSafeSegment(target)) return void 0;
896
+ return {
897
+ record,
898
+ target
899
+ };
900
+ };
901
+ app.get(apiRoutes_default.log.path, (context) => {
902
+ const runId = context.req.param(RUN_ID_PARAM);
903
+ const record = runnerOf(runId);
904
+ if (record === void 0) return context.json({ error: `No runner '${runId}' in this session.` }, 404);
905
+ const body = {
906
+ ...logReader.read(record.logPath, logQueryOf(new URL(context.req.url))),
907
+ runId,
908
+ running: record.state === RUNNING_STATE
909
+ };
910
+ return context.json(body);
911
+ });
912
+ app.get(apiRoutes_default.logStream.path, (context) => {
913
+ const runId = context.req.param(RUN_ID_PARAM);
914
+ const record = runnerOf(runId);
915
+ if (record === void 0) return context.json({ error: `No runner '${runId}' in this session.` }, 404);
916
+ const from = numberParam(new URL(context.req.url).searchParams.get(RUNNER_LOG_PARAMS.from) ?? void 0, 0, Number.MAX_SAFE_INTEGER);
917
+ return streamSSE(context, async (stream) => {
918
+ const send = (event) => stream.writeSSE({
919
+ event: RUNNER_LOG_STREAM_EVENT,
920
+ data: JSON.stringify(event)
921
+ });
922
+ let pump = Promise.resolve();
923
+ const queue = (event) => {
924
+ pump = pump.then(() => send(event)).catch(() => void 0);
925
+ };
926
+ let finish = () => void 0;
927
+ const done = new Promise((resolve) => {
928
+ finish = resolve;
929
+ });
930
+ const handle = logTail.follow(record.logPath, {
931
+ from,
932
+ onLines: (lines, completeThrough) => queue({
933
+ lines,
934
+ offset: completeThrough
935
+ }),
936
+ onError: () => finish()
937
+ });
938
+ const poll = setInterval(() => {
939
+ const current = runnerOf(runId);
940
+ if (current !== void 0 && current.state === "running") return;
941
+ queue({
942
+ lines: [],
943
+ ended: true
944
+ });
945
+ finish();
946
+ }, STATE_POLL_MS);
947
+ const heartbeat = setInterval(() => {
948
+ pump = pump.then(() => stream.writeSSE({
949
+ event: RUNNER_LOG_PING_EVENT,
950
+ data: ""
951
+ })).catch(() => void 0);
952
+ }, HEARTBEAT_MS);
953
+ stream.onAbort(() => finish());
954
+ await done;
955
+ clearInterval(poll);
956
+ clearInterval(heartbeat);
957
+ handle.close();
958
+ await pump;
959
+ });
960
+ });
961
+ app.get(apiRoutes_default.screenStream.path, (context) => {
962
+ const runId = context.req.param(RUN_ID_PARAM);
963
+ const attachable = attachableOf(runId);
964
+ if (attachable === void 0) return context.json({ error: NOT_ATTACHABLE }, 404);
965
+ const rawPath = `${attachable.record.logPath}${RAW_LOG_SUFFIX}`;
966
+ const from = numberParam(new URL(context.req.url).searchParams.get(RUNNER_LOG_PARAMS.from) ?? void 0, 0, Number.MAX_SAFE_INTEGER);
967
+ return streamSSE(context, async (stream) => {
968
+ let pump = Promise.resolve();
969
+ const queue = (event) => {
970
+ pump = pump.then(() => stream.writeSSE({
971
+ event: RUNNER_SCREEN_EVENT,
972
+ data: JSON.stringify(event)
973
+ })).catch(() => void 0);
974
+ };
975
+ let finish = () => void 0;
976
+ const done = new Promise((resolve) => {
977
+ finish = resolve;
978
+ });
979
+ let offset = from;
980
+ const drain = () => {
981
+ let size;
982
+ try {
983
+ size = fs.statSync(rawPath).size;
984
+ } catch {
985
+ return;
986
+ }
987
+ if (size < offset) offset = 0;
988
+ if (size === offset) return;
989
+ const length = size - offset;
990
+ const buffer = Buffer.alloc(length);
991
+ const descriptor = fs.openSync(rawPath, "r");
992
+ let read;
993
+ try {
994
+ read = fs.readSync(descriptor, buffer, 0, length, offset);
995
+ } finally {
996
+ fs.closeSync(descriptor);
997
+ }
998
+ if (read <= 0) return;
999
+ offset += read;
1000
+ queue({
1001
+ chunk: buffer.subarray(0, read).toString("base64"),
1002
+ offset
1003
+ });
1004
+ };
1005
+ const poll = setInterval(() => {
1006
+ const current = runnerOf(runId);
1007
+ drain();
1008
+ if (current === void 0 || current.state !== "running") {
1009
+ queue({
1010
+ chunk: "",
1011
+ offset,
1012
+ ended: true
1013
+ });
1014
+ finish();
1015
+ }
1016
+ }, 100);
1017
+ stream.onAbort(() => finish());
1018
+ await done;
1019
+ clearInterval(poll);
1020
+ await pump;
1021
+ });
1022
+ });
1023
+ /**
1024
+ * Types into a live pane.
1025
+ *
1026
+ * This is the one route in the package that writes rather than reads, so it
1027
+ * is deliberately narrow: an owned target, still running, started
1028
+ * interactive, and a body that is nothing but text.
1029
+ */
1030
+ app.post(apiRoutes_default.input.path, async (context) => {
1031
+ const runId = context.req.param(RUN_ID_PARAM);
1032
+ const attachable = attachableOf(runId);
1033
+ if (attachable === void 0) return context.json({ error: NOT_ATTACHABLE }, 404);
1034
+ let body;
1035
+ try {
1036
+ body = await context.req.json();
1037
+ } catch {
1038
+ return context.json({ error: "Expected a JSON body carrying text." }, 400);
1039
+ }
1040
+ const text = isRecord(body) ? body.text : void 0;
1041
+ if (typeof text !== "string" || text === "") return context.json({ error: "Expected a non-empty text." }, 400);
1042
+ if (text.length > 4096) return context.json({ error: "That is more input than a pane takes." }, 413);
1043
+ if (!await pane().input(attachable.target, text)) return context.json({ error: "The runner did not take the input." }, 502);
1044
+ return context.json({ delivered: true });
1045
+ });
1046
+ return app;
1047
+ }
1048
+ //#endregion
1049
+ //#region src/extensions/workspaces/sessions/(backend)/api/runner/route.server.ts
1050
+ /**
1051
+ * Mounts this package's HTTP API at `runner`, which the folder names.
1052
+ *
1053
+ * The folder is the declaration: the build reads the base path off it and hands
1054
+ * the browser a client bound to the same segment, so the mount is stated once
1055
+ * rather than in a constant and in four URL builders that were each free to
1056
+ * drift.
1057
+ */
1058
+ var route_server_default = defineRoute({
1059
+ basePath: RUNNER_API_BASE_PATH,
1060
+ start(context) {
1061
+ const app = createRunnerLogApi({
1062
+ sessionId: context.sessionId ?? "",
1063
+ cwd: context.cwd,
1064
+ environment: context.environment
1065
+ });
1066
+ return {
1067
+ fetch: (request) => app.fetch(request),
1068
+ close: () => void 0
1069
+ };
1070
+ }
1071
+ });
1072
+ //#endregion
1073
+ //#region src/extensions/workspaces/sessions/(backend)/command/runners.server.ts
1074
+ var runners_server_default = defineServerCommand((context) => context.root.command);
1075
+ //#endregion
1076
+ //#region src/extensions/workspaces/sessions/(backend)/hook/session-compact.server.ts
1077
+ var session_compact_server_default = defineHook(({ root }) => ({
1078
+ event: "session_compact",
1079
+ handle: root.recoverCompaction
1080
+ }));
1081
+ //#endregion
1082
+ //#region src/extensions/workspaces/sessions/(backend)/resource/po-use-runner.server.ts
1083
+ var po_use_runner_server_default = defineResource({
1084
+ name: "po-use-runner",
1085
+ description: "Use Doom Pi Runner to supervise shell commands, inspect durable logs, provide interactive input, and stop background runs.",
1086
+ when: DOOM_HELP_WHEN,
1087
+ kind: "skill",
1088
+ path: packageResourcePath(import.meta.url, "src/prompts/po-use-runner/SKILL.md"),
1089
+ read: () => readPackageResource(import.meta.url, "src/prompts/po-use-runner/SKILL.md")
1090
+ });
1091
+ //#endregion
1092
+ //#region src/extensions/workspaces/sessions/(backend)/tool/bash.server.ts
1093
+ var bash_server_default = defineServerTool((context) => context.root.tool);
1094
+ //#endregion
1095
+ //#region generated/server.ts
1096
+ const at = (value, context) => typeof value === "function" ? value(context) : value;
1097
+ const via = (identity, value) => value === void 0 ? void 0 : {
1098
+ ...identity,
1099
+ ...value
1100
+ };
1101
+ const facet = defineServerPlugin({
1102
+ name: "@agimon-ai/po-runner",
1103
+ providerOverrides: composeServerProviderOverrides(root_server_default),
1104
+ global: () => ({ get channels() {
1105
+ return [() => via({ frameType: "runner_runs" }, runnerRuns_server_default())];
1106
+ } }),
1107
+ workspace: () => ({ get channels() {
1108
+ return [() => via({ frameType: "runner_runs" }, runnerRuns_server_default())];
1109
+ } }),
1110
+ session: async (context) => {
1111
+ const scopeSession = await root_server_default(context);
1112
+ const contextSession = {
1113
+ ...context,
1114
+ root: scopeSession.value
1115
+ };
1116
+ return {
1117
+ ...composeRootHooks(scopeSession),
1118
+ get api() {
1119
+ return [at(route_server_default, contextSession)];
1120
+ },
1121
+ get channels() {
1122
+ return [() => via({ frameType: "runner_runs" }, runnerRuns_server_default())];
1123
+ },
1124
+ get commands() {
1125
+ return [via({ name: "runners" }, at(runners_server_default, contextSession))];
1126
+ },
1127
+ get hooks() {
1128
+ return [via({ event: "session_compact" }, at(session_compact_server_default, contextSession))];
1129
+ },
1130
+ get resources() {
1131
+ return [at(po_use_runner_server_default, contextSession)];
1132
+ },
1133
+ get tools() {
1134
+ return [via({ name: "bash" }, at(bash_server_default, contextSession))];
1135
+ },
1136
+ services: [...scopeSession.services ?? []],
1137
+ get activities() {
1138
+ return [...scopeSession.activities ?? []];
1139
+ }
1140
+ };
1141
+ }
1142
+ });
1143
+ //#endregion
1144
+ export { facet as default, facet };
1145
+
1146
+ //# sourceMappingURL=server.mjs.map