@pentoshi/clai 4.8.4 → 4.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (318) hide show
  1. package/README.md +91 -4
  2. package/dist/agent/compaction-executor.d.ts +3 -5
  3. package/dist/agent/compaction-executor.js +165 -28
  4. package/dist/agent/compaction-executor.js.map +1 -1
  5. package/dist/agent/finalize-gate.js +0 -9
  6. package/dist/agent/finalize-gate.js.map +1 -1
  7. package/dist/agent/plan-mode-reminders.js +5 -5
  8. package/dist/agent/plan-mode-reminders.js.map +1 -1
  9. package/dist/agent/plan-tool.d.ts +1 -0
  10. package/dist/agent/plan-tool.js +50 -21
  11. package/dist/agent/plan-tool.js.map +1 -1
  12. package/dist/agent/reliability-policy.d.ts +9 -0
  13. package/dist/agent/reliability-policy.js +36 -1
  14. package/dist/agent/reliability-policy.js.map +1 -1
  15. package/dist/agent/runner.d.ts +4 -0
  16. package/dist/agent/runner.js +193 -116
  17. package/dist/agent/runner.js.map +1 -1
  18. package/dist/agent/task-analyzer.d.ts +8 -18
  19. package/dist/agent/task-analyzer.js +75 -182
  20. package/dist/agent/task-analyzer.js.map +1 -1
  21. package/dist/agent/task-evidence.js +10 -0
  22. package/dist/agent/task-evidence.js.map +1 -1
  23. package/dist/agent/tool-call-parser.js +14 -13
  24. package/dist/agent/tool-call-parser.js.map +1 -1
  25. package/dist/app/adapters/current-agent-adapter.d.ts +5 -1
  26. package/dist/app/adapters/current-agent-adapter.js +2 -1
  27. package/dist/app/adapters/current-agent-adapter.js.map +1 -1
  28. package/dist/app/commands/catalog.js +10 -0
  29. package/dist/app/commands/catalog.js.map +1 -1
  30. package/dist/app/commands/registry.js +1 -0
  31. package/dist/app/commands/registry.js.map +1 -1
  32. package/dist/app/controllers/session-compact-helper.js +3 -6
  33. package/dist/app/controllers/session-compact-helper.js.map +1 -1
  34. package/dist/app/ports/transcript-item.d.ts +4 -0
  35. package/dist/classic/app/ClassicApp.js +1 -1
  36. package/dist/classic/app/ClassicApp.js.map +1 -1
  37. package/dist/classic/app/action-handlers.js +4 -0
  38. package/dist/classic/app/action-handlers.js.map +1 -1
  39. package/dist/classic/app/app-wiring.js +1 -0
  40. package/dist/classic/app/app-wiring.js.map +1 -1
  41. package/dist/classic/app/wiring-lifecycle.js +1 -0
  42. package/dist/classic/app/wiring-lifecycle.js.map +1 -1
  43. package/dist/classic/blocks/compacted-lines.js +3 -0
  44. package/dist/classic/blocks/compacted-lines.js.map +1 -1
  45. package/dist/classic/blocks/thinking-lines.js +11 -2
  46. package/dist/classic/blocks/thinking-lines.js.map +1 -1
  47. package/dist/classic/bootstrap/start-classic.d.ts +1 -0
  48. package/dist/classic/bootstrap/start-classic.js +16 -0
  49. package/dist/classic/bootstrap/start-classic.js.map +1 -1
  50. package/dist/classic/chrome/Composer.d.ts +6 -0
  51. package/dist/classic/chrome/Composer.js +2 -3
  52. package/dist/classic/chrome/Composer.js.map +1 -1
  53. package/dist/classic/chrome/composer-controller.d.ts +6 -1
  54. package/dist/classic/chrome/composer-controller.js +18 -8
  55. package/dist/classic/chrome/composer-controller.js.map +1 -1
  56. package/dist/classic/chrome/editor-view.d.ts +2 -1
  57. package/dist/classic/chrome/editor-view.js +1 -1
  58. package/dist/classic/chrome/editor-view.js.map +1 -1
  59. package/dist/classic/chrome/status-rows.js +3 -2
  60. package/dist/classic/chrome/status-rows.js.map +1 -1
  61. package/dist/classic/panels/TextEditorPanel.d.ts +3 -0
  62. package/dist/classic/panels/TextEditorPanel.js +7 -0
  63. package/dist/classic/panels/TextEditorPanel.js.map +1 -0
  64. package/dist/classic/panels/panel-controller.js +28 -1
  65. package/dist/classic/panels/panel-controller.js.map +1 -1
  66. package/dist/classic/panels/panel-effect.d.ts +3 -0
  67. package/dist/classic/panels/panel-effect.js.map +1 -1
  68. package/dist/classic/panels/panel-effects.js +3 -0
  69. package/dist/classic/panels/panel-effects.js.map +1 -1
  70. package/dist/classic/panels/panel-host.js +3 -0
  71. package/dist/classic/panels/panel-host.js.map +1 -1
  72. package/dist/classic/panels/panel-types.d.ts +2 -0
  73. package/dist/classic/panels/secret-panel.d.ts +1 -1
  74. package/dist/classic/panels/secret-panel.js +4 -2
  75. package/dist/classic/panels/secret-panel.js.map +1 -1
  76. package/dist/classic/panels/text-editor-panel.d.ts +33 -0
  77. package/dist/classic/panels/text-editor-panel.js +101 -0
  78. package/dist/classic/panels/text-editor-panel.js.map +1 -0
  79. package/dist/index.js +60 -7
  80. package/dist/index.js.map +1 -1
  81. package/dist/interactive-session/transport-node-pty.d.ts +10 -1
  82. package/dist/interactive-session/transport-node-pty.js +36 -12
  83. package/dist/interactive-session/transport-node-pty.js.map +1 -1
  84. package/dist/llm/adapters/anthropic-tools.d.ts +2 -1
  85. package/dist/llm/adapters/anthropic-tools.js +55 -4
  86. package/dist/llm/adapters/anthropic-tools.js.map +1 -1
  87. package/dist/llm/anthropic.js +1 -1
  88. package/dist/llm/anthropic.js.map +1 -1
  89. package/dist/llm/aws-mantle.js +2 -0
  90. package/dist/llm/aws-mantle.js.map +1 -1
  91. package/dist/llm/meta.js +62 -68
  92. package/dist/llm/meta.js.map +1 -1
  93. package/dist/llm/operation-ledger.js +6 -2
  94. package/dist/llm/operation-ledger.js.map +1 -1
  95. package/dist/llm/provider.js +7 -7
  96. package/dist/llm/request-plan.js +7 -2
  97. package/dist/llm/request-plan.js.map +1 -1
  98. package/dist/llm/tool-protocol.d.ts +1 -0
  99. package/dist/llm/tool-protocol.js +7 -0
  100. package/dist/llm/tool-protocol.js.map +1 -1
  101. package/dist/mcp/client.d.ts +27 -0
  102. package/dist/mcp/client.js +119 -0
  103. package/dist/mcp/client.js.map +1 -0
  104. package/dist/mcp/config-file.d.ts +35 -0
  105. package/dist/mcp/config-file.js +217 -0
  106. package/dist/mcp/config-file.js.map +1 -0
  107. package/dist/mcp/discovery.d.ts +4 -0
  108. package/dist/mcp/discovery.js +409 -0
  109. package/dist/mcp/discovery.js.map +1 -0
  110. package/dist/mcp/format.d.ts +17 -0
  111. package/dist/mcp/format.js +122 -0
  112. package/dist/mcp/format.js.map +1 -0
  113. package/dist/mcp/index.d.ts +15 -0
  114. package/dist/mcp/index.js +16 -0
  115. package/dist/mcp/index.js.map +1 -0
  116. package/dist/mcp/jsonrpc.d.ts +40 -0
  117. package/dist/mcp/jsonrpc.js +175 -0
  118. package/dist/mcp/jsonrpc.js.map +1 -0
  119. package/dist/mcp/manager.d.ts +36 -0
  120. package/dist/mcp/manager.js +300 -0
  121. package/dist/mcp/manager.js.map +1 -0
  122. package/dist/mcp/mentions.d.ts +9 -0
  123. package/dist/mcp/mentions.js +44 -0
  124. package/dist/mcp/mentions.js.map +1 -0
  125. package/dist/mcp/names.d.ts +15 -0
  126. package/dist/mcp/names.js +59 -0
  127. package/dist/mcp/names.js.map +1 -0
  128. package/dist/mcp/results.d.ts +6 -0
  129. package/dist/mcp/results.js +182 -0
  130. package/dist/mcp/results.js.map +1 -0
  131. package/dist/mcp/runtime.d.ts +107 -0
  132. package/dist/mcp/runtime.js +505 -0
  133. package/dist/mcp/runtime.js.map +1 -0
  134. package/dist/mcp/substitution.d.ts +13 -0
  135. package/dist/mcp/substitution.js +74 -0
  136. package/dist/mcp/substitution.js.map +1 -0
  137. package/dist/mcp/transport-http.d.ts +53 -0
  138. package/dist/mcp/transport-http.js +433 -0
  139. package/dist/mcp/transport-http.js.map +1 -0
  140. package/dist/mcp/transport-stdio.d.ts +39 -0
  141. package/dist/mcp/transport-stdio.js +268 -0
  142. package/dist/mcp/transport-stdio.js.map +1 -0
  143. package/dist/mcp/transport.d.ts +20 -0
  144. package/dist/mcp/transport.js +44 -0
  145. package/dist/mcp/transport.js.map +1 -0
  146. package/dist/mcp/types.d.ts +179 -0
  147. package/dist/mcp/types.js +30 -0
  148. package/dist/mcp/types.js.map +1 -0
  149. package/dist/mcp/validation.d.ts +16 -0
  150. package/dist/mcp/validation.js +222 -0
  151. package/dist/mcp/validation.js.map +1 -0
  152. package/dist/modes/agent.d.ts +2 -0
  153. package/dist/modes/agent.js.map +1 -1
  154. package/dist/noninteractive/start-noninteractive.js +4 -0
  155. package/dist/noninteractive/start-noninteractive.js.map +1 -1
  156. package/dist/prompts/embedded.js +2 -2
  157. package/dist/prompts/embedded.js.map +1 -1
  158. package/dist/prompts/index.d.ts +3 -0
  159. package/dist/prompts/index.js +70 -55
  160. package/dist/prompts/index.js.map +1 -1
  161. package/dist/prompts/system.agent.md +34 -10
  162. package/dist/prompts/system.ask.md +8 -0
  163. package/dist/safety/classifier.js +4 -0
  164. package/dist/safety/classifier.js.map +1 -1
  165. package/dist/session-runtime/binding.d.ts +5 -0
  166. package/dist/session-runtime/binding.js +28 -0
  167. package/dist/session-runtime/binding.js.map +1 -0
  168. package/dist/session-runtime/child-bridge.d.ts +31 -0
  169. package/dist/session-runtime/child-bridge.js +169 -0
  170. package/dist/session-runtime/child-bridge.js.map +1 -0
  171. package/dist/session-runtime/client.d.ts +8 -0
  172. package/dist/session-runtime/client.js +448 -0
  173. package/dist/session-runtime/client.js.map +1 -0
  174. package/dist/session-runtime/discovery.d.ts +6 -0
  175. package/dist/session-runtime/discovery.js +100 -0
  176. package/dist/session-runtime/discovery.js.map +1 -0
  177. package/dist/session-runtime/host.d.ts +77 -0
  178. package/dist/session-runtime/host.js +758 -0
  179. package/dist/session-runtime/host.js.map +1 -0
  180. package/dist/session-runtime/launch.d.ts +11 -0
  181. package/dist/session-runtime/launch.js +68 -0
  182. package/dist/session-runtime/launch.js.map +1 -0
  183. package/dist/session-runtime/paths.d.ts +8 -0
  184. package/dist/session-runtime/paths.js +92 -0
  185. package/dist/session-runtime/paths.js.map +1 -0
  186. package/dist/session-runtime/protocol.d.ts +22 -0
  187. package/dist/session-runtime/protocol.js +149 -0
  188. package/dist/session-runtime/protocol.js.map +1 -0
  189. package/dist/session-runtime/replay-buffer.d.ts +12 -0
  190. package/dist/session-runtime/replay-buffer.js +50 -0
  191. package/dist/session-runtime/replay-buffer.js.map +1 -0
  192. package/dist/session-runtime/store.d.ts +14 -0
  193. package/dist/session-runtime/store.js +143 -0
  194. package/dist/session-runtime/store.js.map +1 -0
  195. package/dist/session-runtime/types.d.ts +102 -0
  196. package/dist/session-runtime/types.js +2 -0
  197. package/dist/session-runtime/types.js.map +1 -0
  198. package/dist/store/logs.js +17 -6
  199. package/dist/store/logs.js.map +1 -1
  200. package/dist/store/plan.d.ts +2 -0
  201. package/dist/store/plan.js.map +1 -1
  202. package/dist/store/session-workspace.js +2 -1
  203. package/dist/store/session-workspace.js.map +1 -1
  204. package/dist/tools/definitions.js +18 -0
  205. package/dist/tools/definitions.js.map +1 -1
  206. package/dist/tools/external-tools.d.ts +30 -0
  207. package/dist/tools/external-tools.js +52 -0
  208. package/dist/tools/external-tools.js.map +1 -0
  209. package/dist/tools/registry.js +36 -5
  210. package/dist/tools/registry.js.map +1 -1
  211. package/dist/tui-v2/bootstrap/start-tui-v2.d.ts +1 -0
  212. package/dist/tui-v2/bootstrap/start-tui-v2.js +16 -0
  213. package/dist/tui-v2/bootstrap/start-tui-v2.js.map +1 -1
  214. package/dist/tui-v2/components/completion/completion-menu.d.ts +4 -6
  215. package/dist/tui-v2/components/completion/completion-menu.js +34 -16
  216. package/dist/tui-v2/components/completion/completion-menu.js.map +1 -1
  217. package/dist/tui-v2/components/composer/composer-input-box.js +3 -1
  218. package/dist/tui-v2/components/composer/composer-input-box.js.map +1 -1
  219. package/dist/tui-v2/components/modal/secret-modal.js +6 -4
  220. package/dist/tui-v2/components/modal/secret-modal.js.map +1 -1
  221. package/dist/tui-v2/components/modal/text-editor-modal.d.ts +19 -0
  222. package/dist/tui-v2/components/modal/text-editor-modal.js +85 -0
  223. package/dist/tui-v2/components/modal/text-editor-modal.js.map +1 -0
  224. package/dist/tui-v2/components/overlay/overlay-host.js +2 -1
  225. package/dist/tui-v2/components/overlay/overlay-host.js.map +1 -1
  226. package/dist/tui-v2/components/transcript/compacted-row.js +12 -3
  227. package/dist/tui-v2/components/transcript/compacted-row.js.map +1 -1
  228. package/dist/tui-v2/components/transcript/thinking-block.d.ts +9 -1
  229. package/dist/tui-v2/components/transcript/thinking-block.js +253 -49
  230. package/dist/tui-v2/components/transcript/thinking-block.js.map +1 -1
  231. package/dist/tui-v2/components/transcript/thinking-presentation.d.ts +46 -0
  232. package/dist/tui-v2/components/transcript/thinking-presentation.js +84 -0
  233. package/dist/tui-v2/components/transcript/thinking-presentation.js.map +1 -0
  234. package/dist/tui-v2/components/transcript/transcript-row.d.ts +2 -0
  235. package/dist/tui-v2/components/transcript/transcript-row.js +7 -2
  236. package/dist/tui-v2/components/transcript/transcript-row.js.map +1 -1
  237. package/dist/tui-v2/components/transcript/transcript-view.js +195 -83
  238. package/dist/tui-v2/components/transcript/transcript-view.js.map +1 -1
  239. package/dist/tui-v2/composer/composer-editor.js +54 -39
  240. package/dist/tui-v2/composer/composer-editor.js.map +1 -1
  241. package/dist/tui-v2/composer/composer-highlight.d.ts +20 -0
  242. package/dist/tui-v2/composer/composer-highlight.js +97 -0
  243. package/dist/tui-v2/composer/composer-highlight.js.map +1 -0
  244. package/dist/tui-v2/composer/textarea-keybindings.d.ts +5 -0
  245. package/dist/tui-v2/composer/textarea-keybindings.js +12 -0
  246. package/dist/tui-v2/composer/textarea-keybindings.js.map +1 -1
  247. package/dist/ui/mentions.js +4 -1
  248. package/dist/ui/mentions.js.map +1 -1
  249. package/dist/ui-core/actions/action-id.d.ts +1 -1
  250. package/dist/ui-core/actions/action-id.js +1 -0
  251. package/dist/ui-core/actions/action-id.js.map +1 -1
  252. package/dist/ui-core/actions/format-shortcuts.js +5 -0
  253. package/dist/ui-core/actions/format-shortcuts.js.map +1 -1
  254. package/dist/ui-core/actions/keymap.js +3 -0
  255. package/dist/ui-core/actions/keymap.js.map +1 -1
  256. package/dist/ui-core/bootstrap/composition-root.d.ts +7 -0
  257. package/dist/ui-core/bootstrap/composition-root.js +7 -1
  258. package/dist/ui-core/bootstrap/composition-root.js.map +1 -1
  259. package/dist/ui-core/commands/command-handlers.js +5 -2
  260. package/dist/ui-core/commands/command-handlers.js.map +1 -1
  261. package/dist/ui-core/commands/config-commands.d.ts +1 -0
  262. package/dist/ui-core/commands/config-commands.js +6 -0
  263. package/dist/ui-core/commands/config-commands.js.map +1 -1
  264. package/dist/ui-core/commands/mcp-commands.d.ts +3 -0
  265. package/dist/ui-core/commands/mcp-commands.js +310 -0
  266. package/dist/ui-core/commands/mcp-commands.js.map +1 -0
  267. package/dist/ui-core/commands/picker-commands.d.ts +1 -1
  268. package/dist/ui-core/commands/picker-commands.js +70 -27
  269. package/dist/ui-core/commands/picker-commands.js.map +1 -1
  270. package/dist/ui-core/commands/session-commands.js +1 -0
  271. package/dist/ui-core/commands/session-commands.js.map +1 -1
  272. package/dist/ui-core/composer/completion-viewport.d.ts +40 -0
  273. package/dist/ui-core/composer/completion-viewport.js +105 -0
  274. package/dist/ui-core/composer/completion-viewport.js.map +1 -0
  275. package/dist/ui-core/controllers/overlay-controller.d.ts +24 -3
  276. package/dist/ui-core/controllers/overlay-controller.js +35 -4
  277. package/dist/ui-core/controllers/overlay-controller.js.map +1 -1
  278. package/dist/ui-core/rendering/artifact-pager-source.d.ts +1 -0
  279. package/dist/ui-core/rendering/artifact-pager-source.js +67 -1
  280. package/dist/ui-core/rendering/artifact-pager-source.js.map +1 -1
  281. package/dist/ui-core/rendering/duration.d.ts +3 -1
  282. package/dist/ui-core/rendering/duration.js +14 -0
  283. package/dist/ui-core/rendering/duration.js.map +1 -1
  284. package/dist/ui-core/rendering/exit-summary.js +4 -4
  285. package/dist/ui-core/rendering/format-help.js +4 -0
  286. package/dist/ui-core/rendering/format-help.js.map +1 -1
  287. package/dist/ui-core/rendering/intro-header.js +4 -4
  288. package/dist/ui-core/rendering/open-tool-output.js +90 -32
  289. package/dist/ui-core/rendering/open-tool-output.js.map +1 -1
  290. package/dist/ui-core/rendering/theme.d.ts +5 -3
  291. package/dist/ui-core/rendering/theme.js +8 -4
  292. package/dist/ui-core/rendering/theme.js.map +1 -1
  293. package/dist/ui-core/rendering/wordmark.d.ts +2 -2
  294. package/dist/ui-core/rendering/wordmark.js +62 -62
  295. package/dist/ui-core/rendering/wordmark.js.map +1 -1
  296. package/dist/ui-core/state/thinking-copy.d.ts +13 -0
  297. package/dist/ui-core/state/thinking-copy.js +33 -0
  298. package/dist/ui-core/state/thinking-copy.js.map +1 -0
  299. package/dist/ui-core/state/transcript-hydrate.js +20 -0
  300. package/dist/ui-core/state/transcript-hydrate.js.map +1 -1
  301. package/dist/ui-core/state/transcript-reducer.js +140 -62
  302. package/dist/ui-core/state/transcript-reducer.js.map +1 -1
  303. package/dist/ui-core/state/transcript-store.d.ts +10 -0
  304. package/dist/ui-core/state/transcript-store.js +235 -31
  305. package/dist/ui-core/state/transcript-store.js.map +1 -1
  306. package/dist/ui-core/state/transcript-types.d.ts +10 -0
  307. package/dist/ui-core/state/transcript-types.js +1 -0
  308. package/dist/ui-core/state/transcript-types.js.map +1 -1
  309. package/dist/ui-core/state/transcript-window.d.ts +32 -0
  310. package/dist/ui-core/state/transcript-window.js +63 -0
  311. package/dist/ui-core/state/transcript-window.js.map +1 -0
  312. package/dist/version.generated.d.ts +2 -2
  313. package/dist/version.generated.js +2 -2
  314. package/dist/version.generated.js.map +1 -1
  315. package/package.json +1 -1
  316. package/dist/tui-v2/composer/skill-highlight.d.ts +0 -3
  317. package/dist/tui-v2/composer/skill-highlight.js +0 -63
  318. package/dist/tui-v2/composer/skill-highlight.js.map +0 -1
