@code-yeongyu/senpi 2026.8.30 → 2026.9.2

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 (373) hide show
  1. package/CHANGELOG.md +174 -2
  2. package/README.md +3 -0
  3. package/dist/core/agent-session.d.ts +28 -0
  4. package/dist/core/agent-session.d.ts.map +1 -1
  5. package/dist/core/agent-session.js +161 -14
  6. package/dist/core/agent-session.js.map +1 -1
  7. package/dist/core/compaction/compaction-execution.d.ts +14 -0
  8. package/dist/core/compaction/compaction-execution.d.ts.map +1 -0
  9. package/dist/core/compaction/compaction-execution.js +121 -0
  10. package/dist/core/compaction/compaction-execution.js.map +1 -0
  11. package/dist/core/compaction/compaction-settings.d.ts +17 -0
  12. package/dist/core/compaction/compaction-settings.d.ts.map +1 -0
  13. package/dist/core/compaction/compaction-settings.js +17 -0
  14. package/dist/core/compaction/compaction-settings.js.map +1 -0
  15. package/dist/core/compaction/compaction.d.ts +13 -26
  16. package/dist/core/compaction/compaction.d.ts.map +1 -1
  17. package/dist/core/compaction/compaction.js +7 -136
  18. package/dist/core/compaction/compaction.js.map +1 -1
  19. package/dist/core/compaction/ideal-compaction-settings.d.ts +9 -0
  20. package/dist/core/compaction/ideal-compaction-settings.d.ts.map +1 -0
  21. package/dist/core/compaction/ideal-compaction-settings.js +7 -0
  22. package/dist/core/compaction/ideal-compaction-settings.js.map +1 -0
  23. package/dist/core/compaction-settings-access.d.ts +19 -0
  24. package/dist/core/compaction-settings-access.d.ts.map +1 -0
  25. package/dist/core/compaction-settings-access.js +10 -0
  26. package/dist/core/compaction-settings-access.js.map +1 -0
  27. package/dist/core/compaction-settings-resolver.d.ts +22 -0
  28. package/dist/core/compaction-settings-resolver.d.ts.map +1 -0
  29. package/dist/core/compaction-settings-resolver.js +46 -0
  30. package/dist/core/compaction-settings-resolver.js.map +1 -0
  31. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.d.ts +9 -1
  32. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.d.ts.map +1 -1
  33. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.js +10 -3
  34. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.js.map +1 -1
  35. package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts +24 -0
  36. package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts.map +1 -0
  37. package/dist/core/extensions/builtin/compaction/context-pipeline.js +43 -0
  38. package/dist/core/extensions/builtin/compaction/context-pipeline.js.map +1 -0
  39. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +1 -1
  40. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
  41. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +8 -2
  42. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js.map +1 -1
  43. package/dist/core/extensions/builtin/compaction/emergency-prune.d.ts +17 -0
  44. package/dist/core/extensions/builtin/compaction/emergency-prune.d.ts.map +1 -0
  45. package/dist/core/extensions/builtin/compaction/emergency-prune.js +64 -0
  46. package/dist/core/extensions/builtin/compaction/emergency-prune.js.map +1 -0
  47. package/dist/core/extensions/builtin/compaction/extension-wiring.d.ts +27 -0
  48. package/dist/core/extensions/builtin/compaction/extension-wiring.d.ts.map +1 -0
  49. package/dist/core/extensions/builtin/compaction/extension-wiring.js +84 -0
  50. package/dist/core/extensions/builtin/compaction/extension-wiring.js.map +1 -0
  51. package/dist/core/extensions/builtin/compaction/idle-retry.d.ts +1 -1
  52. package/dist/core/extensions/builtin/compaction/idle-retry.d.ts.map +1 -1
  53. package/dist/core/extensions/builtin/compaction/idle-retry.js +1 -1
  54. package/dist/core/extensions/builtin/compaction/idle-retry.js.map +1 -1
  55. package/dist/core/extensions/builtin/compaction/idle.d.ts +1 -0
  56. package/dist/core/extensions/builtin/compaction/idle.d.ts.map +1 -1
  57. package/dist/core/extensions/builtin/compaction/idle.js +13 -2
  58. package/dist/core/extensions/builtin/compaction/idle.js.map +1 -1
  59. package/dist/core/extensions/builtin/compaction/index.d.ts +1 -1
  60. package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
  61. package/dist/core/extensions/builtin/compaction/index.js +152 -154
  62. package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
  63. package/dist/core/extensions/builtin/compaction/log.d.ts +1 -1
  64. package/dist/core/extensions/builtin/compaction/log.d.ts.map +1 -1
  65. package/dist/core/extensions/builtin/compaction/log.js +2 -0
  66. package/dist/core/extensions/builtin/compaction/log.js.map +1 -1
  67. package/dist/core/extensions/builtin/compaction/model-selection.d.ts +14 -0
  68. package/dist/core/extensions/builtin/compaction/model-selection.d.ts.map +1 -0
  69. package/dist/core/extensions/builtin/compaction/model-selection.js +37 -0
  70. package/dist/core/extensions/builtin/compaction/model-selection.js.map +1 -0
  71. package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts +30 -0
  72. package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts.map +1 -0
  73. package/dist/core/extensions/builtin/compaction/model-usability-budget.js +74 -0
  74. package/dist/core/extensions/builtin/compaction/model-usability-budget.js.map +1 -0
  75. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.d.ts +9 -0
  76. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.d.ts.map +1 -0
  77. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.js +2 -0
  78. package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.js.map +1 -0
  79. package/dist/core/extensions/builtin/compaction/openai-remote.d.ts +3 -6
  80. package/dist/core/extensions/builtin/compaction/openai-remote.d.ts.map +1 -1
  81. package/dist/core/extensions/builtin/compaction/openai-remote.js.map +1 -1
  82. package/dist/core/extensions/builtin/compaction/orchestration.d.ts +46 -0
  83. package/dist/core/extensions/builtin/compaction/orchestration.d.ts.map +1 -0
  84. package/dist/core/extensions/builtin/compaction/orchestration.js +103 -0
  85. package/dist/core/extensions/builtin/compaction/orchestration.js.map +1 -0
  86. package/dist/core/extensions/builtin/compaction/policy.d.ts +12 -2
  87. package/dist/core/extensions/builtin/compaction/policy.d.ts.map +1 -1
  88. package/dist/core/extensions/builtin/compaction/policy.js +52 -26
  89. package/dist/core/extensions/builtin/compaction/policy.js.map +1 -1
  90. package/dist/core/extensions/builtin/compaction/speculation-lead.d.ts +8 -0
  91. package/dist/core/extensions/builtin/compaction/speculation-lead.d.ts.map +1 -0
  92. package/dist/core/extensions/builtin/compaction/speculation-lead.js +17 -0
  93. package/dist/core/extensions/builtin/compaction/speculation-lead.js.map +1 -0
  94. package/dist/core/extensions/builtin/compaction/speculative-job.d.ts +22 -0
  95. package/dist/core/extensions/builtin/compaction/speculative-job.d.ts.map +1 -0
  96. package/dist/core/extensions/builtin/compaction/speculative-job.js +16 -0
  97. package/dist/core/extensions/builtin/compaction/speculative-job.js.map +1 -0
  98. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts +23 -0
  99. package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts.map +1 -0
  100. package/dist/core/extensions/builtin/compaction/speculative-summary.js +132 -0
  101. package/dist/core/extensions/builtin/compaction/speculative-summary.js.map +1 -0
  102. package/dist/core/extensions/builtin/compaction/speculative.d.ts +8 -13
  103. package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
  104. package/dist/core/extensions/builtin/compaction/speculative.js +21 -197
  105. package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
  106. package/dist/core/extensions/builtin/compaction/token-budget-reminder.d.ts +24 -0
  107. package/dist/core/extensions/builtin/compaction/token-budget-reminder.d.ts.map +1 -0
  108. package/dist/core/extensions/builtin/compaction/token-budget-reminder.js +25 -0
  109. package/dist/core/extensions/builtin/compaction/token-budget-reminder.js.map +1 -0
  110. package/dist/core/extensions/builtin/compaction/tool-admission.d.ts +27 -0
  111. package/dist/core/extensions/builtin/compaction/tool-admission.d.ts.map +1 -0
  112. package/dist/core/extensions/builtin/compaction/tool-admission.js +56 -0
  113. package/dist/core/extensions/builtin/compaction/tool-admission.js.map +1 -0
  114. package/dist/core/extensions/builtin/hooks/trust-state-json.d.ts +5 -0
  115. package/dist/core/extensions/builtin/hooks/trust-state-json.d.ts.map +1 -0
  116. package/dist/core/extensions/builtin/hooks/trust-state-json.js +76 -0
  117. package/dist/core/extensions/builtin/hooks/trust-state-json.js.map +1 -0
  118. package/dist/core/extensions/builtin/hooks/trust-storage.d.ts +7 -1
  119. package/dist/core/extensions/builtin/hooks/trust-storage.d.ts.map +1 -1
  120. package/dist/core/extensions/builtin/hooks/trust-storage.js +60 -8
  121. package/dist/core/extensions/builtin/hooks/trust-storage.js.map +1 -1
  122. package/dist/core/extensions/builtin/hooks/trust.d.ts +1 -2
  123. package/dist/core/extensions/builtin/hooks/trust.d.ts.map +1 -1
  124. package/dist/core/extensions/builtin/hooks/trust.js +1 -72
  125. package/dist/core/extensions/builtin/hooks/trust.js.map +1 -1
  126. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.d.ts +3 -0
  127. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.d.ts.map +1 -0
  128. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js +108 -0
  129. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js.map +1 -0
  130. package/dist/core/extensions/builtin/prompt-preset/presets.d.ts.map +1 -1
  131. package/dist/core/extensions/builtin/prompt-preset/presets.js +11 -0
  132. package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
  133. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts +1 -1
  134. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts.map +1 -1
  135. package/dist/core/extensions/builtin/prompt-preset/settings.js +1 -0
  136. package/dist/core/extensions/builtin/prompt-preset/settings.js.map +1 -1
  137. package/dist/core/extensions/builtin/recommended-models/index.d.ts +1 -1
  138. package/dist/core/extensions/builtin/recommended-models/index.d.ts.map +1 -1
  139. package/dist/core/extensions/builtin/recommended-models/index.js +1 -1
  140. package/dist/core/extensions/builtin/recommended-models/index.js.map +1 -1
  141. package/dist/core/extensions/builtin/terminal/runtime-session.d.ts +11 -0
  142. package/dist/core/extensions/builtin/terminal/runtime-session.d.ts.map +1 -1
  143. package/dist/core/extensions/builtin/terminal/runtime-session.js +18 -2
  144. package/dist/core/extensions/builtin/terminal/runtime-session.js.map +1 -1
  145. package/dist/core/extensions/builtin/ttsr/index.d.ts.map +1 -1
  146. package/dist/core/extensions/builtin/ttsr/index.js +4 -0
  147. package/dist/core/extensions/builtin/ttsr/index.js.map +1 -1
  148. package/dist/core/extensions/builtin/ttsr/manager.d.ts +2 -0
  149. package/dist/core/extensions/builtin/ttsr/manager.d.ts.map +1 -1
  150. package/dist/core/extensions/builtin/ttsr/manager.js +28 -1
  151. package/dist/core/extensions/builtin/ttsr/manager.js.map +1 -1
  152. package/dist/core/extensions/runner.d.ts +5 -0
  153. package/dist/core/extensions/runner.d.ts.map +1 -1
  154. package/dist/core/extensions/runner.js +7 -0
  155. package/dist/core/extensions/runner.js.map +1 -1
  156. package/dist/core/retry-fallback/controller.d.ts +14 -0
  157. package/dist/core/retry-fallback/controller.d.ts.map +1 -1
  158. package/dist/core/retry-fallback/controller.js +33 -3
  159. package/dist/core/retry-fallback/controller.js.map +1 -1
  160. package/dist/core/retry-fallback/log.js +1 -1
  161. package/dist/core/retry-fallback/log.js.map +1 -1
  162. package/dist/core/retry-fallback/settings.d.ts.map +1 -1
  163. package/dist/core/retry-fallback/settings.js +1 -0
  164. package/dist/core/retry-fallback/settings.js.map +1 -1
  165. package/dist/core/sdk.d.ts.map +1 -1
  166. package/dist/core/sdk.js +5 -0
  167. package/dist/core/sdk.js.map +1 -1
  168. package/dist/core/session-activity.d.ts +47 -0
  169. package/dist/core/session-activity.d.ts.map +1 -0
  170. package/dist/core/session-activity.js +58 -0
  171. package/dist/core/session-activity.js.map +1 -0
  172. package/dist/core/session-manager.d.ts +8 -12
  173. package/dist/core/session-manager.d.ts.map +1 -1
  174. package/dist/core/session-manager.js +118 -7
  175. package/dist/core/session-manager.js.map +1 -1
  176. package/dist/core/session-resident-store.d.ts +8 -1
  177. package/dist/core/session-resident-store.d.ts.map +1 -1
  178. package/dist/core/session-resident-store.js +12 -5
  179. package/dist/core/session-resident-store.js.map +1 -1
  180. package/dist/core/settings-manager.d.ts +8 -85
  181. package/dist/core/settings-manager.d.ts.map +1 -1
  182. package/dist/core/settings-manager.js +9 -17
  183. package/dist/core/settings-manager.js.map +1 -1
  184. package/dist/core/settings-public-types.d.ts +11 -0
  185. package/dist/core/settings-public-types.d.ts.map +1 -0
  186. package/dist/core/settings-public-types.js +2 -0
  187. package/dist/core/settings-public-types.js.map +1 -0
  188. package/dist/core/settings-shapes.d.ts +36 -0
  189. package/dist/core/settings-shapes.d.ts.map +1 -0
  190. package/dist/core/settings-shapes.js +2 -0
  191. package/dist/core/settings-shapes.js.map +1 -0
  192. package/dist/core/shared-host-policy.d.ts +6 -0
  193. package/dist/core/shared-host-policy.d.ts.map +1 -0
  194. package/dist/core/shared-host-policy.js +7 -0
  195. package/dist/core/shared-host-policy.js.map +1 -0
  196. package/dist/core/terminal-settings.d.ts +22 -0
  197. package/dist/core/terminal-settings.d.ts.map +1 -0
  198. package/dist/core/terminal-settings.js +2 -0
  199. package/dist/core/terminal-settings.js.map +1 -0
  200. package/dist/index.d.ts +1 -1
  201. package/dist/index.d.ts.map +1 -1
  202. package/dist/index.js +1 -1
  203. package/dist/index.js.map +1 -1
  204. package/dist/main.d.ts +4 -4
  205. package/dist/main.d.ts.map +1 -1
  206. package/dist/main.js +27 -11
  207. package/dist/main.js.map +1 -1
  208. package/dist/modes/app-server/daemon/process.d.ts +13 -2
  209. package/dist/modes/app-server/daemon/process.d.ts.map +1 -1
  210. package/dist/modes/app-server/daemon/process.js +58 -12
  211. package/dist/modes/app-server/daemon/process.js.map +1 -1
  212. package/dist/modes/app-server/daemon.js +65 -7
  213. package/dist/modes/app-server/daemon.js.map +1 -1
  214. package/dist/modes/index.d.ts +1 -1
  215. package/dist/modes/index.d.ts.map +1 -1
  216. package/dist/modes/index.js +1 -1
  217. package/dist/modes/index.js.map +1 -1
  218. package/dist/modes/interactive/interactive-host-runtime.d.ts +84 -1
  219. package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -1
  220. package/dist/modes/interactive/interactive-host-runtime.js +435 -112
  221. package/dist/modes/interactive/interactive-host-runtime.js.map +1 -1
  222. package/dist/modes/interactive/interactive-mode.d.ts +11 -1
  223. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  224. package/dist/modes/interactive/interactive-mode.js +59 -6
  225. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  226. package/dist/modes/interactive/tips/catalog/ethos-tips.js +1 -1
  227. package/dist/modes/interactive/tips/catalog/ethos-tips.js.map +1 -1
  228. package/dist/modes/rpc/connection-handler.d.ts +12 -5
  229. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  230. package/dist/modes/rpc/connection-handler.js +180 -25
  231. package/dist/modes/rpc/connection-handler.js.map +1 -1
  232. package/dist/modes/rpc/custom-capability.d.ts +2 -0
  233. package/dist/modes/rpc/custom-capability.d.ts.map +1 -1
  234. package/dist/modes/rpc/custom-capability.js +2 -0
  235. package/dist/modes/rpc/custom-capability.js.map +1 -1
  236. package/dist/modes/rpc/host-ensure.d.ts +17 -0
  237. package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
  238. package/dist/modes/rpc/host-ensure.js +150 -23
  239. package/dist/modes/rpc/host-ensure.js.map +1 -1
  240. package/dist/modes/rpc/host-lifecycle.d.ts +54 -0
  241. package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
  242. package/dist/modes/rpc/host-lifecycle.js +259 -69
  243. package/dist/modes/rpc/host-lifecycle.js.map +1 -1
  244. package/dist/modes/rpc/host-watchdog.d.ts +2 -2
  245. package/dist/modes/rpc/host-watchdog.d.ts.map +1 -1
  246. package/dist/modes/rpc/host-watchdog.js +89 -21
  247. package/dist/modes/rpc/host-watchdog.js.map +1 -1
  248. package/dist/modes/rpc/multi-session-host.d.ts +38 -0
  249. package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
  250. package/dist/modes/rpc/multi-session-host.js +149 -61
  251. package/dist/modes/rpc/multi-session-host.js.map +1 -1
  252. package/dist/modes/rpc/ownership-safe-lock.d.ts +14 -0
  253. package/dist/modes/rpc/ownership-safe-lock.d.ts.map +1 -0
  254. package/dist/modes/rpc/ownership-safe-lock.js +87 -0
  255. package/dist/modes/rpc/ownership-safe-lock.js.map +1 -0
  256. package/dist/modes/rpc/rpc-client.d.ts +13 -2
  257. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  258. package/dist/modes/rpc/rpc-client.js +46 -12
  259. package/dist/modes/rpc/rpc-client.js.map +1 -1
  260. package/dist/modes/rpc/rpc-types.d.ts +21 -3
  261. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  262. package/dist/modes/rpc/rpc-types.js +1 -0
  263. package/dist/modes/rpc/rpc-types.js.map +1 -1
  264. package/dist/modes/rpc/session-binding.d.ts +2 -1
  265. package/dist/modes/rpc/session-binding.d.ts.map +1 -1
  266. package/dist/modes/rpc/session-binding.js +1 -0
  267. package/dist/modes/rpc/session-binding.js.map +1 -1
  268. package/dist/modes/rpc/session-command-router.d.ts +54 -1
  269. package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
  270. package/dist/modes/rpc/session-command-router.js +180 -3
  271. package/dist/modes/rpc/session-command-router.js.map +1 -1
  272. package/dist/modes/rpc/session-event-writer.d.ts +18 -0
  273. package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
  274. package/dist/modes/rpc/session-event-writer.js +88 -8
  275. package/dist/modes/rpc/session-event-writer.js.map +1 -1
  276. package/dist/modes/rpc/session-registry.d.ts +11 -1
  277. package/dist/modes/rpc/session-registry.d.ts.map +1 -1
  278. package/dist/modes/rpc/session-registry.js +25 -0
  279. package/dist/modes/rpc/session-registry.js.map +1 -1
  280. package/dist/modes/rpc/socket-transport.d.ts +13 -0
  281. package/dist/modes/rpc/socket-transport.d.ts.map +1 -0
  282. package/dist/modes/rpc/socket-transport.js +92 -0
  283. package/dist/modes/rpc/socket-transport.js.map +1 -0
  284. package/dist/modes/rpc/widget-line-renderer.d.ts +17 -0
  285. package/dist/modes/rpc/widget-line-renderer.d.ts.map +1 -0
  286. package/dist/modes/rpc/widget-line-renderer.js +73 -0
  287. package/dist/modes/rpc/widget-line-renderer.js.map +1 -0
  288. package/dist/utils/fs-watch.d.ts.map +1 -1
  289. package/dist/utils/fs-watch.js +11 -2
  290. package/dist/utils/fs-watch.js.map +1 -1
  291. package/docs/app-server.md +2 -2
  292. package/docs/containerization.md +2 -2
  293. package/docs/development.md +7 -7
  294. package/docs/extensions.md +5 -5
  295. package/docs/grok-neo.md +1 -1
  296. package/docs/index.md +1 -1
  297. package/docs/packages.md +2 -2
  298. package/docs/quickstart.md +4 -4
  299. package/docs/release-guide.md +21 -21
  300. package/docs/rpc.md +83 -6
  301. package/docs/sdk.md +1 -1
  302. package/docs/settings.md +4 -4
  303. package/docs/skills.md +2 -2
  304. package/docs/terminal-tools.md +1 -1
  305. package/docs/termux.md +1 -1
  306. package/docs/tui.md +1 -1
  307. package/examples/AGENTS.md +1 -1
  308. package/examples/sdk/README.md +1 -1
  309. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +52 -0
  310. package/node_modules/@code-yeongyu/senpi-codemode/README.md +2 -2
  311. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  312. package/node_modules/@code-yeongyu/senpi-codemode/src/extension/skill-contribution.ts +71 -0
  313. package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +3 -1
  314. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/SKILL.md +44 -0
  315. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/breaking-changes.md +75 -0
  316. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/build.md +114 -0
  317. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/dev-tooling.md +34 -0
  318. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/http-networking.md +113 -0
  319. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/install.md +93 -0
  320. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/node-compat-platforms.md +36 -0
  321. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/performance.md +33 -0
  322. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/runtime-apis.md +156 -0
  323. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/security.md +52 -0
  324. package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/test.md +103 -0
  325. package/node_modules/@earendil-works/pi-agent-core/README.md +3 -0
  326. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  327. package/node_modules/@earendil-works/pi-ai/README.md +6 -3
  328. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
  329. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +24 -7
  330. package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
  331. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +7 -0
  332. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts.map +1 -1
  333. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js +316 -2
  334. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
  335. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.d.ts +4 -0
  336. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.d.ts.map +1 -1
  337. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.js +23 -0
  338. package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.js.map +1 -1
  339. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts +24 -0
  340. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
  341. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +20 -2
  342. package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
  343. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  344. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
  345. package/node_modules/@earendil-works/pi-ai/dist/providers/data/anthropic.json +1 -1
  346. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
  347. package/node_modules/@earendil-works/pi-ai/dist/providers/data/google.json +1 -1
  348. package/node_modules/@earendil-works/pi-ai/dist/providers/data/groq.json +1 -1
  349. package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
  350. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.json +1 -1
  351. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  352. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  353. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  354. package/node_modules/@earendil-works/pi-pty/dist/screen-operations.d.ts +42 -0
  355. package/node_modules/@earendil-works/pi-pty/dist/screen-operations.d.ts.map +1 -0
  356. package/node_modules/@earendil-works/pi-pty/dist/screen-operations.js +34 -0
  357. package/node_modules/@earendil-works/pi-pty/dist/screen-operations.js.map +1 -0
  358. package/node_modules/@earendil-works/pi-pty/dist/screen-text.d.ts +8 -0
  359. package/node_modules/@earendil-works/pi-pty/dist/screen-text.d.ts.map +1 -0
  360. package/node_modules/@earendil-works/pi-pty/dist/screen-text.js +51 -0
  361. package/node_modules/@earendil-works/pi-pty/dist/screen-text.js.map +1 -0
  362. package/node_modules/@earendil-works/pi-pty/dist/screen.d.ts +45 -0
  363. package/node_modules/@earendil-works/pi-pty/dist/screen.d.ts.map +1 -1
  364. package/node_modules/@earendil-works/pi-pty/dist/screen.js +178 -55
  365. package/node_modules/@earendil-works/pi-pty/dist/screen.js.map +1 -1
  366. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  367. package/node_modules/@earendil-works/pi-telemetry/README.md +6 -3
  368. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  369. package/node_modules/@earendil-works/pi-tui/README.md +5 -4
  370. package/node_modules/@earendil-works/pi-tui/native/darwin/README.md +2 -2
  371. package/node_modules/@earendil-works/pi-tui/native/win32/README.md +2 -2
  372. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  373. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"session-event-writer.js","sourceRoot":"","sources":["../../../src/modes/rpc/session-event-writer.ts"],"names":[],"mappings":"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","sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { serializeJsonLine } from \"./jsonl.ts\";\nimport { SocketEventSinkActor } from \"./socket-event-fanout.ts\";\n\ntype RawWriter = (chunk: string) => void;\ntype BackpressureWaiter = () => Promise<void>;\ntype FlushScheduler = (flush: () => Promise<void>) => void;\ntype RpcRecord = Record<string, unknown>;\ntype CompactDeltaType = \"text_delta\" | \"thinking_delta\" | \"toolcall_delta\";\n\ntype QueueNode = {\n\tvalue: RpcRecord;\n\tkey?: string;\n\tprevious?: QueueNode;\n\tnext?: QueueNode;\n\tresolve?: () => void;\n\treject?: (cause: unknown) => void;\n};\n\ntype RecordQueue = {\n\tsessionId?: string;\n\ttargetId?: string;\n\thead?: QueueNode;\n\ttail?: QueueNode;\n\tlatestByKey: Map<string, QueueNode>;\n\tready: boolean;\n};\n\nconst MESSAGE_KEY = \"message\";\nconst COMPACT_DELTA_TYPES = new Set<CompactDeltaType>([\"text_delta\", \"thinking_delta\", \"toolcall_delta\"]);\n\nfunction compactDelta(value: RpcRecord): { type: CompactDeltaType; contentIndex: number; delta: string } | undefined {\n\tif (value.type !== \"message_update\" || !Object.hasOwn(value, \"message\")) return undefined;\n\tconst event = value.assistantMessageEvent;\n\tif (typeof event !== \"object\" || event === null) return undefined;\n\tconst typedEvent = event as Record<string, unknown>;\n\tif (\n\t\ttypeof typedEvent.type !== \"string\" ||\n\t\t!COMPACT_DELTA_TYPES.has(typedEvent.type as CompactDeltaType) ||\n\t\ttypeof typedEvent.contentIndex !== \"number\" ||\n\t\ttypeof typedEvent.delta !== \"string\"\n\t) {\n\t\treturn undefined;\n\t}\n\treturn {\n\t\ttype: typedEvent.type as CompactDeltaType,\n\t\tcontentIndex: typedEvent.contentIndex,\n\t\tdelta: typedEvent.delta,\n\t};\n}\n\nfunction toolUpdateKey(value: RpcRecord): string | undefined {\n\treturn value.type === \"tool_execution_update\" && typeof value.toolCallId === \"string\"\n\t\t? `tool:${value.toolCallId}`\n\t\t: undefined;\n}\n\n/**\n * Process-wide stdout scheduler for multi-session RPC mode.\n *\n * Each queue contains complete structured JSONL records for one routing handle.\n * Draining takes one record per queue in round-robin order and waits for stdout\n * backpressure before selecting the next one. A record is deliberately written\n * by itself: coalescing records from different sessions would obscure the\n * scheduling boundary and violate D9.\n */\nexport interface SessionEventWriterConnection {\n\treadonly writeRaw: RawWriter;\n\treadonly waitForBackpressure: BackpressureWaiter;\n}\n\nexport class SessionEventWriter {\n\tprivate readonly queues = new Map<string, RecordQueue>();\n\tprivate readonly connections = new Map<\n\t\tstring,\n\t\t{ connection: SessionEventWriterConnection; actor: SocketEventSinkActor }\n\t>();\n\tprivate readonly sessionSnapshots = new Map<string, string[]>();\n\tprivate readonly connectionContext = new AsyncLocalStorage<string>();\n\tprivate readonly controlQueue: RecordQueue = { latestByKey: new Map(), ready: false };\n\tprivate readonly readyQueues: RecordQueue[] = [];\n\tprivate readonly sealedSessions = new Set<string>();\n\tprivate readonly writeRaw: RawWriter;\n\tprivate readonly waitForBackpressure?: BackpressureWaiter;\n\tprivate readonly scheduleFlush: FlushScheduler;\n\tprivate flushScheduled = false;\n\tprivate drainPromise?: Promise<void>;\n\tprivate inFlight?: { queue: RecordQueue; node: QueueNode };\n\tprivate failure?: unknown;\n\n\tconstructor(writeRaw: RawWriter, scheduleFlush?: FlushScheduler);\n\tconstructor(writeRaw: RawWriter, waitForBackpressure: BackpressureWaiter, scheduleFlush?: FlushScheduler);\n\tconstructor(\n\t\twriteRaw: RawWriter,\n\t\twaitOrSchedule?: BackpressureWaiter | FlushScheduler,\n\t\tscheduleFlush?: FlushScheduler,\n\t) {\n\t\tthis.writeRaw = writeRaw;\n\t\tif (waitOrSchedule && scheduleFlush === undefined && waitOrSchedule.length > 0) {\n\t\t\tthis.scheduleFlush = waitOrSchedule as FlushScheduler;\n\t\t} else {\n\t\t\tthis.waitForBackpressure = waitOrSchedule as BackpressureWaiter | undefined;\n\t\t\tthis.scheduleFlush = scheduleFlush ?? ((flush) => queueMicrotask(() => void flush()));\n\t\t}\n\t}\n\n\tget bufferedRecordCount(): number {\n\t\tlet count = this.inFlight ? 1 : 0;\n\t\tfor (const queue of this.allQueues()) {\n\t\t\tfor (let node = queue.head; node; node = node.next) count++;\n\t\t}\n\t\treturn count;\n\t}\n\n\tget bufferedByteLength(): number {\n\t\tlet bytes = this.inFlight ? Buffer.byteLength(serializeJsonLine(this.inFlight.node.value)) : 0;\n\t\tfor (const queue of this.allQueues()) {\n\t\t\tfor (let node = queue.head; node; node = node.next) {\n\t\t\t\tbytes += Buffer.byteLength(serializeJsonLine(node.value));\n\t\t\t}\n\t\t}\n\t\treturn bytes;\n\t}\n\n\tregisterConnection(id: string, connection: SessionEventWriterConnection): void {\n\t\tconst actor = new SocketEventSinkActor(connection, () => {\n\t\t\tif (this.connections.get(id)?.actor === actor) this.connections.delete(id);\n\t\t});\n\t\tthis.connections.set(id, { connection, actor });\n\t\tfor (const snapshot of this.sessionSnapshots.values()) for (const line of snapshot) actor.enqueue(line);\n\t}\n\n\tunregisterConnection(id: string): void {\n\t\tconst registered = this.connections.get(id);\n\t\tif (!registered) return;\n\t\tregistered.actor.close();\n\t\tthis.connections.delete(id);\n\t}\n\n\t/** Execute a connection's command with its response destination in context. */\n\twithConnection<T>(id: string, task: () => T): T {\n\t\treturn this.connectionContext.run(id, task);\n\t}\n\n\t/** Connection id of the command currently being dispatched, when one owns it. */\n\tcurrentConnection(): string | undefined {\n\t\treturn this.connectionContext.getStore();\n\t}\n\n\t/** Queue a session record. Lifecycle/events are broadcast; responses/UI are targeted. */\n\tenqueue(sessionId: string, value: object): boolean {\n\t\tif (this.sealedSessions.has(sessionId)) return false;\n\t\tconst targetId = this.connectionContext.getStore();\n\t\tconst record = value as RpcRecord;\n\t\tconst isTargeted =\n\t\t\trecord.type === \"response\" ||\n\t\t\trecord.type === \"bash_execution_update\" ||\n\t\t\t(record.type === \"extension_ui_request\" &&\n\t\t\t\t[\"select\", \"confirm\", \"input\", \"editor\"].includes(String(record.method)));\n\t\tconst tagged = { ...value, sessionId } as RpcRecord;\n\t\tconst line = serializeJsonLine(tagged);\n\t\tthis.rememberSnapshot(sessionId, tagged, line);\n\t\tconst targets = isTargeted ? [targetId] : this.connections.size > 0 ? [...this.connections.keys()] : [undefined];\n\t\tfor (const target of targets) {\n\t\t\tif (target !== undefined && !this.connections.has(target)) continue;\n\t\t\tconst registered = target === undefined ? undefined : this.connections.get(target);\n\t\t\tif (registered)\n\t\t\t\tregistered.actor.enqueue(line, compactDelta(tagged) && tagged.message !== null ? MESSAGE_KEY : undefined);\n\t\t\telse this.appendSessionRecord(sessionId, tagged, target);\n\t\t}\n\t\tthis.requestFlush();\n\t\treturn true;\n\t}\n\n\t/** Queue one untagged host-control response for the current connection. */\n\tenqueueControl(value: object): Promise<void> {\n\t\tif (this.failure !== undefined) return Promise.reject(this.failure);\n\t\tconst targetId = this.connectionContext.getStore();\n\t\tconst registered = targetId === undefined ? undefined : this.connections.get(targetId);\n\t\tif (registered) {\n\t\t\tregistered.actor.enqueue(serializeJsonLine(value));\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\tconst queue = targetId === undefined ? this.controlQueue : this.connectionQueue(targetId);\n\t\tconst completion = new Promise<void>((resolve, reject) => {\n\t\t\tthis.append(queue, { ...value }, undefined, resolve, reject);\n\t\t});\n\t\tthis.markReady(queue);\n\t\tthis.requestFlush();\n\t\treturn completion;\n\t}\n\n\t/**\n\t * Prevent subsequent records for a session and append its terminal response.\n\t * Existing records retain FIFO order; this response is therefore that\n\t * session's final stdout record.\n\t */\n\tcloseSession(sessionId: string, response: object): void {\n\t\tif (this.sealedSessions.has(sessionId)) return;\n\t\tthis.sealedSessions.add(sessionId);\n\t\tconst targetId = this.connectionContext.getStore();\n\t\tconst lifecycle = { type: \"session_closed\", sessionId };\n\t\tfor (const connectionId of this.connections.keys()) {\n\t\t\tthis.connections.get(connectionId)!.actor.enqueue(serializeJsonLine(lifecycle));\n\t\t}\n\t\tconst taggedResponse = { ...response, sessionId };\n\t\tconst registered = targetId === undefined ? undefined : this.connections.get(targetId);\n\t\tif (registered) registered.actor.enqueue(serializeJsonLine(taggedResponse));\n\t\telse this.appendSessionRecord(sessionId, taggedResponse, targetId);\n\t\tthis.requestFlush();\n\t}\n\n\t/** Drain every retained lane and the current in-flight record. */\n\tflush(): Promise<void> {\n\t\tif (this.failure !== undefined) return Promise.reject(this.failure);\n\t\tthis.flushScheduled = false;\n\t\tif (this.drainPromise) return this.drainPromise;\n\t\tif (this.readyQueues.length === 0)\n\t\t\treturn Promise.all([...this.connections.values()].map(({ actor }) => actor.flush())).then(() => undefined);\n\t\tlet resolveDrain!: () => void;\n\t\tlet rejectDrain!: (cause: unknown) => void;\n\t\tconst drain = new Promise<void>((resolve, reject) => {\n\t\t\tresolveDrain = resolve;\n\t\t\trejectDrain = reject;\n\t\t});\n\t\tthis.drainPromise = drain;\n\t\tvoid this.drainUntilEmpty().then(resolveDrain, rejectDrain);\n\t\tvoid drain.then(\n\t\t\t() => {\n\t\t\t\tif (this.drainPromise === drain) this.drainPromise = undefined;\n\t\t\t\tif (this.readyQueues.length > 0) this.requestFlush();\n\t\t\t},\n\t\t\t(cause) => {\n\t\t\t\tif (this.drainPromise === drain) this.drainPromise = undefined;\n\t\t\t\tthis.fail(cause);\n\t\t\t},\n\t\t);\n\t\treturn drain;\n\t}\n\n\tprivate async drainUntilEmpty(): Promise<void> {\n\t\tdo {\n\t\t\tawait this.drainReadyQueues();\n\t\t} while (this.readyQueues.length > 0);\n\t\tawait Promise.all([...this.connections.values()].map(({ actor }) => actor.flush()));\n\t}\n\n\tprivate async drainReadyQueues(): Promise<void> {\n\t\twhile (this.readyQueues.length > 0) {\n\t\t\tconst queue = this.readyQueues.shift()!;\n\t\t\tqueue.ready = false;\n\t\t\tconst node = queue.head;\n\t\t\tif (!node) continue;\n\n\t\t\tthis.unlink(queue, node);\n\t\t\tthis.inFlight = { queue, node };\n\t\t\ttry {\n\t\t\t\t// D9: exactly one complete record per raw write. The next lane is not\n\t\t\t\t// selected until this record has cleared stdout backpressure.\n\t\t\t\tconst connection = queue.targetId ? this.connections.get(queue.targetId)?.connection : undefined;\n\t\t\t\tconst writeRaw = connection?.writeRaw ?? this.writeRaw;\n\t\t\t\tconst waitForBackpressure = connection?.waitForBackpressure ?? this.waitForBackpressure;\n\t\t\t\tif (!connection && queue.targetId) {\n\t\t\t\t\tnode.resolve?.();\n\t\t\t\t} else {\n\t\t\t\t\twriteRaw(serializeJsonLine(node.value));\n\t\t\t\t\tif (waitForBackpressure) await waitForBackpressure();\n\t\t\t\t\tnode.resolve?.();\n\t\t\t\t}\n\t\t\t} catch (cause) {\n\t\t\t\tnode.reject?.(cause);\n\t\t\t\tthrow cause;\n\t\t\t} finally {\n\t\t\t\tthis.inFlight = undefined;\n\t\t\t}\n\n\t\t\tif (queue.head) {\n\t\t\t\tthis.markReady(queue);\n\t\t\t} else if (queue.sessionId || queue.targetId) {\n\t\t\t\tfor (const [key, candidate] of this.queues) {\n\t\t\t\t\tif (candidate === queue) this.queues.delete(key);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate rememberSnapshot(sessionId: string, value: RpcRecord, line: string): void {\n\t\tconst event = value.assistantMessageEvent as Record<string, unknown> | undefined;\n\t\tif (value.type === \"message_start\" || (value.type === \"message_update\" && event?.type === \"text_start\")) {\n\t\t\tthis.sessionSnapshots.set(sessionId, [line]);\n\t\t} else if (this.sessionSnapshots.has(sessionId)) {\n\t\t\tthis.sessionSnapshots.get(sessionId)!.push(line);\n\t\t}\n\t\tif (value.type === \"message_end\") this.sessionSnapshots.delete(sessionId);\n\t}\n\n\tprivate connectionQueue(targetId: string): RecordQueue {\n\t\tconst key = `connection:${targetId}`;\n\t\tlet queue = this.queues.get(key);\n\t\tif (!queue) {\n\t\t\tqueue = { targetId, latestByKey: new Map(), ready: false };\n\t\t\tthis.queues.set(key, queue);\n\t\t}\n\t\treturn queue;\n\t}\n\n\tprivate appendSessionRecord(sessionId: string, value: RpcRecord, targetId?: string): void {\n\t\tconst key = `${targetId ?? \"default\"}:${sessionId}`;\n\t\tlet queue = this.queues.get(key);\n\t\tif (!queue) {\n\t\t\tqueue = { sessionId, targetId, latestByKey: new Map(), ready: false };\n\t\t\tthis.queues.set(key, queue);\n\t\t}\n\n\t\tconst delta = compactDelta(value);\n\t\tif (delta) {\n\t\t\tconst previousFull = queue.latestByKey.get(MESSAGE_KEY);\n\t\t\tif (previousFull) this.demoteAndMerge(queue, previousFull);\n\t\t\tconst node = this.append(queue, value, MESSAGE_KEY);\n\t\t\tqueue.latestByKey.set(MESSAGE_KEY, node);\n\t\t\tthis.markReady(queue);\n\t\t\treturn;\n\t\t}\n\n\t\tconst toolKey = toolUpdateKey(value);\n\t\tif (toolKey) {\n\t\t\tconst previous = queue.latestByKey.get(toolKey);\n\t\t\tif (previous) this.unlink(queue, previous);\n\t\t\tconst node = this.append(queue, value, toolKey);\n\t\t\tqueue.latestByKey.set(toolKey, node);\n\t\t\tthis.markReady(queue);\n\t\t\treturn;\n\t\t}\n\n\t\t// All non-compactable records are ordering barriers. In particular this\n\t\t// includes delta-only/full non-delta message updates, protocol responses,\n\t\t// extension UI requests, errors, retries, lifecycle, and unknown records.\n\t\tqueue.latestByKey.clear();\n\t\tthis.append(queue, value);\n\t\tthis.markReady(queue);\n\t}\n\n\tprivate demoteAndMerge(queue: RecordQueue, node: QueueNode): void {\n\t\tconst event = node.value.assistantMessageEvent as Record<string, unknown>;\n\t\tnode.value = {\n\t\t\t...node.value,\n\t\t\tmessage: null,\n\t\t\tassistantMessageEvent: { ...event, partial: null },\n\t\t};\n\t\tconst current = compactDelta(node.value);\n\t\tconst preceding = node.previous;\n\t\tconst previous = preceding ? compactDelta(preceding.value) : undefined;\n\t\tif (\n\t\t\tpreceding &&\n\t\t\tprevious &&\n\t\t\tcurrent &&\n\t\t\tpreceding.value.message === null &&\n\t\t\tprevious.type === current.type &&\n\t\t\tprevious.contentIndex === current.contentIndex\n\t\t) {\n\t\t\tconst precedingEvent = preceding.value.assistantMessageEvent as Record<string, unknown>;\n\t\t\tpreceding.value = {\n\t\t\t\t...preceding.value,\n\t\t\t\tassistantMessageEvent: { ...precedingEvent, delta: previous.delta + current.delta },\n\t\t\t};\n\t\t\tthis.unlink(queue, node);\n\t\t}\n\t}\n\n\tprivate append(\n\t\tqueue: RecordQueue,\n\t\tvalue: RpcRecord,\n\t\tkey?: string,\n\t\tresolve?: () => void,\n\t\treject?: (cause: unknown) => void,\n\t): QueueNode {\n\t\tconst node: QueueNode = { value, key, previous: queue.tail, resolve, reject };\n\t\tif (queue.tail) queue.tail.next = node;\n\t\telse queue.head = node;\n\t\tqueue.tail = node;\n\t\treturn node;\n\t}\n\n\tprivate unlink(queue: RecordQueue, node: QueueNode): void {\n\t\tif (node.previous) node.previous.next = node.next;\n\t\telse queue.head = node.next;\n\t\tif (node.next) node.next.previous = node.previous;\n\t\telse queue.tail = node.previous;\n\t\tif (node.key && queue.latestByKey.get(node.key) === node) queue.latestByKey.delete(node.key);\n\t\tnode.previous = undefined;\n\t\tnode.next = undefined;\n\t}\n\n\tprivate markReady(queue: RecordQueue): void {\n\t\tif (queue.ready || this.inFlight?.queue === queue || !queue.head) return;\n\t\tqueue.ready = true;\n\t\tthis.readyQueues.push(queue);\n\t}\n\n\tprivate requestFlush(): void {\n\t\tif (this.failure !== undefined || this.flushScheduled || this.drainPromise) return;\n\t\tthis.flushScheduled = true;\n\t\tthis.scheduleFlush(() => this.flush());\n\t}\n\n\tprivate fail(cause: unknown): void {\n\t\tif (this.failure !== undefined) return;\n\t\tthis.failure = cause;\n\t\tfor (const queue of this.allQueues()) {\n\t\t\tfor (let node = queue.head; node; node = node.next) node.reject?.(cause);\n\t\t}\n\t}\n\n\tprivate *allQueues(): Iterable<RecordQueue> {\n\t\tyield* this.queues.values();\n\t\tyield this.controlQueue;\n\t}\n}\n"]}
