@gajae-code/coding-agent 0.17.1 → 0.17.4

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 (375) hide show
  1. package/CHANGELOG.md +266 -0
  2. package/dist/types/async/job-manager.d.ts +7 -6
  3. package/dist/types/cli/daemon-cli.d.ts +3 -1
  4. package/dist/types/cli/github-release.d.ts +17 -0
  5. package/dist/types/cli/public-command-entry.d.ts +56 -0
  6. package/dist/types/cli/public-command-errors.d.ts +126 -0
  7. package/dist/types/cli/public-command-evidence.d.ts +99 -0
  8. package/dist/types/cli/public-command-help.d.ts +65 -0
  9. package/dist/types/cli/public-command-registry.d.ts +69 -0
  10. package/dist/types/cli/session-picker.d.ts +1 -1
  11. package/dist/types/cli/setup-cli.d.ts +1 -0
  12. package/dist/types/cli/skills-cli.d.ts +5 -0
  13. package/dist/types/cli.d.ts +3 -0
  14. package/dist/types/commands/daemon.d.ts +4 -50
  15. package/dist/types/commands/sdk.d.ts +20 -37
  16. package/dist/types/commands/setup.d.ts +3 -0
  17. package/dist/types/commands/skills.d.ts +9 -0
  18. package/dist/types/config/autorouting-tier-map.d.ts +24 -0
  19. package/dist/types/config/file-lock.d.ts +10 -1
  20. package/dist/types/config/model-profile-activation.d.ts +63 -4
  21. package/dist/types/config/model-registry.d.ts +20 -2
  22. package/dist/types/config/settings-schema.d.ts +11 -0
  23. package/dist/types/coordinator-mcp/question-state.d.ts +6 -1
  24. package/dist/types/coordinator-mcp/server.d.ts +3 -0
  25. package/dist/types/daemon/operator-contract.d.ts +5 -1
  26. package/dist/types/eval/js/worker-protocol.d.ts +2 -0
  27. package/dist/types/extensibility/extensions/types.d.ts +12 -0
  28. package/dist/types/extensibility/gjc-plugins/registry.d.ts +4 -0
  29. package/dist/types/extensibility/runtime-skill-discovery.d.ts +18 -0
  30. package/dist/types/extensibility/shared-events.d.ts +3 -1
  31. package/dist/types/gjc-runtime/session-state-lock.d.ts +61 -0
  32. package/dist/types/internal-urls/embedded-protocol.d.ts +9 -0
  33. package/dist/types/internal-urls/index.d.ts +1 -0
  34. package/dist/types/internal-urls/parse.d.ts +9 -1
  35. package/dist/types/main.d.ts +22 -0
  36. package/dist/types/modes/acp/acp-agent.d.ts +94 -1
  37. package/dist/types/modes/acp/startup-provenance.d.ts +16 -0
  38. package/dist/types/modes/components/custom-provider-wizard.d.ts +19 -1
  39. package/dist/types/modes/components/session-selector.d.ts +5 -2
  40. package/dist/types/modes/components/thinking-selector.d.ts +2 -1
  41. package/dist/types/modes/components/user-message-selector.d.ts +5 -2
  42. package/dist/types/modes/controllers/command-controller.d.ts +1 -1
  43. package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
  44. package/dist/types/modes/interactive-mode.d.ts +1 -1
  45. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +11 -1
  46. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +14 -1
  47. package/dist/types/modes/types.d.ts +2 -2
  48. package/dist/types/runtime/process-lifecycle.d.ts +2 -0
  49. package/dist/types/runtime-mcp/manager.d.ts +56 -0
  50. package/dist/types/runtime-mcp/pool.d.ts +17 -0
  51. package/dist/types/runtime-mcp/redaction.d.ts +20 -0
  52. package/dist/types/runtime-mcp/startup-policy.d.ts +6 -0
  53. package/dist/types/runtime-mcp/tool-bridge.d.ts +9 -0
  54. package/dist/types/runtime-mcp/transports/http.d.ts +11 -0
  55. package/dist/types/sdk/acp/adapter.d.ts +27 -0
  56. package/dist/types/sdk/acp/final-text.d.ts +8 -0
  57. package/dist/types/sdk/broker/broker.d.ts +13 -2
  58. package/dist/types/sdk/broker/ensure.d.ts +46 -1
  59. package/dist/types/sdk/broker/identity.d.ts +3 -1
  60. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +23 -3
  61. package/dist/types/sdk/broker/lifecycle.d.ts +15 -8
  62. package/dist/types/sdk/broker/runtime.d.ts +1 -1
  63. package/dist/types/sdk/broker/session-index.d.ts +22 -3
  64. package/dist/types/sdk/broker/spawn-authority.d.ts +4 -0
  65. package/dist/types/sdk/broker/stderr-drainer.d.ts +13 -0
  66. package/dist/types/sdk/bus/index.d.ts +19 -0
  67. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +3 -1
  68. package/dist/types/sdk/bus/telegram-daemon.d.ts +5 -0
  69. package/dist/types/sdk/cli/master-cli.d.ts +6 -10
  70. package/dist/types/sdk/cli/rows.d.ts +19 -1
  71. package/dist/types/sdk/cli/session-cli.d.ts +22 -5
  72. package/dist/types/sdk/client/client.d.ts +2 -0
  73. package/dist/types/sdk/guides/cli.d.ts +3 -4
  74. package/dist/types/sdk/guides/verify.d.ts +2 -0
  75. package/dist/types/sdk/host/host.d.ts +9 -0
  76. package/dist/types/sdk/host/session-runtime.d.ts +31 -0
  77. package/dist/types/sdk/host/types.d.ts +10 -0
  78. package/dist/types/sdk/index.d.ts +1 -0
  79. package/dist/types/sdk/prompt-deadline-flush.d.ts +83 -0
  80. package/dist/types/sdk/prompt-deadline-manager.d.ts +38 -1
  81. package/dist/types/sdk/prompt-failure.d.ts +30 -1
  82. package/dist/types/sdk/prompt-status.d.ts +8 -0
  83. package/dist/types/sdk/prompt-tool-boundary.d.ts +73 -0
  84. package/dist/types/sdk/router/replay-retention-gap-cache.d.ts +13 -0
  85. package/dist/types/sdk/router/session-router.d.ts +2 -0
  86. package/dist/types/sdk/startup-capability.d.ts +2 -0
  87. package/dist/types/sdk/transport/relay.d.ts +1 -0
  88. package/dist/types/sdk/transport/serve-cli.d.ts +73 -2
  89. package/dist/types/sdk/transport/stdio.d.ts +5 -1
  90. package/dist/types/session/agent-session.d.ts +168 -21
  91. package/dist/types/session/fallback-chain-controller.d.ts +6 -6
  92. package/dist/types/session/fold-coordinator.d.ts +17 -3
  93. package/dist/types/session/internal/managed-session-storage.d.ts +7 -1
  94. package/dist/types/session/session-manager.d.ts +64 -1
  95. package/dist/types/session/session-work-lease.d.ts +14 -0
  96. package/dist/types/setup/model-onboarding-guidance.d.ts +1 -1
  97. package/dist/types/setup/provider-onboarding.d.ts +81 -1
  98. package/dist/types/thinking.d.ts +3 -1
  99. package/dist/types/tools/bash.d.ts +37 -11
  100. package/dist/types/tools/job.d.ts +1 -1
  101. package/dist/types/tools/steer-fold.d.ts +31 -0
  102. package/dist/types/utils/git.d.ts +28 -2
  103. package/dist/types/utils/mupdf-embedded.d.ts +2 -0
  104. package/dist/types/utils/mupdf-wasm-embedded.d.ts +2 -0
  105. package/dist/types/utils/mupdf.d.ts +4 -0
  106. package/dist/types/utils/session-title-generation.d.ts +6 -0
  107. package/dist/types/utils/title-generator.d.ts +11 -2
  108. package/dist/types/web/scrapers/types.d.ts +3 -0
  109. package/package.json +18 -10
  110. package/scripts/build-binary.ts +9 -3
  111. package/scripts/compile-args.ts +0 -9
  112. package/scripts/embed-mupdf.ts +52 -0
  113. package/scripts/generate-sdk-operation-inventory.ts +31 -1
  114. package/scripts/vendor-markit.ts +196 -0
  115. package/src/async/job-manager.ts +60 -9
  116. package/src/cli/daemon-cli.ts +53 -18
  117. package/src/cli/github-release.ts +87 -5
  118. package/src/cli/mcp-cli.ts +38 -4
  119. package/src/cli/public-command-entry.ts +450 -0
  120. package/src/cli/public-command-errors.ts +581 -0
  121. package/src/cli/public-command-evidence.ts +717 -0
  122. package/src/cli/public-command-help.ts +360 -0
  123. package/src/cli/public-command-registry.ts +535 -0
  124. package/src/cli/session-picker.ts +2 -1
  125. package/src/cli/setup-cli.ts +9 -1
  126. package/src/cli/skills-cli.ts +46 -2
  127. package/src/cli.ts +61 -1
  128. package/src/commands/daemon.ts +65 -69
  129. package/src/commands/sdk.ts +232 -100
  130. package/src/commands/setup.ts +2 -0
  131. package/src/commands/skills.ts +11 -0
  132. package/src/config/autorouting-tier-map.ts +16 -0
  133. package/src/config/file-lock.ts +199 -68
  134. package/src/config/model-profile-activation.ts +406 -53
  135. package/src/config/model-registry.ts +204 -25
  136. package/src/config/settings-schema.ts +26 -2
  137. package/src/coordinator-mcp/policy.ts +10 -5
  138. package/src/coordinator-mcp/question-gate-codec.ts +17 -0
  139. package/src/coordinator-mcp/question-state.ts +175 -8
  140. package/src/coordinator-mcp/server.ts +528 -87
  141. package/src/coordinator-mcp/session-reaper.ts +6 -4
  142. package/src/crash/record-loader.ts +6 -2
  143. package/src/daemon/operator-contract.ts +26 -12
  144. package/src/debug/report-bundle.ts +114 -24
  145. package/src/defaults/gjc/skills/ultragoal/SKILL.md +1 -1
  146. package/src/eval/js/context-manager.ts +8 -8
  147. package/src/eval/js/worker-core.ts +9 -4
  148. package/src/eval/js/worker-protocol.ts +2 -0
  149. package/src/extensibility/extensions/runner.ts +52 -4
  150. package/src/extensibility/extensions/types.ts +10 -0
  151. package/src/extensibility/gjc-plugins/registry.ts +196 -37
  152. package/src/extensibility/runtime-skill-discovery.ts +61 -3
  153. package/src/extensibility/shared-events.ts +3 -1
  154. package/src/gjc-runtime/managed-owner-admission.ts +67 -50
  155. package/src/gjc-runtime/session-state-lock.ts +165 -24
  156. package/src/gjc-runtime/ultragoal-succession.ts +31 -3
  157. package/src/internal-urls/docs-index.generated.ts +21 -19
  158. package/src/internal-urls/embedded-protocol.ts +83 -0
  159. package/src/internal-urls/index.ts +1 -0
  160. package/src/internal-urls/parse.ts +21 -1
  161. package/src/internal-urls/router.ts +4 -2
  162. package/src/main.ts +123 -55
  163. package/src/modes/acp/acp-agent.ts +593 -47
  164. package/src/modes/acp/acp-event-mapper.ts +9 -0
  165. package/src/modes/acp/startup-provenance.ts +59 -0
  166. package/src/modes/components/custom-provider-wizard.ts +308 -7
  167. package/src/modes/components/model-selector.ts +31 -15
  168. package/src/modes/components/oauth-selector.ts +9 -0
  169. package/src/modes/components/session-selector.ts +47 -4
  170. package/src/modes/components/status-line/segments.ts +6 -1
  171. package/src/modes/components/thinking-selector.ts +7 -3
  172. package/src/modes/components/user-message-selector.ts +57 -15
  173. package/src/modes/controllers/command-controller.ts +58 -32
  174. package/src/modes/controllers/extension-ui-controller.ts +33 -7
  175. package/src/modes/controllers/input-controller.ts +4 -0
  176. package/src/modes/controllers/selector-controller.ts +177 -18
  177. package/src/modes/interactive-mode.ts +21 -7
  178. package/src/modes/runtime-init.ts +1 -0
  179. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +124 -7
  180. package/src/modes/shared/agent-wire/workflow-gate-types.ts +16 -2
  181. package/src/modes/types.ts +2 -2
  182. package/src/prompts/agent-fragments/browser-aside.md +1 -0
  183. package/src/prompts/system/title-system.md +1 -1
  184. package/src/prompts/tools/bash.md +1 -1
  185. package/src/prompts/tools/job.md +1 -1
  186. package/src/prompts/tools/read.md +2 -0
  187. package/src/runtime/network-prewarm-service.test.ts +36 -1
  188. package/src/runtime/network-prewarm-service.ts +28 -3
  189. package/src/runtime/process-lifecycle.ts +22 -11
  190. package/src/runtime-mcp/config.ts +16 -1
  191. package/src/runtime-mcp/manager.ts +689 -55
  192. package/src/runtime-mcp/pool.test.ts +31 -0
  193. package/src/runtime-mcp/pool.ts +304 -28
  194. package/src/runtime-mcp/redaction.ts +42 -0
  195. package/src/runtime-mcp/startup-policy.ts +7 -0
  196. package/src/runtime-mcp/tool-bridge.ts +71 -0
  197. package/src/runtime-mcp/transports/http.ts +108 -25
  198. package/src/sdk/acp/adapter.ts +90 -9
  199. package/src/sdk/acp/final-text.ts +19 -2
  200. package/src/sdk/broker/broker.ts +378 -52
  201. package/src/sdk/broker/ensure.ts +97 -19
  202. package/src/sdk/broker/identity.ts +9 -1
  203. package/src/sdk/broker/lifecycle-ledger.ts +95 -31
  204. package/src/sdk/broker/lifecycle.ts +690 -141
  205. package/src/sdk/broker/runtime.ts +1 -1
  206. package/src/sdk/broker/session-index.ts +97 -4
  207. package/src/sdk/broker/spawn-authority.ts +35 -7
  208. package/src/sdk/broker/stderr-drainer.ts +59 -0
  209. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  210. package/src/sdk/bus/chat-daemon-runtime.ts +1 -0
  211. package/src/sdk/bus/index.ts +721 -84
  212. package/src/sdk/bus/telegram-daemon-cli.ts +31 -2
  213. package/src/sdk/bus/telegram-daemon-contract.ts +3 -1
  214. package/src/sdk/bus/telegram-daemon.ts +10 -3
  215. package/src/sdk/cli/master-cli.ts +47 -36
  216. package/src/sdk/cli/rows.ts +30 -7
  217. package/src/sdk/cli/session-cli.ts +687 -184
  218. package/src/sdk/client/client.ts +18 -0
  219. package/src/sdk/guides/catalog.ts +2 -2
  220. package/src/sdk/guides/cli.ts +20 -62
  221. package/src/sdk/guides/verify.ts +14 -0
  222. package/src/sdk/host/host.ts +49 -5
  223. package/src/sdk/host/session-runtime.test.ts +636 -9
  224. package/src/sdk/host/session-runtime.ts +499 -118
  225. package/src/sdk/host/types.ts +12 -1
  226. package/src/sdk/host/websocket-transport.lifecycle.test.ts +84 -0
  227. package/src/sdk/host/websocket-transport.ts +40 -6
  228. package/src/sdk/index.ts +11 -0
  229. package/src/sdk/prompt-deadline-flush.ts +334 -0
  230. package/src/sdk/prompt-deadline-manager.ts +136 -4
  231. package/src/sdk/prompt-failure.ts +43 -1
  232. package/src/sdk/prompt-status.ts +8 -0
  233. package/src/sdk/prompt-tool-boundary.ts +121 -0
  234. package/src/sdk/protocol/operation-inventory.generated.json +106 -0
  235. package/src/sdk/router/replay-retention-gap-cache.ts +27 -0
  236. package/src/sdk/router/session-router.ts +31 -4
  237. package/src/sdk/session.ts +194 -16
  238. package/src/sdk/startup-capability.ts +1 -1
  239. package/src/sdk/transport/relay.ts +71 -6
  240. package/src/sdk/transport/serve-cli.ts +494 -49
  241. package/src/sdk/transport/socket.ts +12 -11
  242. package/src/sdk/transport/stdio.ts +7 -3
  243. package/src/session/agent-session.ts +2437 -400
  244. package/src/session/fallback-chain-controller.ts +6 -7
  245. package/src/session/fold-coordinator.ts +24 -5
  246. package/src/session/internal/managed-session-scope.ts +58 -18
  247. package/src/session/internal/managed-session-storage.ts +304 -11
  248. package/src/session/session-manager.ts +382 -44
  249. package/src/session/session-work-lease.ts +34 -0
  250. package/src/session-import/codex.ts +12 -3
  251. package/src/setup/model-onboarding-guidance.ts +1 -1
  252. package/src/setup/provider-onboarding.ts +397 -24
  253. package/src/slash-commands/builtin-registry.ts +258 -14
  254. package/src/task/index.ts +14 -2
  255. package/src/thinking.ts +21 -2
  256. package/src/tools/bash.ts +98 -78
  257. package/src/tools/fetch.ts +119 -20
  258. package/src/tools/job.ts +151 -25
  259. package/src/tools/output-meta.ts +15 -2
  260. package/src/tools/path-utils.ts +27 -3
  261. package/src/tools/read.ts +3 -3
  262. package/src/tools/steer-fold.ts +107 -0
  263. package/src/tools/tool-catalog.generated.ts +29 -2
  264. package/src/tools/tool-errors.ts +4 -0
  265. package/src/utils/git.ts +53 -3
  266. package/src/utils/markit.ts +55 -41
  267. package/src/utils/mupdf-assets.d.ts +4 -0
  268. package/src/utils/mupdf-embedded.ts +4 -0
  269. package/src/utils/mupdf-wasm-embedded.ts +3 -0
  270. package/src/utils/mupdf-wasm.ts +24 -2
  271. package/src/utils/mupdf.ts +129 -0
  272. package/src/utils/session-title-generation.ts +29 -0
  273. package/src/utils/title-generator.ts +46 -2
  274. package/src/web/scrapers/types.ts +24 -3
  275. package/vendor/markit-ai/LICENSE +21 -0
  276. package/vendor/markit-ai/MANIFEST.json +412 -0
  277. package/vendor/markit-ai/dist/commands/config.d.ts +4 -0
  278. package/vendor/markit-ai/dist/commands/config.js +139 -0
  279. package/vendor/markit-ai/dist/commands/convert.d.ts +6 -0
  280. package/vendor/markit-ai/dist/commands/convert.js +113 -0
  281. package/vendor/markit-ai/dist/commands/formats.d.ts +2 -0
  282. package/vendor/markit-ai/dist/commands/formats.js +92 -0
  283. package/vendor/markit-ai/dist/commands/init.d.ts +2 -0
  284. package/vendor/markit-ai/dist/commands/init.js +29 -0
  285. package/vendor/markit-ai/dist/commands/onboard.d.ts +2 -0
  286. package/vendor/markit-ai/dist/commands/onboard.js +61 -0
  287. package/vendor/markit-ai/dist/commands/plugin.d.ts +4 -0
  288. package/vendor/markit-ai/dist/commands/plugin.js +58 -0
  289. package/vendor/markit-ai/dist/config.d.ts +26 -0
  290. package/vendor/markit-ai/dist/config.js +42 -0
  291. package/vendor/markit-ai/dist/converters/audio.d.ts +7 -0
  292. package/vendor/markit-ai/dist/converters/audio.js +104 -0
  293. package/vendor/markit-ai/dist/converters/csv.d.ts +7 -0
  294. package/vendor/markit-ai/dist/converters/csv.js +83 -0
  295. package/vendor/markit-ai/dist/converters/docx.d.ts +6 -0
  296. package/vendor/markit-ai/dist/converters/docx.js +57 -0
  297. package/vendor/markit-ai/dist/converters/epub.d.ts +8 -0
  298. package/vendor/markit-ai/dist/converters/epub.js +128 -0
  299. package/vendor/markit-ai/dist/converters/github.d.ts +18 -0
  300. package/vendor/markit-ai/dist/converters/github.js +148 -0
  301. package/vendor/markit-ai/dist/converters/html.d.ts +6 -0
  302. package/vendor/markit-ai/dist/converters/html.js +30 -0
  303. package/vendor/markit-ai/dist/converters/image.d.ts +6 -0
  304. package/vendor/markit-ai/dist/converters/image.js +124 -0
  305. package/vendor/markit-ai/dist/converters/ipynb.d.ts +6 -0
  306. package/vendor/markit-ai/dist/converters/ipynb.js +75 -0
  307. package/vendor/markit-ai/dist/converters/iwork.d.ts +20 -0
  308. package/vendor/markit-ai/dist/converters/iwork.js +391 -0
  309. package/vendor/markit-ai/dist/converters/json.d.ts +6 -0
  310. package/vendor/markit-ai/dist/converters/json.js +21 -0
  311. package/vendor/markit-ai/dist/converters/pdf/columns.d.ts +35 -0
  312. package/vendor/markit-ai/dist/converters/pdf/columns.js +93 -0
  313. package/vendor/markit-ai/dist/converters/pdf/extract.d.ts +19 -0
  314. package/vendor/markit-ai/dist/converters/pdf/extract.js +514 -0
  315. package/vendor/markit-ai/dist/converters/pdf/grid.d.ts +25 -0
  316. package/vendor/markit-ai/dist/converters/pdf/grid.js +795 -0
  317. package/vendor/markit-ai/dist/converters/pdf/headers.d.ts +24 -0
  318. package/vendor/markit-ai/dist/converters/pdf/headers.js +108 -0
  319. package/vendor/markit-ai/dist/converters/pdf/index.d.ts +19 -0
  320. package/vendor/markit-ai/dist/converters/pdf/index.js +136 -0
  321. package/vendor/markit-ai/dist/converters/pdf/mupdf-loader.js +9 -0
  322. package/vendor/markit-ai/dist/converters/pdf/render.d.ts +24 -0
  323. package/vendor/markit-ai/dist/converters/pdf/render.js +513 -0
  324. package/vendor/markit-ai/dist/converters/pdf/types.d.ts +75 -0
  325. package/vendor/markit-ai/dist/converters/pdf/types.js +1 -0
  326. package/vendor/markit-ai/dist/converters/plain-text.d.ts +6 -0
  327. package/vendor/markit-ai/dist/converters/plain-text.js +87 -0
  328. package/vendor/markit-ai/dist/converters/pptx.d.ts +8 -0
  329. package/vendor/markit-ai/dist/converters/pptx.js +289 -0
  330. package/vendor/markit-ai/dist/converters/rss.d.ts +11 -0
  331. package/vendor/markit-ai/dist/converters/rss.js +138 -0
  332. package/vendor/markit-ai/dist/converters/wikipedia.d.ts +6 -0
  333. package/vendor/markit-ai/dist/converters/wikipedia.js +33 -0
  334. package/vendor/markit-ai/dist/converters/xlsx.d.ts +8 -0
  335. package/vendor/markit-ai/dist/converters/xlsx.js +147 -0
  336. package/vendor/markit-ai/dist/converters/xml.d.ts +6 -0
  337. package/vendor/markit-ai/dist/converters/xml.js +18 -0
  338. package/vendor/markit-ai/dist/converters/yaml.d.ts +6 -0
  339. package/vendor/markit-ai/dist/converters/yaml.js +17 -0
  340. package/vendor/markit-ai/dist/converters/zip.d.ts +8 -0
  341. package/vendor/markit-ai/dist/converters/zip.js +57 -0
  342. package/vendor/markit-ai/dist/index.d.ts +30 -0
  343. package/vendor/markit-ai/dist/index.js +26 -0
  344. package/vendor/markit-ai/dist/main.d.ts +2 -0
  345. package/vendor/markit-ai/dist/main.js +191 -0
  346. package/vendor/markit-ai/dist/markit.d.ts +45 -0
  347. package/vendor/markit-ai/dist/markit.js +267 -0
  348. package/vendor/markit-ai/dist/plugins/api.d.ts +7 -0
  349. package/vendor/markit-ai/dist/plugins/api.js +42 -0
  350. package/vendor/markit-ai/dist/plugins/index.d.ts +4 -0
  351. package/vendor/markit-ai/dist/plugins/index.js +3 -0
  352. package/vendor/markit-ai/dist/plugins/installer.d.ts +25 -0
  353. package/vendor/markit-ai/dist/plugins/installer.js +176 -0
  354. package/vendor/markit-ai/dist/plugins/loader.d.ts +6 -0
  355. package/vendor/markit-ai/dist/plugins/loader.js +61 -0
  356. package/vendor/markit-ai/dist/plugins/types.d.ts +25 -0
  357. package/vendor/markit-ai/dist/plugins/types.js +1 -0
  358. package/vendor/markit-ai/dist/providers/anthropic.d.ts +2 -0
  359. package/vendor/markit-ai/dist/providers/anthropic.js +47 -0
  360. package/vendor/markit-ai/dist/providers/index.d.ts +21 -0
  361. package/vendor/markit-ai/dist/providers/index.js +56 -0
  362. package/vendor/markit-ai/dist/providers/openai.d.ts +2 -0
  363. package/vendor/markit-ai/dist/providers/openai.js +76 -0
  364. package/vendor/markit-ai/dist/providers/types.d.ts +26 -0
  365. package/vendor/markit-ai/dist/providers/types.js +1 -0
  366. package/vendor/markit-ai/dist/types.d.ts +36 -0
  367. package/vendor/markit-ai/dist/types.js +1 -0
  368. package/vendor/markit-ai/dist/utils/exit-codes.d.ts +4 -0
  369. package/vendor/markit-ai/dist/utils/exit-codes.js +4 -0
  370. package/vendor/markit-ai/dist/utils/output.d.ts +22 -0
  371. package/vendor/markit-ai/dist/utils/output.js +31 -0
  372. package/vendor/markit-ai/dist/utils/turndown.d.ts +8 -0
  373. package/vendor/markit-ai/dist/utils/turndown.js +70 -0
  374. package/vendor/markit-ai/package.json +74 -0
  375. package/vendor/markit-ai.patch +49 -0
