@the-open-engine/zeroshot 6.29.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 (304) hide show
  1. package/cli/index.js +2 -4
  2. package/lib/agent-cli-provider/adapters/codex.d.ts.map +1 -1
  3. package/lib/agent-cli-provider/adapters/codex.js +0 -1
  4. package/lib/agent-cli-provider/adapters/codex.js.map +1 -1
  5. package/lib/cluster/client.cjs +30 -7
  6. package/lib/cluster/client.d.cts +52 -0
  7. package/lib/cluster/client.d.mts +52 -0
  8. package/lib/cluster/client.d.ts +4 -6
  9. package/lib/cluster/client.mjs +32 -9
  10. package/lib/cluster/connection-state.cjs +25 -0
  11. package/lib/cluster/connection-state.d.cts +13 -0
  12. package/lib/cluster/connection-state.d.mts +13 -0
  13. package/lib/cluster/connection-state.d.ts +13 -0
  14. package/lib/cluster/connection-state.mjs +21 -0
  15. package/lib/{target/hosted-run/contracts.js → cluster/connection-types.cjs} +0 -1
  16. package/lib/cluster/connection-types.d.cts +33 -0
  17. package/lib/cluster/connection-types.d.mts +33 -0
  18. package/lib/cluster/connection-types.d.ts +33 -0
  19. package/lib/cluster/connection-types.mjs +1 -0
  20. package/lib/cluster/connection.cjs +18 -46
  21. package/lib/cluster/connection.d.cts +26 -0
  22. package/lib/cluster/connection.d.mts +26 -0
  23. package/lib/cluster/connection.d.ts +7 -25
  24. package/lib/cluster/connection.mjs +12 -42
  25. package/lib/cluster/errors.cjs +9 -1
  26. package/lib/cluster/errors.d.cts +29 -0
  27. package/lib/cluster/errors.d.mts +29 -0
  28. package/lib/cluster/errors.d.ts +4 -0
  29. package/lib/cluster/errors.mjs +7 -0
  30. package/lib/cluster/frames.d.cts +12 -0
  31. package/lib/cluster/frames.d.mts +12 -0
  32. package/lib/cluster/generated/protocol-schema.d.cts +1 -0
  33. package/lib/cluster/generated/protocol-schema.d.mts +1 -0
  34. package/lib/cluster/generated/protocol.d.cts +781 -0
  35. package/lib/cluster/generated/protocol.d.mts +781 -0
  36. package/lib/cluster/index.cjs +2 -2
  37. package/lib/cluster/index.d.cts +13 -0
  38. package/lib/cluster/index.d.mts +13 -0
  39. package/lib/cluster/index.d.ts +3 -3
  40. package/lib/cluster/index.mjs +2 -2
  41. package/lib/cluster/json-source.cjs +1 -0
  42. package/lib/cluster/json-source.d.cts +5 -0
  43. package/lib/cluster/json-source.d.mts +5 -0
  44. package/lib/cluster/json-source.d.ts +1 -0
  45. package/lib/cluster/json-source.mjs +1 -0
  46. package/lib/cluster/payload-value.cjs +1 -0
  47. package/lib/cluster/payload-value.d.cts +8 -0
  48. package/lib/cluster/payload-value.d.mts +8 -0
  49. package/lib/cluster/payload-value.d.ts +1 -0
  50. package/lib/cluster/payload-value.mjs +1 -0
  51. package/lib/cluster/queue.d.cts +15 -0
  52. package/lib/cluster/queue.d.mts +15 -0
  53. package/lib/cluster/socket.cjs +8 -0
  54. package/lib/cluster/socket.d.cts +13 -0
  55. package/lib/cluster/socket.d.mts +13 -0
  56. package/lib/cluster/socket.d.ts +2 -0
  57. package/lib/cluster/socket.mjs +7 -0
  58. package/lib/cluster/subscriptions.d.cts +73 -0
  59. package/lib/cluster/subscriptions.d.mts +73 -0
  60. package/lib/cluster/subscriptions.d.ts +5 -1
  61. package/lib/cluster/validators.cjs +1 -0
  62. package/lib/cluster/validators.d.cts +7 -0
  63. package/lib/cluster/validators.d.mts +7 -0
  64. package/lib/cluster/validators.d.ts +1 -0
  65. package/lib/cluster/validators.mjs +1 -0
  66. package/lib/cluster-worker/engine-adapter.js +4 -10
  67. package/lib/cluster-worker/profiles.js +1 -42
  68. package/lib/hosted-session/authority.cjs +61 -0
  69. package/lib/hosted-session/authority.d.cts +3 -0
  70. package/lib/hosted-session/authority.d.mts +3 -0
  71. package/lib/hosted-session/authority.d.ts +3 -0
  72. package/lib/hosted-session/authority.mjs +57 -0
  73. package/lib/hosted-session/coordinator.cjs +78 -51
  74. package/lib/hosted-session/coordinator.d.cts +11 -0
  75. package/lib/hosted-session/coordinator.d.mts +11 -0
  76. package/lib/hosted-session/coordinator.d.ts +4 -2
  77. package/lib/hosted-session/coordinator.mjs +75 -51
  78. package/lib/hosted-session/errors.cjs +25 -0
  79. package/lib/hosted-session/errors.d.cts +10 -0
  80. package/lib/hosted-session/errors.d.mts +10 -0
  81. package/lib/hosted-session/errors.d.ts +10 -0
  82. package/lib/hosted-session/errors.mjs +19 -0
  83. package/lib/hosted-session/index.cjs +4 -1
  84. package/lib/hosted-session/index.d.cts +2 -0
  85. package/lib/hosted-session/index.d.mts +2 -0
  86. package/lib/hosted-session/index.d.ts +2 -2
  87. package/lib/hosted-session/index.mjs +1 -1
  88. package/lib/hosted-session/reconnecting-watch.cjs +131 -0
  89. package/lib/hosted-session/reconnecting-watch.d.cts +13 -0
  90. package/lib/hosted-session/reconnecting-watch.d.mts +13 -0
  91. package/lib/hosted-session/reconnecting-watch.d.ts +13 -0
  92. package/lib/hosted-session/reconnecting-watch.mjs +127 -0
  93. package/lib/hosted-session/types.d.cts +32 -0
  94. package/lib/hosted-session/types.d.mts +32 -0
  95. package/lib/hosted-session/types.d.ts +19 -7
  96. package/lib/hosted-target/access-url.cjs +44 -0
  97. package/lib/hosted-target/access-url.d.cts +2 -0
  98. package/lib/hosted-target/access-url.d.mts +2 -0
  99. package/lib/hosted-target/access-url.d.ts +2 -0
  100. package/lib/hosted-target/access-url.mjs +41 -0
  101. package/lib/hosted-target/adapter-request.cjs +12 -0
  102. package/lib/hosted-target/adapter-request.d.cts +17 -0
  103. package/lib/hosted-target/adapter-request.d.mts +17 -0
  104. package/lib/hosted-target/adapter-request.d.ts +17 -0
  105. package/lib/hosted-target/adapter-request.mjs +9 -0
  106. package/lib/hosted-target/adapter-types.cjs +2 -0
  107. package/lib/hosted-target/adapter-types.d.cts +27 -0
  108. package/lib/hosted-target/adapter-types.d.mts +27 -0
  109. package/lib/hosted-target/adapter-types.d.ts +27 -0
  110. package/lib/hosted-target/adapter-types.mjs +1 -0
  111. package/lib/hosted-target/bounds.cjs +10 -0
  112. package/lib/hosted-target/bounds.d.cts +7 -0
  113. package/lib/hosted-target/bounds.d.mts +7 -0
  114. package/lib/hosted-target/bounds.d.ts +7 -0
  115. package/lib/hosted-target/bounds.mjs +7 -0
  116. package/lib/hosted-target/capsule-error-response.cjs +76 -0
  117. package/lib/hosted-target/capsule-error-response.d.cts +2 -0
  118. package/lib/hosted-target/capsule-error-response.d.mts +2 -0
  119. package/lib/hosted-target/capsule-error-response.d.ts +2 -0
  120. package/lib/hosted-target/capsule-error-response.mjs +73 -0
  121. package/lib/hosted-target/errors.cjs +88 -0
  122. package/lib/hosted-target/errors.d.cts +36 -0
  123. package/lib/hosted-target/errors.d.mts +36 -0
  124. package/lib/hosted-target/errors.d.ts +36 -0
  125. package/lib/hosted-target/errors.mjs +75 -0
  126. package/lib/hosted-target/index.cjs +16 -0
  127. package/lib/hosted-target/index.d.cts +3 -0
  128. package/lib/hosted-target/index.d.mts +3 -0
  129. package/lib/hosted-target/index.d.ts +3 -0
  130. package/lib/hosted-target/index.mjs +2 -0
  131. package/lib/hosted-target/response-validation.cjs +169 -0
  132. package/lib/hosted-target/response-validation.d.cts +5 -0
  133. package/lib/hosted-target/response-validation.d.mts +5 -0
  134. package/lib/hosted-target/response-validation.d.ts +5 -0
  135. package/lib/hosted-target/response-validation.mjs +163 -0
  136. package/lib/hosted-target/retry-executor.cjs +51 -0
  137. package/lib/hosted-target/retry-executor.d.cts +8 -0
  138. package/lib/hosted-target/retry-executor.d.mts +8 -0
  139. package/lib/hosted-target/retry-executor.d.ts +8 -0
  140. package/lib/hosted-target/retry-executor.mjs +48 -0
  141. package/lib/hosted-target/retry.cjs +78 -0
  142. package/lib/hosted-target/retry.d.cts +9 -0
  143. package/lib/hosted-target/retry.d.mts +9 -0
  144. package/lib/hosted-target/retry.d.ts +9 -0
  145. package/lib/hosted-target/retry.mjs +73 -0
  146. package/lib/hosted-target/target-adapter.cjs +10 -0
  147. package/lib/hosted-target/target-adapter.d.cts +3 -0
  148. package/lib/hosted-target/target-adapter.d.mts +3 -0
  149. package/lib/hosted-target/target-adapter.d.ts +3 -0
  150. package/lib/hosted-target/target-adapter.mjs +7 -0
  151. package/lib/hosted-target/types.cjs +4 -0
  152. package/lib/hosted-target/types.d.cts +50 -0
  153. package/lib/hosted-target/types.d.mts +50 -0
  154. package/lib/hosted-target/types.d.ts +50 -0
  155. package/lib/hosted-target/types.mjs +1 -0
  156. package/lib/hosted-target/zero-cloud-v1-adapter.cjs +185 -0
  157. package/lib/hosted-target/zero-cloud-v1-adapter.d.cts +13 -0
  158. package/lib/hosted-target/zero-cloud-v1-adapter.d.mts +13 -0
  159. package/lib/hosted-target/zero-cloud-v1-adapter.d.ts +13 -0
  160. package/lib/hosted-target/zero-cloud-v1-adapter.mjs +181 -0
  161. package/lib/start-cluster.js +3 -3
  162. package/lib/target/bounded-response.cjs +51 -0
  163. package/lib/target/bounded-response.d.cts +1 -0
  164. package/lib/target/bounded-response.d.mts +1 -0
  165. package/lib/target/bounded-response.d.ts +1 -0
  166. package/lib/target/bounded-response.js +51 -0
  167. package/lib/target/bounded-response.mjs +48 -0
  168. package/lib/target/credential-lock.js +1 -3
  169. package/lib/target/credential-store.js +9 -4
  170. package/lib/target/device-flow.cjs +213 -0
  171. package/lib/target/device-flow.d.cts +54 -0
  172. package/lib/target/device-flow.d.mts +54 -0
  173. package/lib/target/device-flow.d.ts +26 -14
  174. package/lib/target/device-flow.js +162 -58
  175. package/lib/target/device-flow.mjs +203 -0
  176. package/lib/target/discovery-errors.cjs +10 -0
  177. package/lib/target/discovery-errors.d.cts +3 -0
  178. package/lib/target/discovery-errors.d.mts +3 -0
  179. package/lib/target/discovery-errors.d.ts +3 -0
  180. package/lib/target/discovery-errors.js +10 -0
  181. package/lib/target/discovery-errors.mjs +6 -0
  182. package/lib/target/discovery-sections.cjs +191 -0
  183. package/lib/target/discovery-sections.d.cts +52 -0
  184. package/lib/target/discovery-sections.d.mts +52 -0
  185. package/lib/target/discovery-sections.d.ts +52 -0
  186. package/lib/target/discovery-sections.js +191 -0
  187. package/lib/target/discovery-sections.mjs +179 -0
  188. package/lib/target/discovery-validation.cjs +109 -0
  189. package/lib/target/discovery-validation.d.cts +28 -0
  190. package/lib/target/discovery-validation.d.mts +28 -0
  191. package/lib/target/discovery-validation.d.ts +28 -0
  192. package/lib/target/discovery-validation.js +109 -0
  193. package/lib/target/discovery-validation.mjs +99 -0
  194. package/lib/target/discovery.cjs +112 -0
  195. package/lib/target/discovery.d.cts +74 -0
  196. package/lib/target/discovery.d.mts +74 -0
  197. package/lib/target/discovery.d.ts +67 -5
  198. package/lib/target/discovery.js +94 -79
  199. package/lib/target/discovery.mjs +105 -0
  200. package/lib/target/index.d.ts +6 -6
  201. package/lib/target/index.js +36 -36
  202. package/lib/target/oauth-http.d.ts +2 -0
  203. package/lib/target/oauth-http.js +25 -0
  204. package/lib/target/refresh-exchange.d.ts +11 -0
  205. package/lib/target/refresh-exchange.js +24 -0
  206. package/lib/target/refresh-revocation.d.ts +8 -0
  207. package/lib/target/refresh-revocation.js +19 -0
  208. package/lib/target/route-template.cjs +85 -0
  209. package/lib/target/route-template.d.cts +7 -0
  210. package/lib/target/route-template.d.mts +7 -0
  211. package/lib/target/route-template.d.ts +7 -0
  212. package/lib/target/route-template.js +85 -0
  213. package/lib/target/route-template.mjs +81 -0
  214. package/lib/target/session-errors.d.ts +4 -0
  215. package/lib/target/session-errors.js +12 -0
  216. package/lib/target/session-verification.d.ts +10 -0
  217. package/lib/target/session-verification.js +42 -0
  218. package/lib/target/target-registry.d.ts +7 -3
  219. package/lib/target/target-registry.js +41 -10
  220. package/lib/target/target-session-manager.d.ts +48 -0
  221. package/lib/target/target-session-manager.js +226 -0
  222. package/lib/target/target-session.d.ts +39 -32
  223. package/lib/target/target-session.js +63 -151
  224. package/lib/target/token-response.cjs +51 -0
  225. package/lib/target/token-response.d.cts +7 -0
  226. package/lib/target/token-response.d.mts +7 -0
  227. package/lib/target/token-response.d.ts +7 -0
  228. package/lib/target/token-response.js +51 -0
  229. package/lib/target/token-response.mjs +48 -0
  230. package/package.json +4 -7
  231. package/scripts/build-cluster.js +23 -3
  232. package/scripts/opcore-introduced-check.js +0 -2
  233. package/src/agent-cli-provider/adapters/codex.ts +0 -1
  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/isolation-manager.js +1 -16
  266. package/src/target/bounded-response.ts +68 -0
  267. package/src/target/credential-lock.ts +1 -3
  268. package/src/target/credential-store.ts +14 -10
  269. package/src/target/device-flow.ts +209 -85
  270. package/src/target/discovery-errors.ts +6 -0
  271. package/src/target/discovery-sections.ts +251 -0
  272. package/src/target/discovery-validation.ts +144 -0
  273. package/src/target/discovery.ts +163 -97
  274. package/src/target/index.ts +15 -11
  275. package/src/target/oauth-http.ts +27 -0
  276. package/src/target/refresh-exchange.ts +36 -0
  277. package/src/target/refresh-revocation.ts +29 -0
  278. package/src/target/route-template.ts +105 -0
  279. package/src/target/session-errors.ts +9 -0
  280. package/src/target/session-verification.ts +51 -0
  281. package/src/target/target-registry.ts +60 -27
  282. package/src/target/target-session-manager.ts +285 -0
  283. package/src/target/target-session.ts +105 -226
  284. package/src/target/token-response.ts +62 -0
  285. package/docker/zeroshot-oecp/Cargo.toml +0 -12
  286. package/docker/zeroshot-oecp/Dockerfile +0 -65
  287. package/docker/zeroshot-oecp/src/main.rs +0 -32
  288. package/lib/target/bounded-json.d.ts +0 -6
  289. package/lib/target/bounded-json.js +0 -43
  290. package/lib/target/hosted-run/client.d.ts +0 -26
  291. package/lib/target/hosted-run/client.js +0 -158
  292. package/lib/target/hosted-run/commands.d.ts +0 -4
  293. package/lib/target/hosted-run/commands.js +0 -113
  294. package/lib/target/hosted-run/contracts.d.ts +0 -49
  295. package/lib/target/hosted-run/input.d.ts +0 -5
  296. package/lib/target/hosted-run/input.js +0 -200
  297. package/lib/target/hosted-run.d.ts +0 -4
  298. package/lib/target/hosted-run.js +0 -12
  299. package/src/target/bounded-json.ts +0 -48
  300. package/src/target/hosted-run/client.ts +0 -198
  301. package/src/target/hosted-run/commands.ts +0 -140
  302. package/src/target/hosted-run/contracts.ts +0 -53
  303. package/src/target/hosted-run/input.ts +0 -199
  304. package/src/target/hosted-run.ts +0 -8
