pi-kot 0.1.20 → 0.1.21

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 (330) hide show
  1. package/README.md +253 -17
  2. package/package.json +8 -60
  3. package/bin/pi-kot.mjs +0 -148
  4. package/dist/client/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  5. package/dist/client/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  6. package/dist/client/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  7. package/dist/client/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  8. package/dist/client/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  9. package/dist/client/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  10. package/dist/client/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  11. package/dist/client/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  12. package/dist/client/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  13. package/dist/client/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  14. package/dist/client/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  15. package/dist/client/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  16. package/dist/client/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  17. package/dist/client/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  18. package/dist/client/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  19. package/dist/client/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  20. package/dist/client/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  21. package/dist/client/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  22. package/dist/client/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  23. package/dist/client/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  24. package/dist/client/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  25. package/dist/client/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  26. package/dist/client/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  27. package/dist/client/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  28. package/dist/client/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  29. package/dist/client/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  30. package/dist/client/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  31. package/dist/client/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  32. package/dist/client/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  33. package/dist/client/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  34. package/dist/client/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  35. package/dist/client/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  36. package/dist/client/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  37. package/dist/client/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  38. package/dist/client/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  39. package/dist/client/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  40. package/dist/client/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  41. package/dist/client/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  42. package/dist/client/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  43. package/dist/client/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  44. package/dist/client/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  45. package/dist/client/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  46. package/dist/client/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  47. package/dist/client/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  48. package/dist/client/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  49. package/dist/client/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  50. package/dist/client/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  51. package/dist/client/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  52. package/dist/client/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  53. package/dist/client/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  54. package/dist/client/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  55. package/dist/client/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  56. package/dist/client/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  57. package/dist/client/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  58. package/dist/client/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  59. package/dist/client/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  60. package/dist/client/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  61. package/dist/client/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  62. package/dist/client/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  63. package/dist/client/assets/index-C5quN7Km.js +0 -448
  64. package/dist/client/assets/index-C5quN7Km.js.map +0 -1
  65. package/dist/client/assets/index-CuQOwQs1.css +0 -1
  66. package/dist/client/index.html +0 -14
  67. package/dist/server/ask-user-question/envelope.d.ts +0 -11
  68. package/dist/server/ask-user-question/envelope.d.ts.map +0 -1
  69. package/dist/server/ask-user-question/envelope.js +0 -41
  70. package/dist/server/ask-user-question/envelope.js.map +0 -1
  71. package/dist/server/ask-user-question/plan-mode-question-tool.d.ts +0 -26
  72. package/dist/server/ask-user-question/plan-mode-question-tool.d.ts.map +0 -1
  73. package/dist/server/ask-user-question/plan-mode-question-tool.js +0 -273
  74. package/dist/server/ask-user-question/plan-mode-question-tool.js.map +0 -1
  75. package/dist/server/ask-user-question/prompt-strings.d.ts +0 -4
  76. package/dist/server/ask-user-question/prompt-strings.d.ts.map +0 -1
  77. package/dist/server/ask-user-question/prompt-strings.js +0 -18
  78. package/dist/server/ask-user-question/prompt-strings.js.map +0 -1
  79. package/dist/server/ask-user-question/registry.d.ts +0 -39
  80. package/dist/server/ask-user-question/registry.d.ts.map +0 -1
  81. package/dist/server/ask-user-question/registry.js +0 -124
  82. package/dist/server/ask-user-question/registry.js.map +0 -1
  83. package/dist/server/ask-user-question/tool.d.ts +0 -4
  84. package/dist/server/ask-user-question/tool.d.ts.map +0 -1
  85. package/dist/server/ask-user-question/tool.js +0 -68
  86. package/dist/server/ask-user-question/tool.js.map +0 -1
  87. package/dist/server/ask-user-question/types.d.ts +0 -50
  88. package/dist/server/ask-user-question/types.d.ts.map +0 -1
  89. package/dist/server/ask-user-question/types.js +0 -7
  90. package/dist/server/ask-user-question/types.js.map +0 -1
  91. package/dist/server/ask-user-question/validate.d.ts +0 -3
  92. package/dist/server/ask-user-question/validate.d.ts.map +0 -1
  93. package/dist/server/ask-user-question/validate.js +0 -67
  94. package/dist/server/ask-user-question/validate.js.map +0 -1
  95. package/dist/server/compaction-continuation.d.ts +0 -113
  96. package/dist/server/compaction-continuation.d.ts.map +0 -1
  97. package/dist/server/compaction-continuation.js +0 -65
  98. package/dist/server/compaction-continuation.js.map +0 -1
  99. package/dist/server/compaction-history.d.ts +0 -62
  100. package/dist/server/compaction-history.d.ts.map +0 -1
  101. package/dist/server/compaction-history.js +0 -180
  102. package/dist/server/compaction-history.js.map +0 -1
  103. package/dist/server/config-manager.d.ts +0 -97
  104. package/dist/server/config-manager.d.ts.map +0 -1
  105. package/dist/server/config-manager.js +0 -352
  106. package/dist/server/config-manager.js.map +0 -1
  107. package/dist/server/config.d.ts +0 -24
  108. package/dist/server/config.d.ts.map +0 -1
  109. package/dist/server/config.js +0 -67
  110. package/dist/server/config.js.map +0 -1
  111. package/dist/server/extension-manager.d.ts +0 -116
  112. package/dist/server/extension-manager.d.ts.map +0 -1
  113. package/dist/server/extension-manager.js +0 -586
  114. package/dist/server/extension-manager.js.map +0 -1
  115. package/dist/server/extension-ui-bridge.d.ts +0 -35
  116. package/dist/server/extension-ui-bridge.d.ts.map +0 -1
  117. package/dist/server/extension-ui-bridge.js +0 -228
  118. package/dist/server/extension-ui-bridge.js.map +0 -1
  119. package/dist/server/extensions-discovery.d.ts +0 -26
  120. package/dist/server/extensions-discovery.d.ts.map +0 -1
  121. package/dist/server/extensions-discovery.js +0 -107
  122. package/dist/server/extensions-discovery.js.map +0 -1
  123. package/dist/server/file-manager.d.ts +0 -79
  124. package/dist/server/file-manager.d.ts.map +0 -1
  125. package/dist/server/file-manager.js +0 -535
  126. package/dist/server/file-manager.js.map +0 -1
  127. package/dist/server/file-references.d.ts +0 -5
  128. package/dist/server/file-references.d.ts.map +0 -1
  129. package/dist/server/file-references.js +0 -249
  130. package/dist/server/file-references.js.map +0 -1
  131. package/dist/server/file-searcher.d.ts +0 -29
  132. package/dist/server/file-searcher.d.ts.map +0 -1
  133. package/dist/server/file-searcher.js +0 -318
  134. package/dist/server/file-searcher.js.map +0 -1
  135. package/dist/server/git-clone.d.ts +0 -56
  136. package/dist/server/git-clone.d.ts.map +0 -1
  137. package/dist/server/git-clone.js +0 -173
  138. package/dist/server/git-clone.js.map +0 -1
  139. package/dist/server/git-hunk-stager.d.ts +0 -56
  140. package/dist/server/git-hunk-stager.d.ts.map +0 -1
  141. package/dist/server/git-hunk-stager.js +0 -137
  142. package/dist/server/git-hunk-stager.js.map +0 -1
  143. package/dist/server/git-runner.d.ts +0 -346
  144. package/dist/server/git-runner.d.ts.map +0 -1
  145. package/dist/server/git-runner.js +0 -884
  146. package/dist/server/git-runner.js.map +0 -1
  147. package/dist/server/index.d.ts +0 -22
  148. package/dist/server/index.d.ts.map +0 -1
  149. package/dist/server/index.js +0 -262
  150. package/dist/server/index.js.map +0 -1
  151. package/dist/server/lifecycle-notifications.d.ts +0 -28
  152. package/dist/server/lifecycle-notifications.d.ts.map +0 -1
  153. package/dist/server/lifecycle-notifications.js +0 -38
  154. package/dist/server/lifecycle-notifications.js.map +0 -1
  155. package/dist/server/mcp/config.d.ts +0 -23
  156. package/dist/server/mcp/config.d.ts.map +0 -1
  157. package/dist/server/mcp/config.js +0 -139
  158. package/dist/server/mcp/config.js.map +0 -1
  159. package/dist/server/mcp/manager.d.ts +0 -40
  160. package/dist/server/mcp/manager.d.ts.map +0 -1
  161. package/dist/server/mcp/manager.js +0 -435
  162. package/dist/server/mcp/manager.js.map +0 -1
  163. package/dist/server/mcp/stdio-trust.d.ts +0 -5
  164. package/dist/server/mcp/stdio-trust.d.ts.map +0 -1
  165. package/dist/server/mcp/stdio-trust.js +0 -78
  166. package/dist/server/mcp/stdio-trust.js.map +0 -1
  167. package/dist/server/mcp/tool-bridge.d.ts +0 -33
  168. package/dist/server/mcp/tool-bridge.d.ts.map +0 -1
  169. package/dist/server/mcp/tool-bridge.js +0 -138
  170. package/dist/server/mcp/tool-bridge.js.map +0 -1
  171. package/dist/server/orchestration/config.d.ts +0 -5
  172. package/dist/server/orchestration/config.d.ts.map +0 -1
  173. package/dist/server/orchestration/config.js +0 -35
  174. package/dist/server/orchestration/config.js.map +0 -1
  175. package/dist/server/orchestration/event-bridge.d.ts +0 -32
  176. package/dist/server/orchestration/event-bridge.d.ts.map +0 -1
  177. package/dist/server/orchestration/event-bridge.js +0 -110
  178. package/dist/server/orchestration/event-bridge.js.map +0 -1
  179. package/dist/server/orchestration/inbox.d.ts +0 -9
  180. package/dist/server/orchestration/inbox.d.ts.map +0 -1
  181. package/dist/server/orchestration/inbox.js +0 -186
  182. package/dist/server/orchestration/inbox.js.map +0 -1
  183. package/dist/server/orchestration/init.d.ts +0 -2
  184. package/dist/server/orchestration/init.d.ts.map +0 -1
  185. package/dist/server/orchestration/init.js +0 -22
  186. package/dist/server/orchestration/init.js.map +0 -1
  187. package/dist/server/orchestration/store.d.ts +0 -33
  188. package/dist/server/orchestration/store.d.ts.map +0 -1
  189. package/dist/server/orchestration/store.js +0 -331
  190. package/dist/server/orchestration/store.js.map +0 -1
  191. package/dist/server/orchestration/tools.d.ts +0 -15
  192. package/dist/server/orchestration/tools.d.ts.map +0 -1
  193. package/dist/server/orchestration/tools.js +0 -621
  194. package/dist/server/orchestration/tools.js.map +0 -1
  195. package/dist/server/orchestration/types.d.ts +0 -68
  196. package/dist/server/orchestration/types.d.ts.map +0 -1
  197. package/dist/server/orchestration/types.js +0 -43
  198. package/dist/server/orchestration/types.js.map +0 -1
  199. package/dist/server/orchestration/worker-lifecycle.d.ts +0 -15
  200. package/dist/server/orchestration/worker-lifecycle.d.ts.map +0 -1
  201. package/dist/server/orchestration/worker-lifecycle.js +0 -45
  202. package/dist/server/orchestration/worker-lifecycle.js.map +0 -1
  203. package/dist/server/project-manager.d.ts +0 -25
  204. package/dist/server/project-manager.d.ts.map +0 -1
  205. package/dist/server/project-manager.js +0 -157
  206. package/dist/server/project-manager.js.map +0 -1
  207. package/dist/server/pty-manager.d.ts +0 -54
  208. package/dist/server/pty-manager.d.ts.map +0 -1
  209. package/dist/server/pty-manager.js +0 -220
  210. package/dist/server/pty-manager.js.map +0 -1
  211. package/dist/server/routes/_schemas.d.ts +0 -16
  212. package/dist/server/routes/_schemas.d.ts.map +0 -1
  213. package/dist/server/routes/_schemas.js +0 -12
  214. package/dist/server/routes/_schemas.js.map +0 -1
  215. package/dist/server/routes/ask-user-question.d.ts +0 -3
  216. package/dist/server/routes/ask-user-question.d.ts.map +0 -1
  217. package/dist/server/routes/ask-user-question.js +0 -105
  218. package/dist/server/routes/ask-user-question.js.map +0 -1
  219. package/dist/server/routes/auth.d.ts +0 -8
  220. package/dist/server/routes/auth.d.ts.map +0 -1
  221. package/dist/server/routes/auth.js +0 -225
  222. package/dist/server/routes/auth.js.map +0 -1
  223. package/dist/server/routes/config.d.ts +0 -3
  224. package/dist/server/routes/config.d.ts.map +0 -1
  225. package/dist/server/routes/config.js +0 -568
  226. package/dist/server/routes/config.js.map +0 -1
  227. package/dist/server/routes/control.d.ts +0 -3
  228. package/dist/server/routes/control.d.ts.map +0 -1
  229. package/dist/server/routes/control.js +0 -365
  230. package/dist/server/routes/control.js.map +0 -1
  231. package/dist/server/routes/exec.d.ts +0 -3
  232. package/dist/server/routes/exec.d.ts.map +0 -1
  233. package/dist/server/routes/exec.js +0 -426
  234. package/dist/server/routes/exec.js.map +0 -1
  235. package/dist/server/routes/extension-commands.d.ts +0 -22
  236. package/dist/server/routes/extension-commands.d.ts.map +0 -1
  237. package/dist/server/routes/extension-commands.js +0 -178
  238. package/dist/server/routes/extension-commands.js.map +0 -1
  239. package/dist/server/routes/extensions.d.ts +0 -8
  240. package/dist/server/routes/extensions.d.ts.map +0 -1
  241. package/dist/server/routes/extensions.js +0 -414
  242. package/dist/server/routes/extensions.js.map +0 -1
  243. package/dist/server/routes/files.d.ts +0 -3
  244. package/dist/server/routes/files.d.ts.map +0 -1
  245. package/dist/server/routes/files.js +0 -835
  246. package/dist/server/routes/files.js.map +0 -1
  247. package/dist/server/routes/git.d.ts +0 -3
  248. package/dist/server/routes/git.d.ts.map +0 -1
  249. package/dist/server/routes/git.js +0 -1058
  250. package/dist/server/routes/git.js.map +0 -1
  251. package/dist/server/routes/mcp.d.ts +0 -3
  252. package/dist/server/routes/mcp.d.ts.map +0 -1
  253. package/dist/server/routes/mcp.js +0 -403
  254. package/dist/server/routes/mcp.js.map +0 -1
  255. package/dist/server/routes/orchestration.d.ts +0 -3
  256. package/dist/server/routes/orchestration.d.ts.map +0 -1
  257. package/dist/server/routes/orchestration.js +0 -251
  258. package/dist/server/routes/orchestration.js.map +0 -1
  259. package/dist/server/routes/projects.d.ts +0 -3
  260. package/dist/server/routes/projects.d.ts.map +0 -1
  261. package/dist/server/routes/projects.js +0 -421
  262. package/dist/server/routes/projects.js.map +0 -1
  263. package/dist/server/routes/prompt.d.ts +0 -3
  264. package/dist/server/routes/prompt.d.ts.map +0 -1
  265. package/dist/server/routes/prompt.js +0 -311
  266. package/dist/server/routes/prompt.js.map +0 -1
  267. package/dist/server/routes/session-extensions.d.ts +0 -11
  268. package/dist/server/routes/session-extensions.d.ts.map +0 -1
  269. package/dist/server/routes/session-extensions.js +0 -171
  270. package/dist/server/routes/session-extensions.js.map +0 -1
  271. package/dist/server/routes/sessions.d.ts +0 -3
  272. package/dist/server/routes/sessions.d.ts.map +0 -1
  273. package/dist/server/routes/sessions.js +0 -706
  274. package/dist/server/routes/sessions.js.map +0 -1
  275. package/dist/server/routes/skills.d.ts +0 -14
  276. package/dist/server/routes/skills.d.ts.map +0 -1
  277. package/dist/server/routes/skills.js +0 -448
  278. package/dist/server/routes/skills.js.map +0 -1
  279. package/dist/server/routes/stream.d.ts +0 -3
  280. package/dist/server/routes/stream.d.ts.map +0 -1
  281. package/dist/server/routes/stream.js +0 -112
  282. package/dist/server/routes/stream.js.map +0 -1
  283. package/dist/server/routes/terminal.d.ts +0 -28
  284. package/dist/server/routes/terminal.d.ts.map +0 -1
  285. package/dist/server/routes/terminal.js +0 -211
  286. package/dist/server/routes/terminal.js.map +0 -1
  287. package/dist/server/routes/tunnel.d.ts +0 -13
  288. package/dist/server/routes/tunnel.d.ts.map +0 -1
  289. package/dist/server/routes/tunnel.js +0 -231
  290. package/dist/server/routes/tunnel.js.map +0 -1
  291. package/dist/server/session-registry.d.ts +0 -164
  292. package/dist/server/session-registry.d.ts.map +0 -1
  293. package/dist/server/session-registry.js +0 -754
  294. package/dist/server/session-registry.js.map +0 -1
  295. package/dist/server/skill-overrides.d.ts +0 -47
  296. package/dist/server/skill-overrides.d.ts.map +0 -1
  297. package/dist/server/skill-overrides.js +0 -178
  298. package/dist/server/skill-overrides.js.map +0 -1
  299. package/dist/server/sse-bridge.d.ts +0 -31
  300. package/dist/server/sse-bridge.d.ts.map +0 -1
  301. package/dist/server/sse-bridge.js +0 -158
  302. package/dist/server/sse-bridge.js.map +0 -1
  303. package/dist/server/tool-overrides.d.ts +0 -39
  304. package/dist/server/tool-overrides.d.ts.map +0 -1
  305. package/dist/server/tool-overrides.js +0 -121
  306. package/dist/server/tool-overrides.js.map +0 -1
  307. package/dist/server/tunnel/executable-search.d.ts +0 -45
  308. package/dist/server/tunnel/executable-search.d.ts.map +0 -1
  309. package/dist/server/tunnel/executable-search.js +0 -150
  310. package/dist/server/tunnel/executable-search.js.map +0 -1
  311. package/dist/server/tunnel/install-help.d.ts +0 -19
  312. package/dist/server/tunnel/install-help.d.ts.map +0 -1
  313. package/dist/server/tunnel/install-help.js +0 -47
  314. package/dist/server/tunnel/install-help.js.map +0 -1
  315. package/dist/server/tunnel/providers/ngrok.d.ts +0 -34
  316. package/dist/server/tunnel/providers/ngrok.d.ts.map +0 -1
  317. package/dist/server/tunnel/providers/ngrok.js +0 -464
  318. package/dist/server/tunnel/providers/ngrok.js.map +0 -1
  319. package/dist/server/tunnel/registry.d.ts +0 -15
  320. package/dist/server/tunnel/registry.d.ts.map +0 -1
  321. package/dist/server/tunnel/registry.js +0 -58
  322. package/dist/server/tunnel/registry.js.map +0 -1
  323. package/dist/server/tunnel/service.d.ts +0 -15
  324. package/dist/server/tunnel/service.d.ts.map +0 -1
  325. package/dist/server/tunnel/service.js +0 -158
  326. package/dist/server/tunnel/service.js.map +0 -1
  327. package/dist/server/tunnel/types.d.ts +0 -166
  328. package/dist/server/tunnel/types.d.ts.map +0 -1
  329. package/dist/server/tunnel/types.js +0 -217
  330. package/dist/server/tunnel/types.js.map +0 -1