@@ -59,6 +59,7 @@ import { loadCapability, reset as resetCapabilities } from "../capability";
59
59
  import { type Rule, ruleCapability, setActiveRules } from "../capability/rule";
60
60
  import type { SourceMeta } from "../capability/types";
61
61
  import { AUTOROUTING_INACTIVE_WARNING } from "../config/autorouting-contract";
62
+ import { ModelProfileCredentialError, resolveMissingSessionModelRecovery } from "../config/model-profile-activation";
62
63
  import { resolveModelProfileName } from "../config/model-profile-contract";
63
64
  import { resolveProfileBindings } from "../config/model-profiles";
64
65
  import { kNoAuth, ModelRegistry } from "../config/model-registry";
@@ -144,7 +145,7 @@ import {
144
145
  createOptionalRuntimeServices,
145
146
  type OptionalRuntimeServicesOverrides,
146
147
  } from "../runtime/optional-runtime-services";
147
- import { loadAllMCPConfigs, MCPManager } from "../runtime-mcp";
148
+ import { isMCPStartupTimeoutError, loadAllMCPConfigs, MCPManager } from "../runtime-mcp";
148
149
  import type { MCPLoadResult } from "../runtime-mcp/manager";
149
150
  import type { MCPServerConfig } from "../runtime-mcp/types";