1
+ {"version":3,"file":"session-event-writer.js","sourceRoot":"","sources":["../../../src/modes/rpc/session-event-writer.ts"],"names":[],"mappings":"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","sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { serializeJsonLine } from \"./jsonl.ts\";\nimport { SocketEventSinkActor } from \"./socket-event-fanout.ts\";\n\ntype RawWriter = (chunk: string) => void;\ntype BackpressureWaiter = () => Promise<void>;\ntype FlushScheduler = (flush: () => Promise<void>) => void;\ntype RpcRecord = Record<string, unknown>;\ntype CompactDeltaType = \"text_delta\" | \"thinking_delta\" | \"toolcall_delta\";\n\ntype QueueNode = {\n\tvalue: RpcRecord;\n\tkey?: string;\n\tprevious?: QueueNode;\n\tnext?: QueueNode;\n\tresolve?: () => void;\n\treject?: (cause: unknown) => void;\n};\n\ntype RecordQueue = {\n\tsessionId?: string;\n\ttargetId?: string;\n\thead?: QueueNode;\n\ttail?: QueueNode;\n\tlatestByKey: Map<string, QueueNode>;\n\tready: boolean;\n};\n\nconst MESSAGE_KEY = \"message\";\nconst COMPACT_DELTA_TYPES = new Set<CompactDeltaType>([\"text_delta\", \"thinking_delta\", \"toolcall_delta\"]);\n\nfunction compactDelta(value: RpcRecord): { type: CompactDeltaType; contentIndex: number; delta: string } | undefined {\n\tif (value.type !== \"message_update\" || !Object.hasOwn(value, \"message\")) return undefined;\n\tconst event = value.assistantMessageEvent;\n\tif (typeof event !== \"object\" || event === null) return undefined;\n\tconst typedEvent = event as Record<string, unknown>;\n\tif (\n\t\ttypeof typedEvent.type !== \"string\" ||\n\t\t!COMPACT_DELTA_TYPES.has(typedEvent.type as CompactDeltaType) ||\n\t\ttypeof typedEvent.contentIndex !== \"number\" ||\n\t\ttypeof typedEvent.delta !== \"string\"\n\t) {\n\t\treturn undefined;\n\t}\n\treturn {\n\t\ttype: typedEvent.type as CompactDeltaType,\n\t\tcontentIndex: typedEvent.contentIndex,\n\t\tdelta: typedEvent.delta,\n\t};\n}\n\nfunction toolUpdateKey(value: RpcRecord): string | undefined {\n\treturn value.type === \"tool_execution_update\" && typeof value.toolCallId === \"string\"\n\t\t? `tool:${value.toolCallId}`\n\t\t: undefined;\n}\n\n/**\n * Process-wide stdout scheduler for multi-session RPC mode.\n *\n * Each queue contains complete structured JSONL records for one routing handle.\n * Draining takes one record per queue in round-robin order and waits for stdout\n * backpressure before selecting the next one. A record is deliberately written\n * by itself: coalescing records from different sessions would obscure the\n * scheduling boundary and violate D9.\n */\nexport interface SessionEventWriterConnection {\n\treadonly writeRaw: RawWriter;\n\treadonly waitForBackpressure: BackpressureWaiter;\n}\n\nexport const RENDERED_COMPONENT_RECORD = \"__senpiRenderedComponent\";\n\nexport class SessionEventWriter {\n\tprivate readonly queues = new Map<string, RecordQueue>();\n\tprivate readonly connections = new Map<\n\t\tstring,\n\t\t{ connection: SessionEventWriterConnection; actor: SocketEventSinkActor }\n\t>();\n\tprivate readonly sessionSnapshots = new Map<string, Array<{ line: string; rendered: boolean }>>();\n\tprivate readonly connectionContext = new AsyncLocalStorage<string>();\n\tprivate readonly connectionCapabilities = new Map<string, Set<string>>();\n\tprivate readonly connectionSessions = new Map<string, Set<string>>();\n\tprivate readonly registeredCapabilityConnections = new Set<string>();\n\tprivate readonly controlQueue: RecordQueue = { latestByKey: new Map(), ready: false };\n\tprivate readonly readyQueues: RecordQueue[] = [];\n\tprivate readonly sealedSessions = new Set<string>();\n\tprivate readonly writeRaw: RawWriter;\n\tprivate readonly waitForBackpressure?: BackpressureWaiter;\n\tprivate readonly scheduleFlush: FlushScheduler;\n\tprivate flushScheduled = false;\n\tprivate drainPromise?: Promise<void>;\n\tprivate inFlight?: { queue: RecordQueue; node: QueueNode };\n\tprivate failure?: unknown;\n\n\tconstructor(writeRaw: RawWriter, scheduleFlush?: FlushScheduler);\n\tconstructor(writeRaw: RawWriter, waitForBackpressure: BackpressureWaiter, scheduleFlush?: FlushScheduler);\n\tconstructor(\n\t\twriteRaw: RawWriter,\n\t\twaitOrSchedule?: BackpressureWaiter | FlushScheduler,\n\t\tscheduleFlush?: FlushScheduler,\n\t) {\n\t\tthis.writeRaw = writeRaw;\n\t\tif (waitOrSchedule && scheduleFlush === undefined && waitOrSchedule.length > 0) {\n\t\t\tthis.scheduleFlush = waitOrSchedule as FlushScheduler;\n\t\t} else {\n\t\t\tthis.waitForBackpressure = waitOrSchedule as BackpressureWaiter | undefined;\n\t\t\tthis.scheduleFlush = scheduleFlush ?? ((flush) => queueMicrotask(() => void flush()));\n\t\t}\n\t}\n\n\tget bufferedRecordCount(): number {\n\t\tlet count = this.inFlight ? 1 : 0;\n\t\tfor (const queue of this.allQueues()) {\n\t\t\tfor (let node = queue.head; node; node = node.next) count++;\n\t\t}\n\t\treturn count;\n\t}\n\n\tget bufferedByteLength(): number {\n\t\tlet bytes = this.inFlight ? Buffer.byteLength(serializeJsonLine(this.inFlight.node.value)) : 0;\n\t\tfor (const queue of this.allQueues()) {\n\t\t\tfor (let node = queue.head; node; node = node.next) {\n\t\t\t\tbytes += Buffer.byteLength(serializeJsonLine(node.value));\n\t\t\t}\n\t\t}\n\t\treturn bytes;\n\t}\n\n\tregisterConnection(id: string, connection: SessionEventWriterConnection): void {\n\t\tconst actor = new SocketEventSinkActor(connection, () => {\n\t\t\tif (this.connections.get(id)?.actor === actor) {\n\t\t\t\tthis.connections.delete(id);\n\t\t\t\tthis.connectionCapabilities.delete(id);\n\t\t\t\tthis.connectionSessions.delete(id);\n\t\t\t\tthis.registeredCapabilityConnections.delete(id);\n\t\t\t}\n\t\t});\n\t\tthis.connections.set(id, { connection, actor });\n\t\tthis.connectionCapabilities.set(id, new Set());\n\t\tthis.connectionSessions.set(id, new Set());\n\t\tfor (const snapshot of this.sessionSnapshots.values())\n\t\t\tfor (const record of snapshot) if (!record.rendered) actor.enqueue(record.line);\n\t}\n\n\tunregisterConnection(id: string): void {\n\t\tconst registered = this.connections.get(id);\n\t\tif (!registered) return;\n\t\tregistered.actor.close();\n\t\tthis.connections.delete(id);\n\t\tthis.connectionCapabilities.delete(id);\n\t\tthis.connectionSessions.delete(id);\n\t\tthis.registeredCapabilityConnections.delete(id);\n\t}\n\n\tattachConnectionToSession(id: string, sessionId: string): void {\n\t\tif (!this.connections.has(id)) return;\n\t\tconst sessions = this.connectionSessions.get(id) ?? new Set<string>();\n\t\tsessions.add(sessionId);\n\t\tthis.connectionSessions.set(id, sessions);\n\t\tif (this.connectionCapabilities.get(id)?.has(\"rendered_components\"))\n\t\t\tfor (const record of this.sessionSnapshots.get(sessionId) ?? [])\n\t\t\t\tif (record.rendered) this.connections.get(id)!.actor.enqueue(record.line);\n\t}\n\n\tdetachConnectionFromSession(id: string, sessionId: string): void {\n\t\tthis.connectionSessions.get(id)?.delete(sessionId);\n\t}\n\n\tsetConnectionCapabilities(id: string, capabilities: readonly string[]): void {\n\t\tconst registered = this.connections.get(id);\n\t\tif (!registered) return;\n\t\tconst wasCapable = this.connectionCapabilities.get(id)?.has(\"rendered_components\") ?? false;\n\t\tthis.connectionCapabilities.set(id, new Set(capabilities));\n\t\tthis.registeredCapabilityConnections.add(id);\n\t\tif (!wasCapable && capabilities.includes(\"rendered_components\"))\n\t\t\tfor (const sessionId of this.connectionSessions.get(id) ?? [])\n\t\t\t\tfor (const record of this.sessionSnapshots.get(sessionId) ?? [])\n\t\t\t\t\tif (record.rendered) registered.actor.enqueue(record.line);\n\t}\n\n\tclearConnectionCapabilities(id: string): void {\n\t\tif (this.connections.has(id)) {\n\t\t\tthis.connectionCapabilities.set(id, new Set());\n\t\t\tthis.registeredCapabilityConnections.delete(id);\n\t\t}\n\t}\n\n\thasRegisteredConnectionCapabilities(id: string): boolean {\n\t\treturn this.registeredCapabilityConnections.has(id);\n\t}\n\n\tgetConnectionCapabilities(id: string): readonly string[] | undefined {\n\t\tif (!this.registeredCapabilityConnections.has(id)) return undefined;\n\t\treturn [...(this.connectionCapabilities.get(id) ?? [])];\n\t}\n\n\thasCapableConnection(sessionId: string): boolean {\n\t\tfor (const [id, capabilities] of this.connectionCapabilities)\n\t\t\tif (capabilities.has(\"rendered_components\") && this.connectionSessions.get(id)?.has(sessionId)) return true;\n\t\treturn false;\n\t}\n\n\t/** Execute a connection's command with its response destination in context. */\n\twithConnection<T>(id: string, task: () => T): T {\n\t\treturn this.connectionContext.run(id, task);\n\t}\n\n\t/** Connection id of the command currently being dispatched, when one owns it. */\n\tcurrentConnection(): string | undefined {\n\t\treturn this.connectionContext.getStore();\n\t}\n\n\t/** Queue a session record. Lifecycle/events are broadcast; responses/UI are targeted. */\n\tenqueue(sessionId: string, value: object): boolean {\n\t\tif (this.sealedSessions.has(sessionId)) return false;\n\t\tconst targetId = this.connectionContext.getStore();\n\t\tconst record = value as RpcRecord;\n\t\tconst isTargeted =\n\t\t\trecord.type === \"response\" ||\n\t\t\trecord.type === \"bash_execution_update\" ||\n\t\t\t(record.type === \"extension_ui_request\" &&\n\t\t\t\t[\"select\", \"confirm\", \"input\", \"editor\"].includes(String(record.method)));\n\t\tconst tagged = { ...value, sessionId } as RpcRecord;\n\t\tconst { [RENDERED_COMPONENT_RECORD]: _rendered, ...wireTagged } = tagged;\n\t\tconst line = serializeJsonLine(wireTagged);\n\t\tthis.rememberSnapshot(sessionId, tagged, line);\n\t\tconst targets = isTargeted\n\t\t\t? [targetId]\n\t\t\t: record[RENDERED_COMPONENT_RECORD] && this.connections.size > 0\n\t\t\t\t? [...this.connections.keys()].filter(\n\t\t\t\t\t\t(id) =>\n\t\t\t\t\t\t\tthis.connectionCapabilities.get(id)?.has(\"rendered_components\") &&\n\t\t\t\t\t\t\tthis.connectionSessions.get(id)?.has(sessionId),\n\t\t\t\t\t)\n\t\t\t\t: this.connections.size > 0\n\t\t\t\t\t? [...this.connections.keys()]\n\t\t\t\t\t: [undefined];\n\t\tfor (const target of targets) {\n\t\t\tif (target !== undefined && !this.connections.has(target)) continue;\n\t\t\tconst registered = target === undefined ? undefined : this.connections.get(target);\n\t\t\tif (registered)\n\t\t\t\tregistered.actor.enqueue(line, compactDelta(tagged) && tagged.message !== null ? MESSAGE_KEY : undefined);\n\t\t\telse this.appendSessionRecord(sessionId, wireTagged, target);\n\t\t}\n\t\tthis.requestFlush();\n\t\treturn true;\n\t}\n\n\t/** Queue one untagged host-control response for the current connection. */\n\tenqueueControl(value: object): Promise<void> {\n\t\tif (this.failure !== undefined) return Promise.reject(this.failure);\n\t\tconst targetId = this.connectionContext.getStore();\n\t\tconst registered = targetId === undefined ? undefined : this.connections.get(targetId);\n\t\tif (registered) {\n\t\t\tregistered.actor.enqueue(serializeJsonLine(value));\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\tconst queue = targetId === undefined ? this.controlQueue : this.connectionQueue(targetId);\n\t\tconst completion = new Promise<void>((resolve, reject) => {\n\t\t\tthis.append(queue, { ...value }, undefined, resolve, reject);\n\t\t});\n\t\tthis.markReady(queue);\n\t\tthis.requestFlush();\n\t\treturn completion;\n\t}\n\n\t/**\n\t * Prevent subsequent records for a session and append its terminal response.\n\t * Existing records retain FIFO order; this response is therefore that\n\t * session's final stdout record.\n\t */\n\tcloseSession(sessionId: string, response: object): void {\n\t\tif (this.sealedSessions.has(sessionId)) return;\n\t\tthis.sealedSessions.add(sessionId);\n\t\tconst targetId = this.connectionContext.getStore();\n\t\tconst lifecycle = { type: \"session_closed\", sessionId };\n\t\tfor (const connectionId of this.connections.keys()) {\n\t\t\tthis.connections.get(connectionId)!.actor.enqueue(serializeJsonLine(lifecycle));\n\t\t}\n\t\tconst taggedResponse = { ...response, sessionId };\n\t\tconst registered = targetId === undefined ? undefined : this.connections.get(targetId);\n\t\tif (registered) registered.actor.enqueue(serializeJsonLine(taggedResponse));\n\t\telse this.appendSessionRecord(sessionId, taggedResponse, targetId);\n\t\tthis.requestFlush();\n\t}\n\n\t/**\n\t * Drops per-session bookkeeping for a handle whose runtime is fully disposed.\n\t * Routing handles are unique per process epoch, so nothing can legitimately\n\t * emit under this id again; without this every host-closed session would\n\t * leave a permanent sealed-handle (and snapshot) entry behind.\n\t */\n\tforgetSession(sessionId: string): void {\n\t\tthis.sealedSessions.delete(sessionId);\n\t\tthis.sessionSnapshots.delete(sessionId);\n\t}\n\n\t/** Drain every retained lane and the current in-flight record. */\n\tflush(): Promise<void> {\n\t\tif (this.failure !== undefined) return Promise.reject(this.failure);\n\t\tthis.flushScheduled = false;\n\t\tif (this.drainPromise) return this.drainPromise;\n\t\tif (this.readyQueues.length === 0)\n\t\t\treturn Promise.all([...this.connections.values()].map(({ actor }) => actor.flush())).then(() => undefined);\n\t\tlet resolveDrain!: () => void;\n\t\tlet rejectDrain!: (cause: unknown) => void;\n\t\tconst drain = new Promise<void>((resolve, reject) => {\n\t\t\tresolveDrain = resolve;\n\t\t\trejectDrain = reject;\n\t\t});\n\t\tthis.drainPromise = drain;\n\t\tvoid this.drainUntilEmpty().then(resolveDrain, rejectDrain);\n\t\tvoid drain.then(\n\t\t\t() => {\n\t\t\t\tif (this.drainPromise === drain) this.drainPromise = undefined;\n\t\t\t\tif (this.readyQueues.length > 0) this.requestFlush();\n\t\t\t},\n\t\t\t(cause) => {\n\t\t\t\tif (this.drainPromise === drain) this.drainPromise = undefined;\n\t\t\t\tthis.fail(cause);\n\t\t\t},\n\t\t);\n\t\treturn drain;\n\t}\n\n\tprivate async drainUntilEmpty(): Promise<void> {\n\t\tdo {\n\t\t\tawait this.drainReadyQueues();\n\t\t} while (this.readyQueues.length > 0);\n\t\tawait Promise.all([...this.connections.values()].map(({ actor }) => actor.flush()));\n\t}\n\n\tprivate async drainReadyQueues(): Promise<void> {\n\t\twhile (this.readyQueues.length > 0) {\n\t\t\tconst queue = this.readyQueues.shift()!;\n\t\t\tqueue.ready = false;\n\t\t\tconst node = queue.head;\n\t\t\tif (!node) continue;\n\n\t\t\tthis.unlink(queue, node);\n\t\t\tthis.inFlight = { queue, node };\n\t\t\ttry {\n\t\t\t\t// D9: exactly one complete record per raw write. The next lane is not\n\t\t\t\t// selected until this record has cleared stdout backpressure.\n\t\t\t\tconst connection = queue.targetId ? this.connections.get(queue.targetId)?.connection : undefined;\n\t\t\t\tconst writeRaw = connection?.writeRaw ?? this.writeRaw;\n\t\t\t\tconst waitForBackpressure = connection?.waitForBackpressure ?? this.waitForBackpressure;\n\t\t\t\tif (!connection && queue.targetId) {\n\t\t\t\t\tnode.resolve?.();\n\t\t\t\t} else {\n\t\t\t\t\twriteRaw(serializeJsonLine(node.value));\n\t\t\t\t\tif (waitForBackpressure) await waitForBackpressure();\n\t\t\t\t\tnode.resolve?.();\n\t\t\t\t}\n\t\t\t} catch (cause) {\n\t\t\t\tnode.reject?.(cause);\n\t\t\t\tthrow cause;\n\t\t\t} finally {\n\t\t\t\tthis.inFlight = undefined;\n\t\t\t}\n\n\t\t\tif (queue.head) {\n\t\t\t\tthis.markReady(queue);\n\t\t\t} else if (queue.sessionId || queue.targetId) {\n\t\t\t\tfor (const [key, candidate] of this.queues) {\n\t\t\t\t\tif (candidate === queue) this.queues.delete(key);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate rememberSnapshot(sessionId: string, value: RpcRecord, line: string): void {\n\t\tconst event = value.assistantMessageEvent as Record<string, unknown> | undefined;\n\t\tconst record = { line, rendered: value[RENDERED_COMPONENT_RECORD] === true };\n\t\tif (value.type === \"message_start\" || (value.type === \"message_update\" && event?.type === \"text_start\")) {\n\t\t\tthis.sessionSnapshots.set(sessionId, [record]);\n\t\t} else if (this.sessionSnapshots.has(sessionId)) {\n\t\t\tthis.sessionSnapshots.get(sessionId)!.push(record);\n\t\t}\n\t\tif (value.type === \"message_end\") this.sessionSnapshots.delete(sessionId);\n\t}\n\n\tprivate connectionQueue(targetId: string): RecordQueue {\n\t\tconst key = `connection:${targetId}`;\n\t\tlet queue = this.queues.get(key);\n\t\tif (!queue) {\n\t\t\tqueue = { targetId, latestByKey: new Map(), ready: false };\n\t\t\tthis.queues.set(key, queue);\n\t\t}\n\t\treturn queue;\n\t}\n\n\tprivate appendSessionRecord(sessionId: string, value: RpcRecord, targetId?: string): void {\n\t\tconst key = `${targetId ?? \"default\"}:${sessionId}`;\n\t\tlet queue = this.queues.get(key);\n\t\tif (!queue) {\n\t\t\tqueue = { sessionId, targetId, latestByKey: new Map(), ready: false };\n\t\t\tthis.queues.set(key, queue);\n\t\t}\n\n\t\tconst delta = compactDelta(value);\n\t\tif (delta) {\n\t\t\tconst previousFull = queue.latestByKey.get(MESSAGE_KEY);\n\t\t\tif (previousFull) this.demoteAndMerge(queue, previousFull);\n\t\t\tconst node = this.append(queue, value, MESSAGE_KEY);\n\t\t\tqueue.latestByKey.set(MESSAGE_KEY, node);\n\t\t\tthis.markReady(queue);\n\t\t\treturn;\n\t\t}\n\n\t\tconst toolKey = toolUpdateKey(value);\n\t\tif (toolKey) {\n\t\t\tconst previous = queue.latestByKey.get(toolKey);\n\t\t\tif (previous) this.unlink(queue, previous);\n\t\t\tconst node = this.append(queue, value, toolKey);\n\t\t\tqueue.latestByKey.set(toolKey, node);\n\t\t\tthis.markReady(queue);\n\t\t\treturn;\n\t\t}\n\n\t\t// All non-compactable records are ordering barriers. In particular this\n\t\t// includes delta-only/full non-delta message updates, protocol responses,\n\t\t// extension UI requests, errors, retries, lifecycle, and unknown records.\n\t\tqueue.latestByKey.clear();\n\t\tthis.append(queue, value);\n\t\tthis.markReady(queue);\n\t}\n\n\tprivate demoteAndMerge(queue: RecordQueue, node: QueueNode): void {\n\t\tconst event = node.value.assistantMessageEvent as Record<string, unknown>;\n\t\tnode.value = {\n\t\t\t...node.value,\n\t\t\tmessage: null,\n\t\t\tassistantMessageEvent: { ...event, partial: null },\n\t\t};\n\t\tconst current = compactDelta(node.value);\n\t\tconst preceding = node.previous;\n\t\tconst previous = preceding ? compactDelta(preceding.value) : undefined;\n\t\tif (\n\t\t\tpreceding &&\n\t\t\tprevious &&\n\t\t\tcurrent &&\n\t\t\tpreceding.value.message === null &&\n\t\t\tprevious.type === current.type &&\n\t\t\tprevious.contentIndex === current.contentIndex\n\t\t) {\n\t\t\tconst precedingEvent = preceding.value.assistantMessageEvent as Record<string, unknown>;\n\t\t\tpreceding.value = {\n\t\t\t\t...preceding.value,\n\t\t\t\tassistantMessageEvent: { ...precedingEvent, delta: previous.delta + current.delta },\n\t\t\t};\n\t\t\tthis.unlink(queue, node);\n\t\t}\n\t}\n\n\tprivate append(\n\t\tqueue: RecordQueue,\n\t\tvalue: RpcRecord,\n\t\tkey?: string,\n\t\tresolve?: () => void,\n\t\treject?: (cause: unknown) => void,\n\t): QueueNode {\n\t\tconst node: QueueNode = { value, key, previous: queue.tail, resolve, reject };\n\t\tif (queue.tail) queue.tail.next = node;\n\t\telse queue.head = node;\n\t\tqueue.tail = node;\n\t\treturn node;\n\t}\n\n\tprivate unlink(queue: RecordQueue, node: QueueNode): void {\n\t\tif (node.previous) node.previous.next = node.next;\n\t\telse queue.head = node.next;\n\t\tif (node.next) node.next.previous = node.previous;\n\t\telse queue.tail = node.previous;\n\t\tif (node.key && queue.latestByKey.get(node.key) === node) queue.latestByKey.delete(node.key);\n\t\tnode.previous = undefined;\n\t\tnode.next = undefined;\n\t}\n\n\tprivate markReady(queue: RecordQueue): void {\n\t\tif (queue.ready || this.inFlight?.queue === queue || !queue.head) return;\n\t\tqueue.ready = true;\n\t\tthis.readyQueues.push(queue);\n\t}\n\n\tprivate requestFlush(): void {\n\t\tif (this.failure !== undefined || this.flushScheduled || this.drainPromise) return;\n\t\tthis.flushScheduled = true;\n\t\tthis.scheduleFlush(() => this.flush());\n\t}\n\n\tprivate fail(cause: unknown): void {\n\t\tif (this.failure !== undefined) return;\n\t\tthis.failure = cause;\n\t\tfor (const queue of this.allQueues()) {\n\t\t\tfor (let node = queue.head; node; node = node.next) node.reject?.(cause);\n\t\t}\n\t}\n\n\tprivate *allQueues(): Iterable<RecordQueue> {\n\t\tyield* this.queues.values();\n\t\tyield this.controlQueue;\n\t}\n}\n"]}
@@ -23,15 +23,21 @@ export interface RpcSessionEntry {
23
23
  cwd: string;
24
24
  /** Live attachments (open + later attaches). The runtime is disposed only when the last one closes. */
25
25
  attachments: number;
26
+ /** Timestamp of the last routed command / observed activity; drives idle eviction. */
27
+ lastCommandAt: number;
26
28
  lifecycleMutex: Promise<void>;
27
29
  }