@@ -1,754 +0,0 @@
1
- import { createAgentSession, DefaultResourceLoader, SessionManager, } from "@earendil-works/pi-coding-agent";
2
- import { compactionContinuationExtension } from "./compaction-continuation.js";
3
- import { mkdir, rename, readdir, stat } from "node:fs/promises";
4
- import { createAskUserQuestionTool } from "./ask-user-question/tool.js";
5
- import { createPlanModeQuestionTool } from "./ask-user-question/plan-mode-question-tool.js";
6
- import { join, basename } from "node:path";
7
- import { config } from "./config.js";
8
- import { isOrchestrationEnabled } from "./orchestration/config.js";
9
- /**
10
- * Build a DefaultResourceLoader with pi-kot's always-on extensions.
11
- * Currently registers the compaction continuation extension that nudges
12
- * the model to keep working after an overflow-driven auto-compaction.
13
- * Pass the result as `resourceLoader` to createAgentSession().
14
- *
15
- * Must call reload() before passing to the SDK so the loader is
16
- * in an operational state (the SDK skips resourceLoader.reload()
17
- * when a pre-built resourceLoader is provided).
18
- */
19
- export async function buildResourceLoader(cwd) {
20
- const loader = new DefaultResourceLoader({
21
- cwd,
22
- agentDir: config.piConfigDir,
23
- extensionFactories: [compactionContinuationExtension],
24
- });
25
- await loader.reload();
26
- return loader;
27
- }
28
- import { isSupervisor } from "./orchestration/store.js";
29
- import { createOrchestrationTools } from "./orchestration/tools.js";
30
- import { bridgeWorkerAgentEvent } from "./orchestration/event-bridge.js";
31
- import { discoverExtensionResources } from "./extensions-discovery.js";
32
- import { notifySupervisorDisposed, notifySupervisorIdle } from "./orchestration/inbox.js";
33
- import { customToolsForProject as mcpCustomToolsForProject, ensureGlobalLoaded as mcpEnsureGlobalLoaded, ensureProjectLoaded as mcpEnsureProjectLoaded, isGloballyEnabled as mcpIsGloballyEnabled, } from "./mcp/manager.js";
34
- import { filterEnabledTools, readToolOverrides, isToolEffective } from "./tool-overrides.js";
35
- /**
36
- * Build the ExtensionBindings for a session with real command context
37
- * actions (navigateTree, fork, etc.) so extension commands like
38
- * pi-rewind's `/rewind` can navigate the conversation tree.
39
- *
40
- * Without this, `ctx.navigateTree()` is a no-op that returns
41
- * `{ cancelled: false }` without actually navigating.
42
- */
43
- export function buildBindings(session) {
44
- return {
45
- commandContextActions: {
46
- waitForIdle: async () => { },
47
- newSession: async () => ({ cancelled: false }),
48
- fork: async () => ({ cancelled: false }),
49
- switchSession: async () => ({ cancelled: false }),
50
- reload: async () => { },
51
- navigateTree: async (targetId, options) => {
52
- return session.navigateTree(targetId, options);
53
- },
54
- },
55
- };
56
- }
57
- const registry = new Map();
58
- function sessionDirFor(projectId) {
59
- return join(config.sessionDir, projectId);
60
- }
61
- async function ensureSessionDir(projectId) {
62
- const dir = sessionDirFor(projectId);
63
- await mkdir(dir, { recursive: true });
64
- return dir;
65
- }
66
- export async function discoverSessionsOnDisk(projectId, workspacePath) {
67
- const dir = sessionDirFor(projectId);
68
- try {
69
- const infos = await SessionManager.list(workspacePath, dir);
70
- return infos.map((info) => ({
71
- sessionId: info.id,
72
- path: info.path,
73
- createdAt: info.created,
74
- modifiedAt: info.modified,
75
- messageCount: info.messageCount,
76
- name: info.name,
77
- }));
78
- }
79
- catch (err) {
80
- if (err.code === "ENOENT")
81
- return [];
82
- throw err;
83
- }
84
- }
85
- export async function listSessionsForProject(projectId, workspacePath) {
86
- const live = listSessions(projectId);
87
- const liveById = new Map(live.map((l) => [
88
- l.sessionId,
89
- {
90
- sessionId: l.sessionId,
91
- projectId: l.projectId,
92
- isLive: true,
93
- name: l.name ?? l.session.sessionName,
94
- createdAt: l.createdAt,
95
- lastActivityAt: l.lastActivityAt,
96
- messageCount: l.session.messages.length,
97
- },
98
- ]));
99
- const disk = await discoverSessionsOnDisk(projectId, workspacePath);
100
- for (const d of disk) {
101
- const merged = liveById.get(d.sessionId);
102
- if (merged !== undefined) {
103
- merged.messageCount = d.messageCount;
104
- continue;
105
- }
106
- liveById.set(d.sessionId, {
107
- sessionId: d.sessionId,
108
- projectId,
109
- isLive: false,
110
- name: d.name,
111
- createdAt: d.createdAt,
112
- lastActivityAt: d.modifiedAt,
113
- messageCount: d.messageCount,
114
- });
115
- }
116
- return Array.from(liveById.values()).sort((a, b) => b.lastActivityAt.getTime() - a.lastActivityAt.getTime());
117
- }
118
- /**
119
- * Create a new session. Uses disk-backed SessionManager for persistence.
120
- */
121
- export async function createSession(projectId, workspacePath) {
122
- const dir = await ensureSessionDir(projectId);
123
- const sessionManager = SessionManager.create(workspacePath, dir);
124
- const sessionId = sessionManager.getSessionId();
125
- const mcpTools = await resolveMcpCustomTools(projectId, workspacePath);
126
- const orchestrationTools = await resolveOrchestrationTools(sessionId);
127
- const customTools = [
128
- ...mcpTools,
129
- createAskUserQuestionTool(sessionId),
130
- createPlanModeQuestionTool(sessionId),
131
- ...orchestrationTools,
132
- ];
133
- const resourceLoader = await buildResourceLoader(workspacePath);
134
- const { session } = await createAgentSession({
135
- cwd: workspacePath,
136
- sessionManager,
137
- agentDir: config.piConfigDir,
138
- customTools,
139
- resourceLoader,
140
- });
141
- // Trigger session_start event and wire real command context actions
142
- // (navigateTree, etc.) so extension commands like /rewind can
143
- // navigate the conversation tree.
144
- await session.bindExtensions(buildBindings(session)).catch(() => {
145
- // best-effort
146
- });
147
- const now = new Date();
148
- const live = {
149
- session,
150
- sessionId: session.sessionId,
151
- projectId,
152
- workspacePath,
153
- sessionManager,
154
- clients: new Set(),
155
- createdAt: now,
156
- lastActivityAt: now,
157
- lastAgentStartIndex: undefined,
158
- unsubscribe: () => undefined,
159
- name: sessionManager.getSessionName(),
160
- currentExecAbort: undefined,
161
- };
162
- // Wire the registry's event subscription
163
- live.unsubscribe = session.subscribe((event) => {
164
- live.lastActivityAt = new Date();
165
- if (event.type === "agent_start") {
166
- live.lastAgentStartIndex = live.session.messages.length;
167
- }
168
- // Bridge orchestration lifecycle events (fire-and-forget)
169
- if (event.type === "agent_start" || event.type === "agent_end") {
170
- void bridgeWorkerAgentEvent({ sessionId: live.sessionId, session: live.session }, event);
171
- }
172
- // Notify supervisor idle — compatibility recovery for undelivered items
173
- if (event.type === "agent_end") {
174
- void notifySupervisorIdle(live.sessionId);
175
- }
176
- // Fan out to all connected SSE clients
177
- for (const client of live.clients) {
178
- try {
179
- client.send(event);
180
- }
181
- catch {
182
- live.clients.delete(client);
183
- }
184
- }
185
- });
186
- registry.set(live.sessionId, live);
187
- return live;
188
- }
189
- /** Get a live session by id. Returns undefined if not in the registry. */
190
- export function getSession(sessionId) {
191
- return registry.get(sessionId);
192
- }
193
- /** List live sessions, optionally filtered by projectId. */
194
- export function listSessions(projectId) {
195
- const all = Array.from(registry.values());
196
- return projectId === undefined ? all : all.filter((s) => s.projectId === projectId);
197
- }
198
- /** Number of active sessions. */
199
- export function sessionCount() {
200
- return registry.size;
201
- }
202
- /** Register a session in the registry (used by session resume). */
203
- export function registerSession(live) {
204
- registry.set(live.sessionId, live);
205
- }
206
- /* ── Archive / Unarchive ── */
207
- function archivedDirFor(projectId) {
208
- return join(config.sessionDir, projectId, "_archived");
209
- }
210
- /**
211
- * Archive a session: move JSONL to _archived/ subfolder, remove from live registry.
212
- * Works for both live and disk-only sessions.
213
- * Returns true if archived, false if not found on disk or in registry.
214
- */
215
- export async function archiveSession(sessionId, projectId) {
216
- // Always check registry first — live session takes precedence
217
- const live = registry.get(sessionId);
218
- const resolvedProjectId = live?.projectId ?? projectId;
219
- if (resolvedProjectId === undefined)
220
- return false;
221
- const pid = resolvedProjectId;
222
- const srcDir = join(config.sessionDir, pid);
223
- let fileMoved = false;
224
- // Find and move the JSONL file
225
- try {
226
- const files = await readdir(srcDir);
227
- const match = files.find((f) => f.endsWith(".jsonl") && f.includes(sessionId));
228
- if (match) {
229
- const archiveDir = archivedDirFor(pid);
230
- await mkdir(archiveDir, { recursive: true });
231
- await rename(join(srcDir, match), join(archiveDir, match));
232
- fileMoved = true;
233
- }
234
- }
235
- catch {
236
- // best-effort file move
237
- }
238
- // Remove from live registry if present
239
- if (live !== undefined) {
240
- try {
241
- await live.session.abort();
242
- }
243
- catch { }
244
- try {
245
- live.unsubscribe();
246
- }
247
- catch { }
248
- for (const client of live.clients) {
249
- try {
250
- client.close();
251
- }
252
- catch { }
253
- }
254
- live.clients.clear();
255
- try {
256
- live.session.dispose();
257
- }
258
- catch { }
259
- registry.delete(sessionId);
260
- }
261
- return fileMoved || live !== undefined;
262
- }
263
- /**
264
- * Unarchive a session: move JSONL back from _archived/ to main dir.
265
- * Does NOT warm it back into the live registry — that happens on SSE connect.
266
- * Returns true if restored, false if no archive file found.
267
- */
268
- export async function unarchiveSession(sessionId, projectId) {
269
- const archiveDir = archivedDirFor(projectId);
270
- try {
271
- const files = await readdir(archiveDir);
272
- const match = files.find((f) => f.endsWith(".jsonl") && f.includes(sessionId));
273
- if (!match)
274
- return false;
275
- const srcDir = join(config.sessionDir, projectId);
276
- await rename(join(archiveDir, match), join(srcDir, match));
277
- return true;
278
- }
279
- catch {
280
- return false;
281
- }
282
- }
283
- /**
284
- * List archived sessions for a project.
285
- */
286
- export async function listArchivedSessions(projectId, workspacePath) {
287
- const archiveDir = archivedDirFor(projectId);
288
- try {
289
- await stat(archiveDir);
290
- }
291
- catch {
292
- return []; // archive dir doesn't exist
293
- }
294
- try {
295
- const files = await readdir(archiveDir);
296
- const jsonls = files.filter((f) => f.endsWith(".jsonl"));
297
- const results = [];
298
- for (const file of jsonls) {
299
- try {
300
- const sessionPath = join(archiveDir, file);
301
- const sm = SessionManager.open(sessionPath);
302
- // Derive sessionId from the filename (UUID after timestamp prefix)
303
- const base = basename(file, ".jsonl");
304
- const underscoreIdx = base.indexOf("_");
305
- const sessionId = underscoreIdx !== -1 ? base.slice(underscoreIdx + 1) : base;
306
- const ctx = sm.buildSessionContext();
307
- const info = SessionManager.list(workspacePath, archiveDir);
308
- const match = (await info).find((i) => i.id === sessionId);
309
- results.push({
310
- sessionId,
311
- projectId,
312
- isLive: false,
313
- name: match?.name ?? sm.getSessionName(),
314
- createdAt: match?.created ?? new Date(0),
315
- lastActivityAt: match?.modified ?? new Date(0),
316
- messageCount: ctx.messages.length,
317
- });
318
- }
319
- catch {
320
- // skip corrupt files
321
- }
322
- }
323
- return results.sort((a, b) => b.lastActivityAt.getTime() - a.lastActivityAt.getTime());
324
- }
325
- catch {
326
- return [];
327
- }
328
- }
329
- /**
330
- * Rename a live session. Persists via SessionManager.appendSessionInfo.
331
- * Returns true if renamed, false if session not live.
332
- */
333
- export function renameSession(sessionId, name) {
334
- const live = registry.get(sessionId);
335
- if (live === undefined)
336
- return false;
337
- const trimmed = name.trim();
338
- if (trimmed.length === 0)
339
- return false;
340
- live.sessionManager.appendSessionInfo(trimmed);
341
- live.name = trimmed;
342
- return true;
343
- }
344
- /**
345
- * Auto-name a session from the first user prompt text.
346
- * Called when the first prompt is sent. Truncates to 60 chars.
347
- */
348
- export function autoNameSession(sessionId, promptText) {
349
- const live = registry.get(sessionId);
350
- if (live === undefined)
351
- return;
352
- // Only auto-name if no name is already set
353
- if (live.name !== undefined)
354
- return;
355
- const name = promptText.trim().slice(0, 60).replace(/\n/g, " ");
356
- if (name.length === 0)
357
- return;
358
- live.sessionManager.appendSessionInfo(name);
359
- live.name = name;
360
- }
361
- /**
362
- * Resolve MCP custom tools for a session.
363
- * Resolve MCP custom tools — ensures global + project
364
- * MCP config is loaded, respects the master disabled toggle, and returns
365
- * the union of all connected, enabled server tools for this project.
366
- */
367
- async function resolveMcpCustomTools(projectId, workspacePath) {
368
- await mcpEnsureGlobalLoaded().catch(() => undefined);
369
- if (!mcpIsGloballyEnabled())
370
- return [];
371
- await mcpEnsureProjectLoaded(projectId, workspacePath).catch(() => undefined);
372
- const tools = mcpCustomToolsForProject(projectId);
373
- // Apply tool-level overrides (global disabled set + per-project tri-state)
374
- const overrides = await readToolOverrides().catch(() => undefined);
375
- if (overrides === undefined)
376
- return tools;
377
- return tools.filter((t) => isToolEffective(overrides, projectId, "mcp", t.name));
378
- }
379
- /**
380
- * Resolve orchestration tools for a session, if supervisor mode is active.
381
- * Returns empty array when orchestration is disabled or the session isn't
382
- * a registered supervisor.
383
- */
384
- async function resolveOrchestrationTools(sessionId) {
385
- if (!isOrchestrationEnabled())
386
- return [];
387
- try {
388
- if (!(await isSupervisor(sessionId)))
389
- return [];
390
- return createOrchestrationTools(sessionId);
391
- }
392
- catch {
393
- return [];
394
- }
395
- }
396
- /** Builtin tool names known to the SDK. */
397
- const BUILTIN_TOOL_NAMES = ["read", "bash", "edit", "write", "grep", "find", "ls"];
398
- /**
399
- * Build the tools allowlist for createAgentSession, respecting tool
400
- * overrides (global disabled set + per-project tri-state) across
401
- * builtin, MCP/custom, and extension-contributed tools.
402
- */
403
- async function buildToolsAllowlist(customTools, projectId, cwd) {
404
- const overrides = await readToolOverrides();
405
- const extResources = await discoverExtensionResources(cwd);
406
- // Classify each custom tool: forge-native tools (askUserQuestion,
407
- // orchestration) are treated as "builtin"; MCP tools remain "mcp".
408
- const builtinCustomToolNames = new Set([
409
- "ask_user_question",
410
- ...BUILTIN_TOOL_NAMES,
411
- ]);
412
- const candidates = [
413
- ...BUILTIN_TOOL_NAMES.map((n) => ({ family: "builtin", name: n })),
414
- ...customTools.map((t) => ({
415
- family: builtinCustomToolNames.has(t.name)
416
- ? "builtin"
417
- : "mcp",
418
- name: t.name,
419
- })),
420
- ...extResources.tools.map((t) => ({
421
- family: "extension",
422
- name: t.name,
423
- })),
424
- ];
425
- const enabled = filterEnabledTools(overrides, projectId, candidates);
426
- return enabled.map((e) => e.name);
427
- }
428
- /**
429
- * Rebuild a live session's AgentSession with updated custom tools.
430
- * Preserves the SessionManager (messages intact), SSE clients stay
431
- * attached, and the old session is disposed cleanly.
432
- */
433
- export async function rebuildSessionTools(sessionId) {
434
- const live = registry.get(sessionId);
435
- if (live === undefined)
436
- return;
437
- const mcpTools = await resolveMcpCustomTools(live.projectId, live.workspacePath);
438
- const orchestrationTools = await resolveOrchestrationTools(sessionId);
439
- const customTools = [
440
- ...mcpTools,
441
- createAskUserQuestionTool(sessionId),
442
- createPlanModeQuestionTool(sessionId),
443
- ...orchestrationTools,
444
- ];
445
- // Unsubscribe old subscription, abort any in-flight turn
446
- try {
447
- live.unsubscribe();
448
- }
449
- catch { /* ignore */ }
450
- try {
451
- await live.session.abort();
452
- }
453
- catch { /* ignore */ }
454
- // Create new AgentSession with same SessionManager but updated tools
455
- const resourceLoader = await buildResourceLoader(live.workspacePath);
456
- const toolsAllowlist = await buildToolsAllowlist(customTools, live.projectId, live.workspacePath);
457
- const { session } = await createAgentSession({
458
- cwd: live.workspacePath,
459
- sessionManager: live.sessionManager,
460
- agentDir: config.piConfigDir,
461
- customTools,
462
- resourceLoader,
463
- tools: toolsAllowlist,
464
- });
465
- // Wire real command context actions (navigateTree, etc.) so
466
- // extension commands like /rewind can navigate the conversation.
467
- await session.bindExtensions(buildBindings(session)).catch(() => {
468
- // best-effort
469
- });
470
- // Dispose old session
471
- try {
472
- live.session.dispose();
473
- }
474
- catch { /* ignore */ }
475
- // Swap in new session
476
- live.session = session;
477
- // Re-subscribe
478
- live.unsubscribe = session.subscribe((event) => {
479
- live.lastActivityAt = new Date();
480
- if (event.type === "agent_start") {
481
- live.lastAgentStartIndex = live.session.messages.length;
482
- }
483
- if (event.type === "agent_start" || event.type === "agent_end") {
484
- void bridgeWorkerAgentEvent({ sessionId: live.sessionId, session: live.session }, event);
485
- }
486
- if (event.type === "agent_end") {
487
- void notifySupervisorIdle(live.sessionId);
488
- }
489
- for (const client of live.clients) {
490
- try {
491
- client.send(event);
492
- }
493
- catch {
494
- live.clients.delete(client);
495
- }
496
- }
497
- });
498
- // Notify SSE clients about the rebuild
499
- for (const client of live.clients) {
500
- try {
501
- client.send({
502
- type: "custom_tools_changed",
503
- sessionId: live.sessionId,
504
- toolCount: customTools.length,
505
- });
506
- }
507
- catch {
508
- live.clients.delete(client);
509
- }
510
- }
511
- }
512
- /** Dispose a live session — abort, unsubscribe, close clients, remove from registry. */
513
- export async function disposeSession(sessionId) {
514
- const live = registry.get(sessionId);
515
- if (live === undefined)
516
- return false;
517
- try {
518
- await live.session.abort();
519
- }
520
- catch {
521
- // best-effort
522
- }
523
- try {
524
- live.unsubscribe();
525
- }
526
- catch {
527
- // ignore
528
- }
529
- for (const client of live.clients) {
530
- try {
531
- client.close();
532
- }
533
- catch {
534
- // ignore
535
- }
536
- }
537
- live.clients.clear();
538
- try {
539
- live.session.dispose();
540
- }
541
- catch {
542
- // ignore
543
- }
544
- registry.delete(live.sessionId);
545
- // Clean up orchestration dedupe state for this session
546
- notifySupervisorDisposed(live.sessionId);
547
- return true;
548
- }
549
- /** Dispose all sessions (called on server shutdown). */
550
- export async function disposeAllSessions() {
551
- const ids = Array.from(registry.keys());
552
- await Promise.all(ids.map((id) => disposeSession(id)));
553
- }
554
- /**
555
- * Find a session's location on disk. Returns projectId and workspacePath
556
- * by scanning all project session dirs.
557
- */
558
- export async function findSessionLocation(sessionId) {
559
- // Check all project directories
560
- const { readProjects } = await import("./project-manager.js");
561
- try {
562
- const projects = await readProjects();
563
- for (const project of projects) {
564
- const dir = join(config.sessionDir, project.id);
565
- try {
566
- const files = await readdir(dir);
567
- if (files.some((f) => f.includes(sessionId))) {
568
- return { projectId: project.id, workspacePath: project.path };
569
- }
570
- }
571
- catch {
572
- // dir doesn't exist, skip
573
- }
574
- }
575
- }
576
- catch {
577
- // can't read projects
578
- }
579
- return undefined;
580
- }
581
- /**
582
- * Resume a cold session from disk. Opens the JSONL, creates an AgentSession,
583
- * registers it in the registry, and returns the LiveSession.
584
- */
585
- export async function resumeSessionById(sessionId) {
586
- const loc = await findSessionLocation(sessionId);
587
- if (loc === undefined) {
588
- throw new Error(`session_not_found: ${sessionId}`);
589
- }
590
- const dir = join(config.sessionDir, loc.projectId);
591
- const files = await readdir(dir);
592
- const match = files.find((f) => f.endsWith(".jsonl") && f.includes(sessionId));
593
- if (match === undefined) {
594
- throw new Error(`session_not_found: ${sessionId}`);
595
- }
596
- const sessionPath = join(dir, match);
597
- const sessionManager = SessionManager.open(sessionPath);
598
- const mcpTools = await resolveMcpCustomTools(loc.projectId, loc.workspacePath);
599
- const orchestrationTools = await resolveOrchestrationTools(sessionId);
600
- const customTools = [
601
- ...mcpTools,
602
- createAskUserQuestionTool(sessionId),
603
- createPlanModeQuestionTool(sessionId),
604
- ...orchestrationTools,
605
- ];
606
- const resourceLoader = await buildResourceLoader(loc.workspacePath);
607
- const { session } = await createAgentSession({
608
- cwd: loc.workspacePath,
609
- sessionManager,
610
- agentDir: config.piConfigDir,
611
- customTools,
612
- resourceLoader,
613
- });
614
- // Wire real command context actions (navigateTree, etc.) so
615
- // extension commands like /rewind can navigate the conversation.
616
- await session.bindExtensions(buildBindings(session)).catch(() => {
617
- // best-effort
618
- });
619
- const now = new Date();
620
- const live = {
621
- session,
622
- sessionId,
623
- projectId: loc.projectId,
624
- workspacePath: loc.workspacePath,
625
- sessionManager,
626
- clients: new Set(),
627
- createdAt: now,
628
- lastActivityAt: now,
629
- lastAgentStartIndex: undefined,
630
- unsubscribe: () => undefined,
631
- name: sessionManager.getSessionName(),
632
- currentExecAbort: undefined,
633
- };
634
- live.unsubscribe = session.subscribe((event) => {
635
- live.lastActivityAt = new Date();
636
- if (event.type === "agent_start") {
637
- live.lastAgentStartIndex = live.session.messages.length;
638
- }
639
- // Bridge orchestration lifecycle events (fire-and-forget)
640
- if (event.type === "agent_start" || event.type === "agent_end") {
641
- void bridgeWorkerAgentEvent({ sessionId: live.sessionId, session: live.session }, event);
642
- }
643
- // Notify supervisor idle on agent_end
644
- if (event.type === "agent_end") {
645
- void notifySupervisorIdle(live.sessionId);
646
- }
647
- for (const client of live.clients) {
648
- try {
649
- client.send(event);
650
- }
651
- catch {
652
- live.clients.delete(client);
653
- }
654
- }
655
- });
656
- registry.set(live.sessionId, live);
657
- return live;
658
- }
659
- /**
660
- * Fork a session at a given entry. Creates a new JSONL file containing
661
- * the path-to-leaf from root to the given entry, registers the new
662
- * session, and returns it.
663
- *
664
- * NOTE: `createBranchedSession` mutates the source session's in-memory
665
- * file reference to point at the new fork (SDK behavior). We handle this
666
- * by capturing the source file before and re-opening the source after.
667
- */
668
- export async function forkSession(sessionId, entryId) {
669
- const sourceLive = registry.get(sessionId);
670
- if (sourceLive === undefined) {
671
- // Try to resume cold first, then fork
672
- const resumed = await resumeSessionById(sessionId);
673
- return forkSession(resumed.sessionId, entryId);
674
- }
675
- // Capture the source file path BEFORE createBranchedSession mutates it
676
- const sourceSessionFile = sourceLive.sessionManager.getSessionFile();
677
- if (sourceSessionFile === undefined) {
678
- throw new Error("fork_failed: source session has no file (in-memory only)");
679
- }
680
- const sourceDir = join(config.sessionDir, sourceLive.projectId);
681
- // Create the branched session file
682
- const newPath = sourceLive.sessionManager.createBranchedSession(entryId);
683
- if (newPath === undefined) {
684
- throw new Error("fork_failed: createBranchedSession returned undefined");
685
- }
686
- // Re-open the SOURCE session from the original file to undo SDK mutation
687
- const restoredSourceSM = SessionManager.open(sourceSessionFile, sourceDir, sourceLive.workspacePath);
688
- sourceLive.sessionManager = restoredSourceSM;
689
- // Open the new fork as a SessionManager
690
- const dir = join(config.sessionDir, sourceLive.projectId);
691
- const forkedSM = SessionManager.open(newPath, dir, sourceLive.workspacePath);
692
- const forkedId = forkedSM.getSessionId();
693
- const mcpTools = await resolveMcpCustomTools(sourceLive.projectId, sourceLive.workspacePath);
694
- const orchestrationTools = await resolveOrchestrationTools(forkedId);
695
- const customTools = [
696
- ...mcpTools,
697
- createAskUserQuestionTool(forkedId),
698
- createPlanModeQuestionTool(forkedId),
699
- ...orchestrationTools,
700
- ];
701
- const resourceLoader = await buildResourceLoader(sourceLive.workspacePath);
702
- const { session } = await createAgentSession({
703
- cwd: sourceLive.workspacePath,
704
- sessionManager: forkedSM,
705
- agentDir: config.piConfigDir,
706
- customTools,
707
- resourceLoader,
708
- });
709
- // Wire real command context actions (navigateTree, etc.) so
710
- // extension commands like /rewind can navigate the conversation.
711
- await session.bindExtensions(buildBindings(session)).catch(() => {
712
- // best-effort
713
- });
714
- const now = new Date();
715
- const forkedLive = {
716
- session,
717
- sessionId: session.sessionId,
718
- projectId: sourceLive.projectId,
719
- workspacePath: sourceLive.workspacePath,
720
- sessionManager: forkedSM,
721
- clients: new Set(),
722
- createdAt: now,
723
- lastActivityAt: now,
724
- lastAgentStartIndex: undefined,
725
- unsubscribe: () => undefined,
726
- name: forkedSM.getSessionName(),
727
- currentExecAbort: undefined,
728
- };
729
- forkedLive.unsubscribe = session.subscribe((event) => {
730
- forkedLive.lastActivityAt = new Date();
731
- if (event.type === "agent_start") {
732
- forkedLive.lastAgentStartIndex = forkedLive.session.messages.length;
733
- }
734
- // Bridge orchestration lifecycle events (fire-and-forget)
735
- if (event.type === "agent_start" || event.type === "agent_end") {
736
- void bridgeWorkerAgentEvent({ sessionId: forkedLive.sessionId, session: forkedLive.session }, event);
737
- }
738
- // Notify supervisor idle on agent_end
739
- if (event.type === "agent_end") {
740
- void notifySupervisorIdle(forkedLive.sessionId);
741
- }
742
- for (const client of forkedLive.clients) {
743
- try {
744
- client.send(event);
745
- }
746
- catch {
747
- forkedLive.clients.delete(client);
748
- }
749
- }
750
- });
751
- registry.set(forkedLive.sessionId, forkedLive);
752
- return forkedLive;
753
- }
754
- //# sourceMappingURL=session-registry.js.map