150
151
  import {
@@ -1516,6 +1517,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
1516
1517
  let processCwdClaimed = false;
1517
1518
  let hasRegistered = false;
1518
1519
  let asyncJobManager: AsyncJobManager | undefined;
1520
+ let asyncJobManagerOwned = false;
1519
1521
  let asyncJobManagerAdmitted = false;
1520
1522
  let priorAsyncJobManager: AsyncJobManager | undefined;
1521
1523
  let cleanupOwnedMcpManager: (() => Promise<void>) | undefined;
@@ -1967,9 +1969,22 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
1967
1969
  const persistedProfileOwnsDefault = acceptedPersistedProfileName
1968
1970
  ? resolveProfileBindings(persistedProfiles.get(acceptedPersistedProfileName)!).defaultSelector !== undefined
1969
1971
  : false;
1970
- const startupActiveModelProfile =
1972
+ let startupActiveModelProfile =
1971
1973
  acceptedInheritedProfileName ??
1972
1974
  (!hasExplicitModel && acceptedPersistedProfileName ? acceptedPersistedProfileName : undefined);
1975
+ let savedDefaultWasUnresolved = false;
1976
+ let deferredMissingSessionRecovery = false;
1977
+ let retainedRecoveryBindingsAfterLateRestore = false;
1978
+ let recoveredSessionDefault:
1979
+ | {
1980
+ entries: string[];
1981
+ profileName: string;
1982
+ activeIndex: number;
1983
+ thinkingLevel?: ThinkingLevel;
1984
+ explicitThinkingLevel: boolean;
1985
+ skips: Array<{ selector: string; reason: string }>;
1986
+ }
1987
+ | undefined;
1973
1988
  // If session has data, restore its configured default chain rather than the
1974
1989
  // scalar runtime model, which may be a stale fallback from the prior run.
1975
1990
  if (!hasExplicitModel && !model && hasExistingSession && defaultModelEntries.length > 0) {
@@ -1993,6 +2008,33 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
1993
2008
  if (model && preferredCredentialProvider && model.provider !== preferredCredentialProvider) {
1994
2009
  model = undefined;
1995
2010
  }
2011
+ savedDefaultWasUnresolved = !model;
2012
+ if (!model && resumeModelBehavior !== "useCurrentDefault") {
2013
+ try {
2014
+ const recovery = await resolveMissingSessionModelRecovery({
2015
+ modelRegistry,
2016
+ settings,
2017
+ defaultEntries: defaultModelEntries,
2018
+ skips: restoredDefaultResolution.skips,
2019
+ savedDefault: existingSession.models.default,
2020
+ credentialSessionId,
2021
+ ...(persistedProfileOwnsDefault ? { aliasIntent: "preset-equivalent" as const } : {}),
2022
+ });
2023
+ deferredMissingSessionRecovery = true;
2024
+ if (
2025
+ recovery?.model &&
2026
+ (!preferredCredentialProvider || recovery.model.provider === preferredCredentialProvider)
2027
+ ) {
2028
+ model = recovery.model;
2029
+ recoveredSessionDefault = recovery;
2030
+ startupActiveModelProfile = undefined;
2031
+ modelFallbackMessage =
2032
+ "Saved session model is no longer registered; restored the durable default preset instead.";
2033
+ }
2034
+ } catch {
2035
+ deferredMissingSessionRecovery = true;
2036
+ }
2037
+ }
1996
2038
  if (!model) modelFallbackMessage = `Could not restore model ${defaultModelEntries.join(" -> ")}`;
1997
2039
  });
