@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 @@
1
+ {"version":3,"file":"server.mjs","names":["routes","rootSession","channelRunnerRuns","apiRoute","commandRunners","hookSessionCompact","resourcePoUseRunner","toolBash"],"sources":["../../src/constants/runnerSettings.ts","../../src/constants/runnerRuntime.ts","../../src/constants/webRunners.ts","../../src/constants/webRunnerRuns.ts","../../src/services/webRunnerRuns/index.ts","../../src/services/runnerServerRuntime/index.ts","../../src/services/runnerSettings/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/services/runnersChannel/index.ts","../../src/extensions/(backend)/channel/runnerRuns.server.ts","../../src/constants/runnerLogApi.ts","../../src/constants/webRunnerLog.ts","../../src/services/logTail/index.ts","../../src/types/webRunnerLog.ts","../../src/types/apiRoutes.ts","../../src/services/runnerLogApi/index.ts","../../src/extensions/workspaces/sessions/(backend)/api/runner/route.server.ts","../../src/extensions/workspaces/sessions/(backend)/command/runners.server.ts","../../src/extensions/workspaces/sessions/(backend)/hook/session-compact.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/po-use-runner.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/bash.server.ts","../../generated/server.ts"],"sourcesContent":["export const RUNNER_SETTINGS_FILE = 'po-runner.json';\nexport const RATIO_KEYS = ['headRatio', 'errorBudgetRatio'] as const;\nexport const MAX_RESULT_BYTES_CEILING = 262_144;\nexport const MAX_RESULT_LINES_CEILING = 5_000;\nexport const MAX_RESULT_TOKENS_CEILING = 100_000;\nexport const MAX_ERROR_ENTRIES_CEILING = 100;\nexport const MAX_PATTERNS = 32;\nexport const MAX_PATTERN_LENGTH = 512;\n","export const LEADER_SOURCE = '@agimon-ai/po-runner';\nexport const LEADER_GROUP_ORDER = 67;\nexport const ERR_REQUIRES_INTERACTIVE = '/runners requires interactive mode';\nexport const ERR_STOP_USAGE = 'Usage: /runners stop <runner-id> [reason]';\nexport const ERR_START_USAGE = 'Usage: /runners start [name=x] [cwd=y] [interactive=true] -- <command>';\nexport const SESSION_START_EVENT = 'session_start';\nexport const RUNNER_FINISHED_MESSAGE = 'doom-runner-finished';\nexport const COMPLETED_STATE = 'completed';\nexport const RMUX_BACKEND = 'rmux';\nexport const STOPPED_REASON = 'stopped';\nexport const RUNNER_STATUS_KEY = 'doom-runner-runners';\nexport const BACKGROUND_WORK_PROVIDER = 'doom-runner';\nexport const RUNNER_FOOTER_ORDER = 10;\nexport const RUNNER_STATUS_POLL_MS = 500;\nexport const HISTORY_SWEEP_INTERVAL_MS = 600_000;\n","export const RUNNER_RUNS_TYPE = 'runner_runs';\n","export const FINISHED_RUNNER_RETENTION_MS = 600_000;\n","import { FINISHED_RUNNER_RETENTION_MS } from '../../constants/webRunnerRuns';\nimport type { RunnerRecord } from '../../types/runnerRegistry';\nimport type { RunnerRunView } from '../../types/webRunners';\nimport { isRunnerRecord } from '../runnerRecord';\n\n/** How long a finished runner stays in the cockpit's feed after it exited. */\n\n/** One on-disk metadata record, or undefined when the text is not a runner record. */\nexport function parseRunnerRecord(raw: string): RunnerRecord | undefined {\n try {\n const parsed: unknown = JSON.parse(raw);\n return isRunnerRecord(parsed) ? parsed : undefined;\n } catch {\n return undefined; // Mid-write or foreign file; the next scan settles it.\n }\n}\n\nexport function toRunnerRunView(record: RunnerRecord): RunnerRunView {\n return {\n id: record.id,\n name: record.name,\n pid: record.pid,\n command: record.command,\n cwd: record.cwd,\n interactive: record.interactive,\n backend: record.backend,\n state: record.state,\n promoted: record.promoted,\n startedAt: record.startedAt,\n logPath: record.logPath,\n ...(record.exit\n ? {\n exit: {\n reason: record.exit.reason,\n code: record.exit.code,\n signal: record.exit.signal,\n ...(record.exit.terminationReason === undefined\n ? {}\n : { terminationReason: record.exit.terminationReason }),\n ...(record.exit.stopReason === undefined ? {} : { stopReason: record.exit.stopReason }),\n finishedAt: record.exit.finishedAt,\n },\n }\n : {}),\n };\n}\n\nfunction finishedAt(record: RunnerRecord): number {\n const parsed = record.exit === undefined ? Number.NaN : Date.parse(record.exit.finishedAt);\n return Number.isFinite(parsed) ? parsed : Date.parse(record.startedAt);\n}\n\n/**\n * The feed the cockpit shows: running runners first, newest start first, then\n * the recently finished ones, newest exit first. Finished runners older than\n * the retention window are left out; the registry keeps them for the CLI.\n */\nexport function presentRunnerRuns(records: readonly RunnerRecord[], now: number): RunnerRunView[] {\n const running = records\n .filter((record) => record.state === 'running')\n .sort((left, right) => right.startedAt.localeCompare(left.startedAt));\n const finished = records\n .filter((record) => record.state === 'completed' && now - finishedAt(record) <= FINISHED_RUNNER_RETENTION_MS)\n .sort((left, right) => finishedAt(right) - finishedAt(left));\n return [...running, ...finished].map(toRunnerRunView);\n}\n","import {\n DOOM_BACKGROUND_WORK_SERVICE,\n readDoomBackgroundWorkService,\n type BackgroundProviderWorkItem,\n type BackgroundWorkProviderHandle,\n} from '@agimon-ai/po-core/backgroundWork';\nimport { resolveRootSessionId } from '@agimon-ai/po-core/childProcess';\nimport type { DoomHeadlessActivity, DoomHeadlessExecutionContext } from '@agimon-ai/po-core/headless';\nimport type { DoomServerHostService } from '@agimon-ai/po-core/serverFacet';\nimport { createDoomTelemetry } from '@agimon-ai/po-telemetry';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport {\n BACKGROUND_WORK_PROVIDER,\n HISTORY_SWEEP_INTERVAL_MS,\n RUNNER_STATUS_POLL_MS,\n RUNNER_STATUS_KEY,\n} from '../../constants/runnerRuntime';\nimport { RUNNER_RUNS_TYPE } from '../../constants/webRunners';\nimport { activeRunnerRecovery } from '../compaction';\nimport { cleanupLegacyRunnerStore, reconcileActiveRunners, stopRunnerProcess } from '../reconcile';\nimport { getLogTtlMs } from '../runnerConfig';\nimport type { RunnerDependencies } from '../runnerDependencies/type';\nimport { formatRunnerStatus } from '../runnerRecord';\nimport { formatRunnerFinished } from '../runnerRecord';\nimport { presentRunnerRuns } from '../webRunnerRuns';\n\nconst COMPLETION_RETRY_MS = 1_000;\n\nexport interface RunnerServerRuntime {\n readonly container: RunnerDependencies;\n readonly activity: DoomHeadlessActivity;\n readonly backgroundWorkPlugin: (context: Context) => void;\n ensureSession(sessionId: string): Promise<void>;\n /** Wakes the agent once when this runner, which it sent to the background, exits. */\n watchRunner(id: string): void;\n recoverCompaction(this: void, event: Readonly<Record<string, unknown>>): Promise<void>;\n dispose(this: void): Promise<void>;\n}\nexport function createRunnerServerRuntime(\n container: RunnerDependencies,\n directEvents: NonNullable<DoomServerHostService['context']['directEvents']>,\n /** Absent when no agent runs in this session, so there is nobody to wake. */\n wakeAgent?: (content: string, requestId: string) => Promise<void>,\n execution?: DoomHeadlessExecutionContext,\n): RunnerServerRuntime {\n const telemetry = execution\n ? createDoomTelemetry({\n serviceName: 'doom-runner',\n packageName: '@agimon-ai/po-runner',\n cwd: execution.cwd,\n env: execution.environment,\n enableLogs: true,\n enableTraces: true,\n })\n : undefined;\n let sessionId: string | undefined;\n let recoveredCompactionId: string | undefined;\n let supervision: Promise<void> | undefined;\n let runtimeDisposal: Promise<void> | undefined;\n let disposal: Promise<void> | undefined;\n let backgroundWorkItems: BackgroundProviderWorkItem[] = [];\n let backgroundWorkProvider: BackgroundWorkProviderHandle | undefined;\n // Nothing else tells the model a background runner ended, so without this an\n // agent that finished its turn waiting on one idles until a person prompts it.\n const watched = new Set<string>();\n let unsubscribeWatched: (() => void) | undefined;\n let wakes: Promise<void> = Promise.resolve();\n let closing = false;\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n let statusTimer: ReturnType<typeof setInterval> | undefined;\n let historyTimer: ReturnType<typeof setInterval> | undefined;\n let historySweep: Promise<void> | undefined;\n const sweepHistory = (): Promise<void> => {\n if (closing) return Promise.resolve();\n historySweep ??= (async () => {\n const ttl = getLogTtlMs(container.environment);\n const result = container.paths.sweepHistoryAsync\n ? await container.paths.sweepHistoryAsync(ttl)\n : container.paths.sweepHistory(ttl);\n for (const error of result.errors) process.emitWarning(error);\n })()\n .catch((error: unknown) => process.emitWarning(`Could not sweep doom-runner history: ${String(error)}`))\n .finally(() => {\n historySweep = undefined;\n });\n return historySweep;\n };\n\n // The activity is optional and source-gated. The retained facet owns the\n // session runtime, so disabling the activity must not tear down its jobs.\n const ensureSession = (requestedSessionId: string): Promise<void> => {\n if (closing) return Promise.reject(new Error('Runner runtime is closing.'));\n if (sessionId !== undefined && sessionId !== requestedSessionId) {\n throw new Error(`Runner runtime belongs to session ${sessionId}.`);\n }\n sessionId ??= requestedSessionId;\n supervision ??= (async () => {\n await telemetry?.recordEvent('doom_runner.session_started', { outcome: 'started' });\n if (closing) return;\n container.paths.setSessionId(requestedSessionId);\n if ((await container.lifeline.arm(requestedSessionId)) === undefined) {\n throw new Error('Could not arm runner supervision lifeline.');\n }\n if (closing) return;\n const promotedIds = (await container.runnerRegistry.listAll(requestedSessionId))\n .filter((record) => record.state === 'running' && record.promoted)\n .map((record) => record.id);\n const legacy = await cleanupLegacyRunnerStore({\n registry: container.runnerRegistry,\n launcher: container.launcher,\n rmuxBackend: container.rmuxBackend,\n processControl: container.processControl,\n currentHostPid: process.pid,\n paths: container.paths,\n });\n for (const error of legacy.errors) process.emitWarning(error);\n if (closing) return;\n const reconciled = await reconcileActiveRunners({\n registry: container.runnerRegistry,\n launcher: container.launcher,\n rmuxBackend: container.rmuxBackend,\n processControl: container.processControl,\n currentHostPid: process.pid,\n startup: true,\n startupSessionId: requestedSessionId,\n });\n for (const error of reconciled.errors) process.emitWarning(error);\n await telemetry?.recordEvent('doom_runner.reconciled', {\n 'runner.reclaimed_count': legacy.reclaimed.length + reconciled.reclaimed.length,\n 'runner.error_count': legacy.errors.length + reconciled.errors.length,\n outcome: legacy.errors.length + reconciled.errors.length === 0 ? 'completed' : 'degraded',\n });\n if (!closing) {\n unsubscribeRunnerUpdates ??= container.runnerRegistry.subscribe(\n () => requestPublish(requestedSessionId),\n requestedSessionId,\n );\n // Reconciliation may have completed retained promotions already.\n for (const id of promotedIds) watchRunner(id);\n requestPublish(requestedSessionId);\n await sweepHistory();\n if (closing) return;\n statusTimer ??= setInterval(() => {\n void refreshSession(requestedSessionId);\n }, RUNNER_STATUS_POLL_MS);\n statusTimer.unref?.();\n historyTimer ??= setInterval(() => {\n void sweepHistory();\n }, HISTORY_SWEEP_INTERVAL_MS);\n historyTimer.unref?.();\n }\n })().catch((error: unknown) => {\n supervision = undefined;\n throw error;\n });\n return supervision;\n };\n\n const disposeRuntime = (): Promise<void> => {\n runtimeDisposal ??= (async () => {\n await supervision?.catch((error: unknown) =>\n process.emitWarning(`Could not initialize headless runner supervision: ${String(error)}`),\n );\n const ownedSessionId = sessionId;\n if (ownedSessionId === undefined) return;\n const records = await container.runnerRegistry.listBySession(ownedSessionId).catch(() => []);\n await Promise.all(\n records.map(async (record) => {\n try {\n const stopped = await stopRunnerProcess(record, container.launcher, container.rmuxBackend, {\n registry: container.runnerRegistry,\n intent: {\n reason: 'stopped',\n terminationReason: 'parent_session_cleanup',\n stopReason: 'session ended',\n },\n });\n if (!stopped && container.processControl.isAlive(record.pid)) {\n process.emitWarning(`Could not stop runner ${record.id} during session shutdown`);\n return;\n }\n await container.runnerRegistry.complete(\n record.id,\n { reason: 'stopped', code: null, signal: null, stopReason: 'session ended' },\n ownedSessionId,\n );\n } catch (error) {\n process.emitWarning(`Could not clean up runner ${record.id}: ${String(error)}`);\n }\n }),\n );\n try {\n await container.ptyHost.disposeAll();\n } finally {\n container.lifeline.dispose();\n container.runnerRegistry.close();\n }\n })();\n return runtimeDisposal;\n };\n\n let refreshInFlight: Promise<void> | undefined;\n const refreshSession = (ownedSessionId: string): Promise<void> => {\n if (closing) return Promise.resolve();\n refreshInFlight ??= refreshNow(ownedSessionId).finally(() => {\n refreshInFlight = undefined;\n });\n return refreshInFlight;\n };\n const refreshNow = async (ownedSessionId: string): Promise<void> => {\n if (closing) return;\n try {\n const reconciled = await reconcileActiveRunners({\n registry: container.runnerRegistry,\n launcher: container.launcher,\n rmuxBackend: container.rmuxBackend,\n processControl: container.processControl,\n currentHostPid: process.pid,\n startup: false,\n active: await container.runnerRegistry.listBySession(ownedSessionId),\n });\n for (const error of reconciled.errors) process.emitWarning(error);\n if (!closing) {\n requestPublish(ownedSessionId);\n wakeForFinished(ownedSessionId);\n }\n } catch (error) {\n process.emitWarning(`Could not refresh doom-runner: ${String(error)}`);\n }\n };\n const publishRuns = async (ownedSessionId: string): Promise<void> => {\n try {\n const records = await container.runnerRegistry.listAll(ownedSessionId);\n if (closing) return;\n if (execution) {\n const root = resolveRootSessionId(ownedSessionId, container.environment);\n const count = (await container.runnerRegistry.list()).filter(\n (record) => (record.rootSessionId ?? record.sessionId) === root,\n ).length;\n if (closing) return;\n execution.client.setStatus(RUNNER_STATUS_KEY, formatRunnerStatus(count));\n }\n if (closing) return;\n const nextBackgroundWork = records\n .filter((record) => record.state === 'running' || watched.has(record.id))\n .map((record) => ({\n id: record.id,\n sessionId: record.sessionId,\n label: record.name,\n // An absent status holds ownership until completion admission succeeds.\n ...(record.state === 'running' ? { status: record.state } : {}),\n }));\n if (JSON.stringify(nextBackgroundWork) !== JSON.stringify(backgroundWorkItems)) {\n backgroundWorkItems = nextBackgroundWork;\n backgroundWorkProvider?.update();\n }\n directEvents.publish(RUNNER_RUNS_TYPE, ownedSessionId, {\n runs: presentRunnerRuns(records, Date.now()),\n });\n } catch (error) {\n process.emitWarning(`Could not publish runner state: ${String(error)}`);\n }\n };\n let publishInFlight: Promise<void> | undefined;\n let publishAgain = false;\n let unsubscribeRunnerUpdates: (() => void) | undefined;\n const requestPublish = (ownedSessionId: string): void => {\n if (closing) return;\n publishAgain = true;\n if (publishInFlight !== undefined) return;\n publishInFlight = (async () => {\n do {\n publishAgain = false;\n await publishRuns(ownedSessionId);\n } while (publishAgain && !closing);\n })()\n .catch((error: unknown) => {\n process.emitWarning(`Could not schedule runner state publication: ${String(error)}`);\n })\n .finally(() => {\n publishInFlight = undefined;\n if (publishAgain) requestPublish(ownedSessionId);\n });\n };\n\n // Sequenced so two runners exiting in the same tick each wake the agent once.\n const wakeForFinished = (ownedSessionId: string): void => {\n if (closing) return;\n wakes = wakes\n .then(async () => {\n if (closing) return;\n let retry = false;\n // Deleting the entry being visited is safe for a Set iterator.\n for (const id of watched) {\n if (closing) return;\n try {\n const record = await container.runnerRegistry.get(id, ownedSessionId);\n if (closing) return;\n if (record?.state === 'running') continue;\n // A record swept before it was seen leaves nothing to report.\n if (record)\n await wakeAgent?.(\n formatRunnerFinished(record),\n `runner-finished:${JSON.stringify([ownedSessionId, id])}`,\n );\n if (record)\n await telemetry?.recordEvent('doom_runner.process_finished', {\n outcome: 'completed',\n 'runner.exit_code': record.exit?.code ?? 0,\n 'runner.backend': record.backend,\n });\n watched.delete(id);\n requestPublish(ownedSessionId);\n } catch (error) {\n retry = true;\n process.emitWarning(`Could not report finished runner ${id}: ${String(error)}`);\n }\n }\n if (retry && !closing && retryTimer === undefined) {\n retryTimer = setTimeout(() => {\n retryTimer = undefined;\n wakeForFinished(ownedSessionId);\n }, COMPLETION_RETRY_MS);\n retryTimer.unref?.();\n }\n if (watched.size === 0) {\n clearTimeout(retryTimer);\n retryTimer = undefined;\n unsubscribeWatched?.();\n unsubscribeWatched = undefined;\n }\n })\n .catch((error: unknown) => {\n process.emitWarning(`Could not report a finished runner: ${String(error)}`);\n });\n };\n\n const watchRunner = (id: string): void => {\n const ownedSessionId = sessionId;\n if (!wakeAgent || closing || ownedSessionId === undefined) return;\n watched.add(id);\n requestPublish(ownedSessionId);\n // Independent of the optional activity: the wake-up must not depend on a\n // browser watching the runner list.\n unsubscribeWatched ??= container.runnerRegistry.subscribe(() => wakeForFinished(ownedSessionId), ownedSessionId);\n // It may already have exited between promotion and subscription.\n wakeForFinished(ownedSessionId);\n };\n\n const activity: DoomHeadlessActivity = {\n name: 'runner',\n start: async (executionContext: DoomHeadlessExecutionContext) => {\n await ensureSession(executionContext.sessionId);\n requestPublish(executionContext.sessionId);\n return () => {\n // The retained owner keeps supervision alive. Optional activity toggles\n // must not repeat startup cleanup, subscriptions, or history initialization.\n };\n },\n };\n return {\n container,\n activity,\n ensureSession,\n watchRunner,\n async recoverCompaction(event) {\n if (\n event.status !== 'completed' ||\n closing ||\n !execution ||\n typeof event.entryId !== 'string' ||\n event.entryId === recoveredCompactionId\n )\n return;\n const entries = await execution.session.entries();\n const compacted = entries.findLast((entry) => entry.type === 'compaction');\n if (closing || compacted?.id !== event.entryId) return;\n await ensureSession(execution.sessionId);\n let records;\n try {\n records = await container.runnerRegistry.listBySession(execution.sessionId);\n } catch {\n return;\n }\n if (closing) return;\n const active = records.filter((record) => record.state === 'running');\n const text = activeRunnerRecovery(active);\n if (!text) return;\n await execution.session.appendMessage?.({\n type: 'doom-runner-compaction',\n text,\n display: false,\n details: { sessionId: execution.sessionId, runnerIds: active.map((record) => record.id) },\n });\n if (!closing) recoveredCompactionId = event.entryId;\n },\n backgroundWorkPlugin: (context) => {\n context.inject([DOOM_BACKGROUND_WORK_SERVICE], (serviceContext) => {\n const service = readDoomBackgroundWorkService(serviceContext);\n if (!service) return undefined;\n const registration = service.register({\n provider: BACKGROUND_WORK_PROVIDER,\n listActiveWork: () => backgroundWorkItems,\n });\n backgroundWorkProvider = registration;\n return () => {\n registration.dispose();\n if (backgroundWorkProvider === registration) backgroundWorkProvider = undefined;\n };\n });\n },\n dispose() {\n if (disposal) return disposal;\n closing = true;\n disposal = (async () => {\n // Session cleanup completes every runner it stops, and none of those may\n // start a turn in a session that is going away.\n closing = true;\n clearInterval(statusTimer);\n clearInterval(historyTimer);\n clearTimeout(retryTimer);\n retryTimer = undefined;\n watched.clear();\n unsubscribeWatched?.();\n unsubscribeWatched = undefined;\n unsubscribeRunnerUpdates?.();\n unsubscribeRunnerUpdates = undefined;\n await wakes;\n await publishInFlight;\n await historySweep;\n await refreshInFlight;\n try {\n execution?.client.setStatus(RUNNER_STATUS_KEY, undefined);\n } catch (error) {\n process.emitWarning(`Could not clear runner status: ${String(error)}`);\n }\n await disposeRuntime();\n await telemetry?.recordEvent('doom_runner.session_finished', { outcome: 'stopped' });\n await telemetry?.shutdown();\n })();\n return disposal;\n },\n };\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { CONFIG_DIR_NAME } from '@earendil-works/pi-coding-agent';\n\nimport {\n MAX_ERROR_ENTRIES_CEILING,\n MAX_PATTERNS,\n MAX_PATTERN_LENGTH,\n MAX_RESULT_BYTES_CEILING,\n MAX_RESULT_LINES_CEILING,\n MAX_RESULT_TOKENS_CEILING,\n RATIO_KEYS,\n RUNNER_SETTINGS_FILE,\n} from '../../constants/runnerSettings';\nimport type { IRunnerSettingsLoader, RunnerSettings, RunnerSettingsLoad } from '../../types/runnerSettings';\n\n/** Pi's convention is one JSON file per extension under the config directory. */\n\nconst EMPTY: RunnerSettingsLoad = { settings: {}, issues: [] };\nconst COUNT_KEYS = [\n 'maxResultBytes',\n 'maxResultLines',\n 'successMaxResultBytes',\n 'maxResultTokens',\n 'successMaxResultTokens',\n 'errorMaxEntries',\n 'errorMaxVariantsJoined',\n] as const;\nconst KNOWN_KEYS = new Set<string>([...RATIO_KEYS, ...COUNT_KEYS, 'errorPatterns']);\n/** Ceilings so a project file cannot flood the model's context. */\nconst CEILINGS: Readonly<Record<string, number>> = {\n maxResultBytes: MAX_RESULT_BYTES_CEILING,\n successMaxResultBytes: MAX_RESULT_BYTES_CEILING,\n maxResultTokens: MAX_RESULT_TOKENS_CEILING,\n successMaxResultTokens: MAX_RESULT_TOKENS_CEILING,\n maxResultLines: MAX_RESULT_LINES_CEILING,\n errorMaxEntries: MAX_ERROR_ENTRIES_CEILING,\n errorMaxVariantsJoined: MAX_ERROR_ENTRIES_CEILING,\n};\n\nexport class RunnerSettingsLoader implements IRunnerSettingsLoader {\n load(cwd: string, trusted: boolean): RunnerSettingsLoad {\n // Project-local configuration is untrusted input until the project is.\n if (!trusted) return EMPTY;\n\n let raw: string;\n try {\n raw = fs.readFileSync(path.join(cwd, CONFIG_DIR_NAME, RUNNER_SETTINGS_FILE), 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return EMPTY;\n return { settings: {}, issues: [`${RUNNER_SETTINGS_FILE} could not be read`] };\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return { settings: {}, issues: [`${RUNNER_SETTINGS_FILE} is not valid JSON`] };\n }\n return validate(parsed);\n }\n}\n\nfunction validate(parsed: unknown): RunnerSettingsLoad {\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n return { settings: {}, issues: [`${RUNNER_SETTINGS_FILE} must contain a JSON object`] };\n }\n\n const source = parsed as Record<string, unknown>;\n const settings: Record<string, unknown> = {};\n const issues: string[] = [];\n // A rejected key is reported rather than dropped: a silent typo reads as a\n // setting that simply does not work.\n for (const key of Object.keys(source)) if (!KNOWN_KEYS.has(key)) issues.push(`unknown key ${key}`);\n\n for (const key of COUNT_KEYS) {\n const value = source[key];\n if (value === undefined) continue;\n if (typeof value !== 'number' || !Number.isInteger(value) || value <= 0) {\n issues.push(`${key} must be a positive integer`);\n continue;\n }\n settings[key] = Math.min(value, CEILINGS[key] ?? value);\n }\n\n for (const key of RATIO_KEYS) {\n const value = source[key];\n if (value === undefined) continue;\n if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0 || value >= 1) {\n issues.push(`${key} must be a number above 0 and below 1`);\n continue;\n }\n settings[key] = value;\n }\n\n const patterns = source.errorPatterns;\n if (patterns !== undefined) {\n if (!Array.isArray(patterns) || patterns.some((entry) => typeof entry !== 'string')) {\n issues.push('errorPatterns must be an array of strings');\n } else {\n const accepted: string[] = [];\n for (const pattern of patterns.slice(0, MAX_PATTERNS) as string[]) {\n if (pattern.length > MAX_PATTERN_LENGTH) {\n issues.push('errorPatterns entry is too long');\n continue;\n }\n try {\n new RegExp(pattern, 'iu');\n accepted.push(pattern);\n } catch {\n issues.push(`errorPatterns entry is not a valid regular expression: ${pattern}`);\n }\n }\n if (accepted.length > 0) settings.errorPatterns = accepted;\n }\n }\n\n return { settings: settings as RunnerSettings, issues };\n}\n","import type { DoomServerPluginContext } from '@agimon-ai/po-core/serverFacet';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport { RUNNER_SETTINGS_FILE } from '../../../../../constants/runnerSettings';\nimport { createHeadlessBashTool, createHeadlessRunnersCommand } from '../../../../../services/headless';\nimport { summarizeLog } from '../../../../../services/logReader';\nimport { createRunnerDependencies } from '../../../../../services/runnerDependencies';\nimport { createRunnerServerRuntime } from '../../../../../services/runnerServerRuntime';\nimport { RunnerSettingsLoader } from '../../../../../services/runnerSettings';\n\nexport const RUNNER_SERVER_SCOPE_SERVICE = 'doom/runner-server-scope';\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n 'doom/runner-server-scope': RunnerServerScope;\n }\n}\n\nexport const createRunnerServerRoot = ({ host, agent, signal }: DoomServerPluginContext) => {\n if (!host.context.directEvents) throw new Error('Runner headless facet requires the session direct event bus.');\n if (!host.context.cwd || !host.context.environment) {\n throw new Error('Runner headless facet requires session cwd and environment.');\n }\n // Inherit the current headless Pi bridge's isProjectTrusted: () => true.\n // This preserves runner configuration parity, not a new general trust policy.\n const loaded = new RunnerSettingsLoader().load(host.context.cwd, true);\n const settings = Object.freeze({\n ...loaded.settings,\n ...(loaded.settings.errorPatterns ? { errorPatterns: Object.freeze([...loaded.settings.errorPatterns]) } : {}),\n });\n for (const issue of loaded.issues) process.emitWarning(`${RUNNER_SETTINGS_FILE}: ${issue}`);\n const dependencies = createRunnerDependencies({\n settings,\n cwd: host.context.cwd,\n environment: host.context.environment,\n ...(host.context.executionBudget === undefined ? {} : { executionBudget: host.context.executionBudget }),\n });\n const execution = agent?.context;\n const wakeAgent =\n execution &&\n (async (content: string, requestId: string): Promise<void> => {\n try {\n // 'steer' joins a running turn and starts one on an idle session.\n // Reuse completion identity across retries and acknowledge admission, not settlement.\n if (!execution.session.admitPrompt) throw new Error('The session cannot admit a runner notification.');\n await execution.session.admitPrompt(content, 'steer', undefined, requestId);\n } catch (error) {\n // Keep completion ownership with the watcher until admission succeeds.\n await Promise.resolve()\n .then(() => execution.client.notify({ body: String(error), level: 'warning' }))\n .catch(() => undefined);\n throw error;\n }\n });\n const runtime = createRunnerServerRuntime(dependencies, host.context.directEvents, wakeAgent, execution);\n const bash = (wakeOnExit: boolean) =>\n createHeadlessBashTool(\n {\n run: async (request) => {\n await runtime.ensureSession(request.sessionId);\n const result = await dependencies.bashRunService.run({\n ...request,\n ...(signal ? { signal: request.signal ? AbortSignal.any([signal, request.signal]) : signal } : {}),\n });\n // Without this, nothing tells the agent the runner ended.\n if (wakeOnExit && result.kind === 'promoted') runtime.watchRunner(result.id);\n return result;\n },\n },\n (path, lines, bytes, tokens) => summarizeLog(path, lines, bytes, tokens, settings),\n settings,\n dependencies.environment,\n );\n const value = {\n tool: bash(true),\n // Remote MCP runners must not wake the local agent; the remote caller polls instead.\n remoteTool: bash(false),\n command: createHeadlessRunnersCommand(dependencies),\n recoverCompaction: runtime.recoverCompaction,\n };\n return {\n value,\n services: [\n runtime.backgroundWorkPlugin,\n (context: Context) => {\n context.plugin((providerContext) => providerContext.provide(RUNNER_SERVER_SCOPE_SERVICE, value));\n },\n ],\n activities: [runtime.activity],\n onStart: execution ? () => runtime.ensureSession(execution.sessionId) : undefined,\n onStop: runtime.dispose,\n };\n};\n\nexport type RunnerServerScope = Awaited<ReturnType<typeof createRunnerServerRoot>>['value'];\n","import { defineRoot } from '@agimon-ai/po-core/extensionFile';\n\nimport { createRunnerServerRoot } from './_lib/serverRoot';\n\nexport default defineRoot(createRunnerServerRoot);\n","import type { DoomHubChannel, DoomHubChannelSource } from '@agimon-ai/po-core/hubChannel';\n\nimport { RUNNER_RUNS_TYPE } from '../../constants/webRunners';\nimport { type RunnerRunView } from '../../types/webRunners';\n\nfunction runnerPayload(value: unknown): value is { runs: RunnerRunView[] } {\n return typeof value === 'object' && value !== null && Array.isArray((value as { runs?: unknown }).runs);\n}\n\n/**\n * The runners data channel consumes lifecycle-owned snapshots from the session\n * server. Durable registry files are read by the owning session only, never by\n * this hub channel.\n */\nexport function createRunnersChannel(): DoomHubChannel {\n return {\n frameType: RUNNER_RUNS_TYPE,\n start(host) {\n const latest = new Map<string, RunnerRunView[]>();\n const subscriptions = new Map<string, () => void>();\n const source: DoomHubChannelSource = {\n payloadFor(scope) {\n const runs = latest.get(scope.sessionId);\n return runs === undefined ? undefined : { runs };\n },\n sessionAdded(scope) {\n subscriptions.get(scope.sessionId)?.();\n latest.delete(scope.sessionId);\n const unsubscribe = host.directEvents.subscribe(\n RUNNER_RUNS_TYPE,\n scope.sessionId,\n (payload) => {\n if (!runnerPayload(payload)) return;\n latest.set(scope.sessionId, payload.runs);\n host.publish(scope.sessionId, payload);\n },\n { replayLatest: true },\n );\n subscriptions.set(scope.sessionId, unsubscribe);\n },\n sessionRemoved(sessionId) {\n subscriptions.get(sessionId)?.();\n subscriptions.delete(sessionId);\n latest.delete(sessionId);\n },\n close() {\n for (const unsubscribe of subscriptions.values()) unsubscribe();\n subscriptions.clear();\n latest.clear();\n },\n };\n return source;\n },\n };\n}\n","import { defineChannel } from '@agimon-ai/po-core/extensionFile';\nimport type { DoomHubChannel } from '@agimon-ai/po-core/hubChannel';\n\nimport { createRunnersChannel } from '../../../services/runnersChannel';\nexport default defineChannel(function runnerRunsChannel(): DoomHubChannel {\n return createRunnersChannel();\n});\n","export const LOG_DIR_NAME = 'logs';\nexport const STATE_EXTENSION = '.json';\nexport const RUNNING_STATE = 'running';\nexport const STATE_POLL_MS = 1000;\nexport const HEARTBEAT_MS = 15_000;\nexport const DEFAULT_LINES = 200;\nexport const MAX_LINES = 5000;\nexport const SAFE_SEGMENT = /^[\\w.@-]+$/;\nexport const SCREEN_POLL_MS = 100;\nexport const RAW_LOG_SUFFIX = '.raw';\nexport const MAX_INPUT_CHARS = 4096;\nexport const NOT_ATTACHABLE = 'No attachable runner by that name in this session.';\n","export const RUNNER_API_BASE_PATH = 'runner';\nexport const RUN_ID_PARAM = 'runId';\nexport const RUNNER_SCREEN_EVENT = 'screen';\nexport const RUNNER_LOG_STREAM_EVENT = 'append';\nexport const RUNNER_LOG_PING_EVENT = 'ping';\n","import fs from 'node:fs';\n\nimport { POLL_MS } from '../../constants/logTail';\nimport type { ILogTail, LogTailHandle, LogTailOptions } from '../../types/logTail';\n\n/** How often the tail restats the file; the same cadence the CLI's --follow uses. */\n\n/**\n * Polling tail: read the delta between the last offset and the file's current\n * size, and hand back only complete lines.\n *\n * Same reliability posture as this package's runner watcher: the poll is the\n * mechanism, not an accelerator for a change notification. fs.watchFile only\n * fires when it observes a difference from a baseline it took itself, so a\n * write that lands before its first stat is a change it never reports; a\n * restat every tick has no such window.\n *\n * A write that lands mid-line is common, so the trailing fragment is held\n * until its newline arrives rather than emitted as a line that will change.\n */\nexport class LogTail implements ILogTail {\n follow(logPath: string, options: LogTailOptions): LogTailHandle {\n let offset = options.from;\n let pending = '';\n let closed = false;\n\n const drain = (size: number): void => {\n // A shrunken file was rotated or truncated; start over rather than\n // reading from an offset that now points into different content.\n if (size < offset) {\n offset = 0;\n pending = '';\n }\n if (size === offset) return;\n const length = size - offset;\n const buffer = Buffer.alloc(length);\n const descriptor = fs.openSync(logPath, 'r');\n let bytesRead: number;\n try {\n bytesRead = fs.readSync(descriptor, buffer, 0, length, offset);\n } finally {\n fs.closeSync(descriptor);\n }\n offset = size;\n if (bytesRead <= 0) return;\n pending += buffer.subarray(0, bytesRead).toString('utf8');\n const lines = pending.split('\\n');\n pending = lines.pop() ?? '';\n if (lines.length > 0) options.onLines(lines, offset - Buffer.byteLength(pending, 'utf8'));\n };\n\n const tick = (): void => {\n if (closed) return;\n try {\n drain(fs.statSync(logPath).size);\n } catch (error) {\n // The runner has not opened its log yet; the next tick settles it.\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return;\n options.onError(error instanceof Error ? error : new Error(String(error)));\n }\n };\n\n const timer = setInterval(tick, POLL_MS);\n // Following a log must never be the reason a process stays alive.\n timer.unref?.();\n return {\n close() {\n if (closed) return;\n closed = true;\n clearInterval(timer);\n },\n };\n }\n}\n","import type { LogSlice } from './logReader';\n\n/**\n * The runner log API, shared by this package's session-scoped routes and its\n * cockpit plugin. The two halves run in different processes, so the wire\n * vocabulary is declared here: the browser half may reach `src/types` and\n * nothing else on the server side.\n *\n * Where the routes live is not here. That is `src/types/apiRoutes`, which both\n * halves read, and the generated client turns into the URLs the page addresses.\n * The file a run writes to is still read from its metadata record by the server\n * alone.\n */\n\n/**\n * One chunk of an attached pane's output.\n *\n * Base64 because these are terminal bytes, escape sequences and all, and a\n * server-sent event is a line-oriented text frame that would mangle them.\n */\nexport interface RunnerScreenEvent {\n chunk: string;\n /** Byte offset just past this chunk, so a reconnect resumes rather than replays. */\n offset?: number;\n /** Set once the runner exits, so the page can stop watching. */\n ended?: boolean;\n}\n\n/** The body of a keystroke POST. Text, not key codes: the pane wants bytes. */\nexport interface RunnerInputRequest {\n text: string;\n}\n\n/** The named SSE event carrying a RunnerScreenEvent payload. */\n\n/**\n * A log request as query parameters. `grep` is a literal substring, not a\n * regular expression, because that is what the reader matches; `lines` bounds\n * the answer to the last N lines of whatever survived the filter.\n */\nexport interface RunnerLogQueryParams {\n lines?: number;\n grep?: string;\n ignoreCase?: boolean;\n contextLines?: number;\n}\n\n/** The slice the log route answers with, plus which runner it came from. */\nexport interface RunnerLogResponse extends LogSlice {\n runId: string;\n /** True while the runner is still writing, so the page knows following is worth offering. */\n running: boolean;\n}\n\n/**\n * One server-sent event on the follow stream: the lines appended since the last\n * one. The stream never filters: a page that sets a query stops following and\n * reads a filtered slice instead, because grep with context is a whole-file\n * answer and cannot be assembled from a chunk at a time.\n */\nexport interface RunnerLogStreamEvent {\n /** Appended lines, in order; empty when the event only reports the runner ending. */\n lines: string[];\n /**\n * Byte offset just past the last line in this event.\n *\n * A follower that loses the stream resumes here. Without it the page could\n * only fall back to the offset its last slice reported, which every line\n * delivered since has already moved past, so a reconnect would replay them.\n */\n offset?: number;\n /** Set once the runner exits, so the page can stop following without polling the run list. */\n ended?: boolean;\n}\n\n/** The named SSE event carrying a RunnerLogStreamEvent payload. */\n\n/**\n * The named SSE event that carries nothing.\n *\n * A runner can be alive and silent for minutes, which on the wire is\n * indistinguishable from a connection that died. This is sent on a timer so\n * the socket keeps proving itself. Readers that only listen for `append`\n * ignore it, which is what makes it safe to add.\n */\n\n/** Query parameter names, shared so the page and the route cannot drift apart. */\nexport const RUNNER_LOG_PARAMS = {\n lines: 'lines',\n grep: 'grep',\n ignoreCase: 'ignoreCase',\n contextLines: 'contextLines',\n from: 'from',\n} as const;\n","import { apiResponse, defineApiRoutes } from '@agimon-ai/po-core/web';\n\nimport { RUN_ID_PARAM } from '../constants/webRunnerLog';\nimport { RUNNER_LOG_PARAMS, type RunnerLogResponse } from './webRunnerLog';\n\n/**\n * This package's routes, as data.\n *\n * No scope and no base path: the build reads both off\n * `src/extensions/workspaces/sessions/(backend)/api/runner/`, so the mount is\n * stated once, by the folder that creates it. This package stated it four times\n * before, once per URL builder, each of them re-spelling `/plugins/` and the\n * session prefix by hand.\n *\n * The Hono app registers these paths verbatim and the browser addresses them,\n * so a path cannot move on one side alone. `:runId` is Hono's own parameter\n * syntax for that reason; a caller supplies the value as `params`, and the\n * client encodes the segment.\n */\nexport default defineApiRoutes({\n log: {\n method: 'GET',\n path: `/runners/:${RUN_ID_PARAM}/log`,\n query: [\n RUNNER_LOG_PARAMS.lines,\n RUNNER_LOG_PARAMS.grep,\n RUNNER_LOG_PARAMS.ignoreCase,\n RUNNER_LOG_PARAMS.contextLines,\n ],\n response: apiResponse<RunnerLogResponse>(),\n },\n /**\n * The live tail of that same log.\n *\n * `stream: true`, so the client exposes a URL and no call method: the\n * consumer is the browser's own `EventSource`, and a relayed call would\n * buffer a stream that never ends.\n */\n logStream: {\n method: 'GET',\n path: `/runners/:${RUN_ID_PARAM}/log/stream`,\n query: [RUNNER_LOG_PARAMS.from],\n stream: true,\n },\n /** The unscrubbed pane bytes, for a terminal emulator rather than a reader. */\n screenStream: {\n method: 'GET',\n path: `/runners/:${RUN_ID_PARAM}/screen/stream`,\n query: [RUNNER_LOG_PARAMS.from],\n stream: true,\n },\n input: {\n method: 'POST',\n path: `/runners/:${RUN_ID_PARAM}/screen/input`,\n },\n});\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { DoomApi, DoomApiContext, DoomApiHandler } from '@agimon-ai/po-core/packageApi';\nimport { Hono } from 'hono';\nimport { streamSSE } from 'hono/streaming';\n\nimport {\n DEFAULT_LINES,\n HEARTBEAT_MS,\n LOG_DIR_NAME,\n MAX_INPUT_CHARS,\n MAX_LINES,\n NOT_ATTACHABLE,\n RAW_LOG_SUFFIX,\n RUNNING_STATE,\n SAFE_SEGMENT,\n SCREEN_POLL_MS,\n STATE_EXTENSION,\n STATE_POLL_MS,\n} from '../../constants/runnerLogApi';\nimport {\n RUN_ID_PARAM,\n RUNNER_API_BASE_PATH,\n RUNNER_LOG_PING_EVENT,\n RUNNER_LOG_STREAM_EVENT,\n RUNNER_SCREEN_EVENT,\n} from '../../constants/webRunnerLog';\nimport { LogReader } from '../../services/logReader';\nimport { LogTail } from '../../services/logTail';\nimport { PtyBackendChain } from '../../services/ptyBackendChain';\nimport { RmuxBackend } from '../../services/rmuxBackend';\nimport { RunnerPaths, resolveRunnerStoreDirectory, runnerStateDirFor } from '../../services/runnerPaths';\nimport { TmuxBackend } from '../../services/tmuxBackend';\nimport { parseRunnerRecord } from '../../services/webRunnerRuns';\nimport routes from '../../types/apiRoutes';\nimport type { ILogReader, LogQuery } from '../../types/logReader';\nimport type { ILogTail } from '../../types/logTail';\nimport type { IRmuxBackend } from '../../types/rmuxBackend';\nimport type { RunnerRecord } from '../../types/runnerRegistry';\nimport {\n RUNNER_LOG_PARAMS,\n type RunnerLogResponse,\n type RunnerLogStreamEvent,\n type RunnerScreenEvent,\n} from '../../types/webRunnerLog';\n\n/** How often a follow re-reads the record to notice the runner exiting. */\n/**\n * How often a silent but living stream proves it is still there. Short enough\n * that an idle proxy does not reap the socket, long enough to cost nothing.\n */\n/** Kept in step with LogQuery's own default, so an unasked-for tail is the same size everywhere. */\n/** A page that asks for more than this gets this; the whole point of the route is a bounded read. */\n/** Path segments the client supplies are names, never paths. */\n/** Backends that expose a pane another process can read and write. */\nconst MULTIPLEXER_BACKENDS: ReadonlySet<string> = new Set(['rmux', 'tmux']);\n/** How often an attached pane's new bytes are picked up. */\n/** The unscrubbed copy the runner's sink writes beside the log, for interactive runs. */\n/** One keystroke batch; a paste is not a file transfer. */\n/** Said the same way for every reason, so the route never reports which check failed. */\n\nexport interface RunnerLogApiOptions {\n /** The session these routes answer for; the host owns exactly one. */\n sessionId: string;\n /** The store root; defaults to this environment's agent directory. */\n storeDir?: string;\n environment?: Readonly<Record<string, string | undefined>>;\n cwd?: string;\n logReader?: ILogReader;\n logTail?: ILogTail;\n /**\n * Reaches a live pane to read its screen and send it input.\n *\n * A session API is handed nothing but its session id, so it cannot touch the\n * in-process PTY handles the extension holds. This talks to the multiplexer\n * over its own socket instead, the same way the CLI's `input` verb does,\n * which is what makes an attached pane reachable across processes at all.\n */\n pane?: IRmuxBackend;\n}\n\n/** Rejects anything that could climb out of the session's own directory before a path is built. */\nfunction isSafeSegment(value: string): boolean {\n return value !== '' && value !== '.' && value !== '..' && SAFE_SEGMENT.test(value);\n}\n\n/**\n * The log file a run wrote, or undefined when there is no such run or its\n * record points somewhere it has no business pointing.\n *\n * The record names its own log path, and that record is written by another\n * process, so the path is checked rather than trusted: it must sit inside this\n * session's own logs directory. Without that check a doctored record would\n * turn this route into an arbitrary file read.\n */\nfunction resolveLogFile(stateDir: string, logsDir: string, sessionId: string, runId: string): RunnerRecord | undefined {\n const statePath = path.join(stateDir, `${runId}${STATE_EXTENSION}`);\n let raw: string;\n try {\n raw = fs.readFileSync(statePath, 'utf8');\n } catch {\n return undefined; // No such run in this session; the route answers 404.\n }\n const record = parseRunnerRecord(raw);\n if (record === undefined || record.id !== runId || record.sessionId !== sessionId) return undefined;\n const resolved = path.resolve(record.logPath);\n if (resolved !== logsDir && !resolved.startsWith(`${logsDir}${path.sep}`)) return undefined;\n return record;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction numberParam(value: string | undefined, fallback: number, max: number): number {\n const parsed = value === undefined ? Number.NaN : Number.parseInt(value, 10);\n if (!Number.isFinite(parsed) || parsed < 0) return fallback;\n return Math.min(parsed, max);\n}\n\nfunction logQueryOf(url: URL): LogQuery {\n const grep = url.searchParams.get(RUNNER_LOG_PARAMS.grep) ?? undefined;\n return {\n lines: numberParam(url.searchParams.get(RUNNER_LOG_PARAMS.lines) ?? undefined, DEFAULT_LINES, MAX_LINES),\n ...(grep === undefined || grep === '' ? {} : { grep }),\n ignoreCase: url.searchParams.get(RUNNER_LOG_PARAMS.ignoreCase) === 'true',\n contextLines: numberParam(url.searchParams.get(RUNNER_LOG_PARAMS.contextLines) ?? undefined, 0, MAX_LINES),\n };\n}\n\n/**\n * This package's HTTP surface: one runner's log, as a bounded slice and as a\n * live tail.\n *\n * The routes are mounted inside one session's own server, so they name a runner\n * and nothing else; the session is the host, not a parameter. The reader only\n * ever returns the last N lines of what matched, so both routes stay bounded no\n * matter how large the file on disk is.\n *\n * Paths come from src/types/apiRoutes, the one table the browser's generated\n * client reads too, so this app and the cockpit cannot disagree about where a\n * route lives. They stay relative to the mount the host strips.\n */\nexport function createRunnerLogApi(options: RunnerLogApiOptions): Hono {\n const logReader = options.logReader ?? new LogReader();\n const logTail = options.logTail ?? new LogTail();\n const sessionId = options.sessionId;\n const paths = new RunnerPaths(options.cwd, options.environment);\n const storeDir = options.storeDir ?? resolveRunnerStoreDirectory(options.environment ?? process.env);\n const stateDir =\n options.storeDir === undefined ? paths.stateDirectory(sessionId) : runnerStateDirFor(storeDir, sessionId);\n const logsDir =\n options.storeDir === undefined ? paths.logDirectory(sessionId) : path.join(storeDir, sessionId, LOG_DIR_NAME);\n const app = new Hono();\n\n // Built on first use, not on mount: most sessions never attach to a pane,\n // and constructing this probes the filesystem for a multiplexer binary.\n let paneBackend: IRmuxBackend | undefined = options.pane;\n const pane = (): IRmuxBackend => {\n paneBackend ??= (() => {\n const paths = new RunnerPaths(options.cwd, options.environment);\n return new PtyBackendChain(new RmuxBackend(paths), new TmuxBackend(paths));\n })();\n return paneBackend;\n };\n\n /** The record behind a request, or undefined when this session has no such run. */\n const runnerOf = (runId: string): RunnerRecord | undefined =>\n isSafeSegment(runId) ? resolveLogFile(stateDir, logsDir, sessionId, runId) : undefined;\n\n /**\n * The pane a request may attach to.\n *\n * Same posture as the log routes: the record is written by another process,\n * so nothing on it is trusted until it is checked. The target must be one\n * this package owns, the run must still be up, and it must have been started\n * interactive. A non-interactive run has no terminal to type into, and a\n * subprocess-backed run has no pane at all.\n */\n const attachableOf = (runId: string): { record: RunnerRecord; target: string } | undefined => {\n const record = runnerOf(runId);\n if (record === undefined || record.state !== RUNNING_STATE || record.interactive !== true) return undefined;\n const target = record.backendTarget;\n if (target === undefined || !MULTIPLEXER_BACKENDS.has(record.backend) || !isSafeSegment(target)) return undefined;\n return { record, target };\n };\n app.get(routes.log.path, (context) => {\n const runId = context.req.param(RUN_ID_PARAM);\n const record = runnerOf(runId);\n if (record === undefined) return context.json({ error: `No runner '${runId}' in this session.` }, 404);\n const slice = logReader.read(record.logPath, logQueryOf(new URL(context.req.url)));\n const body: RunnerLogResponse = { ...slice, runId, running: record.state === RUNNING_STATE };\n return context.json(body);\n });\n\n app.get(routes.logStream.path, (context) => {\n const runId = context.req.param(RUN_ID_PARAM);\n const record = runnerOf(runId);\n if (record === undefined) return context.json({ error: `No runner '${runId}' in this session.` }, 404);\n const from = numberParam(\n new URL(context.req.url).searchParams.get(RUNNER_LOG_PARAMS.from) ?? undefined,\n 0,\n Number.MAX_SAFE_INTEGER,\n );\n\n return streamSSE(context, async (stream) => {\n const send = (event: RunnerLogStreamEvent): Promise<void> =>\n stream.writeSSE({ event: RUNNER_LOG_STREAM_EVENT, data: JSON.stringify(event) });\n\n // The tail and the state poll both push onto one queue, so the stream\n // writes in the order things happened rather than interleaving two\n // writers onto the same socket.\n let pump: Promise<void> = Promise.resolve();\n const queue = (event: RunnerLogStreamEvent): void => {\n pump = pump.then(() => send(event)).catch(() => undefined);\n };\n\n let finish = (): void => undefined;\n const done = new Promise<void>((resolve) => {\n finish = resolve;\n });\n const handle = logTail.follow(record.logPath, {\n from,\n onLines: (lines, completeThrough) => queue({ lines, offset: completeThrough }),\n onError: () => finish(),\n });\n // A finished runner writes nothing more, so the page is told once and\n // the stream ends rather than holding a socket open forever.\n const poll = setInterval(() => {\n const current = runnerOf(runId);\n if (current !== undefined && current.state === RUNNING_STATE) return;\n queue({ lines: [], ended: true });\n finish();\n }, STATE_POLL_MS);\n // A runner can be alive and produce nothing for minutes. Without this the\n // page cannot tell that from a stream that quietly died.\n const heartbeat = setInterval(() => {\n pump = pump.then(() => stream.writeSSE({ event: RUNNER_LOG_PING_EVENT, data: '' })).catch(() => undefined);\n }, HEARTBEAT_MS);\n\n stream.onAbort(() => finish());\n await done;\n clearInterval(poll);\n clearInterval(heartbeat);\n handle.close();\n await pump;\n });\n });\n\n app.get(routes.screenStream.path, (context) => {\n const runId = context.req.param(RUN_ID_PARAM);\n const attachable = attachableOf(runId);\n if (attachable === undefined) return context.json({ error: NOT_ATTACHABLE }, 404);\n // The record's log path is already proven to sit inside this session's own\n // logs directory, and the raw copy is that same path with a suffix, so it\n // cannot point anywhere new.\n const rawPath = `${attachable.record.logPath}${RAW_LOG_SUFFIX}`;\n const from = numberParam(\n new URL(context.req.url).searchParams.get(RUNNER_LOG_PARAMS.from) ?? undefined,\n 0,\n Number.MAX_SAFE_INTEGER,\n );\n\n return streamSSE(context, async (stream) => {\n let pump: Promise<void> = Promise.resolve();\n const queue = (event: RunnerScreenEvent): void => {\n pump = pump\n .then(() => stream.writeSSE({ event: RUNNER_SCREEN_EVENT, data: JSON.stringify(event) }))\n .catch(() => undefined);\n };\n\n let finish = (): void => undefined;\n const done = new Promise<void>((resolve) => {\n finish = resolve;\n });\n\n let offset = from;\n const drain = (): void => {\n let size: number;\n try {\n size = fs.statSync(rawPath).size;\n } catch {\n return; // The sink has not opened the file yet; the next tick settles it.\n }\n // The sink starts the file over when it passes its ceiling, so a\n // smaller file is a fresh one rather than a bad offset.\n if (size < offset) offset = 0;\n if (size === offset) return;\n const length = size - offset;\n const buffer = Buffer.alloc(length);\n const descriptor = fs.openSync(rawPath, 'r');\n let read: number;\n try {\n read = fs.readSync(descriptor, buffer, 0, length, offset);\n } finally {\n fs.closeSync(descriptor);\n }\n if (read <= 0) return;\n offset += read;\n // Bytes, not lines: a terminal's escape sequences straddle newlines and\n // mean nothing once split on them.\n queue({ chunk: buffer.subarray(0, read).toString('base64'), offset });\n };\n\n const poll = setInterval(() => {\n const current = runnerOf(runId);\n drain();\n if (current === undefined || current.state !== RUNNING_STATE) {\n queue({ chunk: '', offset, ended: true });\n finish();\n }\n }, SCREEN_POLL_MS);\n\n stream.onAbort(() => finish());\n await done;\n clearInterval(poll);\n await pump;\n });\n });\n\n /**\n * Types into a live pane.\n *\n * This is the one route in the package that writes rather than reads, so it\n * is deliberately narrow: an owned target, still running, started\n * interactive, and a body that is nothing but text.\n */\n app.post(routes.input.path, async (context) => {\n const runId = context.req.param(RUN_ID_PARAM);\n const attachable = attachableOf(runId);\n if (attachable === undefined) return context.json({ error: NOT_ATTACHABLE }, 404);\n\n let body: unknown;\n try {\n body = await context.req.json();\n } catch {\n return context.json({ error: 'Expected a JSON body carrying text.' }, 400);\n }\n const text = isRecord(body) ? body.text : undefined;\n if (typeof text !== 'string' || text === '') return context.json({ error: 'Expected a non-empty text.' }, 400);\n if (text.length > MAX_INPUT_CHARS) return context.json({ error: 'That is more input than a pane takes.' }, 413);\n\n const delivered = await pane().input(attachable.target, text);\n if (!delivered) return context.json({ error: 'The runner did not take the input.' }, 502);\n return context.json({ delivered: true });\n });\n\n return app;\n}\n\n/** The named export a host imports from this package's built session entry. */\nexport const api: DoomApi = {\n basePath: RUNNER_API_BASE_PATH,\n start(context: DoomApiContext): DoomApiHandler {\n // The host is one session's server, so its id is the whole scope; a hub\n // would have handed no session at all, and there is nothing to answer.\n const app = createRunnerLogApi({\n sessionId: context.sessionId ?? '',\n cwd: context.cwd,\n environment: context.environment,\n });\n return {\n fetch: (request) => app.fetch(request),\n // Nothing outlives a request: a follow's watch and its poll are both\n // torn down when its own stream ends or the socket aborts.\n close: () => undefined,\n };\n },\n};\n","import { defineRoute } from '@agimon-ai/po-core/extensionFile';\n\nimport { api } from '../../../../../../services/runnerLogApi';\n\n/**\n * Mounts this package's HTTP API at `runner`, which the folder names.\n *\n * The folder is the declaration: the build reads the base path off it and hands\n * the browser a client bound to the same segment, so the mount is stated once\n * rather than in a constant and in four URL builders that were each free to\n * drift.\n */\nexport default defineRoute(api);\n","import { defineServerCommand, type WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/po-core/serverFacet';\n\nimport type { RunnerServerScope } from '../_lib/serverRoot';\nexport default defineServerCommand(\n (context: WithRoot<DoomServerPluginContext, RunnerServerScope>) => context.root.command,\n);\n","import { defineHook, type WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/po-core/serverFacet';\n\nimport type { RunnerServerScope } from '../_lib/serverRoot';\n\nexport default defineHook(({ root }: WithRoot<DoomServerPluginContext, RunnerServerScope>) => ({\n event: 'session_compact' as const,\n handle: root.recoverCompaction,\n}));\n","import { defineResource } from '@agimon-ai/po-core/extensionFile';\nimport { DOOM_HELP_WHEN } from '@agimon-ai/po-core/help';\nimport { packageResourcePath, readPackageResource } from '@agimon-ai/po-core/serverFacet';\n\nexport default defineResource({\n name: 'po-use-runner',\n description:\n 'Use Doom Pi Runner to supervise shell commands, inspect durable logs, provide interactive input, and stop background runs.',\n when: DOOM_HELP_WHEN,\n kind: 'skill' as const,\n path: packageResourcePath(import.meta.url, 'src/prompts/po-use-runner/SKILL.md'),\n read: () => readPackageResource(import.meta.url, 'src/prompts/po-use-runner/SKILL.md'),\n});\n","import { defineServerTool, type WithRoot } from '@agimon-ai/po-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/po-core/serverFacet';\n\nimport type { RunnerServerScope } from '../_lib/serverRoot';\nexport default defineServerTool((context: WithRoot<DoomServerPluginContext, RunnerServerScope>) => context.root.tool);\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/po-core/serverFacet';\nimport { composeServerProviderOverrides } from '@agimon-ai/po-core/serverFacet';\nimport { composeRootHooks } from '@agimon-ai/po-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport channelRunnerRuns from '../src/extensions/(backend)/channel/runnerRuns.server';\nimport apiRoute from '../src/extensions/workspaces/sessions/(backend)/api/runner/route.server';\nimport commandRunners from '../src/extensions/workspaces/sessions/(backend)/command/runners.server';\nimport hookSessionCompact from '../src/extensions/workspaces/sessions/(backend)/hook/session-compact.server';\nimport resourcePoUseRunner from '../src/extensions/workspaces/sessions/(backend)/resource/po-use-runner.server';\nimport toolBash from '../src/extensions/workspaces/sessions/(backend)/tool/bash.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/po-runner',\n providerOverrides: composeServerProviderOverrides(rootSession),\n global: () => ({\n get channels(): DoomServerSessionPlugin['channels'] { return [() => via({ frameType: 'runner_runs' }, channelRunnerRuns())]; },\n }),\n workspace: () => ({\n get channels(): DoomServerSessionPlugin['channels'] { return [() => via({ frameType: 'runner_runs' }, channelRunnerRuns())]; },\n }),\n session: async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, contextSession)]; },\n get channels(): DoomServerSessionPlugin['channels'] { return [() => via({ frameType: 'runner_runs' }, channelRunnerRuns())]; },\n get commands(): DoomServerSessionPlugin['commands'] { return [via({ name: 'runners' }, at(commandRunners, contextSession))]; },\n get hooks(): DoomServerSessionPlugin['hooks'] { return [via({ event: 'session_compact' }, at(hookSessionCompact, contextSession))]; },\n get resources(): DoomServerSessionPlugin['resources'] { return [at(resourcePoUseRunner, contextSession)]; },\n get tools(): DoomServerSessionPlugin['tools'] { return [via({ name: 'bash' }, at(toolBash, contextSession))]; },\n services: [...(scopeSession.services ?? [])],\n get activities(): DoomServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default facet;\n"],"mappings":"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"}