@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
@@ -40,15 +40,17 @@
40
40
  import { spawn } from "node:child_process";
41
41
  import { randomUUID } from "node:crypto";
42
42
  import { realpathSync, writeSync } from "node:fs";
43
- import { access, chmod, mkdir, readFile, rm, unlink } from "node:fs/promises";
43
+ import { access, chmod, mkdir, readFile, rm, unlink, writeFile } from "node:fs/promises";
44
44
  import { createConnection, createServer } from "node:net";
45
45
  import { tmpdir } from "node:os";
46
- import { dirname, join, resolve } from "node:path";
46
+ import { dirname, extname, join, resolve } from "node:path";
47
47
  import { fileURLToPath } from "node:url";
48
- import { getAgentDir } from "../../config.js";
48
+ import { getAgentDir, isBunBinary } from "../../config.js";
49
+ import { readProcessStartTime } from "../app-server/daemon/process.js";
49
50
  import { createHostDaemonPaths } from "./host-ensure.js";
50
51
  import { HOST_CLEANUP_PATHS_ENV, HOST_SCRATCH_DIR_ENV, HOST_WATCH_FD_ENV, HOST_WATCH_PPID_ENV, } from "./host-watchdog.js";
51
52
  import { attachJsonlLineReader, MAX_RPC_LINE_CHARACTERS } from "./jsonl.js";
53
+ import { authenticateSocket, createSocketSecret, readSocketSecret, resolveSocketTransportAddress, SOCKET_SECRET_FILE_ENV, sendSocketHandshake, socketSecretPath, } from "./socket-transport.js";
52
54
  /** Environment override for the cold-start policy: `transient` or `persistent`. */
53
55
  export const HOST_COLD_START_ENV = "SENPI_RPC_HOST_COLD_START";
54
56
  /** Environment override for the idle-exit window in milliseconds. */
@@ -56,6 +58,8 @@ export const HOST_IDLE_EXIT_MS_ENV = "SENPI_RPC_HOST_IDLE_EXIT_MS";
56
58
  /** Default idle-exit window: 15 minutes of continuous no-connection, no-turn idle. */
57
59
  export const DEFAULT_HOST_IDLE_EXIT_MS = 15 * 60_000;
58
60
  const CHILD_STOP_TIMEOUT_MS = 5_000;
61
+ /** Win32 named-pipe shutdown can leave supervisor handles live after close starts. */
62
+ const WINDOWS_SUPERVISOR_SHUTDOWN_HARD_EXIT_MS = 2_000;
59
63
  /**
60
64
  * Child stdio slot carrying the supervisor-lifetime pipe. The supervisor holds
61
65
  * the write end open and never writes; the kernel closes it when the supervisor
@@ -68,10 +72,24 @@ const CHILD_WATCH_FD = 3;
68
72
  * regardless of where the public socket lives, and private against other local
69
73
  * users, so it gets its own 0700 directory under the OS temp directory.
70
74
  */