1998
2040
  }
@@ -2028,6 +2070,14 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
2028
2070
  thinkingLevel = restoredThinkingLevel;
2029
2071
  }
2030
2072
 
2073
+ if (
2074
+ thinkingLevel === undefined &&
2075
+ (restoredThinkingLevel === undefined || restoredThinkingLevel === ThinkingLevel.Inherit) &&
2076
+ recoveredSessionDefault?.explicitThinkingLevel
2077
+ ) {
2078
+ thinkingLevel = recoveredSessionDefault.thinkingLevel;
2079
+ }
2080
+
2031
2081
  if (thinkingLevel === undefined && !hasExplicitModel && defaultRoleSpec.explicitThinkingLevel) {
2032
2082
  thinkingLevel = defaultRoleSpec.thinkingLevel;
2033
2083
  }
@@ -2296,6 +2346,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
2296
2346
  },
2297
2347
  })
2298
2348
  : options.inheritedAsyncJobManager;
2349
+ asyncJobManagerOwned = backgroundJobsEnabled === true && !options.parentTaskPrefix;
2299
2350
 
2300
2351
  let promptMetadataModel: Model | undefined;
2301
2352
  const getActiveModelString = (): string | undefined => {
@@ -3128,10 +3179,12 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
3128
3179
  // consumed (publication happens before the starter can run), which is
3129
3180
  // acceptable only because deferral never carries plugin-bundle servers.
3130
3181
  gjcProducersComplete = false;
3131
- logger.warn("GJC plugin MCP connect failed", {
3132
- path: `mcp:${server}`,
3133
- error: safeErrorForLog(err),
3134
- });
3182
+ if (!isMCPStartupTimeoutError(err)) {
3183
+ logger.warn("GJC plugin MCP connect failed", {
3184
+ path: `mcp:${server}`,
3185
+ error: safeErrorForLog(err),
3186
+ });
3187
+ }
3135
3188
  }
