@the-open-engine/zeroshot 6.28.0 → 6.29.1

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 (283) hide show
  1. package/README.md +3 -3
  2. package/cli/index.js +20 -224
  3. package/docker/zeroshot-cluster/Dockerfile +2 -3
  4. package/lib/cluster/client.cjs +30 -7
  5. package/lib/cluster/client.d.cts +52 -0
  6. package/lib/cluster/client.d.mts +52 -0
  7. package/lib/cluster/client.d.ts +4 -6
  8. package/lib/cluster/client.mjs +32 -9
  9. package/lib/cluster/connection-state.cjs +25 -0
  10. package/lib/cluster/connection-state.d.cts +13 -0
  11. package/lib/cluster/connection-state.d.mts +13 -0
  12. package/lib/cluster/connection-state.d.ts +13 -0
  13. package/lib/cluster/connection-state.mjs +21 -0
  14. package/lib/cluster/connection-types.cjs +2 -0
  15. package/lib/cluster/connection-types.d.cts +33 -0
  16. package/lib/cluster/connection-types.d.mts +33 -0
  17. package/lib/cluster/connection-types.d.ts +33 -0
  18. package/lib/cluster/connection-types.mjs +1 -0
  19. package/lib/cluster/connection.cjs +18 -46
  20. package/lib/cluster/connection.d.cts +26 -0
  21. package/lib/cluster/connection.d.mts +26 -0
  22. package/lib/cluster/connection.d.ts +7 -25
  23. package/lib/cluster/connection.mjs +12 -42
  24. package/lib/cluster/errors.cjs +9 -1
  25. package/lib/cluster/errors.d.cts +29 -0
  26. package/lib/cluster/errors.d.mts +29 -0
  27. package/lib/cluster/errors.d.ts +4 -0
  28. package/lib/cluster/errors.mjs +7 -0
  29. package/lib/cluster/frames.d.cts +12 -0
  30. package/lib/cluster/frames.d.mts +12 -0
  31. package/lib/cluster/generated/protocol-schema.d.cts +1 -0
  32. package/lib/cluster/generated/protocol-schema.d.mts +1 -0
  33. package/lib/cluster/generated/protocol.d.cts +781 -0
  34. package/lib/cluster/generated/protocol.d.mts +781 -0
  35. package/lib/cluster/index.cjs +2 -2
  36. package/lib/cluster/index.d.cts +13 -0
  37. package/lib/cluster/index.d.mts +13 -0
  38. package/lib/cluster/index.d.ts +3 -3
  39. package/lib/cluster/index.mjs +2 -2
  40. package/lib/cluster/json-source.cjs +1 -0
  41. package/lib/cluster/json-source.d.cts +5 -0
  42. package/lib/cluster/json-source.d.mts +5 -0
  43. package/lib/cluster/json-source.d.ts +1 -0
  44. package/lib/cluster/json-source.mjs +1 -0
  45. package/lib/cluster/payload-value.cjs +1 -0
  46. package/lib/cluster/payload-value.d.cts +8 -0
  47. package/lib/cluster/payload-value.d.mts +8 -0
  48. package/lib/cluster/payload-value.d.ts +1 -0
  49. package/lib/cluster/payload-value.mjs +1 -0
  50. package/lib/cluster/queue.d.cts +15 -0
  51. package/lib/cluster/queue.d.mts +15 -0
  52. package/lib/cluster/socket.cjs +8 -0
  53. package/lib/cluster/socket.d.cts +13 -0
  54. package/lib/cluster/socket.d.mts +13 -0
  55. package/lib/cluster/socket.d.ts +2 -0
  56. package/lib/cluster/socket.mjs +7 -0
  57. package/lib/cluster/subscriptions.d.cts +73 -0
  58. package/lib/cluster/subscriptions.d.mts +73 -0
  59. package/lib/cluster/subscriptions.d.ts +5 -1
  60. package/lib/cluster/validators.cjs +1 -0
  61. package/lib/cluster/validators.d.cts +7 -0
  62. package/lib/cluster/validators.d.mts +7 -0
  63. package/lib/cluster/validators.d.ts +1 -0
  64. package/lib/cluster/validators.mjs +1 -0
  65. package/lib/cluster-worker/engine-adapter.js +1 -11
  66. package/lib/cluster-worker/engine-input.js +14 -0
  67. package/lib/hosted-session/authority.cjs +61 -0
  68. package/lib/hosted-session/authority.d.cts +3 -0
  69. package/lib/hosted-session/authority.d.mts +3 -0
  70. package/lib/hosted-session/authority.d.ts +3 -0
  71. package/lib/hosted-session/authority.mjs +57 -0
  72. package/lib/hosted-session/coordinator.cjs +78 -51
  73. package/lib/hosted-session/coordinator.d.cts +11 -0
  74. package/lib/hosted-session/coordinator.d.mts +11 -0
  75. package/lib/hosted-session/coordinator.d.ts +4 -2
  76. package/lib/hosted-session/coordinator.mjs +75 -51
  77. package/lib/hosted-session/errors.cjs +25 -0
  78. package/lib/hosted-session/errors.d.cts +10 -0
  79. package/lib/hosted-session/errors.d.mts +10 -0
  80. package/lib/hosted-session/errors.d.ts +10 -0
  81. package/lib/hosted-session/errors.mjs +19 -0
  82. package/lib/hosted-session/index.cjs +4 -1
  83. package/lib/hosted-session/index.d.cts +2 -0
  84. package/lib/hosted-session/index.d.mts +2 -0
  85. package/lib/hosted-session/index.d.ts +2 -2
  86. package/lib/hosted-session/index.mjs +1 -1
  87. package/lib/hosted-session/reconnecting-watch.cjs +131 -0
  88. package/lib/hosted-session/reconnecting-watch.d.cts +13 -0
  89. package/lib/hosted-session/reconnecting-watch.d.mts +13 -0
  90. package/lib/hosted-session/reconnecting-watch.d.ts +13 -0
  91. package/lib/hosted-session/reconnecting-watch.mjs +127 -0
  92. package/lib/hosted-session/types.d.cts +32 -0
  93. package/lib/hosted-session/types.d.mts +32 -0
  94. package/lib/hosted-session/types.d.ts +19 -7
  95. package/lib/hosted-target/access-url.cjs +44 -0
  96. package/lib/hosted-target/access-url.d.cts +2 -0
  97. package/lib/hosted-target/access-url.d.mts +2 -0
  98. package/lib/hosted-target/access-url.d.ts +2 -0
  99. package/lib/hosted-target/access-url.mjs +41 -0
  100. package/lib/hosted-target/adapter-request.cjs +12 -0
  101. package/lib/hosted-target/adapter-request.d.cts +17 -0
  102. package/lib/hosted-target/adapter-request.d.mts +17 -0
  103. package/lib/hosted-target/adapter-request.d.ts +17 -0
  104. package/lib/hosted-target/adapter-request.mjs +9 -0
  105. package/lib/hosted-target/adapter-types.cjs +2 -0
  106. package/lib/hosted-target/adapter-types.d.cts +27 -0
  107. package/lib/hosted-target/adapter-types.d.mts +27 -0
  108. package/lib/hosted-target/adapter-types.d.ts +27 -0
  109. package/lib/hosted-target/adapter-types.mjs +1 -0
  110. package/lib/hosted-target/bounds.cjs +10 -0
  111. package/lib/hosted-target/bounds.d.cts +7 -0
  112. package/lib/hosted-target/bounds.d.mts +7 -0
  113. package/lib/hosted-target/bounds.d.ts +7 -0
  114. package/lib/hosted-target/bounds.mjs +7 -0
  115. package/lib/hosted-target/capsule-error-response.cjs +76 -0
  116. package/lib/hosted-target/capsule-error-response.d.cts +2 -0
  117. package/lib/hosted-target/capsule-error-response.d.mts +2 -0
  118. package/lib/hosted-target/capsule-error-response.d.ts +2 -0
  119. package/lib/hosted-target/capsule-error-response.mjs +73 -0
  120. package/lib/hosted-target/errors.cjs +88 -0
  121. package/lib/hosted-target/errors.d.cts +36 -0
  122. package/lib/hosted-target/errors.d.mts +36 -0
  123. package/lib/hosted-target/errors.d.ts +36 -0
  124. package/lib/hosted-target/errors.mjs +75 -0
  125. package/lib/hosted-target/index.cjs +16 -0
  126. package/lib/hosted-target/index.d.cts +3 -0
  127. package/lib/hosted-target/index.d.mts +3 -0
  128. package/lib/hosted-target/index.d.ts +3 -0
  129. package/lib/hosted-target/index.mjs +2 -0
  130. package/lib/hosted-target/response-validation.cjs +169 -0
  131. package/lib/hosted-target/response-validation.d.cts +5 -0
  132. package/lib/hosted-target/response-validation.d.mts +5 -0
  133. package/lib/hosted-target/response-validation.d.ts +5 -0
  134. package/lib/hosted-target/response-validation.mjs +163 -0
  135. package/lib/hosted-target/retry-executor.cjs +51 -0
  136. package/lib/hosted-target/retry-executor.d.cts +8 -0
  137. package/lib/hosted-target/retry-executor.d.mts +8 -0
  138. package/lib/hosted-target/retry-executor.d.ts +8 -0
  139. package/lib/hosted-target/retry-executor.mjs +48 -0
  140. package/lib/hosted-target/retry.cjs +78 -0
  141. package/lib/hosted-target/retry.d.cts +9 -0
  142. package/lib/hosted-target/retry.d.mts +9 -0
  143. package/lib/hosted-target/retry.d.ts +9 -0
  144. package/lib/hosted-target/retry.mjs +73 -0
  145. package/lib/hosted-target/target-adapter.cjs +10 -0
  146. package/lib/hosted-target/target-adapter.d.cts +3 -0
  147. package/lib/hosted-target/target-adapter.d.mts +3 -0
  148. package/lib/hosted-target/target-adapter.d.ts +3 -0
  149. package/lib/hosted-target/target-adapter.mjs +7 -0
  150. package/lib/hosted-target/types.cjs +4 -0
  151. package/lib/hosted-target/types.d.cts +50 -0
  152. package/lib/hosted-target/types.d.mts +50 -0
  153. package/lib/hosted-target/types.d.ts +50 -0
  154. package/lib/hosted-target/types.mjs +1 -0
  155. package/lib/hosted-target/zero-cloud-v1-adapter.cjs +185 -0
  156. package/lib/hosted-target/zero-cloud-v1-adapter.d.cts +13 -0
  157. package/lib/hosted-target/zero-cloud-v1-adapter.d.mts +13 -0
  158. package/lib/hosted-target/zero-cloud-v1-adapter.d.ts +13 -0
  159. package/lib/hosted-target/zero-cloud-v1-adapter.mjs +181 -0
  160. package/lib/target/bounded-response.cjs +51 -0
  161. package/lib/target/bounded-response.d.cts +1 -0
  162. package/lib/target/bounded-response.d.mts +1 -0
  163. package/lib/target/bounded-response.d.ts +1 -0
  164. package/lib/target/bounded-response.js +51 -0
  165. package/lib/target/bounded-response.mjs +48 -0
  166. package/lib/target/credential-lock.js +1 -3
  167. package/lib/target/credential-store.js +9 -4
  168. package/lib/target/device-flow.cjs +213 -0
  169. package/lib/target/device-flow.d.cts +54 -0
  170. package/lib/target/device-flow.d.mts +54 -0
  171. package/lib/target/device-flow.d.ts +26 -10
  172. package/lib/target/device-flow.js +162 -53
  173. package/lib/target/device-flow.mjs +203 -0
  174. package/lib/target/discovery-errors.cjs +10 -0
  175. package/lib/target/discovery-errors.d.cts +3 -0
  176. package/lib/target/discovery-errors.d.mts +3 -0
  177. package/lib/target/discovery-errors.d.ts +3 -0
  178. package/lib/target/discovery-errors.js +10 -0
  179. package/lib/target/discovery-errors.mjs +6 -0
  180. package/lib/target/discovery-sections.cjs +191 -0
  181. package/lib/target/discovery-sections.d.cts +52 -0
  182. package/lib/target/discovery-sections.d.mts +52 -0
  183. package/lib/target/discovery-sections.d.ts +52 -0
  184. package/lib/target/discovery-sections.js +191 -0
  185. package/lib/target/discovery-sections.mjs +179 -0
  186. package/lib/target/discovery-validation.cjs +109 -0
  187. package/lib/target/discovery-validation.d.cts +28 -0
  188. package/lib/target/discovery-validation.d.mts +28 -0
  189. package/lib/target/discovery-validation.d.ts +28 -0
  190. package/lib/target/discovery-validation.js +109 -0
  191. package/lib/target/discovery-validation.mjs +99 -0
  192. package/lib/target/discovery.cjs +112 -0
  193. package/lib/target/discovery.d.cts +74 -0
  194. package/lib/target/discovery.d.mts +74 -0
  195. package/lib/target/discovery.d.ts +68 -5
  196. package/lib/target/discovery.js +93 -101
  197. package/lib/target/discovery.mjs +105 -0
  198. package/lib/target/index.d.ts +6 -6
  199. package/lib/target/index.js +36 -36
  200. package/lib/target/oauth-http.d.ts +2 -0
  201. package/lib/target/oauth-http.js +25 -0
  202. package/lib/target/refresh-exchange.d.ts +11 -0
  203. package/lib/target/refresh-exchange.js +24 -0
  204. package/lib/target/refresh-revocation.d.ts +8 -0
  205. package/lib/target/refresh-revocation.js +19 -0
  206. package/lib/target/route-template.cjs +85 -0
  207. package/lib/target/route-template.d.cts +7 -0
  208. package/lib/target/route-template.d.mts +7 -0
  209. package/lib/target/route-template.d.ts +7 -0
  210. package/lib/target/route-template.js +85 -0
  211. package/lib/target/route-template.mjs +81 -0
  212. package/lib/target/session-errors.d.ts +4 -0
  213. package/lib/target/session-errors.js +12 -0
  214. package/lib/target/session-verification.d.ts +10 -0
  215. package/lib/target/session-verification.js +42 -0
  216. package/lib/target/target-registry.d.ts +7 -3
  217. package/lib/target/target-registry.js +41 -10
  218. package/lib/target/target-session-manager.d.ts +48 -0
  219. package/lib/target/target-session-manager.js +226 -0
  220. package/lib/target/target-session.d.ts +39 -31
  221. package/lib/target/target-session.js +63 -150
  222. package/lib/target/token-response.cjs +51 -0
  223. package/lib/target/token-response.d.cts +7 -0
  224. package/lib/target/token-response.d.mts +7 -0
  225. package/lib/target/token-response.d.ts +7 -0
  226. package/lib/target/token-response.js +51 -0
  227. package/lib/target/token-response.mjs +48 -0
  228. package/package.json +16 -6
  229. package/scripts/audit-production-dependencies.js +150 -0
  230. package/scripts/build-cluster.js +23 -3
  231. package/scripts/opcore-agent-gate.js +159 -0
  232. package/scripts/opcore-agent-tool-overlays.js +154 -0
  233. package/scripts/opcore-introduced-check.js +288 -0
  234. package/src/cluster/client.ts +42 -15
  235. package/src/cluster/connection-state.ts +33 -0
  236. package/src/cluster/connection-types.ts +28 -0
  237. package/src/cluster/connection.ts +37 -68
  238. package/src/cluster/errors.ts +5 -0
  239. package/src/cluster/index.ts +3 -1
  240. package/src/cluster/json-source.ts +1 -0
  241. package/src/cluster/payload-value.ts +1 -0
  242. package/src/cluster/socket.ts +13 -0
  243. package/src/cluster/subscriptions.ts +7 -2
  244. package/src/cluster/validators.ts +1 -0
  245. package/src/cluster/ws.d.ts +1 -1
  246. package/src/hosted-session/authority.ts +77 -0
  247. package/src/hosted-session/coordinator.ts +113 -56
  248. package/src/hosted-session/errors.ts +21 -0
  249. package/src/hosted-session/index.ts +14 -2
  250. package/src/hosted-session/reconnecting-watch.ts +148 -0
  251. package/src/hosted-session/types.ts +22 -8
  252. package/src/hosted-target/access-url.ts +46 -0
  253. package/src/hosted-target/adapter-request.ts +28 -0
  254. package/src/hosted-target/adapter-types.ts +39 -0
  255. package/src/hosted-target/bounds.ts +1 -0
  256. package/src/hosted-target/capsule-error-response.ts +107 -0
  257. package/src/hosted-target/errors.ts +36 -35
  258. package/src/hosted-target/index.ts +10 -23
  259. package/src/hosted-target/response-validation.ts +170 -62
  260. package/src/hosted-target/retry-executor.ts +62 -0
  261. package/src/hosted-target/retry.ts +47 -11
  262. package/src/hosted-target/target-adapter.ts +12 -8
  263. package/src/hosted-target/types.ts +19 -18
  264. package/src/hosted-target/zero-cloud-v1-adapter.ts +229 -316
  265. package/src/target/bounded-response.ts +68 -0
  266. package/src/target/credential-lock.ts +1 -3
  267. package/src/target/credential-store.ts +14 -10
  268. package/src/target/device-flow.ts +206 -71
  269. package/src/target/discovery-errors.ts +6 -0
  270. package/src/target/discovery-sections.ts +251 -0
  271. package/src/target/discovery-validation.ts +144 -0
  272. package/src/target/discovery.ts +163 -115
  273. package/src/target/index.ts +15 -11
  274. package/src/target/oauth-http.ts +27 -0
  275. package/src/target/refresh-exchange.ts +36 -0
  276. package/src/target/refresh-revocation.ts +29 -0
  277. package/src/target/route-template.ts +105 -0
  278. package/src/target/session-errors.ts +9 -0
  279. package/src/target/session-verification.ts +51 -0
  280. package/src/target/target-registry.ts +60 -27
  281. package/src/target/target-session-manager.ts +285 -0
  282. package/src/target/target-session.ts +105 -222
  283. package/src/target/token-response.ts +62 -0