28
30
  export declare class RpcSessionRegistryError extends Error {
29
- readonly code: "unknown_session" | "session_closing" | "session_path_in_use" | "invalid_path" | "open_failed";
31
+ readonly code: "unknown_session" | "session_closing" | "session_path_in_use" | "invalid_path" | "open_failed" | "too_many_sessions";
30
32
  constructor(code: RpcSessionRegistryError["code"], reason?: string);
31
33
  }
32
34
  export interface RpcSessionRegistryOptions {
33
35
  agentDir: string;
34
36
  createRuntime: CreateAgentSessionRuntimeFactory;
37
+ /** Injectable clock (defaults to Date.now) so idle bookkeeping is testable. */
38
+ now?: () => number;
39
+ /** Cap on concurrently opening/open sessions; attach-on-open is exempt. */
40
+ maxSessions?: number;
35
41
  }
36
42
  export interface OpenRpcSession {
37
43
  sessionId: string;
@@ -46,7 +52,10 @@ export declare class RpcSessionRegistry {
46
52
  private readonly reservations;
47
53
  private nextHandle;
48
54
  private readonly options;
55
+ private readonly now;
49
56
  constructor(options: RpcSessionRegistryOptions);
57
+ /** Number of live entries, including ones still opening or closing. */
58
+ get size(): number;
50
59
  openSession(profile: RpcSessionLaunchProfile): Promise<OpenRpcSession>;
51
60
  /**
52
61
  * Read-only lookup with no state transitions or attachment accounting.
@@ -78,5 +87,6 @@ export declare class RpcSessionRegistry {
78
87
  /** Reconcile path and durable identity after runtime replacement. */
79
88
  private syncRuntimeMetadata;
80
89
  private validateProfile;
90
+ private countActiveSessions;
81
91
  }
82
92
  //# sourceMappingURL=session-registry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-registry.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/session-registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-registry.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/session-registry.ts"],"names":[],"mappings":"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"}
@@ -29,6 +29,11 @@ export class RpcSessionRegistry {
29
29
  this.reservations = new Set();
30
30
  this.nextHandle = 0;
31
31
  this.options = options;
32
+ this.now = options.now ?? Date.now;
33
+ }
34
+ /** Number of live entries, including ones still opening or closing. */
35
+ get size() {
36
+ return this.entries.size;
32
37
  }
33
38
  async openSession(profile) {
34
39
  this.validateProfile(profile);
@@ -46,6 +51,7 @@ export class RpcSessionRegistry {
46
51
  entry.attachments += 1;
47
52
  if (!entry.durableSessionId)
48
53
  throw new RpcSessionRegistryError("session_path_in_use");
54
+ entry.lastCommandAt = this.now();
49
55
  return {
50
56
  sessionId: handle,
51
57
  durableSessionId: entry.durableSessionId,
@@ -53,6 +59,13 @@ export class RpcSessionRegistry {
53
59
  attached: true,
54
60
  };
55
61
  }
62
+ const maxSessions = this.options.maxSessions;
63
+ if (maxSessions !== undefined && this.countActiveSessions() >= maxSessions) {
64
+ // Reconnect-churn backstop: every open_session owns a complete runtime
65
+ // (hundreds of MB measured), so admission is bounded. Attachments to a
66
+ // live session add none and stay allowed via the branch above.
67
+ throw new RpcSessionRegistryError("too_many_sessions");
68
+ }
56
69
  if (sessionPath)
57
70
  this.reservations.add(sessionPath);
58
71
  // Resume vs create parity (D1 + omo SenpiSessionRuntime.ts:198-200):
@@ -73,6 +86,7 @@ export class RpcSessionRegistry {
73
86
  reservationKey: sessionPath,
74
87
  cwd: storedProfile.cwd,
75
88
  attachments: 1,
89
+ lastCommandAt: this.now(),
76
90
  lifecycleMutex: Promise.resolve(),
77
91
  };
78
92
  entry.switchSession = (sessionPath, options) => {
@@ -159,6 +173,9 @@ export class RpcSessionRegistry {
159
173
  }
160
174
  if (entry.state !== "open" && entry.state !== "closing")
161
175
  throw new RpcSessionRegistryError("unknown_session");
176
+ // Every routed command counts as activity for idle eviction. Lookups that
177
+ // must not refresh idleness (sweeps, listing) use peek()/list() instead.
178
+ entry.lastCommandAt = this.now();
162
179
  return entry;
163
180
  }
164
181
  /**
@@ -249,5 +266,13 @@ export class RpcSessionRegistry {
249
266
  throw new RpcSessionRegistryError("invalid_path");
250
267
  }
251
268
  }
269
+ countActiveSessions() {
270
+ let count = 0;
271
+ for (const entry of this.entries.values()) {
272
+ if (entry.state === "opening" || entry.state === "open")
273
+ count += 1;
274
+ }
275
+ return count;
276
+ }
252
277
  }
253
278
  //# sourceMappingURL=session-registry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-registry.js","sourceRoot":"","sources":["../../../src/modes/rpc/session-registry.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, realpathSync } from \"node:fs\";\nimport { basename, dirname, isAbsolute, resolve } from \"node:path\";\nimport { ProviderScope, runWithProviderScope } from \"@earendil-works/pi-ai/node/provider-scope\";\nimport {\n\ttype AgentSessionLaunchProfile,\n\tAgentSessionRuntime,\n\ttype CreateAgentSessionRuntimeFactory,\n\tcreateAgentSessionRuntime,\n} from \"../../core/agent-session-runtime.ts\";\nimport { SessionManager } from \"../../core/session-manager.ts\";\n\n/** The immutable flags selected when a routing session is opened. */\nexport interface RpcSessionLaunchProfile extends AgentSessionLaunchProfile {\n\tsessionPath?: string;\n}\n\nexport type SessionRuntime = AgentSessionRuntime;\nexport type RpcSessionState = \"opening\" | \"open\" | \"closing\" | \"closed\";\n\nexport interface RpcSessionEntry {\n\tstate: RpcSessionState;\n\truntime?: SessionRuntime;\n\t/** Resolves replacement against the runtime currently owned by this entry. */\n\tswitchSession?: SessionRuntime[\"switchSession\"];\n\t/** Rebind callback installed by the shared RPC connection handler. */\n\trebindSession?: Parameters<SessionRuntime[\"setRebindSession\"]>[0];\n\tscope: ProviderScope;\n\tprofile: Readonly<RpcSessionLaunchProfile>;\n\tdurableSessionId?: string;\n\tsessionPath?: string;\n\t/** Canonical reservation key for path-opened sessions; matches the reservations set. */\n\treservationKey?: string;\n\t/** Current runtime cwd, which can change when a session is replaced. */\n\tcwd: string;\n\t/** Live attachments (open + later attaches). The runtime is disposed only when the last one closes. */\n\tattachments: number;\n\tlifecycleMutex: Promise<void>;\n}\n\nexport class RpcSessionRegistryError extends Error {\n\treadonly code: \"unknown_session\" | \"session_closing\" | \"session_path_in_use\" | \"invalid_path\" | \"open_failed\";\n\n\tconstructor(code: RpcSessionRegistryError[\"code\"], reason?: string) {\n\t\tsuper(code === \"open_failed\" && reason ? `${code}: ${reason}` : code);\n\t\tthis.code = code;\n\t\tthis.name = \"RpcSessionRegistryError\";\n\t}\n}\n\nexport interface RpcSessionRegistryOptions {\n\tagentDir: string;\n\tcreateRuntime: CreateAgentSessionRuntimeFactory;\n}\n\nexport interface OpenRpcSession {\n\tsessionId: string;\n\tdurableSessionId: string;\n\tsessionPath?: string;\n\t/** True when this open attached to an already-open session instead of creating one. */\n\tattached?: boolean;\n}\n\nfunction canonicalPath(path: string): string {\n\tconst absolutePath = resolve(path);\n\tif (existsSync(absolutePath)) return realpathSync(absolutePath);\n\treturn `${realpathSync(dirname(absolutePath))}/${basename(absolutePath)}`;\n}\n\nfunction frozenProfile(profile: RpcSessionLaunchProfile): Readonly<RpcSessionLaunchProfile> {\n\treturn Object.freeze({\n\t\t...profile,\n\t\t...(profile.creationModel ? { creationModel: Object.freeze({ ...profile.creationModel }) } : {}),\n\t});\n}\n\n/** Process-local lifecycle owner for multi-session RPC runtimes. */\nexport class RpcSessionRegistry {\n\tprivate readonly entries = new Map<string, RpcSessionEntry>();\n\tprivate readonly reservations = new Set<string>();\n\tprivate nextHandle = 0;\n\tprivate readonly options: RpcSessionRegistryOptions;\n\n\tconstructor(options: RpcSessionRegistryOptions) {\n\t\tthis.options = options;\n\t}\n\n\tasync openSession(profile: RpcSessionLaunchProfile): Promise<OpenRpcSession> {\n\t\tthis.validateProfile(profile);\n\t\tthis.syncRuntimeMetadata();\n\t\tconst sessionPath = profile.sessionPath ? canonicalPath(profile.sessionPath) : undefined;\n\t\tif (sessionPath && this.reservations.has(sessionPath)) {\n\t\t\t// Attach-on-open: a live session outlives individual client attachments, so a\n\t\t\t// resume (or a second surface) for an already-hosted path joins the existing\n\t\t\t// runtime instead of failing. Entries still opening or closing keep the\n\t\t\t// exclusive reservation and reject as before.\n\t\t\tconst existing = [...this.entries].find(\n\t\t\t\t([, entry]) => entry.reservationKey === sessionPath && entry.state === \"open\",\n\t\t\t);\n\t\t\tif (!existing) throw new RpcSessionRegistryError(\"session_path_in_use\");\n\t\t\tconst [handle, entry] = existing;\n\t\t\tentry.attachments += 1;\n\t\t\tif (!entry.durableSessionId) throw new RpcSessionRegistryError(\"session_path_in_use\");\n\t\t\treturn {\n\t\t\t\tsessionId: handle,\n\t\t\t\tdurableSessionId: entry.durableSessionId,\n\t\t\t\tsessionPath: entry.sessionPath,\n\t\t\t\tattached: true,\n\t\t\t};\n\t\t}\n\t\tif (sessionPath) this.reservations.add(sessionPath);\n\n\t\t// Resume vs create parity (D1 + omo SenpiSessionRuntime.ts:198-200):\n\t\t// Create-only launch semantics mirror classic startup flags. A resumed\n\t\t// session restores its persisted model and thinking level instead of being\n\t\t// overridden by the new open_session request.\n\t\tconst isResume = sessionPath !== undefined && existsSync(sessionPath);\n\t\tconst storedProfile = frozenProfile({ ...profile, ...(sessionPath ? { sessionPath } : {}) });\n\t\tconst runtimeProfile = isResume\n\t\t\t? frozenProfile({ ...storedProfile, creationModel: undefined, initialThinkingLevel: undefined })\n\t\t\t: storedProfile;\n\n\t\tconst handle = `rpc-${++this.nextHandle}`;\n\t\tconst entry: RpcSessionEntry = {\n\t\t\tstate: \"opening\",\n\t\t\tscope: new ProviderScope(),\n\t\t\tprofile: storedProfile,\n\t\t\tsessionPath,\n\t\t\treservationKey: sessionPath,\n\t\t\tcwd: storedProfile.cwd,\n\t\t\tattachments: 1,\n\t\t\tlifecycleMutex: Promise.resolve(),\n\t\t};\n\t\tentry.switchSession = (sessionPath, options) => {\n\t\t\tconst operation = entry.lifecycleMutex.then(async () => {\n\t\t\t\tif (entry.state !== \"open\" || !entry.runtime) {\n\t\t\t\t\tthrow new RpcSessionRegistryError(\"unknown_session\");\n\t\t\t\t}\n\t\t\t\tconst runtime = entry.runtime;\n\t\t\t\tconst cwdOverride = options?.cwdOverride;\n\t\t\t\tconst cwdChanged = cwdOverride !== undefined && runtime.session.sessionManager.getCwd() !== cwdOverride;\n\t\t\t\tconst result = await runtime.switchSession(sessionPath, options);\n\t\t\t\tif (result.cancelled || !cwdChanged) return result;\n\n\t\t\t\t// A multi-session binding outlives an individual replacement. Keep the\n\t\t\t\t// entry's runtime object aligned with the replacement so every attached\n\t\t\t\t// client resolves getters and future commands against the new cwd-bound\n\t\t\t\t// runtime, not the object created during open_session.\n\t\t\t\tconst replacement = new AgentSessionRuntime(\n\t\t\t\t\truntime.session,\n\t\t\t\t\truntime.services,\n\t\t\t\t\tthis.options.createRuntime,\n\t\t\t\t\t[...runtime.diagnostics],\n\t\t\t\t\truntime.modelFallbackMessage,\n\t\t\t\t\truntime.launchProfile,\n\t\t\t\t);\n\t\t\t\treplacement.setRebindSession(entry.rebindSession);\n\t\t\t\tentry.runtime = replacement;\n\t\t\t\tthis.syncRuntimeMetadata();\n\t\t\t\treturn result;\n\t\t\t});\n\t\t\tentry.lifecycleMutex = operation.then(\n\t\t\t\t() => undefined,\n\t\t\t\t() => undefined,\n\t\t\t);\n\t\t\treturn operation;\n\t\t};\n\t\tthis.entries.set(handle, entry);\n\t\ttry {\n\t\t\tconst manager = sessionPath\n\t\t\t\t? SessionManager.open(sessionPath, undefined, storedProfile.cwd)\n\t\t\t\t: SessionManager.create(storedProfile.cwd);\n\t\t\tentry.runtime = await runWithProviderScope(entry.scope, () =>\n\t\t\t\tcreateAgentSessionRuntime(this.options.createRuntime, {\n\t\t\t\t\tcwd: manager.getCwd(),\n\t\t\t\t\tagentDir: this.options.agentDir,\n\t\t\t\t\tsessionManager: manager,\n\t\t\t\t\tlaunchProfile: runtimeProfile,\n\t\t\t\t}),\n\t\t\t);\n\t\t\tentry.durableSessionId = manager.getSessionId();\n\t\t\tentry.sessionPath ??= manager.getSessionFile();\n\t\t\tentry.state = \"open\";\n\t\t\treturn { sessionId: handle, durableSessionId: entry.durableSessionId, sessionPath: entry.sessionPath };\n\t\t} catch (error) {\n\t\t\t// Runtime construction may have started extensions, watchers, and provider\n\t\t\t// registrations before it rejects. Keep the reservation and entry private\n\t\t\t// until all of those resources have been torn down, then release them as\n\t\t\t// one rollback so the path can immediately be opened again.\n\t\t\ttry {\n\t\t\t\tawait entry.runtime?.dispose();\n\t\t\t} catch {\n\t\t\t\t// The original construction error remains the externally visible cause.\n\t\t\t} finally {\n\t\t\t\ttry {\n\t\t\t\t\tawait entry.scope.close?.();\n\t\t\t\t} finally {\n\t\t\t\t\tthis.entries.delete(handle);\n\t\t\t\t\tif (sessionPath) this.reservations.delete(sessionPath);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (error instanceof RpcSessionRegistryError) throw error;\n\t\t\tthrow new RpcSessionRegistryError(\"open_failed\", error instanceof Error ? error.message : undefined);\n\t\t}\n\t}\n\n\t/**\n\t * Read-only lookup with no state transitions or attachment accounting.\n\t * Exists so lifecycle decisions (e.g. deferring a dropped connection's\n\t * release while a turn is still streaming) can inspect the live entry\n\t * without claiming it.\n\t */\n\tpeek(handle: string): RpcSessionEntry | undefined {\n\t\treturn this.entries.get(handle);\n\t}\n\n\tgetForCommand(handle: string, command: string): RpcSessionEntry {\n\t\tconst entry = this.entries.get(handle);\n\t\tif (!entry) throw new RpcSessionRegistryError(\"unknown_session\");\n\t\tif (entry.state === \"closing\" && ![\"abort\", \"abort_bash\", \"extension_ui_response\"].includes(command)) {\n\t\t\tthrow new RpcSessionRegistryError(\"session_closing\");\n\t\t}\n\t\tif (entry.state !== \"open\" && entry.state !== \"closing\") throw new RpcSessionRegistryError(\"unknown_session\");\n\t\treturn entry;\n\t}\n\n\t/**\n\t * Starts a close synchronously. Call this before disposing any session-owned\n\t * binding so a concurrent command cannot reach a half-disposed handler.\n\t * Each call releases one attachment; the entry transitions to \"closing\" only\n\t * when the last attachment closes, so callers must check the returned state\n\t * and skip finalization while other attachments remain.\n\t */\n\tbeginClose(handle: string): RpcSessionEntry {\n\t\tconst entry = this.entries.get(handle);\n\t\tif (entry?.state !== \"open\") throw new RpcSessionRegistryError(\"unknown_session\");\n\t\tentry.attachments -= 1;\n\t\tif (entry.attachments > 0) return entry;\n\t\tentry.state = \"closing\";\n\t\treturn entry;\n\t}\n\n\tasync close(handle: string): Promise<void> {\n\t\tconst entry = this.beginClose(handle);\n\t\t// Other attachments may still own the live session; only the last close finalizes.\n\t\tif (entry.state !== \"closing\") return;\n\t\treturn this.closeMarked(handle);\n\t}\n\n\t/** Completes a close previously made visible by beginClose(). */\n\tasync closeMarked(handle: string): Promise<void> {\n\t\tthis.syncRuntimeMetadata();\n\t\tconst entry = this.entries.get(handle);\n\t\tif (entry?.state !== \"closing\") throw new RpcSessionRegistryError(\"unknown_session\");\n\t\tconst previousLifecycle = entry.lifecycleMutex;\n\t\tentry.lifecycleMutex = (async () => {\n\t\t\tawait previousLifecycle;\n\t\t\ttry {\n\t\t\t\tawait entry.runtime?.session.abort();\n\t\t\t\tawait entry.runtime?.session.waitForIdle();\n\t\t\t\tawait entry.runtime?.dispose();\n\t\t\t\tawait entry.scope.close?.();\n\t\t\t} finally {\n\t\t\t\tentry.state = \"closed\";\n\t\t\t\tthis.entries.delete(handle);\n\t\t\t\tif (entry.reservationKey) this.reservations.delete(entry.reservationKey);\n\t\t\t}\n\t\t})();\n\t\treturn entry.lifecycleMutex;\n\t}\n\n\tlist(): Array<{\n\t\tsessionId: string;\n\t\tdurableSessionId?: string;\n\t\tsessionPath?: string;\n\t\tcwd: string;\n\t\tname?: string;\n\t\tstatus: RpcSessionState;\n\t}> {\n\t\tthis.syncRuntimeMetadata();\n\t\treturn [...this.entries].map(([sessionId, entry]) => ({\n\t\t\tsessionId,\n\t\t\tdurableSessionId: entry.durableSessionId,\n\t\t\tsessionPath: entry.sessionPath,\n\t\t\tcwd: entry.cwd,\n\t\t\tname: entry.runtime?.session.sessionManager.getSessionName(),\n\t\t\tstatus: entry.state,\n\t\t}));\n\t}\n\n\t/** Reconcile path and durable identity after runtime replacement. */\n\tprivate syncRuntimeMetadata(): void {\n\t\tfor (const entry of this.entries.values()) {\n\t\t\tconst manager = entry.runtime?.session.sessionManager;\n\t\t\tif (!manager) continue;\n\t\t\tconst currentPath = manager.getSessionFile();\n\t\t\t// Preserve the originally canonicalized key while the runtime still points at\n\t\t\t// the same path. SessionManager may expose a symlink-resolved spelling after\n\t\t\t// opening a file that did not exist yet; treating that as replacement would\n\t\t\t// break ordinary attach-on-open aliases.\n\t\t\tif (currentPath !== entry.sessionPath) {\n\t\t\t\tconst currentKey = currentPath ? canonicalPath(currentPath) : undefined;\n\t\t\t\tif (entry.reservationKey) this.reservations.delete(entry.reservationKey);\n\t\t\t\tif (currentKey) this.reservations.add(currentKey);\n\t\t\t\tentry.reservationKey = currentKey;\n\t\t\t\tentry.sessionPath = currentPath;\n\t\t\t}\n\t\t\tentry.durableSessionId = manager.getSessionId();\n\t\t\tentry.cwd = manager.getCwd();\n\t\t}\n\t}\n\n\tprivate validateProfile(profile: RpcSessionLaunchProfile): void {\n\t\tif (!isAbsolute(profile.cwd) || (profile.sessionPath !== undefined && !isAbsolute(profile.sessionPath))) {\n\t\t\tthrow new RpcSessionRegistryError(\"invalid_path\");\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"session-registry.js","sourceRoot":"","sources":["../../../src/modes/rpc/session-registry.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, realpathSync } from \"node:fs\";\nimport { basename, dirname, isAbsolute, resolve } from \"node:path\";\nimport { ProviderScope, runWithProviderScope } from \"@earendil-works/pi-ai/node/provider-scope\";\nimport {\n\ttype AgentSessionLaunchProfile,\n\tAgentSessionRuntime,\n\ttype CreateAgentSessionRuntimeFactory,\n\tcreateAgentSessionRuntime,\n} from \"../../core/agent-session-runtime.ts\";\nimport { SessionManager } from \"../../core/session-manager.ts\";\n\n/** The immutable flags selected when a routing session is opened. */\nexport interface RpcSessionLaunchProfile extends AgentSessionLaunchProfile {\n\tsessionPath?: string;\n}\n\nexport type SessionRuntime = AgentSessionRuntime;\nexport type RpcSessionState = \"opening\" | \"open\" | \"closing\" | \"closed\";\n\nexport interface RpcSessionEntry {\n\tstate: RpcSessionState;\n\truntime?: SessionRuntime;\n\t/** Resolves replacement against the runtime currently owned by this entry. */\n\tswitchSession?: SessionRuntime[\"switchSession\"];\n\t/** Rebind callback installed by the shared RPC connection handler. */\n\trebindSession?: Parameters<SessionRuntime[\"setRebindSession\"]>[0];\n\tscope: ProviderScope;\n\tprofile: Readonly<RpcSessionLaunchProfile>;\n\tdurableSessionId?: string;\n\tsessionPath?: string;\n\t/** Canonical reservation key for path-opened sessions; matches the reservations set. */\n\treservationKey?: string;\n\t/** Current runtime cwd, which can change when a session is replaced. */\n\tcwd: string;\n\t/** Live attachments (open + later attaches). The runtime is disposed only when the last one closes. */\n\tattachments: number;\n\t/** Timestamp of the last routed command / observed activity; drives idle eviction. */\n\tlastCommandAt: number;\n\tlifecycleMutex: Promise<void>;\n}\n\nexport class RpcSessionRegistryError extends Error {\n\treadonly code:\n\t\t| \"unknown_session\"\n\t\t| \"session_closing\"\n\t\t| \"session_path_in_use\"\n\t\t| \"invalid_path\"\n\t\t| \"open_failed\"\n\t\t| \"too_many_sessions\";\n\n\tconstructor(code: RpcSessionRegistryError[\"code\"], reason?: string) {\n\t\tsuper(code === \"open_failed\" && reason ? `${code}: ${reason}` : code);\n\t\tthis.code = code;\n\t\tthis.name = \"RpcSessionRegistryError\";\n\t}\n}\n\nexport interface RpcSessionRegistryOptions {\n\tagentDir: string;\n\tcreateRuntime: CreateAgentSessionRuntimeFactory;\n\t/** Injectable clock (defaults to Date.now) so idle bookkeeping is testable. */\n\tnow?: () => number;\n\t/** Cap on concurrently opening/open sessions; attach-on-open is exempt. */\n\tmaxSessions?: number;\n}\n\nexport interface OpenRpcSession {\n\tsessionId: string;\n\tdurableSessionId: string;\n\tsessionPath?: string;\n\t/** True when this open attached to an already-open session instead of creating one. */\n\tattached?: boolean;\n}\n\nfunction canonicalPath(path: string): string {\n\tconst absolutePath = resolve(path);\n\tif (existsSync(absolutePath)) return realpathSync(absolutePath);\n\treturn `${realpathSync(dirname(absolutePath))}/${basename(absolutePath)}`;\n}\n\nfunction frozenProfile(profile: RpcSessionLaunchProfile): Readonly<RpcSessionLaunchProfile> {\n\treturn Object.freeze({\n\t\t...profile,\n\t\t...(profile.creationModel ? { creationModel: Object.freeze({ ...profile.creationModel }) } : {}),\n\t});\n}\n\n/** Process-local lifecycle owner for multi-session RPC runtimes. */\nexport class RpcSessionRegistry {\n\tprivate readonly entries = new Map<string, RpcSessionEntry>();\n\tprivate readonly reservations = new Set<string>();\n\tprivate nextHandle = 0;\n\tprivate readonly options: RpcSessionRegistryOptions;\n\tprivate readonly now: () => number;\n\n\tconstructor(options: RpcSessionRegistryOptions) {\n\t\tthis.options = options;\n\t\tthis.now = options.now ?? Date.now;\n\t}\n\n\t/** Number of live entries, including ones still opening or closing. */\n\tget size(): number {\n\t\treturn this.entries.size;\n\t}\n\n\tasync openSession(profile: RpcSessionLaunchProfile): Promise<OpenRpcSession> {\n\t\tthis.validateProfile(profile);\n\t\tthis.syncRuntimeMetadata();\n\t\tconst sessionPath = profile.sessionPath ? canonicalPath(profile.sessionPath) : undefined;\n\t\tif (sessionPath && this.reservations.has(sessionPath)) {\n\t\t\t// Attach-on-open: a live session outlives individual client attachments, so a\n\t\t\t// resume (or a second surface) for an already-hosted path joins the existing\n\t\t\t// runtime instead of failing. Entries still opening or closing keep the\n\t\t\t// exclusive reservation and reject as before.\n\t\t\tconst existing = [...this.entries].find(\n\t\t\t\t([, entry]) => entry.reservationKey === sessionPath && entry.state === \"open\",\n\t\t\t);\n\t\t\tif (!existing) throw new RpcSessionRegistryError(\"session_path_in_use\");\n\t\t\tconst [handle, entry] = existing;\n\t\t\tentry.attachments += 1;\n\t\t\tif (!entry.durableSessionId) throw new RpcSessionRegistryError(\"session_path_in_use\");\n\t\t\tentry.lastCommandAt = this.now();\n\t\t\treturn {\n\t\t\t\tsessionId: handle,\n\t\t\t\tdurableSessionId: entry.durableSessionId,\n\t\t\t\tsessionPath: entry.sessionPath,\n\t\t\t\tattached: true,\n\t\t\t};\n\t\t}\n\t\tconst maxSessions = this.options.maxSessions;\n\t\tif (maxSessions !== undefined && this.countActiveSessions() >= maxSessions) {\n\t\t\t// Reconnect-churn backstop: every open_session owns a complete runtime\n\t\t\t// (hundreds of MB measured), so admission is bounded. Attachments to a\n\t\t\t// live session add none and stay allowed via the branch above.\n\t\t\tthrow new RpcSessionRegistryError(\"too_many_sessions\");\n\t\t}\n\t\tif (sessionPath) this.reservations.add(sessionPath);\n\n\t\t// Resume vs create parity (D1 + omo SenpiSessionRuntime.ts:198-200):\n\t\t// Create-only launch semantics mirror classic startup flags. A resumed\n\t\t// session restores its persisted model and thinking level instead of being\n\t\t// overridden by the new open_session request.\n\t\tconst isResume = sessionPath !== undefined && existsSync(sessionPath);\n\t\tconst storedProfile = frozenProfile({ ...profile, ...(sessionPath ? { sessionPath } : {}) });\n\t\tconst runtimeProfile = isResume\n\t\t\t? frozenProfile({ ...storedProfile, creationModel: undefined, initialThinkingLevel: undefined })\n\t\t\t: storedProfile;\n\n\t\tconst handle = `rpc-${++this.nextHandle}`;\n\t\tconst entry: RpcSessionEntry = {\n\t\t\tstate: \"opening\",\n\t\t\tscope: new ProviderScope(),\n\t\t\tprofile: storedProfile,\n\t\t\tsessionPath,\n\t\t\treservationKey: sessionPath,\n\t\t\tcwd: storedProfile.cwd,\n\t\t\tattachments: 1,\n\t\t\tlastCommandAt: this.now(),\n\t\t\tlifecycleMutex: Promise.resolve(),\n\t\t};\n\t\tentry.switchSession = (sessionPath, options) => {\n\t\t\tconst operation = entry.lifecycleMutex.then(async () => {\n\t\t\t\tif (entry.state !== \"open\" || !entry.runtime) {\n\t\t\t\t\tthrow new RpcSessionRegistryError(\"unknown_session\");\n\t\t\t\t}\n\t\t\t\tconst runtime = entry.runtime;\n\t\t\t\tconst cwdOverride = options?.cwdOverride;\n\t\t\t\tconst cwdChanged = cwdOverride !== undefined && runtime.session.sessionManager.getCwd() !== cwdOverride;\n\t\t\t\tconst result = await runtime.switchSession(sessionPath, options);\n\t\t\t\tif (result.cancelled || !cwdChanged) return result;\n\n\t\t\t\t// A multi-session binding outlives an individual replacement. Keep the\n\t\t\t\t// entry's runtime object aligned with the replacement so every attached\n\t\t\t\t// client resolves getters and future commands against the new cwd-bound\n\t\t\t\t// runtime, not the object created during open_session.\n\t\t\t\tconst replacement = new AgentSessionRuntime(\n\t\t\t\t\truntime.session,\n\t\t\t\t\truntime.services,\n\t\t\t\t\tthis.options.createRuntime,\n\t\t\t\t\t[...runtime.diagnostics],\n\t\t\t\t\truntime.modelFallbackMessage,\n\t\t\t\t\truntime.launchProfile,\n\t\t\t\t);\n\t\t\t\treplacement.setRebindSession(entry.rebindSession);\n\t\t\t\tentry.runtime = replacement;\n\t\t\t\tthis.syncRuntimeMetadata();\n\t\t\t\treturn result;\n\t\t\t});\n\t\t\tentry.lifecycleMutex = operation.then(\n\t\t\t\t() => undefined,\n\t\t\t\t() => undefined,\n\t\t\t);\n\t\t\treturn operation;\n\t\t};\n\t\tthis.entries.set(handle, entry);\n\t\ttry {\n\t\t\tconst manager = sessionPath\n\t\t\t\t? SessionManager.open(sessionPath, undefined, storedProfile.cwd)\n\t\t\t\t: SessionManager.create(storedProfile.cwd);\n\t\t\tentry.runtime = await runWithProviderScope(entry.scope, () =>\n\t\t\t\tcreateAgentSessionRuntime(this.options.createRuntime, {\n\t\t\t\t\tcwd: manager.getCwd(),\n\t\t\t\t\tagentDir: this.options.agentDir,\n\t\t\t\t\tsessionManager: manager,\n\t\t\t\t\tlaunchProfile: runtimeProfile,\n\t\t\t\t}),\n\t\t\t);\n\t\t\tentry.durableSessionId = manager.getSessionId();\n\t\t\tentry.sessionPath ??= manager.getSessionFile();\n\t\t\tentry.state = \"open\";\n\t\t\treturn { sessionId: handle, durableSessionId: entry.durableSessionId, sessionPath: entry.sessionPath };\n\t\t} catch (error) {\n\t\t\t// Runtime construction may have started extensions, watchers, and provider\n\t\t\t// registrations before it rejects. Keep the reservation and entry private\n\t\t\t// until all of those resources have been torn down, then release them as\n\t\t\t// one rollback so the path can immediately be opened again.\n\t\t\ttry {\n\t\t\t\tawait entry.runtime?.dispose();\n\t\t\t} catch {\n\t\t\t\t// The original construction error remains the externally visible cause.\n\t\t\t} finally {\n\t\t\t\ttry {\n\t\t\t\t\tawait entry.scope.close?.();\n\t\t\t\t} finally {\n\t\t\t\t\tthis.entries.delete(handle);\n\t\t\t\t\tif (sessionPath) this.reservations.delete(sessionPath);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (error instanceof RpcSessionRegistryError) throw error;\n\t\t\tthrow new RpcSessionRegistryError(\"open_failed\", error instanceof Error ? error.message : undefined);\n\t\t}\n\t}\n\n\t/**\n\t * Read-only lookup with no state transitions or attachment accounting.\n\t * Exists so lifecycle decisions (e.g. deferring a dropped connection's\n\t * release while a turn is still streaming) can inspect the live entry\n\t * without claiming it.\n\t */\n\tpeek(handle: string): RpcSessionEntry | undefined {\n\t\treturn this.entries.get(handle);\n\t}\n\n\tgetForCommand(handle: string, command: string): RpcSessionEntry {\n\t\tconst entry = this.entries.get(handle);\n\t\tif (!entry) throw new RpcSessionRegistryError(\"unknown_session\");\n\t\tif (entry.state === \"closing\" && ![\"abort\", \"abort_bash\", \"extension_ui_response\"].includes(command)) {\n\t\t\tthrow new RpcSessionRegistryError(\"session_closing\");\n\t\t}\n\t\tif (entry.state !== \"open\" && entry.state !== \"closing\") throw new RpcSessionRegistryError(\"unknown_session\");\n\t\t// Every routed command counts as activity for idle eviction. Lookups that\n\t\t// must not refresh idleness (sweeps, listing) use peek()/list() instead.\n\t\tentry.lastCommandAt = this.now();\n\t\treturn entry;\n\t}\n\n\t/**\n\t * Starts a close synchronously. Call this before disposing any session-owned\n\t * binding so a concurrent command cannot reach a half-disposed handler.\n\t * Each call releases one attachment; the entry transitions to \"closing\" only\n\t * when the last attachment closes, so callers must check the returned state\n\t * and skip finalization while other attachments remain.\n\t */\n\tbeginClose(handle: string): RpcSessionEntry {\n\t\tconst entry = this.entries.get(handle);\n\t\tif (entry?.state !== \"open\") throw new RpcSessionRegistryError(\"unknown_session\");\n\t\tentry.attachments -= 1;\n\t\tif (entry.attachments > 0) return entry;\n\t\tentry.state = \"closing\";\n\t\treturn entry;\n\t}\n\n\tasync close(handle: string): Promise<void> {\n\t\tconst entry = this.beginClose(handle);\n\t\t// Other attachments may still own the live session; only the last close finalizes.\n\t\tif (entry.state !== \"closing\") return;\n\t\treturn this.closeMarked(handle);\n\t}\n\n\t/** Completes a close previously made visible by beginClose(). */\n\tasync closeMarked(handle: string): Promise<void> {\n\t\tthis.syncRuntimeMetadata();\n\t\tconst entry = this.entries.get(handle);\n\t\tif (entry?.state !== \"closing\") throw new RpcSessionRegistryError(\"unknown_session\");\n\t\tconst previousLifecycle = entry.lifecycleMutex;\n\t\tentry.lifecycleMutex = (async () => {\n\t\t\tawait previousLifecycle;\n\t\t\ttry {\n\t\t\t\tawait entry.runtime?.session.abort();\n\t\t\t\tawait entry.runtime?.session.waitForIdle();\n\t\t\t\tawait entry.runtime?.dispose();\n\t\t\t\tawait entry.scope.close?.();\n\t\t\t} finally {\n\t\t\t\tentry.state = \"closed\";\n\t\t\t\tthis.entries.delete(handle);\n\t\t\t\tif (entry.reservationKey) this.reservations.delete(entry.reservationKey);\n\t\t\t}\n\t\t})();\n\t\treturn entry.lifecycleMutex;\n\t}\n\n\tlist(): Array<{\n\t\tsessionId: string;\n\t\tdurableSessionId?: string;\n\t\tsessionPath?: string;\n\t\tcwd: string;\n\t\tname?: string;\n\t\tstatus: RpcSessionState;\n\t}> {\n\t\tthis.syncRuntimeMetadata();\n\t\treturn [...this.entries].map(([sessionId, entry]) => ({\n\t\t\tsessionId,\n\t\t\tdurableSessionId: entry.durableSessionId,\n\t\t\tsessionPath: entry.sessionPath,\n\t\t\tcwd: entry.cwd,\n\t\t\tname: entry.runtime?.session.sessionManager.getSessionName(),\n\t\t\tstatus: entry.state,\n\t\t}));\n\t}\n\n\t/** Reconcile path and durable identity after runtime replacement. */\n\tprivate syncRuntimeMetadata(): void {\n\t\tfor (const entry of this.entries.values()) {\n\t\t\tconst manager = entry.runtime?.session.sessionManager;\n\t\t\tif (!manager) continue;\n\t\t\tconst currentPath = manager.getSessionFile();\n\t\t\t// Preserve the originally canonicalized key while the runtime still points at\n\t\t\t// the same path. SessionManager may expose a symlink-resolved spelling after\n\t\t\t// opening a file that did not exist yet; treating that as replacement would\n\t\t\t// break ordinary attach-on-open aliases.\n\t\t\tif (currentPath !== entry.sessionPath) {\n\t\t\t\tconst currentKey = currentPath ? canonicalPath(currentPath) : undefined;\n\t\t\t\tif (entry.reservationKey) this.reservations.delete(entry.reservationKey);\n\t\t\t\tif (currentKey) this.reservations.add(currentKey);\n\t\t\t\tentry.reservationKey = currentKey;\n\t\t\t\tentry.sessionPath = currentPath;\n\t\t\t}\n\t\t\tentry.durableSessionId = manager.getSessionId();\n\t\t\tentry.cwd = manager.getCwd();\n\t\t}\n\t}\n\n\tprivate validateProfile(profile: RpcSessionLaunchProfile): void {\n\t\tif (!isAbsolute(profile.cwd) || (profile.sessionPath !== undefined && !isAbsolute(profile.sessionPath))) {\n\t\t\tthrow new RpcSessionRegistryError(\"invalid_path\");\n\t\t}\n\t}\n\n\tprivate countActiveSessions(): number {\n\t\tlet count = 0;\n\t\tfor (const entry of this.entries.values()) {\n\t\t\tif (entry.state === \"opening\" || entry.state === \"open\") count += 1;\n\t\t}\n\t\treturn count;\n\t}\n}\n"]}