3136
3189
  const connectedPluginNames = new Set(result.connectedServers.filter(name => pluginNames.has(name)));
3137
3190
  // Retain while any conventional server is still live: "connecting"
@@ -3493,6 +3546,10 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
3493
3546
  if (!session) throw new Error("Terminal abort session is not initialized.");
3494
3547
  return session.abortPromptAndWait(handle, seamOptions);
3495
3548
  },
3549
+ pendingToolExecutions: handle => {
3550
+ if (!session) throw new Error("Terminal abort session is not initialized.");
3551
+ return session.pendingToolExecutions(handle);
3552
+ },
3496
3553
  },
3497
3554
  ensureProviderDaemon: options.ensureNotificationProviderDaemon,
3498
3555
  runBtwTurn: async (question, signal) => {
@@ -3583,6 +3640,10 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
3583
3640
  if (!session) throw new Error("Terminal abort session is not initialized.");
3584
3641
  return session.abortPromptAndWait(handle, seamOptions);
3585
3642
  },
3643
+ pendingToolExecutions: handle => {
3644
+ if (!session) throw new Error("Terminal abort session is not initialized.");
3645
+ return session.pendingToolExecutions(handle);
3646
+ },
3586
3647
  },
3587
3648
  });
3588
3649
  }
@@ -3701,6 +3762,103 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
3701
3762
  extensionsResult.runtime.pendingProviderRegistrations = [];