@@ -0,0 +1,758 @@
1
+ import { randomUUID, timingSafeEqual } from "node:crypto";
2
+ import { chmod, rm } from "node:fs/promises";
3
+ import { createServer } from "node:net";
4
+ import { processIdentityTracker } from "../os/process-identity.js";
5
+ import { processAlive } from "../os/process-tree.js";
6
+ import { startPtyProcess } from "../interactive-session/transport-node-pty.js";
7
+ import { RUNTIME_CHILD_ENV, RUNTIME_HOST_ENV, RUNTIME_SESSION_ENV, RUNTIME_SOCKET_ENV, RUNTIME_TOKEN_ENV, decodeRuntimeHostPayload, } from "./launch.js";
8
+ import { isRuntimeSocketPath, runtimeSocketPath } from "./paths.js";
9
+ import { JsonFrameChannel, readFirstFrame, sendFrame, } from "./protocol.js";
10
+ import { TerminalReplayBuffer } from "./replay-buffer.js";
11
+ import { createRuntimeToken, deleteRuntimeMetadata, reapStaleRuntimeLock, tryAcquireRuntimeLease, writeRuntimeMetadata, } from "./store.js";
12
+ import { RUNTIME_PROTOCOL_VERSION, } from "./types.js";
13
+ const CLIENT_BACKPRESSURE_BYTES = 1024 * 1024;
14
+ const METADATA_DEBOUNCE_MS = 50;
15
+ const FINAL_OUTPUT_DRAIN_MS = 3_000;
16
+ const FORCE_STOP_MS = 8_000;
17
+ const ATTACH_RESET = Buffer.from("\u001b[?1049h\u001b[2J\u001b[H", "utf8");
18
+ function tokensEqual(candidate, expected) {
19
+ if (!/^[a-f0-9]{64}$/i.test(candidate) || !/^[a-f0-9]{64}$/i.test(expected)) {
20
+ return false;
21
+ }
22
+ return timingSafeEqual(Buffer.from(candidate, "hex"), Buffer.from(expected, "hex"));
23
+ }
24
+ function errorText(error) {
25
+ const value = error instanceof Error ? error.message : String(error);
26
+ return value.replace(/\s+/g, " ").trim().slice(0, 300) || "runtime host failed";
27
+ }
28
+ function authFrame(value) {
29
+ if (!value || typeof value !== "object")
30
+ return undefined;
31
+ const frame = value;
32
+ if (frame.version !== RUNTIME_PROTOCOL_VERSION ||
33
+ frame.type !== "auth" ||
34
+ !["probe", "client-control", "client-terminal", "child"].includes(String(frame.role)) ||
35
+ typeof frame.token !== "string") {
36
+ return undefined;
37
+ }
38
+ return frame;
39
+ }
40
+ function dimensionsOf(value) {
41
+ if (value.type !== "resize")
42
+ return undefined;
43
+ const columns = Math.floor(value.columns);
44
+ const rows = Math.floor(value.rows);
45
+ if (columns < 20 || columns > 1_000 || rows < 5 || rows > 500) {
46
+ return undefined;
47
+ }
48
+ return { columns, rows };
49
+ }
50
+ function clientFrame(value) {
51
+ if (!value || typeof value !== "object")
52
+ return undefined;
53
+ const frame = value;
54
+ if (frame.type === "ping" || frame.type === "detach") {
55
+ return frame;
56
+ }
57
+ if (frame.type === "resize" &&
58
+ typeof frame.columns === "number" &&
59
+ typeof frame.rows === "number") {
60
+ return frame;
61
+ }
62
+ return undefined;
63
+ }
64
+ function childFrame(value) {
65
+ if (!value || typeof value !== "object")
66
+ return undefined;
67
+ const frame = value;
68
+ if (frame.type === "minimise")
69
+ return frame;
70
+ if (frame.type === "exiting" &&
71
+ typeof frame.exitCode === "number" &&
72
+ Number.isSafeInteger(frame.exitCode)) {
73
+ return frame;
74
+ }
75
+ if (frame.type === "switch" &&
76
+ typeof frame.sessionId === "string" &&
77
+ typeof frame.closeCurrent === "boolean") {
78
+ return frame;
79
+ }
80
+ if (frame.type === "status" &&
81
+ typeof frame.sessionId === "string" &&
82
+ frame.sessionId.length <= 256 &&
83
+ typeof frame.cwd === "string" &&
84
+ frame.cwd.length <= 4096 &&
85
+ typeof frame.busy === "boolean" &&
86
+ (frame.title === undefined ||
87
+ (typeof frame.title === "string" && frame.title.length <= 256))) {
88
+ return frame;
89
+ }
90
+ return undefined;
91
+ }
92
+ function listen(server, path) {
93
+ return new Promise((resolve, reject) => {
94
+ const onError = (error) => {
95
+ server.off("listening", onListening);
96
+ reject(error);
97
+ };
98
+ const onListening = () => {
99
+ server.off("error", onError);
100
+ resolve();
101
+ };
102
+ server.once("error", onError);
103
+ server.once("listening", onListening);
104
+ server.listen(path);
105
+ });
106
+ }
107
+ function closeServer(server) {
108
+ if (!server?.listening)
109
+ return Promise.resolve();
110
+ return new Promise((resolve) => {
111
+ let settled = false;
112
+ const finish = () => {
113
+ if (settled)
114
+ return;
115
+ settled = true;
116
+ clearTimeout(timer);
117
+ resolve();
118
+ };
119
+ const timer = setTimeout(finish, 1_000);
120
+ timer.unref?.();
121
+ server.close(finish);
122
+ });
123
+ }
124
+ export class SessionRuntimeHost {
125
+ payload;
126
+ token = createRuntimeToken();
127
+ replay = new TerminalReplayBuffer();
128
+ startedAt = new Date().toISOString();
129
+ sessionId;
130
+ cwd;
131
+ socketPath;
132
+ title;
133
+ busy = true;
134
+ attached = false;
135
+ phase = "starting";
136
+ error;
137
+ lease;
138
+ server;
139
+ connections = new Set();
140
+ transport;
141
+ client;
142
+ childSocket;
143
+ childChannel;
144
+ idleTimer;
145
+ forceTimer;
146
+ livenessTimer;
147
+ livenessMisses = 0;
148
+ expectedExitCode;
149
+ metadataTimer;
150
+ metadataDirty = false;
151
+ outputPausedFor;
152
+ outputDrainHandler;
153
+ metadataWrites = Promise.resolve();
154
+ inputWrites = Promise.resolve();
155
+ statusWrites = Promise.resolve();
156
+ closing = false;
157
+ cleaning = false;
158
+ exitOutcome;
159
+ resolveExit;
160
+ exitPromise = new Promise((resolve) => {
161
+ this.resolveExit = resolve;
162
+ });
163
+ signalHandlers = new Map();
164
+ constructor(payload) {
165
+ this.payload = payload;
166
+ this.sessionId = payload.sessionId;
167
+ this.cwd = payload.cwd;
168
+ this.socketPath = runtimeSocketPath(payload.sessionId);
169
+ }
170
+ async run() {
171
+ this.lease = await tryAcquireRuntimeLease(this.sessionId);
172
+ if (!this.lease && (await reapStaleRuntimeLock(this.sessionId))) {
173
+ this.lease = await tryAcquireRuntimeLease(this.sessionId);
174
+ }
175
+ if (!this.lease)
176
+ return;
177
+ try {
178
+ await this.startServer();
179
+ await this.writeMetadataNow();
180
+ this.installSignals();
181
+ await this.startChild();
182
+ this.phase = "running";
183
+ this.queueMetadata();
184
+ const outcome = await this.exitPromise;
185
+ this.exitOutcome = outcome;
186
+ await this.flushTerminalOutput();
187
+ this.sendToClient({
188
+ type: "exit",
189
+ exitCode: outcome.exitCode ?? 1,
190
+ ...(outcome.signal ? { signal: outcome.signal } : {}),
191
+ });
192
+ await new Promise((resolve) => setTimeout(resolve, 300));
193
+ }
194
+ catch (error) {
195
+ this.phase = "failed";
196
+ this.error = errorText(error);
197
+ await this.writeMetadataNow().catch(() => undefined);
198
+ await new Promise((resolve) => setTimeout(resolve, 1_500));
199
+ }
200
+ finally {
201
+ await this.cleanup();
202
+ }
203
+ }
204
+ async startServer() {
205
+ if (process.platform !== "win32" && isRuntimeSocketPath(this.socketPath)) {
206
+ await rm(this.socketPath, { force: true }).catch(() => undefined);
207
+ }
208
+ const server = createServer((socket) => void this.accept(socket));
209
+ this.server = server;
210
+ await listen(server, this.socketPath);
211
+ if (process.platform !== "win32") {
212
+ await chmod(this.socketPath, 0o600).catch(() => undefined);
213
+ }
214
+ }
215
+ async startChild() {
216
+ const env = { ...process.env };
217
+ delete env[RUNTIME_HOST_ENV];
218
+ env[RUNTIME_CHILD_ENV] = "1";
219
+ env[RUNTIME_SOCKET_ENV] = this.socketPath;
220
+ env[RUNTIME_TOKEN_ENV] = this.token;
221
+ env[RUNTIME_SESSION_ENV] = this.sessionId;
222
+ const result = await startPtyProcess({
223
+ file: this.payload.launch.file,
224
+ args: this.payload.launch.args,
225
+ cwd: this.payload.cwd,
226
+ env,
227
+ dimensions: {
228
+ columns: this.payload.columns,
229
+ rows: this.payload.rows,
230
+ },
231
+ });
232
+ this.transport = result.transport;
233
+ this.transport.onOutput((event) => this.publishOutput(event.bytes));
234
+ this.transport.onExit((outcome) => {
235
+ if (this.exitOutcome)
236
+ return;
237
+ this.resolveExit?.(outcome);
238
+ });
239
+ this.armChildLiveness();
240
+ }
241
+ armChildLiveness() {
242
+ if (this.exitOutcome || !this.transport)
243
+ return;
244
+ this.livenessTimer = setTimeout(() => {
245
+ this.livenessTimer = undefined;
246
+ const transport = this.transport;
247
+ if (!transport || this.exitOutcome)
248
+ return;
249
+ const expected = transport.identity;
250
+ const comparison = expected
251
+ ? processIdentityTracker.compare(transport.pid, expected)
252
+ : processAlive(transport.pid)
253
+ ? "unknown"
254
+ : "gone";
255
+ const provenDead = comparison === "gone" || comparison === "mismatch";
256
+ this.livenessMisses = provenDead ? this.livenessMisses + 1 : 0;
257
+ if (this.livenessMisses >= 2) {
258
+ this.resolveExit?.({
259
+ endedAt: Date.now(),
260
+ exitCode: this.expectedExitCode ?? 1,
261
+ });
262
+ return;
263
+ }
264
+ this.armChildLiveness();
265
+ }, 500);
266
+ this.livenessTimer.unref?.();
267
+ }
268
+ async accept(socket) {
269
+ this.connections.add(socket);
270
+ socket.on("error", () => socket.destroy());
271
+ socket.once("close", () => this.connections.delete(socket));
272
+ socket.setNoDelay(true);
273
+ try {
274
+ const first = await readFirstFrame(socket);
275
+ const auth = authFrame(first.value);
276
+ if (!auth || !tokensEqual(auth.token, this.token)) {
277
+ sendFrame(socket, {
278
+ version: RUNTIME_PROTOCOL_VERSION,
279
+ type: "error",
280
+ message: "authentication failed",
281
+ });
282
+ socket.end();
283
+ return;
284
+ }
285
+ if (auth.role === "probe") {
286
+ this.acknowledge(socket);
287
+ socket.end();
288
+ return;
289
+ }
290
+ if (auth.role === "client-control") {
291
+ this.acceptClientControl(socket, auth, first.rest);
292
+ return;
293
+ }
294
+ if (auth.role === "client-terminal") {
295
+ this.acceptClientTerminal(socket, auth, first.rest);
296
+ return;
297
+ }
298
+ this.acceptChild(socket, first.rest);
299
+ }
300
+ catch {
301
+ socket.destroy();
302
+ }
303
+ }
304
+ acknowledge(socket) {
305
+ sendFrame(socket, {
306
+ version: RUNTIME_PROTOCOL_VERSION,
307
+ type: "ack",
308
+ sessionId: this.sessionId,
309
+ });
310
+ }
311
+ acceptClientControl(socket, auth, rest) {
312
+ const clientId = auth.clientId?.trim();
313
+ if (!clientId || clientId.length > 128) {
314
+ socket.destroy();
315
+ return;
316
+ }
317
+ if (this.client) {
318
+ this.disconnectClient("taken-over");
319
+ }
320
+ const client = { id: clientId, control: socket };
321
+ this.client = client;
322
+ this.acknowledge(socket);
323
+ client.channel = new JsonFrameChannel(socket, (value) => this.handleClientFrame(client, value), () => socket.destroy(), rest);
324
+ socket.once("close", () => this.clientClosed(client, socket));
325
+ }
326
+ acceptClientTerminal(socket, auth, rest) {
327
+ const client = this.client;
328
+ if (!client || !auth.clientId || client.id !== auth.clientId) {
329
+ socket.destroy();
330
+ return;
331
+ }
332
+ if (client.terminal) {
333
+ this.releaseOutputBackpressure(client.terminal);
334
+ client.terminal.destroy();
335
+ }
336
+ client.terminal = socket;
337
+ this.attached = true;
338
+ this.cancelIdleTimer();
339
+ this.queueMetadata();
340
+ this.acknowledge(socket);
341
+ this.writeToTerminal(socket, ATTACH_RESET);
342
+ const replay = this.replay.snapshot();
343
+ if (replay.length > 0)
344
+ this.writeToTerminal(socket, replay);
345
+ if (rest.length > 0)
346
+ this.queueInput(rest);
347
+ socket.on("data", (bytes) => {
348
+ if (this.client === client && client.terminal === socket) {
349
+ this.queueInput(bytes);
350
+ }
351
+ });
352
+ socket.once("close", () => this.clientClosed(client, socket));
353
+ socket.resume();
354
+ void this.resize({
355
+ columns: this.payload.columns,
356
+ rows: this.payload.rows,
357
+ });
358
+ }
359
+ acceptChild(socket, rest) {
360
+ this.childChannel?.dispose();
361
+ this.childSocket?.destroy();
362
+ this.childSocket = socket;
363
+ this.acknowledge(socket);
364
+ this.childChannel = new JsonFrameChannel(socket, (value) => this.handleChildFrame(value), () => socket.destroy(), rest);
365
+ socket.once("close", () => {
366
+ if (this.childSocket !== socket)
367
+ return;
368
+ this.childChannel?.dispose();
369
+ this.childChannel = undefined;
370
+ this.childSocket = undefined;
371
+ });
372
+ }
373
+ handleClientFrame(client, value) {
374
+ if (this.client !== client)
375
+ return;
376
+ const frame = clientFrame(value);
377
+ if (!frame)
378
+ return;
379
+ if (frame.type === "ping") {
380
+ client.channel?.send({ type: "pong" });
381
+ return;
382
+ }
383
+ if (frame.type === "detach") {
384
+ this.disconnectClient("requested");
385
+ return;
386
+ }
387
+ const dimensions = dimensionsOf(frame);
388
+ if (dimensions)
389
+ void this.resize(dimensions);
390
+ }
391
+ handleChildFrame(value) {
392
+ const frame = childFrame(value);
393
+ if (!frame)
394
+ return;
395
+ if (frame.type === "minimise") {
396
+ this.disconnectClient("minimise");
397
+ return;
398
+ }
399
+ if (frame.type === "exiting") {
400
+ this.expectedExitCode = frame.exitCode;
401
+ return;
402
+ }
403
+ if (frame.type === "switch") {
404
+ const target = frame.sessionId.trim();
405
+ if (!target || target.length > 256)
406
+ return;
407
+ this.sendToClient({ type: "switch", sessionId: target });
408
+ this.closeClientSockets();
409
+ if (frame.closeCurrent) {
410
+ setTimeout(() => this.requestGracefulStop(), 80).unref?.();
411
+ }
412
+ return;
413
+ }
414
+ this.statusWrites = this.statusWrites
415
+ .then(() => this.applyStatus(frame))
416
+ .catch(() => undefined);
417
+ }
418
+ async applyStatus(frame) {
419
+ let changed = false;
420
+ const nextId = frame.sessionId.trim();
421
+ if (nextId && nextId !== this.sessionId && nextId.length <= 256) {
422
+ const previousId = this.sessionId;
423
+ await this.rebind(nextId);
424
+ changed ||= this.sessionId !== previousId;
425
+ }
426
+ const nextCwd = frame.cwd || this.cwd;
427
+ const nextTitle = frame.title?.trim() || undefined;
428
+ changed ||=
429
+ nextCwd !== this.cwd ||
430
+ nextTitle !== this.title ||
431
+ frame.busy !== this.busy;
432
+ if (!changed)
433
+ return;
434
+ this.cwd = nextCwd;
435
+ this.title = nextTitle;
436
+ this.busy = frame.busy;
437
+ this.queueMetadata();
438
+ this.scheduleIdleTimer();
439
+ }
440
+ async rebind(nextId) {
441
+ let nextLease = await tryAcquireRuntimeLease(nextId);
442
+ if (!nextLease && (await reapStaleRuntimeLock(nextId))) {
443
+ nextLease = await tryAcquireRuntimeLease(nextId);
444
+ }
445
+ if (!nextLease)
446
+ return;
447
+ const previousId = this.sessionId;
448
+ const previousLease = this.lease;
449
+ this.sessionId = nextId;
450
+ this.lease = nextLease;
451
+ await this.writeMetadataNow();
452
+ await deleteRuntimeMetadata(previousId);
453
+ await previousLease?.release();
454
+ }
455
+ publishOutput(bytes) {
456
+ this.replay.append(bytes);
457
+ const terminal = this.client?.terminal;
458
+ if (terminal)
459
+ this.writeToTerminal(terminal, bytes);
460
+ }
461
+ writeToTerminal(terminal, bytes) {
462
+ if (!terminal.writable || terminal.destroyed)
463
+ return;
464
+ const writable = terminal.write(bytes);
465
+ if (!writable ||
466
+ terminal.writableLength >= CLIENT_BACKPRESSURE_BYTES) {
467
+ this.applyOutputBackpressure(terminal);
468
+ }
469
+ }
470
+ applyOutputBackpressure(terminal) {
471
+ if (this.outputPausedFor === terminal)
472
+ return;
473
+ this.releaseOutputBackpressure();
474
+ this.outputPausedFor = terminal;
475
+ this.transport?.pauseOutput();
476
+ const drain = () => this.releaseOutputBackpressure(terminal);
477
+ this.outputDrainHandler = drain;
478
+ terminal.once("drain", drain);
479
+ }
480
+ releaseOutputBackpressure(terminal) {
481
+ if (!this.outputPausedFor)
482
+ return;
483
+ if (terminal && this.outputPausedFor !== terminal)
484
+ return;
485
+ if (this.outputDrainHandler) {
486
+ this.outputPausedFor.off("drain", this.outputDrainHandler);
487
+ }
488
+ this.outputPausedFor = undefined;
489
+ this.outputDrainHandler = undefined;
490
+ this.transport?.resumeOutput();
491
+ }
492
+ async flushTerminalOutput() {
493
+ const deadline = Date.now() + FINAL_OUTPUT_DRAIN_MS;
494
+ while (Date.now() < deadline) {
495
+ const paused = this.outputPausedFor;
496
+ if (paused) {
497
+ await new Promise((resolve) => {
498
+ let settled = false;
499
+ const finish = () => {
500
+ if (settled)
501
+ return;
502
+ settled = true;
503
+ clearTimeout(timeout);
504
+ paused.off("drain", finish);
505
+ resolve();
506
+ };
507
+ const timeout = setTimeout(finish, Math.max(1, Math.min(100, deadline - Date.now())));
508
+ timeout.unref?.();
509
+ paused.once("drain", finish);
510
+ });
511
+ continue;
512
+ }
513
+ const remaining = Math.max(1, deadline - Date.now());
514
+ await Promise.race([
515
+ this.transport?.waitForOutputDrain?.() ?? Promise.resolve(),
516
+ new Promise((resolve) => {
517
+ const timeout = setTimeout(resolve, remaining);
518
+ timeout.unref?.();
519
+ }),
520
+ ]);
521
+ if (!this.outputPausedFor)
522
+ break;
523
+ }
524
+ this.releaseOutputBackpressure();
525
+ const terminal = this.client?.terminal;
526
+ if (!terminal ||
527
+ terminal.destroyed ||
528
+ terminal.writableEnded ||
529
+ !terminal.writable)
530
+ return;
531
+ await new Promise((resolve) => {
532
+ let settled = false;
533
+ const finish = () => {
534
+ if (settled)
535
+ return;
536
+ settled = true;
537
+ clearTimeout(timeout);
538
+ resolve();
539
+ };
540
+ const timeout = setTimeout(finish, 1_000);
541
+ timeout.unref?.();
542
+ terminal.once("close", finish);
543
+ terminal.end(finish);
544
+ });
545
+ }
546
+ queueInput(bytes) {
547
+ const copy = Buffer.from(bytes);
548
+ this.inputWrites = this.inputWrites
549
+ .then(() => this.transport?.write(copy))
550
+ .catch(() => undefined);
551
+ }
552
+ async resize(dimensions) {
553
+ await this.transport?.resize?.(dimensions).catch(() => undefined);
554
+ }
555
+ clientClosed(client, socket) {
556
+ if (client.terminal === socket) {
557
+ client.terminal = undefined;
558
+ this.releaseOutputBackpressure(socket);
559
+ if (this.client === client) {
560
+ this.attached = false;
561
+ this.queueMetadata();
562
+ this.scheduleIdleTimer();
563
+ }
564
+ }
565
+ if (client.control === socket)
566
+ client.channel?.dispose();
567
+ if (this.client !== client)
568
+ return;
569
+ if (!client.control.destroyed || client.terminal)
570
+ return;
571
+ this.client = undefined;
572
+ this.attached = false;
573
+ this.queueMetadata();
574
+ this.scheduleIdleTimer();
575
+ }
576
+ sendToClient(frame) {
577
+ this.client?.channel?.send(frame);
578
+ }
579
+ disconnectClient(reason) {
580
+ this.sendToClient({
581
+ type: "detached",
582
+ reason,
583
+ sessionId: this.sessionId,
584
+ });
585
+ this.closeClientSockets();
586
+ }
587
+ closeClientSockets() {
588
+ const client = this.client;
589
+ if (!client)
590
+ return;
591
+ this.client = undefined;
592
+ this.attached = false;
593
+ this.releaseOutputBackpressure(client.terminal);
594
+ client.channel?.dispose();
595
+ client.control.end();
596
+ setTimeout(() => client.terminal?.end(), 50).unref?.();
597
+ setTimeout(() => {
598
+ client.terminal?.destroy();
599
+ client.control.destroy();
600
+ }, 250).unref?.();
601
+ this.queueMetadata();
602
+ this.scheduleIdleTimer();
603
+ }
604
+ scheduleIdleTimer() {
605
+ this.cancelIdleTimer();
606
+ if (this.closing || this.attached || this.busy)
607
+ return;
608
+ this.idleTimer = setTimeout(() => this.requestGracefulStop(), this.payload.idleTimeoutMs);
609
+ this.idleTimer.unref?.();
610
+ }
611
+ cancelIdleTimer() {
612
+ if (!this.idleTimer)
613
+ return;
614
+ clearTimeout(this.idleTimer);
615
+ this.idleTimer = undefined;
616
+ }
617
+ requestGracefulStop() {
618
+ if (this.closing)
619
+ return;
620
+ this.closing = true;
621
+ this.phase = "stopping";
622
+ this.cancelIdleTimer();
623
+ this.queueMetadata();
624
+ if (!this.childChannel?.send({ type: "shutdown" })) {
625
+ void this.transport?.requestTreeTermination("graceful");
626
+ }
627
+ this.forceTimer = setTimeout(() => {
628
+ void this.transport?.requestTreeTermination("forceful");
629
+ }, FORCE_STOP_MS);
630
+ this.forceTimer.unref?.();
631
+ }
632
+ metadataSnapshot() {
633
+ const now = new Date().toISOString();
634
+ const childPid = this.transport?.pid;
635
+ const childIdentity = this.transport?.identity;
636
+ return {
637
+ version: RUNTIME_PROTOCOL_VERSION,
638
+ sessionId: this.sessionId,
639
+ hostPid: process.pid,
640
+ ...(processIdentityTracker.capture(process.pid)
641
+ ? { hostIdentity: processIdentityTracker.capture(process.pid) }
642
+ : {}),
643
+ ...(childPid ? { childPid } : {}),
644
+ ...(childIdentity ? { childIdentity } : {}),
645
+ socketPath: this.socketPath,
646
+ token: this.token,
647
+ cwd: this.cwd,
648
+ ...(this.title ? { title: this.title } : {}),
649
+ startedAt: this.startedAt,
650
+ updatedAt: now,
651
+ phase: this.phase,
652
+ busy: this.busy,
653
+ attached: this.attached,
654
+ ...(this.error ? { error: this.error } : {}),
655
+ };
656
+ }
657
+ queueMetadata() {
658
+ if (this.cleaning || this.phase === "failed")
659
+ return;
660
+ this.metadataDirty = true;
661
+ if (this.metadataTimer)
662
+ return;
663
+ this.metadataTimer = setTimeout(() => {
664
+ this.metadataTimer = undefined;
665
+ this.flushQueuedMetadata();
666
+ }, METADATA_DEBOUNCE_MS);
667
+ this.metadataTimer.unref?.();
668
+ }
669
+ flushQueuedMetadata() {
670
+ if (!this.metadataDirty || this.phase === "failed")
671
+ return;
672
+ this.metadataDirty = false;
673
+ const snapshot = this.metadataSnapshot();
674
+ this.metadataWrites = this.metadataWrites
675
+ .then(() => writeRuntimeMetadata(snapshot))
676
+ .catch(() => undefined);
677
+ }
678
+ async writeMetadataNow() {
679
+ if (this.metadataTimer) {
680
+ clearTimeout(this.metadataTimer);
681
+ this.metadataTimer = undefined;
682
+ }
683
+ this.metadataDirty = false;
684
+ const snapshot = this.metadataSnapshot();
685
+ const write = this.metadataWrites
686
+ .catch(() => undefined)
687
+ .then(() => writeRuntimeMetadata(snapshot));
688
+ this.metadataWrites = write.catch(() => undefined);
689
+ await write;
690
+ }
691
+ installSignals() {
692
+ for (const signal of ["SIGINT", "SIGTERM"]) {
693
+ const handler = () => this.requestGracefulStop();
694
+ this.signalHandlers.set(signal, handler);
695
+ process.on(signal, handler);
696
+ }
697
+ if (process.platform !== "win32") {
698
+ const handler = () => undefined;
699
+ this.signalHandlers.set("SIGHUP", handler);
700
+ process.on("SIGHUP", handler);
701
+ }
702
+ }
703
+ removeSignals() {
704
+ for (const [signal, handler] of this.signalHandlers) {
705
+ process.off(signal, handler);
706
+ }
707
+ this.signalHandlers.clear();
708
+ }
709
+ async cleanup() {
710
+ if (this.cleaning)
711
+ return;
712
+ this.cleaning = true;
713
+ this.closing = true;
714
+ this.cancelIdleTimer();
715
+ if (this.metadataTimer)
716
+ clearTimeout(this.metadataTimer);
717
+ this.metadataTimer = undefined;
718
+ this.metadataDirty = false;
719
+ if (this.forceTimer)
720
+ clearTimeout(this.forceTimer);
721
+ if (this.livenessTimer)
722
+ clearTimeout(this.livenessTimer);
723
+ this.releaseOutputBackpressure();
724
+ this.removeSignals();
725
+ this.closeClientSockets();
726
+ this.childChannel?.dispose();
727
+ this.childSocket?.destroy();
728
+ for (const socket of this.connections)
729
+ socket.destroy();
730
+ this.connections.clear();
731
+ await closeServer(this.server);
732
+ if (!this.exitOutcome && this.transport) {
733
+ await this.transport.requestTreeTermination("forceful").catch(() => undefined);
734
+ }
735
+ await this.transport?.dispose().catch(() => undefined);
736
+ await this.metadataWrites.catch(() => undefined);
737
+ await deleteRuntimeMetadata(this.sessionId);
738
+ await this.lease?.release();
739
+ if (process.platform !== "win32" && isRuntimeSocketPath(this.socketPath)) {
740
+ await rm(this.socketPath, { force: true }).catch(() => undefined);
741
+ }
742
+ }
743
+ }
744
+ export async function runRuntimeHostFromEnvironment() {
745
+ const encoded = process.env[RUNTIME_HOST_ENV];
746
+ if (!encoded)
747
+ return false;
748
+ delete process.env[RUNTIME_HOST_ENV];
749
+ const payload = decodeRuntimeHostPayload(encoded);
750
+ if (!payload)
751
+ throw new Error("invalid session runtime host payload");
752
+ await new SessionRuntimeHost(payload).run();
753
+ return true;
754
+ }
755
+ export function runtimeHostClientId() {
756
+ return `${process.pid}-${randomUUID()}`;
757
+ }
758
+ //# sourceMappingURL=host.js.map