@@ -0,0 +1,13 @@
1
+ import type { Socket } from "node:net";
2
+ export declare const SOCKET_SECRET_BYTES = 32;
3
+ export declare const SOCKET_SECRET_SUFFIX = ".secret";
4
+ export declare const SOCKET_SECRET_FILE_ENV = "SENPI_RPC_SOCKET_SECRET_FILE";
5
+ export declare const SOCKET_HANDSHAKE_TIMEOUT_MS = 2000;
6
+ export declare function socketSecretPath(logicalPath: string): string;
7
+ export declare function ensureSocketSecret(path: string): Promise<Buffer>;
8
+ export declare function createSocketSecret(path: string): Promise<Buffer>;
9
+ export declare function readSocketSecret(path: string): Promise<Buffer>;
10
+ export declare function resolveSocketTransportAddress(socketPath: string, platform: NodeJS.Platform, secret?: Uint8Array): string;
11
+ export declare function authenticateSocket(socket: Socket, secret: Uint8Array, onAuthenticated: () => void): void;
12
+ export declare function sendSocketHandshake(socket: Socket, secret: Uint8Array): void;
13
+ //# sourceMappingURL=socket-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"socket-transport.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/socket-transport.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAIvC,eAAO,MAAM,mBAAmB,KAAK,CAAC;AACtC,eAAO,MAAM,oBAAoB,YAAY,CAAC;AAC9C,eAAO,MAAM,sBAAsB,iCAAiC,CAAC;AACrE,eAAO,MAAM,2BAA2B,OAAQ,CAAC;AAEjD,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAO5D;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQtE;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMtE;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIpE;AAED,wBAAgB,6BAA6B,CAC5C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,CAAC,QAAQ,EACzB,MAAM,CAAC,EAAE,UAAU,GACjB,MAAM,CAUR;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,IAAI,GAAG,IAAI,CA8BxG;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAE5E"}
@@ -0,0 +1,92 @@
1
+ import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
2
+ import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import { dirname, win32 } from "node:path";
4
+ const WINDOWS_PIPE_PREFIX = "\\\\.\\pipe\\senpi-rpc-";
5
+ export const SOCKET_SECRET_BYTES = 32;
6
+ export const SOCKET_SECRET_SUFFIX = ".secret";
7
+ export const SOCKET_SECRET_FILE_ENV = "SENPI_RPC_SOCKET_SECRET_FILE";
8
+ export const SOCKET_HANDSHAKE_TIMEOUT_MS = 2_000;
9
+ export function socketSecretPath(logicalPath) {
10
+ if (logicalPath.toLowerCase().startsWith("\\\\.\\pipe\\")) {
11
+ throw new Error(`Windows RPC named-pipe addresses need a logical filesystem path for their secret: ${logicalPath}`);
12
+ }
13
+ return `${logicalPath}${SOCKET_SECRET_SUFFIX}`;
14
+ }
15
+ export async function ensureSocketSecret(path) {
16
+ try {
17
+ const existing = await readFile(path);
18
+ if (existing.length === SOCKET_SECRET_BYTES)
19
+ return existing;
20
+ }
21
+ catch (error) {
22
+ if (!isNodeErrorCode(error, "ENOENT"))
23
+ throw error;
24
+ }
25
+ return createSocketSecret(path);
26
+ }
27
+ export async function createSocketSecret(path) {
28
+ await mkdir(dirname(path), { recursive: true });
29
+ const secret = randomBytes(SOCKET_SECRET_BYTES);
30
+ await writeFile(path, secret, { mode: 0o600 });
31
+ await chmod(path, 0o600);
32
+ return secret;
33
+ }
34
+ export async function readSocketSecret(path) {
35
+ const secret = await readFile(path);
36
+ if (secret.length !== SOCKET_SECRET_BYTES)
37
+ throw new Error(`invalid RPC socket secret: ${path}`);
38
+ return secret;
39
+ }
40
+ export function resolveSocketTransportAddress(socketPath, platform, secret) {
41
+ if (platform !== "win32")
42
+ return socketPath;
43
+ if (socketPath.toLowerCase().startsWith("\\\\.\\pipe\\"))
44
+ return socketPath;
45
+ if (!/^[a-zA-Z]:[\\/]/.test(socketPath) && !/^\\\\[^/]/.test(socketPath)) {
46
+ throw new Error(`Windows RPC socket path must be drive-qualified or UNC: ${socketPath}`);
47
+ }
48
+ const canonical = win32.normalize(socketPath).toLowerCase();
49
+ const identity = Buffer.concat([Buffer.from(canonical, "utf8"), Buffer.from(secret ?? [])]);
50
+ const name = createHash("sha256").update(identity).digest("hex").slice(0, 32);
51
+ return `${WINDOWS_PIPE_PREFIX}${name}`;
52
+ }
53
+ export function authenticateSocket(socket, secret, onAuthenticated) {
54
+ let received = Buffer.alloc(0);
55
+ const finish = () => {
56
+ clearTimeout(timer);
57
+ socket.off("data", onData);
58
+ socket.off("error", onError);
59
+ };
60
+ const onError = () => {
61
+ finish();
62
+ socket.destroy();
63
+ };
64
+ const timer = setTimeout(() => {
65
+ finish();
66
+ socket.destroy();
67
+ }, SOCKET_HANDSHAKE_TIMEOUT_MS);
68
+ const onData = (chunk) => {
69
+ received = Buffer.concat([received, chunk]);
70
+ if (received.length < secret.length)
71
+ return;
72
+ finish();
73
+ if (!timingSafeEqual(received.subarray(0, secret.length), Buffer.from(secret))) {
74
+ socket.destroy();
75
+ return;
76
+ }
77
+ const remainder = received.subarray(secret.length);
78
+ if (remainder.length > 0)
79
+ socket.unshift(remainder);
80
+ onAuthenticated();
81
+ };
82
+ socket.on("data", onData);
83
+ socket.once("error", onError);
84
+ socket.once("close", finish);
85
+ }
86
+ export function sendSocketHandshake(socket, secret) {
87
+ socket.write(Buffer.from(secret));
88
+ }
89
+ function isNodeErrorCode(error, code) {
90
+ return error instanceof Error && "code" in error && error.code === code;
91
+ }
92
+ //# sourceMappingURL=socket-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"socket-transport.js","sourceRoot":"","sources":["../../../src/modes/rpc/socket-transport.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomBytes, timingSafeEqual } from \"node:crypto\";\nimport { chmod, mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport type { Socket } from \"node:net\";\nimport { dirname, win32 } from \"node:path\";\n\nconst WINDOWS_PIPE_PREFIX = \"\\\\\\\\.\\\\pipe\\\\senpi-rpc-\";\nexport const SOCKET_SECRET_BYTES = 32;\nexport const SOCKET_SECRET_SUFFIX = \".secret\";\nexport const SOCKET_SECRET_FILE_ENV = \"SENPI_RPC_SOCKET_SECRET_FILE\";\nexport const SOCKET_HANDSHAKE_TIMEOUT_MS = 2_000;\n\nexport function socketSecretPath(logicalPath: string): string {\n\tif (logicalPath.toLowerCase().startsWith(\"\\\\\\\\.\\\\pipe\\\\\")) {\n\t\tthrow new Error(\n\t\t\t`Windows RPC named-pipe addresses need a logical filesystem path for their secret: ${logicalPath}`,\n\t\t);\n\t}\n\treturn `${logicalPath}${SOCKET_SECRET_SUFFIX}`;\n}\n\nexport async function ensureSocketSecret(path: string): Promise<Buffer> {\n\ttry {\n\t\tconst existing = await readFile(path);\n\t\tif (existing.length === SOCKET_SECRET_BYTES) return existing;\n\t} catch (error: unknown) {\n\t\tif (!isNodeErrorCode(error, \"ENOENT\")) throw error;\n\t}\n\treturn createSocketSecret(path);\n}\n\nexport async function createSocketSecret(path: string): Promise<Buffer> {\n\tawait mkdir(dirname(path), { recursive: true });\n\tconst secret = randomBytes(SOCKET_SECRET_BYTES);\n\tawait writeFile(path, secret, { mode: 0o600 });\n\tawait chmod(path, 0o600);\n\treturn secret;\n}\n\nexport async function readSocketSecret(path: string): Promise<Buffer> {\n\tconst secret = await readFile(path);\n\tif (secret.length !== SOCKET_SECRET_BYTES) throw new Error(`invalid RPC socket secret: ${path}`);\n\treturn secret;\n}\n\nexport function resolveSocketTransportAddress(\n\tsocketPath: string,\n\tplatform: NodeJS.Platform,\n\tsecret?: Uint8Array,\n): string {\n\tif (platform !== \"win32\") return socketPath;\n\tif (socketPath.toLowerCase().startsWith(\"\\\\\\\\.\\\\pipe\\\\\")) return socketPath;\n\tif (!/^[a-zA-Z]:[\\\\/]/.test(socketPath) && !/^\\\\\\\\[^/]/.test(socketPath)) {\n\t\tthrow new Error(`Windows RPC socket path must be drive-qualified or UNC: ${socketPath}`);\n\t}\n\tconst canonical = win32.normalize(socketPath).toLowerCase();\n\tconst identity = Buffer.concat([Buffer.from(canonical, \"utf8\"), Buffer.from(secret ?? [])]);\n\tconst name = createHash(\"sha256\").update(identity).digest(\"hex\").slice(0, 32);\n\treturn `${WINDOWS_PIPE_PREFIX}${name}`;\n}\n\nexport function authenticateSocket(socket: Socket, secret: Uint8Array, onAuthenticated: () => void): void {\n\tlet received = Buffer.alloc(0);\n\tconst finish = (): void => {\n\t\tclearTimeout(timer);\n\t\tsocket.off(\"data\", onData);\n\t\tsocket.off(\"error\", onError);\n\t};\n\tconst onError = (): void => {\n\t\tfinish();\n\t\tsocket.destroy();\n\t};\n\tconst timer = setTimeout(() => {\n\t\tfinish();\n\t\tsocket.destroy();\n\t}, SOCKET_HANDSHAKE_TIMEOUT_MS);\n\tconst onData = (chunk: Buffer): void => {\n\t\treceived = Buffer.concat([received, chunk]);\n\t\tif (received.length < secret.length) return;\n\t\tfinish();\n\t\tif (!timingSafeEqual(received.subarray(0, secret.length), Buffer.from(secret))) {\n\t\t\tsocket.destroy();\n\t\t\treturn;\n\t\t}\n\t\tconst remainder = received.subarray(secret.length);\n\t\tif (remainder.length > 0) socket.unshift(remainder);\n\t\tonAuthenticated();\n\t};\n\tsocket.on(\"data\", onData);\n\tsocket.once(\"error\", onError);\n\tsocket.once(\"close\", finish);\n}\n\nexport function sendSocketHandshake(socket: Socket, secret: Uint8Array): void {\n\tsocket.write(Buffer.from(secret));\n}\n\nfunction isNodeErrorCode(error: unknown, code: string): boolean {\n\treturn error instanceof Error && \"code\" in error && error.code === code;\n}\n"]}
@@ -0,0 +1,17 @@
1
+ import type { Component, TUI } from "@earendil-works/pi-tui";
2
+ import { type Theme } from "../interactive/theme/theme.ts";
3
+ export interface LiveComponentRenderer {
4
+ rerender(): void;
5
+ dispose(): void;
6
+ }
7
+ export declare function createLiveComponentRenderer(options: {
8
+ factory: (...args: [TUI, Theme, ...unknown[]]) => Component & {
9
+ dispose?(): void;
10
+ };
11
+ /** Additional arguments are used by footer factories; widgets retain the 2-arg path. */
12
+ factoryArgs?: readonly unknown[];
13
+ getWidth: () => number;
14
+ emit: (lines: string[]) => void;
15
+ onRenderFault?: (error: unknown) => void;
16
+ }): LiveComponentRenderer | undefined;
17
+ //# sourceMappingURL=widget-line-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget-line-renderer.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/widget-line-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAa,KAAK,KAAK,EAAS,MAAM,+BAA+B,CAAC;AAE7E,MAAM,WAAW,qBAAqB;IACrC,QAAQ,IAAI,IAAI,CAAC;IACjB,OAAO,IAAI,IAAI,CAAC;CAChB;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE;IACpD,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC,KAAK,SAAS,GAAG;QAAE,OAAO,CAAC,IAAI,IAAI,CAAA;KAAE,CAAC;IACnF,wFAAwF;IACxF,WAAW,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IACjC,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAChC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACzC,GAAG,qBAAqB,GAAG,SAAS,CA+DpC"}