3702
3763
  }
3703
3764
 
3765
+ // A startup extension can register the saved model after the initial
3766
+ // recovery lookup. Reconsider the saved chain against that completed
3767
+ // catalog before retaining a durable runtime fallback.
3768
+ if (savedDefaultWasUnresolved && defaultModelEntries.length > 0) {
3769
+ const restoredAfterExtensions = await resolveModelChainWithAuth(
3770
+ defaultModelEntries,
3771
+ modelRegistry,
3772
+ settings,
3773
+ credentialSessionId,
3774
+ {
3775
+ managedFallback: defaultModelEntries.length > 1,
3776
+ canonicalSessionId: providerSessionId,
3777
+ ...(persistedProfileOwnsDefault ? { aliasIntent: "preset-equivalent" as const } : {}),
3778
+ },
3779
+ );
3780
+ if (
3781
+ restoredAfterExtensions.model &&
3782
+ (!preferredCredentialProvider || restoredAfterExtensions.model.provider === preferredCredentialProvider)
3783
+ ) {
3784
+ model = restoredAfterExtensions.model;
3785
+ retainedRecoveryBindingsAfterLateRestore = savedDefaultWasUnresolved;
3786
+ if (options.thinkingLevel !== undefined) {
3787
+ thinkingLevel = resolveThinkingLevelForModel(model, options.thinkingLevel);
3788
+ } else if (restoredThinkingLevel !== undefined && restoredThinkingLevel !== ThinkingLevel.Inherit) {
3789
+ thinkingLevel = resolveThinkingLevelForModel(model, restoredThinkingLevel);
3790
+ } else {
3791
+ thinkingLevel = restoredAfterExtensions.explicitThinkingLevel
3792
+ ? restoredAfterExtensions.thinkingLevel
3793
+ : undefined;
3794
+ if (thinkingLevel === undefined && !hasExplicitModel && defaultRoleSpec.explicitThinkingLevel)
3795
+ thinkingLevel = defaultRoleSpec.thinkingLevel;
3796
+ if (thinkingLevel === undefined && hasExplicitDefaultThinkingLevel)
3797
+ thinkingLevel = settings.get("defaultThinkingLevel");
3798
+ if (thinkingLevel === undefined && model.thinking?.defaultLevel !== undefined)
3799
+ thinkingLevel = model.thinking.defaultLevel;
3800
+ if (thinkingLevel === undefined) thinkingLevel = settings.get("defaultThinkingLevel");
3801
+ thinkingLevel = resolveThinkingLevelForModel(model, thinkingLevel);
3802
+ }
3803
+ recoveredSessionDefault = undefined;
3804
+ startupActiveModelProfile =
3805
+ acceptedInheritedProfileName ??
3806
+ (!hasExplicitModel && acceptedPersistedProfileName ? acceptedPersistedProfileName : undefined);
3807
+ modelFallbackMessage = undefined;
3808
+ } else if (deferredMissingSessionRecovery) {
3809
+ const hadProvisionalRecovery = recoveredSessionDefault !== undefined;
3810
+ let lateRecoveryAccepted = false;
3811
+ try {
3812
+ const recovery = await resolveMissingSessionModelRecovery({
3813
+ modelRegistry,
3814
+ settings,
3815
+ defaultEntries: defaultModelEntries,
3816
+ skips: restoredAfterExtensions.skips,
3817
+ savedDefault: existingSession.models.default,
3818
+ credentialSessionId,
3819
+ ...(persistedProfileOwnsDefault ? { aliasIntent: "preset-equivalent" as const } : {}),
3820
+ });
3821
+ if (
3822
+ recovery?.model &&
3823
+ (!preferredCredentialProvider || recovery.model.provider === preferredCredentialProvider)
3824
+ ) {
3825
+ model = recovery.model;
3826
+ if (options.thinkingLevel !== undefined) {
3827
+ thinkingLevel = resolveThinkingLevelForModel(model, options.thinkingLevel);
3828
+ } else if (restoredThinkingLevel !== undefined && restoredThinkingLevel !== ThinkingLevel.Inherit) {
3829
+ thinkingLevel = resolveThinkingLevelForModel(model, restoredThinkingLevel);
3830
+ } else {
3831
+ const recoveredLevel = recovery.explicitThinkingLevel
3832
+ ? recovery.thinkingLevel
3833
+ : defaultRoleSpec.explicitThinkingLevel
3834
+ ? defaultRoleSpec.thinkingLevel
3835
+ : hasExplicitDefaultThinkingLevel
3836
+ ? settings.get("defaultThinkingLevel")
3837
+ : (model.thinking?.defaultLevel ?? settings.get("defaultThinkingLevel"));
3838
+ thinkingLevel = resolveThinkingLevelForModel(model, recoveredLevel);
3839
+ }
3840
+ recoveredSessionDefault = recovery;
3841
+ startupActiveModelProfile = undefined;
3842
+ modelFallbackMessage =
3843
+ "Saved session model is no longer registered; restored the durable default preset instead.";
3844
+ lateRecoveryAccepted = true;
3845
+ }
3846
+ } catch (error) {
3847
+ if (!(error instanceof ModelProfileCredentialError)) throw error;
3848
+ }
3849
+ // A completed extension catalog can make the saved selector registered
3850
+ // again without making it callable. Do not retain the provisional durable
3851
+ // fallback in that case: the saved model remains authoritative for the
3852
+ // normal unavailable-model path below.
3853
+ if (!lateRecoveryAccepted && hadProvisionalRecovery) {
3854
+ model = undefined;
3855
+ recoveredSessionDefault = undefined;
3856
+ startupActiveModelProfile = undefined;
3857
+ modelFallbackMessage = `Could not restore model ${defaultModelEntries.join(" -> ")}`;
3858
+ }
3859
+ }
3860
+ }
3861
+
3704
3862
  let startupCredentialModelRejected = false;