71
- async function createInternalSocketPath() {
75
+ async function createInternalSocketPath(baseDir = tmpdir()) {
76
+ if (process.platform === "win32") {
77
+ const dir = join(baseDir, `internal-${randomUUID()}`);
78
+ await mkdir(dir, { recursive: false, mode: 0o700 });
79
+ return {
80
+ socket: `\\\\.\\pipe\\senpi-rpc-internal-${randomUUID()}`,
81
+ dir,
82
+ secretPath: join(dir, "secret"),
83
+ };
84
+ }
72
85
  const dir = join(tmpdir(), `senpi-rpc-host-internal-${randomUUID().slice(0, 8)}`);
73
86
  await mkdir(dir, { recursive: false, mode: 0o700 });
74
- return { socket: join(dir, "host.sock"), dir };
87
+ await writeFile(join(dir, ".owner"), JSON.stringify({
88
+ pid: process.pid,
89
+ processStartTime: await readProcessStartTime(process.pid),
90
+ createdAt: Date.now(),
91
+ }), { mode: 0o600 });
92
+ return { socket: join(dir, "host.sock"), dir, secretPath: join(dir, ".secret") };
75
93
  }
76
94
  export function parseColdStart(value) {
77
95
  return value === "transient" || value === "persistent" ? value : undefined;
@@ -95,6 +113,17 @@ export function resolveHostPolicy(settings, env) {
95
113
  DEFAULT_HOST_IDLE_EXIT_MS;
96
114
  return { coldStart, idleExitMs };
97
115
  }
116
+ /**
117
+ * How the supervisor reads its child's exit. The RPC host exits 0 only through
118
+ * its own clean shutdown path - including its idle/empty-host policy - so that
119
+ * is an intentional stop, not a crash: the supervisor mirrors its own idle exit
120
+ * instead of reporting failure. Any non-zero code or signal stays a crash.
121
+ */
122
+ export function classifyChildExit(code, signal) {
123
+ if (code === 0 && signal === null)
124
+ return { reason: "rpc host exited on its own idle policy", exitCode: 0 };
125
+ return { reason: `rpc host process exited unexpectedly (${code ?? signal})`, exitCode: 1 };
126
+ }
98
127
  /**
99
128
  * Pure idle-window decision core. `update()` must be called with the CURRENT
100
129
  * activity state; the window only counts continuously idle time and any
@@ -121,6 +150,40 @@ export class IdleExitDecider {
121
150
  return this.now() - this.idleSince >= this.idleExitMs ? "exit" : "idle";
122
151
  }
123
152
  }
153
+ /** Hidden internal launch route: wire-invisible, never advertised by the public CLI surface. */
154
+ export const INTERNAL_SUPERVISOR_FLAG = "--internal-rpc-host-supervisor";
155
+ /**
156
+ * Engine-global flags a rebranded wrapper may legitimately prepend when it
157
+ * re-dispatches this binary. `packages/omo-native` injects `--extension <dir>`
158
+ * for every non-early command, which pushed the sentinel off argv[0].
159
+ */
160
+ const INJECTABLE_PREFIX_FLAGS = new Set(["--extension"]);
161
+ /**
162
+ * Returns the internal supervisor payload when argv selects that route.
163
+ *
164
+ * The route dispatches when the sentinel is argv[0] OR is preceded only by
165
+ * known injectable prefix flags and their values - the one perturbation
166
+ * wrappers legitimately perform. Everything else disqualifies it: a positional
167
+ * operand, `--`, or an unknown flag before the sentinel all return undefined,
168
+ * so a user-supplied value that happens to equal the sentinel can never reach
169
+ * the supervisor.
170
+ *
171
+ * The skipped prefix is deliberately NOT forwarded to the host: a wrapper
172
+ * re-injects its own prefix on every re-entry, so the host child receives it
173
+ * from the wrapper rather than twice from here.
174
+ */
175
+ export function findInternalSupervisorArgs(argv) {
176
+ for (let index = 0; index < argv.length; index++) {
177
+ const arg = argv[index];
178
+ if (arg === INTERNAL_SUPERVISOR_FLAG)
179
+ return argv.slice(index + 1);
180
+ // A prefix flag only counts when its value is actually present.
181
+ if (!INJECTABLE_PREFIX_FLAGS.has(arg) || index + 1 >= argv.length)
182
+ return undefined;
183
+ index++;
184
+ }
185
+ return undefined;
186
+ }
124
187
  /** `--socket <path>` selects the public socket; every other argument is forwarded to the host CLI. */
125
188
  export function parseSupervisorArgs(argv) {
126
189
  const hostArgs = [];
@@ -163,67 +226,136 @@ export function resolveCliMainPath() {
163
226
  const extension = modulePath.endsWith(".ts") ? ".ts" : ".js";
164
227
  return resolve(dirname(modulePath), "..", "..", `cli-main${extension}`);
165
228
  }
229
+ /**
230
+ * Resolves the host child spawn. Explicit child commands (desktop launchers)
231
+ * are forwarded untouched. The default re-enters the committed CLI entry
232
+ * through the runtime, except in compiled standalone binaries, which always
233
+ * boot their embedded entrypoint and would parse a script path as CLI
234
+ * arguments - there the executable itself is the CLI, so the mode flags are
235
+ * passed directly. Exported for tests.
236
+ */
237
+ export function resolveHostChildLaunch(launch, internalSocket, compiled = isBunBinary) {
238
+ if (launch.childCommand) {
239
+ return {
240
+ command: launch.childCommand,
241
+ args: [...(launch.childArgs ?? []), "--listen", `unix://${internalSocket}`],
242
+ };
243
+ }
244
+ return {
245
+ command: process.execPath,
246
+ args: [
247
+ ...(compiled ? [] : [...process.execArgv, resolveCliMainPath()]),
248
+ "--mode",
249
+ "rpc",
250
+ "--multi-session",
251
+ "--listen",
252
+ `unix://${internalSocket}`,
253
+ ...launch.hostArgs,
254
+ ],
255
+ };
256
+ }
257
+ /** Mirrors cross-spawn: survives cmd.exe parsing and `CommandLineToArgvW`. */
258
+ function quoteWindowsShellArg(value) {
259
+ const escaped = value
260
+ .replace(/(\\*)"/g, '$1$1\\"')
261
+ .replace(/(\\*)$/, "$1$1")
262
+ .replace(/([()%!^"<>&|;,])/g, "^$1");
263
+ return `"${escaped}"`;
264
+ }
265
+ /**
266
+ * Windows refuses to spawn a `.cmd`/`.bat` without a shell, and Node's
267
+ * `shell: true` concatenates argv without escaping it. Escape each original
268
+ * value before adding the surrounding quotes so `.cmd`/`.bat` launchers survive
269
+ * cmd.exe parsing without double-escaping.
270
+ * Exported for tests.
271
+ */
272
+ export function spawnableChildLaunch(launch, platform = process.platform) {
273
+ const extension = extname(launch.command).toLowerCase();
274
+ if (platform !== "win32" || (extension !== ".cmd" && extension !== ".bat")) {
275
+ return { ...launch, shell: false };
276
+ }
277
+ return {
278
+ command: quoteWindowsShellArg(launch.command),
279
+ args: launch.args.map(quoteWindowsShellArg),
280
+ shell: true,
281
+ };
282
+ }
166
283
  export async function runHostSupervisor(launch) {
167
284
  const paths = createHostDaemonPaths(launch.agentDir ?? getAgentDir());
168
285
  const policy = resolveHostPolicy(await readSettingsFile(paths.settingsFile), process.env);
169
286
  const publicSocket = launch.socket;
170
- const internal = await createInternalSocketPath();
287
+ const internal = await createInternalSocketPath(paths.dir);
171
288
  const internalSocket = internal.socket;
289
+ const internalSecretPath = internal.secretPath ?? socketSecretPath(internalSocket);
290
+ const internalSecret = process.platform === "win32" ? await createSocketSecret(internalSecretPath) : undefined;
291
+ const publicSecret = process.platform === "win32" ? await readSocketSecret(socketSecretPath(publicSocket)) : undefined;
172
292
  const clientSockets = new Set();
173
293
  const busySessions = new Map();
174
294
  let observerHealthy = false;
175
295
  let observerReconnectTimer;
296
+ let childExitWatchTimer;
176
297
  let shuttingDown = false;
177
298
  let shutdownPromise;
178
- const child = spawn(launch.childCommand ?? process.execPath, launch.childCommand
179
- ? [...(launch.childArgs ?? []), "--listen", `unix://${internalSocket}`]
180
- : [
181
- ...process.execArgv,
182
- resolveCliMainPath(),
183
- "--mode",
184
- "rpc",
185
- "--multi-session",
186
- "--listen",
187
- `unix://${internalSocket}`,
188
- ...launch.hostArgs,
189
- ], {
299
+ const childLaunch = spawnableChildLaunch(resolveHostChildLaunch(launch, internalSocket));
300
+ const child = spawn(childLaunch.command, childLaunch.args, {
190
301
  env: {
191
302
  ...process.env,
192
303
  ...(launch.agentDir ? { SENPI_CODING_AGENT_DIR: launch.agentDir } : {}),
193
304
  [HOST_WATCH_FD_ENV]: String(CHILD_WATCH_FD),
194
305
  [HOST_WATCH_PPID_ENV]: String(process.pid),
195
- [HOST_SCRATCH_DIR_ENV]: internal.dir,
196
- [HOST_CLEANUP_PATHS_ENV]: [publicSocket, paths.pidFile, paths.settingsFile].join("\n"),
306
+ ...(internal.dir ? { [HOST_SCRATCH_DIR_ENV]: internal.dir } : {}),
307
+ ...(internalSecret ? { [SOCKET_SECRET_FILE_ENV]: internalSecretPath } : {}),
308
+ [HOST_CLEANUP_PATHS_ENV]: [
309
+ paths.pidFile,
310
+ paths.settingsFile,
311
+ ...(process.platform === "win32" ? [] : [publicSocket]),
312
+ ].join("\n"),
197
313
  },
198
314
  // Slot 3 is the lifetime pipe: "pipe" gives the child a read end it can
199
315
  // wait on and keeps the write end owned by this process alone.
316
+ shell: childLaunch.shell,
200
317
  stdio: ["ignore", "ignore", "inherit", "pipe"],
318
+ // The supervisor is spawned detached, so on win32 it owns no console. A
319
+ // console-subsystem child started from it would allocate a fresh one,
320
+ // which Windows Terminal renders as an empty window that takes focus.
321
+ // CREATE_NO_WINDOW gives the child a console with no window instead.
322
+ windowsHide: true,
201
323
  });
202
324
  // Nothing is ever written; the pipe exists purely so its EOF is a reliable
203
325
  // death notification. Errors on it must not crash the supervisor.
204
326
  child.stdio[CHILD_WATCH_FD]?.on("error", () => { });
205
327
  child.once("exit", (code, signal) => {
206
- if (!shuttingDown)
207
- void shutdown(`rpc host process exited unexpectedly (${code ?? signal})`, 1);
328
+ if (shuttingDown)
329
+ return;
330
+ const { reason, exitCode } = classifyChildExit(code, signal);
331
+ void shutdown(reason, exitCode);
208
332
  });
209
333
  const server = createServer((client) => {
210
- if (shuttingDown) {
211
- client.destroy();
212
- return;
213
- }
214
- const internal = createConnection(internalSocket);
215
- clientSockets.add(client);
216
- const detach = () => {
217
- clientSockets.delete(client);
218
- internal.destroy();
219
- client.destroy();
334
+ const accept = () => {
335
+ if (shuttingDown) {
336
+ client.destroy();
337
+ return;
338
+ }
339
+ const internal = createConnection(resolveSocketTransportAddress(internalSocket, process.platform, internalSecret));
340
+ if (internalSecret)
341
+ sendSocketHandshake(internal, internalSecret);
342
+ clientSockets.add(client);
343
+ const detach = () => {
344
+ clientSockets.delete(client);
345
+ internal.destroy();
346
+ client.destroy();
347
+ };
348
+ client.pipe(internal);
349
+ internal.pipe(client);
350
+ client.once("close", detach);
351
+ client.once("error", detach);
352
+ internal.once("close", detach);
353
+ internal.once("error", detach);
220
354
  };
221
- client.pipe(internal);
222
- internal.pipe(client);
223
- client.once("close", detach);
224
- client.once("error", detach);
225
- internal.once("close", detach);
226
- internal.once("error", detach);
355
+ if (publicSecret)
356
+ authenticateSocket(client, publicSecret, accept);
357
+ else
358
+ accept();
227
359
  });
228
360
  server.once("error", (cause) => {
229
361
  if (!shuttingDown)
@@ -278,25 +410,40 @@ export async function runHostSupervisor(launch) {
278
410
  process.exit(exitCode);
279
411
  shuttingDown = true;
280
412
  clearInterval(ticker);
281
- writeStderrLine(`senpi rpc host supervisor: ${reason} shutdown`);
282
- for (const client of clientSockets)
283
- client.destroy();
284
- await closeServer(server);
285
- // Unlink the private directory BEFORE the child stop, which can take seconds:
286
- // an external SIGKILL landing during that wait (ensureHost escalates while
287
- // replacing a host) would otherwise leave the directory behind. The child
288
- // keeps serving through its already-open socket fd until it exits, and its
289
- // own watchdog cleanup makes the removal idempotent.
290
- await rm(internal.dir, { recursive: true, force: true });
291
- await stopChild(child);
292
- observer?.destroy();
293
- if (publicSocketOwned)
294
- await rm(publicSocket, { force: true });
295
- // Mirror ensureHost's cleanupState: the pidfile and settings describe a
296
- // live host only; the stderr log stays for diagnostics.
297
- await rm(paths.pidFile, { force: true });
298
- await rm(paths.settingsFile, { force: true });
299
- process.exit(exitCode);
413
+ if (childExitWatchTimer)
414
+ clearInterval(childExitWatchTimer);
415
+ const hardExit = process.platform === "win32"
416
+ ? setTimeout(() => process.exit(exitCode), WINDOWS_SUPERVISOR_SHUTDOWN_HARD_EXIT_MS)
417
+ : undefined;
418
+ try {
419
+ writeStderrLine(`senpi rpc host supervisor: ${reason} shutdown`);
420
+ for (const client of clientSockets)
421
+ client.destroy();
422
+ await closeServer(server);
423
+ // Unlink the private directory BEFORE the child stop, which can take seconds:
424
+ // an external SIGKILL landing during that wait (ensureHost escalates while
425
+ // replacing a host) would otherwise leave the directory behind. The child
426
+ // keeps serving through its already-open socket fd until it exits, and its
427
+ // own watchdog cleanup makes the removal idempotent.
428
+ if (internal.dir)
429
+ await rm(internal.dir, { recursive: true, force: true });
430
+ await stopChild(child);
431
+ observer?.destroy();
432
+ if (publicSocketOwned && process.platform !== "win32")
433
+ await rm(publicSocket, { force: true });
434
+ // Mirror ensureHost's cleanupState: the pidfile and settings describe a
435
+ // live host only; the stderr log stays for diagnostics.
436
+ await rm(paths.pidFile, { force: true });
437
+ await rm(paths.settingsFile, { force: true });
438
+ }
439
+ finally {
440
+ if (hardExit)
441
+ clearTimeout(hardExit);
442
+ // Explicitly terminate after every supervisor shutdown trigger. Windows
443
+ // named-pipe handles can outlive their JavaScript wrappers, so cleanup
444
+ // failure must never leave the supervisor resident or the host orphaned.
445
+ process.exit(exitCode);
446
+ }
300
447
  }
301
448
  let observer;
302
449
  let publicSocketOwned = false;
@@ -306,17 +453,20 @@ export async function runHostSupervisor(launch) {
306
453
  // would leave that directory behind.
307
454
  registerSupervisorSignals(shutdown);
308
455
  try {
309
- await waitForListener(internalSocket, 30_000);
456
+ await waitForListener(internalSocket, 30_000, internalSecret);
310
457
  await connectObserver();
311
458
  await prepareSocketPath(publicSocket);
312
- await listen(server, publicSocket);
459
+ await listen(server, publicSocket, publicSecret);
313
460
  publicSocketOwned = true;
314
461
  }
315
462
  catch (cause) {
316
463
  await shutdown(`startup failed: ${errorMessage(cause)}`, 1);
317
464
  }
318
465
  async function connectObserver() {
319
- const next = createConnection(internalSocket);
466
+ const secret = internalSecret;
467
+ const next = createConnection(resolveSocketTransportAddress(internalSocket, process.platform, secret));
468
+ if (secret)
469
+ sendSocketHandshake(next, secret);
320
470
  await waitForConnect(next, 5_000);
321
471
  observer = next;
322
472
  observerHealthy = true;
@@ -337,6 +487,33 @@ export async function runHostSupervisor(launch) {
337
487
  next.once("close", lost);
338
488
  next.once("error", lost);
339
489
  }
490
+ if (process.platform === "win32" && child.pid !== undefined) {
491
+ const childStartTime = await readProcessStartTime(child.pid, process.platform, 1_000);
492
+ let missingIdentityChecks = 0;
493
+ let checkingChildIdentity = false;
494
+ const checkChildIdentity = () => {
495
+ if (shuttingDown || checkingChildIdentity || child.exitCode !== null || child.signalCode !== null)
496
+ return;
497
+ checkingChildIdentity = true;
498
+ void readProcessStartTime(child.pid, process.platform, 1_000)
499
+ .then((currentStartTime) => {
500
+ if (currentStartTime === undefined)
501
+ missingIdentityChecks++;
502
+ else
503
+ missingIdentityChecks = 0;
504
+ const identityChanged = childStartTime !== undefined && currentStartTime !== undefined && currentStartTime !== childStartTime;
505
+ if (identityChanged || missingIdentityChecks >= 2) {
506
+ void shutdown("rpc host child exit observed by identity watchdog", 0);
507
+ }
508
+ })
509
+ .catch(() => { })
510
+ .finally(() => {
511
+ checkingChildIdentity = false;
512
+ });
513
+ };
514
+ childExitWatchTimer = setInterval(checkChildIdentity, 500);
515
+ childExitWatchTimer.unref?.();
516
+ }
340
517
  writeStderrLine(`senpi rpc host ready on unix://${publicSocket} (coldStart=${policy.coldStart}, idleExitMs=${policy.coldStart === "persistent" ? "never" : String(policy.idleExitMs)})`);
341
518
  await new Promise(() => { });
342
519
  }
@@ -390,18 +567,20 @@ function waitForChildExit(child, timeoutMs) {
390
567
  child.once("exit", onExit);
391
568
  });
392
569
  }
393
- async function waitForListener(socketPath, timeoutMs) {
570
+ async function waitForListener(socketPath, timeoutMs, secret) {
394
571
  const deadline = Date.now() + timeoutMs;
395
572
  while (Date.now() <= deadline) {
396
- if (await canConnect(socketPath))
573
+ if (await canConnect(socketPath, secret))
397
574
  return;
398
575
  await delay(50);
399
576
  }
400
577
  throw new Error(`${socketPath}: host did not start listening within ${timeoutMs}ms`);
401
578
  }
402
- function canConnect(socketPath) {
579
+ function canConnect(socketPath, secret) {
403
580
  return new Promise((resolve) => {
404
- const socket = createConnection(socketPath);
581
+ const socket = createConnection(resolveSocketTransportAddress(socketPath, process.platform, secret));
582
+ if (secret)
583
+ sendSocketHandshake(socket, secret);
405
584
  const settle = (value) => {
406
585
  socket.destroy();
407
586
  resolve(value);
@@ -434,6 +613,8 @@ function waitForConnect(socket, timeoutMs) {
434
613
  });
435
614
  }
436
615
  async function prepareSocketPath(socketPath) {
616
+ if (process.platform === "win32")
617
+ return;
437
618
  await mkdir(dirname(socketPath), { recursive: true, mode: 0o700 });
438
619
  try {
439
620
  await access(socketPath);
@@ -447,14 +628,23 @@ async function prepareSocketPath(socketPath) {
447
628
  throw new Error(`${socketPath}: address already in use by a live server.`);
448
629
  await unlink(socketPath);
449
630
  }
450
- function listen(server, socketPath) {
631
+ function listen(server, socketPath, secret) {
451
632
  return new Promise((resolve, reject) => {
452
633
  server.once("error", reject);
453
- server.listen(socketPath, async () => {
634
+ server.listen({
635
+ path: resolveSocketTransportAddress(socketPath, process.platform, secret),
636
+ readableAll: false,
637
+ writableAll: false,
638
+ }, async () => {
454
639
  server.off("error", reject);
455
- if (!socketPath.startsWith("\0"))
456
- await chmod(socketPath, 0o600);
457
- resolve();
640
+ try {
641
+ if (process.platform !== "win32" && !socketPath.startsWith("\0"))
642
+ await chmod(socketPath, 0o600);
643
+ resolve();
644
+ }
645
+ catch (cause) {
646
+ reject(cause);
647
+ }
458
648
  });
459
649
  });
460
650
  }