@@ -0,0 +1,148 @@
1
+ import type {
2
+ WatchSubscription,
3
+ WatchSubscriptionItem,
4
+ } from '../cluster/index.js';
5
+ import {
6
+ HostedAuthorizationError,
7
+ HostedTransportUncertainError,
8
+ } from './errors.js';
9
+ import type { HostedWatch, InitializedSession } from './types.js';
10
+
11
+ type ReplaceSession = (signal: AbortSignal) => Promise<InitializedSession>;
12
+
13
+ export class ReconnectingHostedWatch implements HostedWatch {
14
+ readonly #replace: ReplaceSession;
15
+ readonly #ownedController = new AbortController();
16
+ readonly #signal: AbortSignal;
17
+ #session: InitializedSession;
18
+ #subscription: WatchSubscription;
19
+ #tail: Promise<void> = Promise.resolve();
20
+ #replacementPromise: Promise<InitializedSession> | undefined;
21
+ #cancelPromise: Promise<void> | undefined;
22
+ #reconnected = false;
23
+ #cancelled = false;
24
+
25
+ constructor(
26
+ replace: ReplaceSession,
27
+ session: InitializedSession,
28
+ subscription: WatchSubscription,
29
+ signal?: AbortSignal,
30
+ ) {
31
+ this.#replace = replace;
32
+ this.#session = session;
33
+ this.#subscription = subscription;
34
+ this.#signal = signal === undefined
35
+ ? this.#ownedController.signal
36
+ : AbortSignal.any([signal, this.#ownedController.signal]);
37
+ }
38
+
39
+ [Symbol.asyncIterator](): this {
40
+ return this;
41
+ }
42
+
43
+ next(): Promise<IteratorResult<WatchSubscriptionItem>> {
44
+ const result = this.#tail.then(() => this.#readNext());
45
+ this.#tail = result.then(() => undefined, () => undefined);
46
+ return result;
47
+ }
48
+
49
+ async #readNext(): Promise<IteratorResult<WatchSubscriptionItem>> {
50
+ while (!this.#cancelled) {
51
+ const item = await this.#subscription.stream.next();
52
+ if (this.#cancelled) return { done: true, value: undefined };
53
+ if (!item.done) return item;
54
+ return this.#handleClosed(item);
55
+ }
56
+ return { done: true, value: undefined };
57
+ }
58
+
59
+ async #handleClosed(
60
+ item: IteratorResult<WatchSubscriptionItem>,
61
+ ): Promise<IteratorResult<WatchSubscriptionItem>> {
62
+ if (this.#session.connection.state === 'OPEN') {
63
+ await this.#session.connection.close();
64
+ return item;
65
+ }
66
+ const { code } = await this.#session.connection.closed;
67
+ if (code === 4401) return this.#reconnect();
68
+ if (code === 4403) throw new HostedAuthorizationError();
69
+ if (code === 1000) return item;
70
+ throw new HostedTransportUncertainError();
71
+ }
72
+
73
+ async #reconnect(): Promise<IteratorResult<WatchSubscriptionItem>> {
74
+ if (this.#reconnected) throw new HostedTransportUncertainError();
75
+ this.#reconnected = true;
76
+ const replacementPromise = this.#replace(this.#signal);
77
+ this.#replacementPromise = replacementPromise;
78
+ let replacement: InitializedSession;
79
+ try {
80
+ replacement = await replacementPromise;
81
+ } catch (error) {
82
+ if (this.#cancelled) return { done: true, value: undefined };
83
+ throw error;
84
+ } finally {
85
+ if (this.#replacementPromise === replacementPromise) {
86
+ this.#replacementPromise = undefined;
87
+ }
88
+ }
89
+ return this.#installReplacement(replacement);
90
+ }
91
+
92
+ async #installReplacement(
93
+ replacement: InitializedSession,
94
+ ): Promise<IteratorResult<WatchSubscriptionItem>> {
95
+ if (this.#cancelled) {
96
+ await replacement.connection.close();
97
+ return { done: true, value: undefined };
98
+ }
99
+ try {
100
+ const subscription = await this.#subscription.stream.reconnect(replacement.connection);
101
+ if (this.#cancelled) {
102
+ await subscription.stream.cancel();
103
+ await replacement.connection.close();
104
+ return { done: true, value: undefined };
105
+ }
106
+ this.#subscription = subscription;
107
+ this.#session = replacement;
108
+ return this.#readNext();
109
+ } catch (error) {
110
+ await replacement.connection.close();
111
+ if (this.#cancelled) return { done: true, value: undefined };
112
+ throw error;
113
+ }
114
+ }
115
+
116
+ async return(): Promise<IteratorResult<WatchSubscriptionItem>> {
117
+ await this.cancel();
118
+ return { done: true, value: undefined };
119
+ }
120
+
121
+ async throw(error?: unknown): Promise<IteratorResult<WatchSubscriptionItem>> {
122
+ await this.cancel();
123
+ throw error;
124
+ }
125
+
126
+ cancel(): Promise<void> {
127
+ this.#cancelPromise ??= this.#cancelOwned();
128
+ return this.#cancelPromise;
129
+ }
130
+
131
+ async #cancelOwned(): Promise<void> {
132
+ this.#cancelled = true;
133
+ this.#ownedController.abort(new DOMException('hosted watch cancelled', 'AbortError'));
134
+ const replacement = this.#replacementPromise;
135
+ const outcomes = await Promise.allSettled([
136
+ this.#subscription.stream.cancel(),
137
+ this.#session.connection.close(),
138
+ ...(replacement === undefined
139
+ ? []
140
+ : [replacement.then(() => undefined, () => undefined)]),
141
+ ]);
142
+ await this.#tail;
143
+ const failure = outcomes.find(
144
+ (outcome): outcome is PromiseRejectedResult => outcome.status === 'rejected',
145
+ );
146
+ if (failure !== undefined) throw failure.reason;
147
+ }
148
+ }
@@ -1,15 +1,20 @@
1
- import type { Connection } from '../cluster/index.js';
2
- import type { ClusterClient, ConnectOptions } from '../cluster/index.js';
3
- import type { InitializeResult } from '../cluster/index.js';
4
-
5
- export interface AccessResponse {
6
- readonly endpoint: string;
7
- readonly token: string;
1
+ import type { Connection, ClusterClient, ConnectOptions, InitializeResult, WatchParams, WatchSubscriptionItem } from '../cluster/index.js';
2
+ export interface HostedAccess {
3
+ readonly protocol: 'openengine.cluster/v1';
4
+ readonly websocketUrl: string;
5
+ readonly accessToken: string;
6
+ readonly tokenType: 'Bearer';
8
7
  readonly expiresAt: string;
9
8
  }
10
9
 
10
+ export interface HostedAccessAdapter {
11
+ access(capsuleId: string, signal?: AbortSignal): Promise<HostedAccess>;
12
+ }
13
+
11
14
  export interface HostedSessionInit {
12
- readonly getAccess: (signal?: AbortSignal) => Promise<AccessResponse>;
15
+ readonly adapter: HostedAccessAdapter;
16
+ readonly capsuleId: string;
17
+ readonly targetAuthority: string;
13
18
  readonly connectOptions?: Omit<ConnectOptions, 'headers' | 'signal'>;
14
19
  readonly clock?: { now(): number };
15
20
  }
@@ -19,3 +24,12 @@ export interface InitializedSession {
19
24
  readonly client: ClusterClient;
20
25
  readonly initializeResult: InitializeResult;
21
26
  }
27
+
28
+ export interface HostedWatch extends AsyncIterator<WatchSubscriptionItem>, AsyncIterable<WatchSubscriptionItem> {
29
+ cancel(): Promise<void>;
30
+ }
31
+
32
+ export interface HostedWatchOptions {
33
+ readonly params: WatchParams;
34
+ readonly signal?: AbortSignal;
35
+ }
@@ -0,0 +1,46 @@
1
+ import type { TargetDiscoveryDescriptor } from '../target/discovery.js';
2
+ import { TargetProtocolError } from './errors.js';
3
+
4
+ function hasForbiddenCodePoint(value: string): boolean {
5
+ for (const character of value) {
6
+ const codePoint = character.codePointAt(0)!;
7
+ if (codePoint <= 0x20 || codePoint === 0x7f) return true;
8
+ }
9
+ return false;
10
+ }
11
+
12
+ function parseAccessUrl(value: string): URL {
13
+ try {
14
+ if (hasForbiddenCodePoint(value)) throw new TypeError('unsafe URL code point');
15
+ const url = new globalThis.URL(value);
16
+ if (url.href !== value) throw new TypeError('non-canonical URL');
17
+ return url;
18
+ } catch {
19
+ throw new TargetProtocolError('Capsule access WebSocket URL is invalid');
20
+ }
21
+ }
22
+
23
+ function matchesAccessRoute(url: URL, target: URL, expectedPath: string): boolean {
24
+ const expectedProtocol = target.protocol === 'http:' ? 'ws:' : 'wss:';
25
+ return url.protocol === expectedProtocol &&
26
+ url.host === target.host &&
27
+ !url.username &&
28
+ !url.password &&
29
+ !url.search &&
30
+ !url.hash &&
31
+ url.pathname === expectedPath;
32
+ }
33
+
34
+ export function validateAccessUrl(
35
+ value: string,
36
+ capsuleId: string,
37
+ descriptor: TargetDiscoveryDescriptor,
38
+ ): void {
39
+ const url = parseAccessUrl(value);
40
+ const expectedPath = descriptor.transport.websocketRouteTemplate.expand({
41
+ capsule_id: capsuleId,
42
+ });
43
+ if (!matchesAccessRoute(url, new globalThis.URL(descriptor.origin), expectedPath)) {
44
+ throw new TargetProtocolError('Capsule access WebSocket URL does not match discovery');
45
+ }
46
+ }
@@ -0,0 +1,28 @@
1
+ import type { RouteTemplate, TargetDiscoveryDescriptor } from '../target/discovery.js';
2
+ import { TargetProtocolError } from './errors.js';
3
+ import type { TargetOperation } from './retry-executor.js';
4
+
5
+ export type AdapterRequest = {
6
+ readonly body?: string;
7
+ readonly headers?: Readonly<Record<string, string>>;
8
+ };
9
+
10
+ export type ExecuteArguments<T> = [
11
+ operation: TargetOperation,
12
+ method: string,
13
+ template: RouteTemplate,
14
+ values: Readonly<Record<string, string | number | undefined>>,
15
+ expectedStatus: number,
16
+ validate: (body: unknown) => T,
17
+ signal?: AbortSignal,
18
+ request?: AdapterRequest,
19
+ ];
20
+
21
+ export function requestUrl(path: string, descriptor: TargetDiscoveryDescriptor): URL {
22
+ const url = new globalThis.URL(path, descriptor.capsule.baseUrl);
23
+ if (url.origin !== descriptor.origin || url.hash ||
24
+ `${url.pathname}${url.search}` !== path) {
25
+ throw new TargetProtocolError('Capsule route changed during URL canonicalization');
26
+ }
27
+ return url;
28
+ }
@@ -0,0 +1,39 @@
1
+ import type { TargetDiscoveryDescriptor } from '../target/discovery.js';
2
+ import type {
3
+ AllocateRequest,
4
+ Capsule,
5
+ CapsuleAccess,
6
+ CapsuleLimits,
7
+ CapsuleListPage,
8
+ Clock,
9
+ HttpTransport,
10
+ ListRequest,
11
+ RetryPolicy,
12
+ TargetAccessTokenProvider,
13
+ } from './types.js';
14
+
15
+ export type CredentialInstallCapability =
16
+ | { readonly supported: false }
17
+ | {
18
+ readonly supported: true;
19
+ readonly descriptor: NonNullable<TargetDiscoveryDescriptor['credentialInstall']>;
20
+ };
21
+
22
+ export interface TargetAdapter {
23
+ allocate(req: AllocateRequest, signal?: AbortSignal): Promise<Capsule>;
24
+ list(req?: ListRequest, signal?: AbortSignal): Promise<CapsuleListPage>;
25
+ inspect(capsuleId: string, signal?: AbortSignal): Promise<Capsule>;
26
+ terminate(capsuleId: string, signal?: AbortSignal): Promise<Capsule>;
27
+ limits(signal?: AbortSignal): Promise<CapsuleLimits>;
28
+ access(capsuleId: string, signal?: AbortSignal): Promise<CapsuleAccess>;
29
+ readonly credentialInstall: CredentialInstallCapability;
30
+ }
31
+
32
+ export interface CreateTargetAdapterOptions {
33
+ readonly descriptor: TargetDiscoveryDescriptor;
34
+ readonly organization: { readonly id: string };
35
+ readonly tokenProvider: TargetAccessTokenProvider;
36
+ readonly transport?: HttpTransport;
37
+ readonly clock?: Clock;
38
+ readonly retryPolicy?: RetryPolicy;
39
+ }
@@ -1,3 +1,4 @@
1
+ /** Shared wire limits for every hosted-target response and retry path. */
1
2
  export const MAX_RESPONSE_BYTES = 2 * 1024 * 1024;
2
3
  export const MAX_PAGINATION_PAGES = 100;
3
4
  export const MAX_RETRY_ATTEMPTS = 3;
@@ -0,0 +1,107 @@
1
+ import { TargetProtocolError, TargetServerError } from './errors.js';
2
+ import { parseRetryAfter } from './retry.js';
3
+ import type { Clock } from './types.js';
4
+
5
+ const ERROR_CODES = Object.freeze({
6
+ unauthorized: { statuses: [401], retryable: false },
7
+ invalid_request: { statuses: [400], retryable: false },
8
+ not_found: { statuses: [404], retryable: false },
9
+ forbidden: { statuses: [402, 403], retryable: false },
10
+ idempotency_conflict: { statuses: [409], retryable: false },
11
+ run_conflict: { statuses: [409], retryable: true },
12
+ rate_limited: { statuses: [429], retryable: true },
13
+ temporarily_unavailable: { statuses: [503], retryable: true },
14
+ internal_error: { statuses: [500], retryable: false },
15
+ });
16
+ type ErrorCode = keyof typeof ERROR_CODES;
17
+
18
+ type CapsuleErrorBody = {
19
+ readonly code: ErrorCode;
20
+ readonly capsuleId: string | null;
21
+ readonly retryable: boolean;
22
+ };
23
+
24
+ function isErrorCode(value: unknown): value is ErrorCode {
25
+ return typeof value === 'string' && value in ERROR_CODES;
26
+ }
27
+
28
+ function isRecordBody(body: unknown): body is Record<string, unknown> {
29
+ return body !== null && typeof body === 'object' && !Array.isArray(body);
30
+ }
31
+
32
+ function hasExactErrorFields(value: Record<string, unknown>): boolean {
33
+ const fields = Object.keys(value);
34
+ const exactFields = ['code', 'message', 'capsule_id', 'retryable'];
35
+ return fields.length === exactFields.length &&
36
+ exactFields.every((field) => field in value);
37
+ }
38
+
39
+ function hasValidErrorValues(value: Record<string, unknown>): value is Record<string, unknown> & {
40
+ readonly code: ErrorCode;
41
+ readonly capsule_id: string | null;
42
+ readonly retryable: boolean;
43
+ } {
44
+ return isErrorCode(value.code) &&
45
+ typeof value.message === 'string' &&
46
+ (value.capsule_id === null || typeof value.capsule_id === 'string') &&
47
+ typeof value.retryable === 'boolean';
48
+ }
49
+
50
+ function parseErrorBody(body: unknown): CapsuleErrorBody {
51
+ if (!isRecordBody(body) || !hasExactErrorFields(body) || !hasValidErrorValues(body)) {
52
+ throw new TargetProtocolError('Capsule error response is malformed');
53
+ }
54
+ const value = body;
55
+ return {
56
+ code: value.code,
57
+ capsuleId: value.capsule_id,
58
+ retryable: value.retryable,
59
+ };
60
+ }
61
+
62
+ function validateChallenge(response: Response): void {
63
+ if (response.status !== 401) return;
64
+ if (response.headers.get('WWW-Authenticate') !== 'Bearer error="invalid_token"') {
65
+ throw new TargetProtocolError('Capsule authentication challenge is malformed');
66
+ }
67
+ }
68
+
69
+ function validatedRetryAfter(
70
+ response: Response,
71
+ retryable: boolean,
72
+ clock: Clock,
73
+ ): number | undefined {
74
+ const header = response.headers.get('Retry-After');
75
+ const retryAfter = parseRetryAfter(header, clock) ?? undefined;
76
+ if (header !== null && retryAfter === undefined) {
77
+ throw new TargetProtocolError('Capsule Retry-After header is malformed');
78
+ }
79
+ if (retryable && retryAfter === undefined) {
80
+ throw new TargetProtocolError('Retryable capsule error omitted Retry-After');
81
+ }
82
+ if (!retryable && retryAfter !== undefined) {
83
+ throw new TargetProtocolError('Permanent capsule error advertised Retry-After');
84
+ }
85
+ return retryAfter;
86
+ }
87
+
88
+ export async function throwCapsuleServerError(
89
+ response: Response,
90
+ readJson: (response: Response) => Promise<unknown>,
91
+ clock: Clock,
92
+ ): Promise<never> {
93
+ const value = parseErrorBody(await readJson(response));
94
+ const contract = ERROR_CODES[value.code];
95
+ if (!contract.statuses.includes(response.status) || contract.retryable !== value.retryable) {
96
+ throw new TargetProtocolError('Capsule error response contradicts its status contract');
97
+ }
98
+ validateChallenge(response);
99
+ const retryAfter = validatedRetryAfter(response, contract.retryable, clock);
100
+ throw new TargetServerError(
101
+ response.status,
102
+ value.code,
103
+ contract.retryable,
104
+ value.capsuleId,
105
+ retryAfter,
106
+ );
107
+ }
@@ -1,37 +1,38 @@
1
- function sanitize(text: string): string {
2
- return text
3
- .replace(/Authorization:\s*Bearer\s+\S+/gi, 'Authorization: Bearer [REDACTED]')
4
- .replace(/token["']?\s*[:=]\s*["'][^"']+["']/gi, 'token: "[REDACTED]"')
5
- .replace(/https?:\/\/[^\s]*(?:token|key|secret|credential|auth)[^\s]*/gi, '[REDACTED_URL]');
6
- }
7
-
8
- function sanitizeCause(cause: unknown): unknown {
9
- if (!cause) return cause;
10
- if (cause instanceof Error) {
11
- const cleaned = new Error(sanitize(cause.message));
12
- cleaned.name = cause.name;
13
- if (cause.cause) cleaned.cause = sanitizeCause(cause.cause);
14
- return cleaned;
15
- }
16
- if (typeof cause === 'string') return sanitize(cause);
17
- return cause;
18
- }
19
-
20
1
  export class TargetAdapterError extends Error {
21
2
  readonly code: string;
22
3
  readonly retryable: boolean;
23
4
 
24
- constructor(code: string, message: string, retryable: boolean, cause?: unknown) {
25
- super(sanitize(message), { cause: sanitizeCause(cause) });
5
+ constructor(code: string, message: string, retryable: boolean) {
6
+ super(message);
26
7
  this.name = 'TargetAdapterError';
27
8
  this.code = code;
28
9
  this.retryable = retryable;
29
10
  }
30
11
  }
12
+ export class TargetServerError extends TargetAdapterError {
13
+ readonly status: number;
14
+ readonly serverCode: string;
15
+ readonly capsuleId: string | null;
16
+ readonly retryAfterMs: number | undefined;
31
17
 
18
+ constructor(
19
+ status: number,
20
+ serverCode: string,
21
+ retryable: boolean,
22
+ capsuleId: string | null,
23
+ retryAfterMs?: number
24
+ ) {
25
+ super('SERVER_REJECTED', `Capsule request failed (${serverCode})`, retryable);
26
+ this.name = 'TargetServerError';
27
+ this.status = status;
28
+ this.serverCode = serverCode;
29
+ this.capsuleId = capsuleId;
30
+ this.retryAfterMs = retryAfterMs;
31
+ }
32
+ }
32
33
  export class TargetAuthError extends TargetAdapterError {
33
- constructor(message: string, cause?: unknown) {
34
- super('AUTH_FAILED', message, false, cause);
34
+ constructor(message: string) {
35
+ super('AUTH_FAILED', message, false);
35
36
  this.name = 'TargetAuthError';
36
37
  }
37
38
  }
@@ -39,8 +40,8 @@ export class TargetAuthError extends TargetAdapterError {
39
40
  export class TargetConflictError extends TargetAdapterError {
40
41
  readonly idempotencyKey: string;
41
42
 
42
- constructor(idempotencyKey: string, message: string, cause?: unknown) {
43
- super('CONFLICT', message, true, cause);
43
+ constructor(idempotencyKey: string, message: string) {
44
+ super('CONFLICT', message, true);
44
45
  this.name = 'TargetConflictError';
45
46
  this.idempotencyKey = idempotencyKey;
46
47
  }
@@ -49,37 +50,37 @@ export class TargetConflictError extends TargetAdapterError {
49
50
  export class TargetRateLimitError extends TargetAdapterError {
50
51
  readonly retryAfterMs: number | undefined;
51
52
 
52
- constructor(message: string, retryAfterMs?: number, cause?: unknown) {
53
- super('RATE_LIMITED', message, true, cause);
53
+ constructor(message: string, retryAfterMs?: number) {
54
+ super('RATE_LIMITED', message, true);
54
55
  this.name = 'TargetRateLimitError';
55
56
  this.retryAfterMs = retryAfterMs;
56
57
  }
57
58
  }
58
59
 
59
60
  export class TargetTransportError extends TargetAdapterError {
60
- constructor(message: string, cause?: unknown) {
61
- super('TRANSPORT', message, true, cause);
61
+ constructor(message: string) {
62
+ super('TRANSPORT', message, true);
62
63
  this.name = 'TargetTransportError';
63
64
  }
64
65
  }
65
66
 
66
67
  export class TargetProtocolError extends TargetAdapterError {
67
- constructor(message: string, cause?: unknown) {
68
- super('PROTOCOL', message, false, cause);
68
+ constructor(message: string) {
69
+ super('PROTOCOL', message, false);
69
70
  this.name = 'TargetProtocolError';
70
71
  }
71
72
  }
72
73
 
73
74
  export class TargetCapacityError extends TargetAdapterError {
74
- constructor(message: string, cause?: unknown) {
75
- super('CAPACITY', message, false, cause);
75
+ constructor(message: string) {
76
+ super('CAPACITY', message, false);
76
77
  this.name = 'TargetCapacityError';
77
78
  }
78
79
  }
79
80
 
80
81
  export class TargetNotFoundError extends TargetAdapterError {
81
- constructor(message: string, cause?: unknown) {
82
- super('NOT_FOUND', message, false, cause);
82
+ constructor(message: string) {
83
+ super('NOT_FOUND', message, false);
83
84
  this.name = 'TargetNotFoundError';
84
85
  }
85
86
  }
@@ -1,5 +1,9 @@
1
- export type { TargetAdapter } from './target-adapter.ts';
2
- export { ZeroCloudV1TargetAdapter } from './zero-cloud-v1-adapter.ts';
1
+ export {
2
+ createTargetAdapter,
3
+ type TargetAdapter,
4
+ type CreateTargetAdapterOptions,
5
+ type CredentialInstallCapability,
6
+ } from './target-adapter.js';
3
7
  export {
4
8
  TargetAdapterError,
5
9
  TargetAuthError,
@@ -9,8 +13,9 @@ export {
9
13
  TargetProtocolError,
10
14
  TargetCapacityError,
11
15
  TargetNotFoundError,
16
+ TargetServerError,
12
17
  isRetryable,
13
- } from './errors.ts';
18
+ } from './errors.js';
14
19
  export type {
15
20
  TargetAccessTokenProvider,
16
21
  CapsuleState,
@@ -19,26 +24,8 @@ export type {
19
24
  CapsuleListPage,
20
25
  CapsuleLimits,
21
26
  AllocateRequest,
27
+ ListRequest,
22
28
  HttpTransport,
23
29
  Clock,
24
30
  RetryPolicy,
25
- TargetDiscovery,
26
- } from './types.ts';
27
- export { KNOWN_CAPSULE_STATES } from './types.ts';
28
- export {
29
- MAX_RESPONSE_BYTES,
30
- MAX_PAGINATION_PAGES,
31
- MAX_RETRY_ATTEMPTS,
32
- MAX_RETRY_ELAPSED_MS,
33
- MAX_ERROR_BODY_BYTES,
34
- IDEMPOTENCY_KEY_PATTERN,
35
- } from './bounds.ts';
36
- export { DefaultRetryPolicy, parseRetryAfter } from './retry.ts';
37
- export {
38
- assertRequiredFields,
39
- assertKnownEnum,
40
- assertCapsule,
41
- assertCapsuleAccess,
42
- assertCapsuleLimits,
43
- assertCapsuleListPage,
44
- } from './response-validation.ts';
31
+ } from './types.js';