3705
3863
  if (startupModelReference && (startupCredentialSelector || startupCredentialProviderMismatch)) {
3706
3864
  const validated =
@@ -4788,6 +4946,14 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
4788
4946
  providerSessionState: options.providerSessionState,
4789
4947
  });
4790
4948
  session.setActiveModelProfile(startupActiveModelProfile);
4949
+ if (retainedRecoveryBindingsAfterLateRestore) session.markStartupRecoveryBindingsRequired();
4950
+ if (recoveredSessionDefault)
4951
+ session.installRecoveredDefaultFallbackChain(
4952
+ recoveredSessionDefault.entries,
4953
+ recoveredSessionDefault.profileName,
4954
+ recoveredSessionDefault.activeIndex,
4955
+ recoveredSessionDefault.skips,
4956
+ );
4791
4957
  session.configWarnings.push(...contextFileWarnings);
4792
4958
  // Determined once, here, where settings are already available. Keep the
4793
4959
  // durable warning for interactive and print consumers; ACP delivery is
@@ -5082,7 +5248,18 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
5082
5248
  let hasErrors = false;
5083
5249
  if (exact) {
5084
5250
  const result = await exact.manager.discoverAndConnect({ configPath: exact.configPath });
5085
- const resultTools = result.tools as CustomTool[];
5251
+ // A slash control may commit while the deferred startup flight is
5252
+ // loading. Re-read the manager's fenced publication rather than
5253
+ // replaying the stale startup snapshot into the session registry. A
5254
+ // deferred manager can still be waiting to publish its first catalog,
5255
+ // though; only that explicit unpublished state may use the discovery
5256
+ // result. Empty published/fenced catalogs are authoritative and must
5257
+ // not replay stale tools across an exact control.
5258
+ const catalog = exact.manager.getToolCatalogSnapshot();
5259
+ const resultTools =
5260
+ catalog.publication === "unpublished"
5261
+ ? (result.tools as CustomTool[])
5262
+ : (catalog.tools as CustomTool[]);
5086
5263
  const toolNames = resultTools.map(tool => tool.name);
5087
5264
  const collidingToolNames = findDeferredExactMcpToolNameCollisions(
5088
5265
  toolNames,
@@ -5196,15 +5373,16 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
5196
5373
  } else {
5197
5374
  if (hasRegistered) agentRegistry.unregister(resolvedAgentId);
5198
5375
  // Admission happens before session construction. Any later startup
5199
- // failure must remove THIS manager's endpoint mapping and restore
5200
- // the prior global only when this manager is still global: otherwise
5201
- // a retry under the same endpoint is falsely rejected and an orphan
5202
- // redirects global-manager consumers away from the live session
5203
- // (review thread P1).
5204
- if (asyncJobManagerAdmitted && asyncJobManager) {
5205
- AsyncJobManager.unregisterManager(asyncJobManager);
5206
- if (AsyncJobManager.instance() === asyncJobManager) {
5207
- AsyncJobManager.setInstance(priorAsyncJobManager);
5376
+ // failure must eventually release THIS manager's endpoint mapping
5377
+ // through disposal and restore the prior global only when this manager
5378
+ // is still global: otherwise a retry under the same endpoint is falsely
5379
+ // rejected and an orphan redirects global-manager consumers away from
5380
+ // the live session (review thread P1).
5381
+ if (asyncJobManagerOwned && asyncJobManager) {
5382
+ if (asyncJobManagerAdmitted) {
5383
+ if (AsyncJobManager.instance() === asyncJobManager) {
5384
+ AsyncJobManager.setInstance(priorAsyncJobManager);
5385
+ }
5208
5386
  }
5209
5387
  await asyncJobManager.dispose({ timeoutMs: 100 });
5210
5388
  }
@@ -161,7 +161,7 @@ export function normalizeSdkStartupFailure(
161
161
  }
162
162
 
163
163
  /** Collect process-scoped credentials without exposing a raw-secret API. */
164
- function lifecycleKnownSecrets(): string[] {
164
+ export function lifecycleKnownSecrets(): string[] {
165
165
  return Object.entries(process.env)
166
166
  .filter(([name, value]) => value && /(?:token|secret|password|credential|api[_-]?key|auth)/iu.test(name))
167
167
  .map(([, value]) => value!);
@@ -3,6 +3,7 @@ import type { Readable, Writable } from "node:stream";
3
3
  export const REQUEST_FRAME_BYTES = 256 * 1024;
4
4
  export const DEFAULT_PENDING_CEILING_BYTES = 8 * 1024 * 1024;
5
5
  export const MIN_PENDING_CEILING_BYTES = REQUEST_FRAME_BYTES;
6
+ export const DEFAULT_UPSTREAM_HELLO_TIMEOUT_MS = 10_000;
6
7
 
7
8
  export type RelayDirection = "downstream->ws" | "ws->downstream";
8
9
  export type TransportError = {
@@ -34,6 +35,19 @@ export type RelayWebSocket = {
34
35
  removeEventListener(type: string, listener: (event: RelayWebSocketEvent) => void): void;
35
36
  };
36
37
 
38
+ /** The upstream host's hello marks the point at which downstream frames may be sent. */
39
+ function isServerHello(text: string): boolean {
40
+ let parsed: unknown;
41
+ try {
42
+ parsed = JSON.parse(text);
43
+ } catch {
44
+ return false;
45
+ }
46
+ return Boolean(
47
+ parsed && typeof parsed === "object" && !Array.isArray(parsed) && (parsed as { type?: unknown }).type === "hello",
48
+ );
49
+ }
50
+
37
51
  export type RelayOptions = {
38
52
  url: string;
39
53
  token: string;
@@ -112,6 +126,14 @@ export async function startRelayPair(options: RelayOptions): Promise<RelayPair>
112
126
  let pendingToDownstream = 0;
113
127
  let writingWs = false;
114
128
  let writingDownstream = false;
129
+ // Capability authority belongs to the downstream client. Buffer its hello and
130
+ // requests until the upstream's (possibly minimal) hello has arrived, then
131
+ // forward the exact bytes unchanged in order.
132
+ let upstreamHelloReceived = false;
133
+ let preHelloToWs: Buffer[] = [];
134
+ let preHelloToWsBytes = 0;
135
+ let upstreamHelloTimer: ReturnType<typeof setTimeout> | undefined;
136
+ let openingSettled = false;
115
137
 
116
138
  const settle = (error?: Error): void => {
117
139
  if (completed) return;
@@ -121,6 +143,8 @@ export async function startRelayPair(options: RelayOptions): Promise<RelayPair>
121
143
  };
122
144
  void finished.promise.catch(() => undefined);
123
145
  const detach = (): void => {
146
+ if (upstreamHelloTimer !== undefined) clearTimeout(upstreamHelloTimer);
147
+ upstreamHelloTimer = undefined;
124
148
  options.downstream.removeListener("data", onData);
125
149
  options.downstream.removeListener("end", onEnd);
126
150
  options.downstream.removeListener("error", onDownstreamError);
@@ -213,7 +237,14 @@ export async function startRelayPair(options: RelayOptions): Promise<RelayPair>
213
237
  downstreamBytes = 0;
214
238
  if (options.validateDownstreamFrame && !options.validateDownstreamFrame(line.toString("utf8")))
215
239
  return fail({ type: "transport_error", code: "protocol_error", direction: "downstream->ws" });
216
- enqueue(toWs, "downstream->ws", line);
240
+ if (!upstreamHelloReceived) {
241
+ if (preHelloToWsBytes + line.length > options.pendingCeilingBytes) {
242
+ fail({ type: "transport_error", code: "pending_overflow", direction: "downstream->ws" });
243
+ return;
244
+ }
245
+ preHelloToWs.push(line);
246
+ preHelloToWsBytes += line.length;
247
+ } else enqueue(toWs, "downstream->ws", line);
217
248
  if (closed) return;
218
249
  start = newline + 1;
219
250
  newline = chunk.indexOf(0x0a, start);
@@ -233,20 +264,54 @@ export async function startRelayPair(options: RelayOptions): Promise<RelayPair>
233
264
  fail({ type: "transport_error", code: "protocol_error", direction: "ws->downstream" });
234
265
  return;
235
266
  }
267
+ if (!upstreamHelloReceived && isServerHello(event.data)) {
268
+ upstreamHelloReceived = true;
269
+ if (upstreamHelloTimer !== undefined) clearTimeout(upstreamHelloTimer);
270
+ upstreamHelloTimer = undefined;
271
+ const queued = preHelloToWs;
272
+ preHelloToWs = [];
273
+ preHelloToWsBytes = 0;
274
+ for (const frame of queued) enqueue(toWs, "downstream->ws", frame);
275
+ }
236
276
  enqueue(toDownstream, "ws->downstream", Buffer.concat([Buffer.from(event.data, "utf8"), Buffer.from("\n")]));
237
277
  };
238
- const onClose = (): void => void close();
239
- const onWebSocketError = (): void => void close(new Error("upstream_error"));
278
+ const onClose = (): void => {
279
+ if (!openingSettled) {
280
+ openingSettled = true;
281
+ opened.reject(new Error("upstream_closed"));
282
+ }
283
+ void close();
284
+ };
285
+ const onWebSocketError = (): void => {
286
+ if (!openingSettled) {
287
+ openingSettled = true;
288
+ opened.reject(new Error("upstream_error"));
289
+ }
290
+ void close(new Error("upstream_error"));
291
+ };
240
292
  const onOpen = (): void => {
293
+ if (openingSettled) return;
294
+ openingSettled = true;
241
295
  cleanupOpening();
296
+ if (!upstreamHelloReceived) {
297
+ upstreamHelloTimer = setTimeout(() => {
298
+ if (!upstreamHelloReceived && !closed)
299
+ fail({ type: "transport_error", code: "protocol_error", direction: "ws->downstream" });
300
+ }, DEFAULT_UPSTREAM_HELLO_TIMEOUT_MS);
301
+ upstreamHelloTimer.unref?.();
302
+ }
242
303
  opened.resolve();
243
304
  };
244
305
  const onOpenError = (): void => {
306
+ if (openingSettled) return;
307
+ openingSettled = true;
245
308
  cleanupOpening();
246
309
  opened.reject(new Error("upstream_error"));
247
310
  };
248
311
  const onAbort = (): void => {
249
312
  const error = new RelayOpenAbortedError();
313
+ if (openingSettled) return;
314
+ openingSettled = true;
250
315
  cleanupOpening();
251
316
  opened.reject(error);
252
317
  void close(error);
@@ -258,6 +323,9 @@ export async function startRelayPair(options: RelayOptions): Promise<RelayPair>
258
323
  };
259
324
  ws.addEventListener("open", onOpen, { once: true });
260
325
  ws.addEventListener("error", onOpenError, { once: true });
326
+ ws.addEventListener("message", onMessage);
327
+ ws.addEventListener("close", onClose);
328
+ ws.addEventListener("error", onWebSocketError);
261
329
  options.signal?.addEventListener("abort", onAbort, { once: true });
262
330
  try {
263
331
  await opened.promise;
@@ -265,9 +333,6 @@ export async function startRelayPair(options: RelayOptions): Promise<RelayPair>
265
333
  await close(error instanceof Error ? error : new Error(String(error)));
266
334
  throw error;
267
335
  }
268
- ws.addEventListener("message", onMessage);
269
- ws.addEventListener("close", onClose);
270
- ws.addEventListener("error", onWebSocketError);
271
336
  options.downstream.on("data", onData);
272
337
  options.downstream.once("end", onEnd);
273
338
  options.downstream.once("error", onDownstreamError);