package/README.md CHANGED
@@ -15,7 +15,7 @@
15
15
  [![npm](https://img.shields.io/npm/v/@the-open-engine/zeroshot?style=flat&labelColor=171411&color=171411)](https://www.npmjs.com/package/@the-open-engine/zeroshot)
16
16
  [![CI](https://img.shields.io/github/actions/workflow/status/the-open-engine/zeroshot/ci.yml?style=flat&labelColor=171411&label=CI)](https://github.com/the-open-engine/zeroshot/actions/workflows/ci.yml)
17
17
  [![License: MIT](https://img.shields.io/badge/license-MIT-171411?style=flat)](LICENSE)
18
- [![node](https://img.shields.io/badge/node-%E2%89%A5%2018-171411?style=flat)](#install)
18
+ [![node](https://img.shields.io/badge/node-%E2%89%A5%2022-171411?style=flat)](#install)
19
19
  [![platforms](https://img.shields.io/badge/platforms-linux%20%C2%B7%20macos-171411?style=flat)](#install)
20
20
  [![stars](https://img.shields.io/github/stars/the-open-engine/zeroshot?style=flat&labelColor=171411&color=171411)](https://github.com/the-open-engine/zeroshot)
21
21
  [![Layer 01 · The Open Engine](https://img.shields.io/badge/Layer_01-The_Open_Engine-C2240C?style=flat&labelColor=171411)](#the-open-engine)
@@ -43,7 +43,7 @@ Zeroshot is an open-source, multi-agent orchestration engine for autonomous soft
43
43
  npm install -g @the-open-engine/zeroshot
44
44
  ```
45
45
 
46
- Requires **Node ≥ 18** and at least one provider CLI (Claude Code, Codex, Gemini, or OpenCode). Linux and macOS today; Windows is deferred.
46
+ Requires **Node ≥ 22** and at least one provider CLI (Claude Code, Codex, Gemini, or OpenCode). The package includes the pinned Opcore constraints CLI; repository hook activation remains explicit. Linux and macOS today; Windows is deferred.
47
47
 
48
48
  <div align="center">
49
49
  <img src="docs/assets/zeroshot-demo.gif" alt="Zeroshot resolving an issue through the executor-verifier loop" width="760">
@@ -207,7 +207,7 @@ Zeroshot is **Layer 01 · Verification** of [The Open Engine](https://theopeneng
207
207
  | 02 | Constraints: **Opcore** | Sibling · alpha |
208
208
  | 03-05 | Intent · Context · Runtime | In development |
209
209
 
210
- Zeroshot runs the loop: an agent writes the change, and an **independent** verifier decides whether it holds: approve, or a reproducible failure. **Opcore** is the sibling layer, a deterministic, local, read-only **constraints** gate for coding agents (currently private alpha `0.1.0-alpha.0`, built in the open, not yet published). Verification asks _"does this meet the goal?"_; constraints ask _"is this within tolerance?"_
210
+ Zeroshot runs the loop: an agent writes the change, and an **independent** verifier decides whether it holds: approve, or a reproducible failure. **Opcore** is the sibling layer, a deterministic, local, read-only **constraints** gate for coding agents. Zeroshot packages Opcore `0.2.1` and uses introduced-change validation so existing repository debt never blocks an otherwise clean change. Verification asks _"does this meet the goal?"_; constraints ask _"is this within tolerance?"_
211
211
 
212
212
  Each layer ships the same way: extracted from the platform we run, then opened. **Trust nothing. Verify everything.**
213
213
 
package/cli/index.js CHANGED
@@ -2647,6 +2647,7 @@ Shell completion:
2647
2647
  );
2648
2648
 
2649
2649
  // Run command - CLUSTER with auto-detection
2650
+
2650
2651
  program
2651
2652
  .command('run <input>')
2652
2653
  .description(
@@ -3959,6 +3960,10 @@ for (const providerName of VALID_PROVIDERS) {
3959
3960
  // Settings management
3960
3961
  const settingsCmd = program.command('settings').description('Manage zeroshot settings');
3961
3962
  const INTERNAL_SETTINGS_KEYS = new Set(['lastUpdateCheckClaim', '_targets']);
3963
+ // Fail closed while hosted commands are unpublished. Keeping these names out of the
3964
+ // default `run` rewrite makes them unknown commands rather than local task input.
3965
+ // Issue #920 deliberately has no CLI lifecycle or runtime execution surface.
3966
+ const UNREGISTERED_HOSTED_COMMAND_NAMES = new Set(['target', 'capsule']);
3962
3967
 
3963
3968
  function visibleSettingKeys() {
3964
3969
  return Object.keys(DEFAULT_SETTINGS).filter((key) => !INTERNAL_SETTINGS_KEYS.has(key));
@@ -4490,211 +4495,7 @@ settingsCmd.action(() => {
4490
4495
  formatSettingsList(settings, true);
4491
4496
  });
4492
4497
 
4493
- // Target management commands
4494
- // Target modules are compiled during install/package preparation for the Node 18+ CLI.
4495
- const importTarget = (mod) => import(`../lib/target/${mod}.js`);
4496
- const targetCmd = program.command('target').description('Manage named remote targets');
4497
-
4498
- targetCmd
4499
- .command('add <name>')
4500
- .description('Register a named remote target')
4501
- .requiredOption('--url <url>', 'Service URL for the target')
4502
- .action(async (name, options) => {
4503
- try {
4504
- const { addTarget } = await importTarget('target-registry');
4505
- const settingsPort = {
4506
- load: () => loadSettings(),
4507
- mutate: (fn) => mutateSettings(fn),
4508
- };
4509
- const record = addTarget(name, options.url, settingsPort);
4510
- console.log(chalk.green(`✓ Target "${name}" added (${record.url})`));
4511
- } catch (error) {
4512
- console.error(chalk.red(error.message));
4513
- process.exit(1);
4514
- }
4515
- });
4516
-
4517
- targetCmd
4518
- .command('login <name>')
4519
- .description('Authenticate with a remote target via device login')
4520
- .action(async (name) => {
4521
- try {
4522
- const { getTarget } = await importTarget('target-registry');
4523
- const { targetLogin } = await importTarget('target-session');
4524
- const { KeyringCredentialStore } = await importTarget('credential-store');
4525
- const { acquireTargetLock } = await importTarget('credential-lock');
4526
- const { discoverTargetSessionEndpoints } = await importTarget('discovery');
4527
-
4528
- const settingsPort = {
4529
- load: () => loadSettings(),
4530
- mutate: (fn) => mutateSettings(fn),
4531
- };
4532
-
4533
- const target = getTarget(name, settingsPort);
4534
- if (!target) {
4535
- console.error(chalk.red(`Target "${name}" not found.`));
4536
- process.exit(1);
4537
- }
4538
-
4539
- const http = { fetch: (url, init) => fetch(url, init) };
4540
- const discoveryEndpoints = await discoverTargetSessionEndpoints(target.url, http);
4541
-
4542
- const credentialStore = await KeyringCredentialStore.create();
4543
- const openPkg = await import('open');
4544
- const browserOpen = openPkg.default || openPkg;
4545
-
4546
- const result = await targetLogin(
4547
- name,
4548
- target,
4549
- credentialStore,
4550
- () => acquireTargetLock(target.id),
4551
- settingsPort,
4552
- {
4553
- http,
4554
- clock: { now: () => Date.now() },
4555
- browserOpener: {
4556
- open: async (url) => {
4557
- await browserOpen(url);
4558
- },
4559
- },
4560
- stderr: process.stderr,
4561
- discoveryEndpoints,
4562
- }
4563
- );
4564
-
4565
- console.log(
4566
- chalk.green(`✓ Logged in to "${name}" (organization: ${result.organization.name})`)
4567
- );
4568
- } catch (error) {
4569
- console.error(chalk.red(error.message));
4570
- process.exit(1);
4571
- }
4572
- });
4573
-
4574
- targetCmd
4575
- .command('list')
4576
- .description('List registered remote targets')
4577
- .option('--json', 'Output as JSON')
4578
- .action(async (options) => {
4579
- try {
4580
- const { listTargets } = await importTarget('target-registry');
4581
- const settingsPort = {
4582
- load: () => loadSettings(),
4583
- mutate: (fn) => mutateSettings(fn),
4584
- };
4585
-
4586
- const targets = listTargets(settingsPort);
4587
-
4588
- if (options.json) {
4589
- const output = targets.map(({ name, record }) => ({
4590
- name,
4591
- id: record.id,
4592
- url: record.url,
4593
- organization: record.organization ?? null,
4594
- loggedIn: false,
4595
- createdAt: record.createdAt,
4596
- }));
4597
-
4598
- // Try to check keyring presence for each target
4599
- try {
4600
- const { KeyringCredentialStore } = await importTarget('credential-store');
4601
- const { targetServiceKey, TARGET_ACCOUNT } = await importTarget('credential-store');
4602
- const store = await KeyringCredentialStore.create();
4603
- for (const item of output) {
4604
- const matchingTarget = targets.find((t) => t.name === item.name);
4605
- if (matchingTarget) {
4606
- const cred = await store.get(
4607
- targetServiceKey(matchingTarget.record.id),
4608
- TARGET_ACCOUNT
4609
- );
4610
- item.loggedIn = cred !== null;
4611
- }
4612
- }
4613
- } catch {
4614
- // Keyring unavailable, all show as not logged in
4615
- }
4616
-
4617
- console.log(JSON.stringify(output, null, 2));
4618
- return;
4619
- }
4620
-
4621
- if (targets.length === 0) {
4622
- console.log(
4623
- chalk.dim(
4624
- 'No targets registered. Use `zeroshot target add <name> --url <url>` to add one.'
4625
- )
4626
- );
4627
- return;
4628
- }
4629
-
4630
- for (const { name, record } of targets) {
4631
- const org = record.organization ? ` (org: ${record.organization.name})` : '';
4632
- console.log(` ${chalk.bold(name)} ${record.url}${org}`);
4633
- }
4634
- } catch (error) {
4635
- console.error(chalk.red(error.message));
4636
- process.exit(1);
4637
- }
4638
- });
4639
-
4640
- targetCmd
4641
- .command('remove <name>')
4642
- .description('Remove a named remote target')
4643
- .option('--force', 'Remove even if remote revocation fails')
4644
- .action(async (name, options) => {
4645
- try {
4646
- const { getTarget, removeTarget } = await importTarget('target-registry');
4647
- const { revokeAndCleanup } = await importTarget('target-session');
4648
- const { acquireTargetLock } = await importTarget('credential-lock');
4649
- const { discoverTargetSessionEndpoints } = await importTarget('discovery');
4650
-
4651
- const settingsPort = {
4652
- load: () => loadSettings(),
4653
- mutate: (fn) => mutateSettings(fn),
4654
- };
4655
-
4656
- const target = getTarget(name, settingsPort);
4657
- if (!target) {
4658
- console.error(chalk.red(`Target "${name}" not found.`));
4659
- process.exit(1);
4660
- }
4661
-
4662
- // Try to revoke and cleanup keyring
4663
- try {
4664
- const { KeyringCredentialStore } = await importTarget('credential-store');
4665
- const credentialStore = await KeyringCredentialStore.create();
4666
- const http = { fetch: (url, init) => fetch(url, init) };
4667
- const discoveryEndpoints = await discoverTargetSessionEndpoints(target.url, http);
4668
- await revokeAndCleanup(
4669
- target,
4670
- credentialStore,
4671
- () => acquireTargetLock(target.id),
4672
- {
4673
- http,
4674
- discoveryEndpoints,
4675
- },
4676
- !!options.force
4677
- );
4678
- } catch (error) {
4679
- if (!options.force) {
4680
- console.error(chalk.red(error.message));
4681
- process.exit(1);
4682
- }
4683
- // Force mode: continue with removal
4684
- }
4685
-
4686
- removeTarget(name, settingsPort);
4687
- console.log(chalk.green(`✓ Target "${name}" removed`));
4688
- } catch (error) {
4689
- console.error(chalk.red(error.message));
4690
- process.exit(1);
4691
- }
4692
- });
4693
-
4694
- targetCmd.action(() => {
4695
- targetCmd.help();
4696
- });
4697
-
4498
+ // Hosted target commands intentionally are not registered on the stable CLI.
4698
4499
  // Providers management
4699
4500
  const providersCmd = program.command('providers').description('Manage AI providers');
4700
4501
  providersCmd.action(async () => {
@@ -6255,6 +6056,16 @@ function isStartupUpdateEligible(argv, options = {}) {
6255
6056
  });
6256
6057
  }
6257
6058
 
6059
+ function applyDefaultCommand(args) {
6060
+ const firstArg = args[0];
6061
+ if (!firstArg || firstArg.startsWith('-')) return;
6062
+
6063
+ const commandNames = program.commands.map((command) => command.name());
6064
+ if (commandNames.includes(firstArg) || UNREGISTERED_HOSTED_COMMAND_NAMES.has(firstArg)) return;
6065
+
6066
+ process.argv.splice(2, 0, 'run');
6067
+ }
6068
+
6258
6069
  // Main entry point
6259
6070
  async function main() {
6260
6071
  printLegacyDistroNotice();
@@ -6280,31 +6091,16 @@ async function main() {
6280
6091
  checkForUpdates({ argv: startupArgs, eligibilityChecked: true });
6281
6092
  }
6282
6093
 
6283
- let args = startupArgs;
6094
+ const args = startupArgs;
6284
6095
 
6285
6096
  if (args.length === 0) {
6286
6097
  program.outputHelp();
6287
6098
  return;
6288
6099
  }
6289
6100
 
6290
- // Default command handling: if first arg doesn't match a known command, treat it as 'run'
6291
- // This allows `zeroshot "task"` to work the same as `zeroshot run "task"`
6292
- args = process.argv.slice(2);
6293
- if (args.length > 0) {
6294
- const firstArg = args[0];
6295
-
6296
- // Skip if it's a flag/option (starts with -)
6297
- // Skip if it's --help or --version (these are handled by commander)
6298
- if (!firstArg.startsWith('-')) {
6299
- // Get all registered command names
6300
- const commandNames = program.commands.map((cmd) => cmd.name());
6301
-
6302
- // If first arg is not a known command, prepend 'run'
6303
- if (!commandNames.includes(firstArg)) {
6304
- process.argv.splice(2, 0, 'run');
6305
- }
6306
- }
6307
- }
6101
+ // Preserve the default local run shorthand without treating hosted-only command
6102
+ // names as task input in the stable parser.
6103
+ applyDefaultCommand(args);
6308
6104
 
6309
6105
  program.parse();
6310
6106
  }
@@ -4,12 +4,11 @@
4
4
  # Build: docker build -t vibe-cluster-base vibe/cluster/docker/vibe-cluster/
5
5
  # Usage: zeroshot run <task> --docker
6
6
 
7
- FROM node:20-slim
7
+ FROM node:22-slim
8
8
 
9
9
  # Upgrade npm to fix Arborist isDescendantOf bug (npm 10.x crash on complex peer deps)
10
10
  # See: https://github.com/npm/cli/issues/7682
11
- # Pinned to npm@11 (the latest line that still supports the node:20-slim base); npm@latest (12.x)
12
- # now requires node >=22 and breaks the build with EBADENGINE.
11
+ # Pinned to npm@11 to keep the container toolchain reproducible with the supported Node 22 line.
13
12
  RUN npm install -g npm@11
14
13
 
15
14
  # Version pinning for infrastructure tools
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ClusterClient = void 0;
4
4
  exports.connect = connect;
5
5
  exports.connectInitialized = connectInitialized;
6
+ /// <reference path="./ws.d.ts" />
6
7
  const protocol_js_1 = require("./generated/protocol.cjs");
7
8
  const connection_js_1 = require("./connection.cjs");
8
9
  const socket_js_1 = require("./socket.cjs");
@@ -82,10 +83,7 @@ class ClusterClient {
82
83
  exports.ClusterClient = ClusterClient;
83
84
  async function defaultWebSocketFactory(url, protocols, options) {
84
85
  const globalWebSocket = globalThis.WebSocket;
85
- if (globalWebSocket) {
86
- if (options?.headers && Object.keys(options.headers).length > 0) {
87
- throw new errors_js_1.ClusterConfigError('WebSocket upgrade headers require the ws library; the browser WebSocket API cannot carry request headers', 'HEADERS_UNSUPPORTED');
88
- }
86
+ if (globalWebSocket && (!options?.headers || Object.keys(options.headers).length === 0)) {
89
87
  return new globalWebSocket(url, protocols);
90
88
  }
91
89
  try {
@@ -114,6 +112,7 @@ async function waitForOpen(socket, signal) {
114
112
  await new Promise((resolve, reject) => {
115
113
  let settled = false;
116
114
  const removers = [];
115
+ let upgradeFailure;
117
116
  const settle = (fn) => {
118
117
  if (settled)
119
118
  return;
@@ -124,10 +123,34 @@ async function waitForOpen(socket, signal) {
124
123
  fn();
125
124
  };
126
125
  const onAbort = () => settle(() => reject(new DOMException('connect aborted locally; the server may still have committed this request', 'AbortError')));
127
- removers.push((0, socket_js_1.addSocketListener)(socket, 'open', () => settle(resolve)), (0, socket_js_1.addSocketListener)(socket, 'error', (error) => settle(() => reject(new errors_js_1.ClusterTransportError('WebSocket failed to open', 'OPEN_FAILED', { cause: error })))), (0, socket_js_1.addSocketListener)(socket, 'close', () => settle(() => reject(new errors_js_1.ClusterTransportError('WebSocket closed before opening', 'OPEN_FAILED')))));
126
+ const onUnexpectedResponse = (...args) => {
127
+ const response = args.find((value) => value !== null && typeof value === 'object' && 'statusCode' in value);
128
+ const status = response?.statusCode;
129
+ upgradeFailure = typeof status === 'number'
130
+ ? new errors_js_1.ClusterUpgradeError(status)
131
+ : new errors_js_1.ClusterTransportError('WebSocket upgrade rejected', 'UPGRADE_REJECTED');
132
+ response?.resume?.();
133
+ if (socket.terminate) {
134
+ socket.terminate();
135
+ }
136
+ else {
137
+ settle(() => reject(upgradeFailure));
138
+ }
139
+ };
140
+ removers.push((0, socket_js_1.addSocketListener)(socket, 'open', () => settle(resolve)), (0, socket_js_1.addSocketListener)(socket, 'error', (error) => settle(() => reject(upgradeFailure ??
141
+ new errors_js_1.ClusterTransportError('WebSocket failed to open', 'OPEN_FAILED', { cause: error })))), (0, socket_js_1.addSocketListener)(socket, 'close', () => settle(() => reject(upgradeFailure ??
142
+ new errors_js_1.ClusterTransportError('WebSocket closed before opening', 'OPEN_FAILED')))), (0, socket_js_1.addSocketEmitterListener)(socket, 'unexpected-response', onUnexpectedResponse));
128
143
  signal?.addEventListener('abort', onAbort, { once: true });
129
144
  });
130
145
  }
146
+ async function disposeFailedSocket(socket) {
147
+ if (socket.readyState === 0 && socket.terminate) {
148
+ socket.terminate();
149
+ }
150
+ else {
151
+ await socket.close();
152
+ }
153
+ }
131
154
  async function connect(url, options = {}) {
132
155
  const factory = options.webSocketFactory ?? defaultWebSocketFactory;
133
156
  let socket;
@@ -141,7 +164,7 @@ async function connect(url, options = {}) {
141
164
  catch (error) {
142
165
  if (socket) {
143
166
  try {
144
- await socket.close();
167
+ await disposeFailedSocket(socket);
145
168
  }
146
169
  catch { /* preserve the construction error */ }
147
170
  }
@@ -162,7 +185,7 @@ async function connectInitialized(url, options = {}) {
162
185
  catch (error) {
163
186
  if (socket) {
164
187
  try {
165
- await socket.close();
188
+ await disposeFailedSocket(socket);
166
189
  }
167
190
  catch { /* preserve the construction error */ }
168
191
  }
@@ -0,0 +1,52 @@
1
+ import type { AgentAttachParams, AgentAttachResult, ApplyParams, ApplyResult, DeleteParams, DeleteResult, GetParams, GetResult, InitializeParams, InitializeResult, LogsParams, LogsResult, PlanParams, PlanResult, ResubmitParams, ResubmitResult, RetryParams, RetryResult, StopParams, StopResult, UpdateParams, UpdateResult, WatchParams } from './generated/protocol.js';
2
+ import { Connection } from './connection.js';
3
+ import type { CallOptions } from './connection.js';
4
+ import type { WebSocketLike } from './socket.js';
5
+ import { AgentAttachSubscriptionStream, LogsSubscriptionStream } from './subscriptions.js';
6
+ import type { WatchSubscription } from './subscriptions.js';
7
+ export type { WatchSubscription } from './subscriptions.js';
8
+ export interface WebSocketFactoryOptions {
9
+ readonly headers?: Readonly<Record<string, string>>;
10
+ }
11
+ export interface ConnectOptions {
12
+ readonly protocols?: string | readonly string[];
13
+ readonly webSocketFactory?: (url: string, protocols?: string | readonly string[], options?: WebSocketFactoryOptions) => WebSocketLike | Promise<WebSocketLike>;
14
+ readonly signal?: AbortSignal;
15
+ readonly initialize?: InitializeParams;
16
+ readonly headers?: Readonly<Record<string, string>>;
17
+ }
18
+ export interface LogsSubscription {
19
+ readonly result: LogsResult;
20
+ readonly stream: LogsSubscriptionStream;
21
+ }
22
+ export interface AgentAttachSubscription {
23
+ readonly result: AgentAttachResult;
24
+ readonly stream: AgentAttachSubscriptionStream;
25
+ }
26
+ export interface CoherentWatchSubscription extends WatchSubscription {
27
+ readonly snapshot: GetResult;
28
+ }
29
+ export interface ConnectInitializedResult {
30
+ readonly connection: Connection;
31
+ readonly client: ClusterClient;
32
+ readonly initializeResult: InitializeResult;
33
+ }
34
+ export declare class ClusterClient {
35
+ readonly connection: Connection;
36
+ constructor(connection: Connection);
37
+ initialize(params?: InitializeParams, options?: CallOptions): Promise<InitializeResult>;
38
+ plan(params: PlanParams, options?: CallOptions): Promise<PlanResult>;
39
+ apply(params: ApplyParams, options?: CallOptions): Promise<ApplyResult>;
40
+ update(params: UpdateParams, options?: CallOptions): Promise<UpdateResult>;
41
+ stop(params: StopParams, options?: CallOptions): Promise<StopResult>;
42
+ retry(params: RetryParams, options?: CallOptions): Promise<RetryResult>;
43
+ resubmit(params: ResubmitParams, options?: CallOptions): Promise<ResubmitResult>;
44
+ delete(params: DeleteParams, options?: CallOptions): Promise<DeleteResult>;
45
+ get(params?: GetParams, options?: CallOptions): Promise<GetResult>;
46
+ watch(params?: WatchParams, options?: CallOptions): Promise<WatchSubscription>;
47
+ watchColdStart(params?: Omit<WatchParams, 'fromCursor'>, options?: CallOptions): Promise<CoherentWatchSubscription>;
48
+ logs(params?: LogsParams, options?: CallOptions): Promise<LogsSubscription>;
49
+ agentAttach(params: AgentAttachParams, options?: CallOptions): Promise<AgentAttachSubscription>;
50
+ }
51
+ export declare function connect(url: string, options?: ConnectOptions): Promise<Connection>;
52
+ export declare function connectInitialized(url: string, options?: ConnectOptions): Promise<ConnectInitializedResult>;
@@ -0,0 +1,52 @@
1
+ import type { AgentAttachParams, AgentAttachResult, ApplyParams, ApplyResult, DeleteParams, DeleteResult, GetParams, GetResult, InitializeParams, InitializeResult, LogsParams, LogsResult, PlanParams, PlanResult, ResubmitParams, ResubmitResult, RetryParams, RetryResult, StopParams, StopResult, UpdateParams, UpdateResult, WatchParams } from './generated/protocol.js';
2
+ import { Connection } from './connection.js';
3
+ import type { CallOptions } from './connection.js';
4
+ import type { WebSocketLike } from './socket.js';
5
+ import { AgentAttachSubscriptionStream, LogsSubscriptionStream } from './subscriptions.js';
6
+ import type { WatchSubscription } from './subscriptions.js';
7
+ export type { WatchSubscription } from './subscriptions.js';
8
+ export interface WebSocketFactoryOptions {
9
+ readonly headers?: Readonly<Record<string, string>>;
10
+ }
11
+ export interface ConnectOptions {
12
+ readonly protocols?: string | readonly string[];
13
+ readonly webSocketFactory?: (url: string, protocols?: string | readonly string[], options?: WebSocketFactoryOptions) => WebSocketLike | Promise<WebSocketLike>;
14
+ readonly signal?: AbortSignal;
15
+ readonly initialize?: InitializeParams;
16
+ readonly headers?: Readonly<Record<string, string>>;
17
+ }
18
+ export interface LogsSubscription {
19
+ readonly result: LogsResult;
20
+ readonly stream: LogsSubscriptionStream;
21
+ }
22
+ export interface AgentAttachSubscription {
23
+ readonly result: AgentAttachResult;
24
+ readonly stream: AgentAttachSubscriptionStream;
25
+ }
26
+ export interface CoherentWatchSubscription extends WatchSubscription {
27
+ readonly snapshot: GetResult;
28
+ }
29
+ export interface ConnectInitializedResult {
30
+ readonly connection: Connection;
31
+ readonly client: ClusterClient;
32
+ readonly initializeResult: InitializeResult;
33
+ }
34
+ export declare class ClusterClient {
35
+ readonly connection: Connection;
36
+ constructor(connection: Connection);
37
+ initialize(params?: InitializeParams, options?: CallOptions): Promise<InitializeResult>;
38
+ plan(params: PlanParams, options?: CallOptions): Promise<PlanResult>;
39
+ apply(params: ApplyParams, options?: CallOptions): Promise<ApplyResult>;
40
+ update(params: UpdateParams, options?: CallOptions): Promise<UpdateResult>;
41
+ stop(params: StopParams, options?: CallOptions): Promise<StopResult>;
42
+ retry(params: RetryParams, options?: CallOptions): Promise<RetryResult>;
43
+ resubmit(params: ResubmitParams, options?: CallOptions): Promise<ResubmitResult>;
44
+ delete(params: DeleteParams, options?: CallOptions): Promise<DeleteResult>;
45
+ get(params?: GetParams, options?: CallOptions): Promise<GetResult>;
46
+ watch(params?: WatchParams, options?: CallOptions): Promise<WatchSubscription>;
47
+ watchColdStart(params?: Omit<WatchParams, 'fromCursor'>, options?: CallOptions): Promise<CoherentWatchSubscription>;
48
+ logs(params?: LogsParams, options?: CallOptions): Promise<LogsSubscription>;
49
+ agentAttach(params: AgentAttachParams, options?: CallOptions): Promise<AgentAttachSubscription>;
50
+ }
51
+ export declare function connect(url: string, options?: ConnectOptions): Promise<Connection>;
52
+ export declare function connectInitialized(url: string, options?: ConnectOptions): Promise<ConnectInitializedResult>;
@@ -1,8 +1,10 @@
1
- import type { AgentAttachParams, AgentAttachResult, ApplyParams, ApplyResult, DeleteParams, DeleteResult, GetParams, GetResult, InitializeParams, InitializeResult, LogsParams, LogsResult, PlanParams, PlanResult, ResubmitParams, ResubmitResult, RetryParams, RetryResult, StopParams, StopResult, UpdateParams, UpdateResult, WatchParams, WatchResult } from './generated/protocol.js';
1
+ import type { AgentAttachParams, AgentAttachResult, ApplyParams, ApplyResult, DeleteParams, DeleteResult, GetParams, GetResult, InitializeParams, InitializeResult, LogsParams, LogsResult, PlanParams, PlanResult, ResubmitParams, ResubmitResult, RetryParams, RetryResult, StopParams, StopResult, UpdateParams, UpdateResult, WatchParams } from './generated/protocol.js';
2
2
  import { Connection } from './connection.js';
3
3
  import type { CallOptions } from './connection.js';
4
4
  import type { WebSocketLike } from './socket.js';
5
- import { AgentAttachSubscriptionStream, LogsSubscriptionStream, WatchSubscriptionStream } from './subscriptions.js';
5
+ import { AgentAttachSubscriptionStream, LogsSubscriptionStream } from './subscriptions.js';
6
+ import type { WatchSubscription } from './subscriptions.js';
7
+ export type { WatchSubscription } from './subscriptions.js';
6
8
  export interface WebSocketFactoryOptions {
7
9
  readonly headers?: Readonly<Record<string, string>>;
8
10
  }
@@ -13,10 +15,6 @@ export interface ConnectOptions {
13
15
  readonly initialize?: InitializeParams;
14
16
  readonly headers?: Readonly<Record<string, string>>;
15
17
  }
16
- export interface WatchSubscription {
17
- readonly result: WatchResult;
18
- readonly stream: WatchSubscriptionStream;
19
- }
20
18
  export interface LogsSubscription {
21
19
  readonly result: LogsResult;
22
20
  readonly stream: LogsSubscriptionStream;
@@ -1,7 +1,8 @@
1
+ /// <reference path="./ws.d.ts" />
1
2
  import { PROTOCOL_VERSION } from './generated/protocol.mjs';
2
3
  import { Connection } from './connection.mjs';
3
- import { addSocketListener } from './socket.mjs';
4
- import { ClusterConfigError, ClusterProtocolError, ClusterTransportError } from './errors.mjs';
4
+ import { addSocketEmitterListener, addSocketListener } from './socket.mjs';
5
+ import { ClusterConfigError, ClusterProtocolError, ClusterTransportError, ClusterUpgradeError } from './errors.mjs';
5
6
  import { AgentAttachSubscriptionStream, LogsSubscriptionStream, WatchSubscriptionStream, } from './subscriptions.mjs';
6
7
  export class ClusterClient {
7
8
  connection;
@@ -76,10 +77,7 @@ export class ClusterClient {
76
77
  }
77
78
  async function defaultWebSocketFactory(url, protocols, options) {
78
79
  const globalWebSocket = globalThis.WebSocket;
79
- if (globalWebSocket) {
80
- if (options?.headers && Object.keys(options.headers).length > 0) {
81
- throw new ClusterConfigError('WebSocket upgrade headers require the ws library; the browser WebSocket API cannot carry request headers', 'HEADERS_UNSUPPORTED');
82
- }
80
+ if (globalWebSocket && (!options?.headers || Object.keys(options.headers).length === 0)) {
83
81
  return new globalWebSocket(url, protocols);
84
82
  }
85
83
  try {
@@ -108,6 +106,7 @@ async function waitForOpen(socket, signal) {
108
106
  await new Promise((resolve, reject) => {
109
107
  let settled = false;
110
108
  const removers = [];
109
+ let upgradeFailure;
111
110
  const settle = (fn) => {
112
111
  if (settled)
113
112
  return;
@@ -118,10 +117,34 @@ async function waitForOpen(socket, signal) {
118
117
  fn();
119
118
  };
120
119
  const onAbort = () => settle(() => reject(new DOMException('connect aborted locally; the server may still have committed this request', 'AbortError')));
121
- removers.push(addSocketListener(socket, 'open', () => settle(resolve)), addSocketListener(socket, 'error', (error) => settle(() => reject(new ClusterTransportError('WebSocket failed to open', 'OPEN_FAILED', { cause: error })))), addSocketListener(socket, 'close', () => settle(() => reject(new ClusterTransportError('WebSocket closed before opening', 'OPEN_FAILED')))));
120
+ const onUnexpectedResponse = (...args) => {
121
+ const response = args.find((value) => value !== null && typeof value === 'object' && 'statusCode' in value);
122
+ const status = response?.statusCode;
123
+ upgradeFailure = typeof status === 'number'
124
+ ? new ClusterUpgradeError(status)
125
+ : new ClusterTransportError('WebSocket upgrade rejected', 'UPGRADE_REJECTED');
126
+ response?.resume?.();
127
+ if (socket.terminate) {
128
+ socket.terminate();
129
+ }
130
+ else {
131
+ settle(() => reject(upgradeFailure));
132
+ }
133
+ };
134
+ removers.push(addSocketListener(socket, 'open', () => settle(resolve)), addSocketListener(socket, 'error', (error) => settle(() => reject(upgradeFailure ??
135
+ new ClusterTransportError('WebSocket failed to open', 'OPEN_FAILED', { cause: error })))), addSocketListener(socket, 'close', () => settle(() => reject(upgradeFailure ??
136
+ new ClusterTransportError('WebSocket closed before opening', 'OPEN_FAILED')))), addSocketEmitterListener(socket, 'unexpected-response', onUnexpectedResponse));
122
137
  signal?.addEventListener('abort', onAbort, { once: true });
123
138
  });
124
139
  }
140
+ async function disposeFailedSocket(socket) {
141
+ if (socket.readyState === 0 && socket.terminate) {
142
+ socket.terminate();
143
+ }
144
+ else {
145
+ await socket.close();
146
+ }
147
+ }
125
148
  export async function connect(url, options = {}) {
126
149
  const factory = options.webSocketFactory ?? defaultWebSocketFactory;
127
150
  let socket;
@@ -135,7 +158,7 @@ export async function connect(url, options = {}) {
135
158
  catch (error) {
136
159
  if (socket) {
137
160
  try {
138
- await socket.close();
161
+ await disposeFailedSocket(socket);
139
162
  }
140
163
  catch { /* preserve the construction error */ }
141
164
  }
@@ -156,7 +179,7 @@ export async function connectInitialized(url, options = {}) {
156
179
  catch (error) {
157
180
  if (socket) {
158
181
  try {
159
- await socket.close();
182
+ await disposeFailedSocket(socket);
160
183
  }
161
184
  catch { /* preserve the construction error */ }
162
185
  }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PROTOCOL_DIAGNOSTIC_CAPACITY = exports.CONNECTION_TRANSITIONS = void 0;
4
+ exports.deferred = deferred;
5
+ if (!Object.prototype.hasOwnProperty.call(Symbol, 'asyncDispose')) {
6
+ Object.defineProperty(Symbol, 'asyncDispose', {
7
+ configurable: false, enumerable: false,
8
+ value: Symbol.for('Symbol.asyncDispose'), writable: false,
9
+ });
10
+ }
11
+ exports.CONNECTION_TRANSITIONS = Object.freeze({
12
+ OPEN: Object.freeze(['CLOSING']),
13
+ CLOSING: Object.freeze(['CLOSED']),
14
+ CLOSED: Object.freeze([]),
15
+ });
16
+ exports.PROTOCOL_DIAGNOSTIC_CAPACITY = 128;
17
+ function deferred() {
18
+ let resolve;
19
+ let reject;
20
+ const promise = new Promise((onResolve, onReject) => {
21
+ resolve = onResolve;
22
+ reject = onReject;
23
+ });
24
+ return { promise, resolve, reject };
25
+ }
@@ -0,0 +1,13 @@
1
+ export type ConnectionState = 'OPEN' | 'CLOSING' | 'CLOSED';
2
+ export declare const CONNECTION_TRANSITIONS: Readonly<Record<ConnectionState, readonly ConnectionState[]>>;
3
+ export declare const PROTOCOL_DIAGNOSTIC_CAPACITY = 128;
4
+ export interface ConnectionCloseSnapshot {
5
+ readonly code: number | null;
6
+ readonly reason: null;
7
+ }
8
+ export type Deferred<T> = {
9
+ readonly promise: Promise<T>;
10
+ readonly resolve: (value: T) => void;
11
+ readonly reject: (reason: unknown) => void;
12
+ };
13
+ export declare function deferred<T>(): Deferred<T>;