@the-open-engine/zeroshot 6.29.0 → 6.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (347) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/cli/index.js +2 -4
  3. package/lib/agent-cli-provider/adapters/codex.d.ts.map +1 -1
  4. package/lib/agent-cli-provider/adapters/codex.js +0 -1
  5. package/lib/agent-cli-provider/adapters/codex.js.map +1 -1
  6. package/lib/agent-cli-provider/contract-actions.d.ts +1 -1
  7. package/lib/agent-cli-provider/contract-actions.d.ts.map +1 -1
  8. package/lib/agent-cli-provider/contract-actions.js +5 -5
  9. package/lib/agent-cli-provider/contract-actions.js.map +1 -1
  10. package/lib/agent-cli-provider/contract-invoke.d.ts +1 -1
  11. package/lib/agent-cli-provider/contract-invoke.d.ts.map +1 -1
  12. package/lib/agent-cli-provider/contract-invoke.js +2 -2
  13. package/lib/agent-cli-provider/contract-invoke.js.map +1 -1
  14. package/lib/agent-cli-provider/contract-support.d.ts +1 -1
  15. package/lib/agent-cli-provider/contract-support.d.ts.map +1 -1
  16. package/lib/agent-cli-provider/contract-support.js +2 -2
  17. package/lib/agent-cli-provider/contract-support.js.map +1 -1
  18. package/lib/agent-cli-provider/contract.d.ts +1 -0
  19. package/lib/agent-cli-provider/contract.d.ts.map +1 -1
  20. package/lib/agent-cli-provider/contract.js +1 -1
  21. package/lib/agent-cli-provider/contract.js.map +1 -1
  22. package/lib/agent-cli-provider/index.d.ts +1 -1
  23. package/lib/agent-cli-provider/index.d.ts.map +1 -1
  24. package/lib/agent-cli-provider/index.js +2 -1
  25. package/lib/agent-cli-provider/index.js.map +1 -1
  26. package/lib/agent-cli-provider/provider-registry.d.ts +1 -0
  27. package/lib/agent-cli-provider/provider-registry.d.ts.map +1 -1
  28. package/lib/agent-cli-provider/provider-registry.js +4 -0
  29. package/lib/agent-cli-provider/provider-registry.js.map +1 -1
  30. package/lib/agent-cli-provider/single-agent-runtime.d.ts +3 -3
  31. package/lib/agent-cli-provider/single-agent-runtime.d.ts.map +1 -1
  32. package/lib/agent-cli-provider/single-agent-runtime.js +22 -48
  33. package/lib/agent-cli-provider/single-agent-runtime.js.map +1 -1
  34. package/lib/cluster/client.cjs +30 -7
  35. package/lib/cluster/client.d.cts +52 -0
  36. package/lib/cluster/client.d.mts +52 -0
  37. package/lib/cluster/client.d.ts +4 -6
  38. package/lib/cluster/client.mjs +32 -9
  39. package/lib/cluster/connection-state.cjs +25 -0
  40. package/lib/cluster/connection-state.d.cts +13 -0
  41. package/lib/cluster/connection-state.d.mts +13 -0
  42. package/lib/cluster/connection-state.d.ts +13 -0
  43. package/lib/cluster/connection-state.mjs +21 -0
  44. package/lib/{target/hosted-run/contracts.js → cluster/connection-types.cjs} +0 -1
  45. package/lib/cluster/connection-types.d.cts +33 -0
  46. package/lib/cluster/connection-types.d.mts +33 -0
  47. package/lib/cluster/connection-types.d.ts +33 -0
  48. package/lib/cluster/connection-types.mjs +1 -0
  49. package/lib/cluster/connection.cjs +18 -46
  50. package/lib/cluster/connection.d.cts +26 -0
  51. package/lib/cluster/connection.d.mts +26 -0
  52. package/lib/cluster/connection.d.ts +7 -25
  53. package/lib/cluster/connection.mjs +12 -42
  54. package/lib/cluster/errors.cjs +9 -1
  55. package/lib/cluster/errors.d.cts +29 -0
  56. package/lib/cluster/errors.d.mts +29 -0
  57. package/lib/cluster/errors.d.ts +4 -0
  58. package/lib/cluster/errors.mjs +7 -0
  59. package/lib/cluster/frames.d.cts +12 -0
  60. package/lib/cluster/frames.d.mts +12 -0
  61. package/lib/cluster/generated/protocol-schema.d.cts +1 -0
  62. package/lib/cluster/generated/protocol-schema.d.mts +1 -0
  63. package/lib/cluster/generated/protocol.d.cts +781 -0
  64. package/lib/cluster/generated/protocol.d.mts +781 -0
  65. package/lib/cluster/index.cjs +2 -2
  66. package/lib/cluster/index.d.cts +13 -0
  67. package/lib/cluster/index.d.mts +13 -0
  68. package/lib/cluster/index.d.ts +3 -3
  69. package/lib/cluster/index.mjs +2 -2
  70. package/lib/cluster/json-source.cjs +1 -0
  71. package/lib/cluster/json-source.d.cts +5 -0
  72. package/lib/cluster/json-source.d.mts +5 -0
  73. package/lib/cluster/json-source.d.ts +1 -0
  74. package/lib/cluster/json-source.mjs +1 -0
  75. package/lib/cluster/payload-value.cjs +1 -0
  76. package/lib/cluster/payload-value.d.cts +8 -0
  77. package/lib/cluster/payload-value.d.mts +8 -0
  78. package/lib/cluster/payload-value.d.ts +1 -0
  79. package/lib/cluster/payload-value.mjs +1 -0
  80. package/lib/cluster/queue.d.cts +15 -0
  81. package/lib/cluster/queue.d.mts +15 -0
  82. package/lib/cluster/socket.cjs +8 -0
  83. package/lib/cluster/socket.d.cts +13 -0
  84. package/lib/cluster/socket.d.mts +13 -0
  85. package/lib/cluster/socket.d.ts +2 -0
  86. package/lib/cluster/socket.mjs +7 -0
  87. package/lib/cluster/subscriptions.d.cts +73 -0
  88. package/lib/cluster/subscriptions.d.mts +73 -0
  89. package/lib/cluster/subscriptions.d.ts +5 -1
  90. package/lib/cluster/validators.cjs +1 -0
  91. package/lib/cluster/validators.d.cts +7 -0
  92. package/lib/cluster/validators.d.mts +7 -0
  93. package/lib/cluster/validators.d.ts +1 -0
  94. package/lib/cluster/validators.mjs +1 -0
  95. package/lib/cluster-worker/engine-adapter-common.js +37 -0
  96. package/lib/cluster-worker/engine-adapter.js +24 -30
  97. package/lib/cluster-worker/engine-start.js +59 -0
  98. package/lib/cluster-worker/index.js +49 -67
  99. package/lib/cluster-worker/profiles.js +1 -42
  100. package/lib/cluster-worker/runtime-dependencies.js +49 -0
  101. package/lib/cluster-worker/runtime-support.js +2 -34
  102. package/lib/cluster-worker/terminal-normalizer.js +9 -10
  103. package/lib/hosted-session/authority.cjs +61 -0
  104. package/lib/hosted-session/authority.d.cts +3 -0
  105. package/lib/hosted-session/authority.d.mts +3 -0
  106. package/lib/hosted-session/authority.d.ts +3 -0
  107. package/lib/hosted-session/authority.mjs +57 -0
  108. package/lib/hosted-session/coordinator.cjs +78 -51
  109. package/lib/hosted-session/coordinator.d.cts +11 -0
  110. package/lib/hosted-session/coordinator.d.mts +11 -0
  111. package/lib/hosted-session/coordinator.d.ts +4 -2
  112. package/lib/hosted-session/coordinator.mjs +75 -51
  113. package/lib/hosted-session/errors.cjs +25 -0
  114. package/lib/hosted-session/errors.d.cts +10 -0
  115. package/lib/hosted-session/errors.d.mts +10 -0
  116. package/lib/hosted-session/errors.d.ts +10 -0
  117. package/lib/hosted-session/errors.mjs +19 -0
  118. package/lib/hosted-session/index.cjs +4 -1
  119. package/lib/hosted-session/index.d.cts +2 -0
  120. package/lib/hosted-session/index.d.mts +2 -0
  121. package/lib/hosted-session/index.d.ts +2 -2
  122. package/lib/hosted-session/index.mjs +1 -1
  123. package/lib/hosted-session/reconnecting-watch.cjs +131 -0
  124. package/lib/hosted-session/reconnecting-watch.d.cts +13 -0
  125. package/lib/hosted-session/reconnecting-watch.d.mts +13 -0
  126. package/lib/hosted-session/reconnecting-watch.d.ts +13 -0
  127. package/lib/hosted-session/reconnecting-watch.mjs +127 -0
  128. package/lib/hosted-session/types.d.cts +32 -0
  129. package/lib/hosted-session/types.d.mts +32 -0
  130. package/lib/hosted-session/types.d.ts +19 -7
  131. package/lib/hosted-target/access-url.cjs +44 -0
  132. package/lib/hosted-target/access-url.d.cts +2 -0
  133. package/lib/hosted-target/access-url.d.mts +2 -0
  134. package/lib/hosted-target/access-url.d.ts +2 -0
  135. package/lib/hosted-target/access-url.mjs +41 -0
  136. package/lib/hosted-target/adapter-request.cjs +12 -0
  137. package/lib/hosted-target/adapter-request.d.cts +17 -0
  138. package/lib/hosted-target/adapter-request.d.mts +17 -0
  139. package/lib/hosted-target/adapter-request.d.ts +17 -0
  140. package/lib/hosted-target/adapter-request.mjs +9 -0
  141. package/lib/hosted-target/adapter-types.cjs +2 -0
  142. package/lib/hosted-target/adapter-types.d.cts +27 -0
  143. package/lib/hosted-target/adapter-types.d.mts +27 -0
  144. package/lib/hosted-target/adapter-types.d.ts +27 -0
  145. package/lib/hosted-target/adapter-types.mjs +1 -0
  146. package/lib/hosted-target/bounds.cjs +10 -0
  147. package/lib/hosted-target/bounds.d.cts +7 -0
  148. package/lib/hosted-target/bounds.d.mts +7 -0
  149. package/lib/hosted-target/bounds.d.ts +7 -0
  150. package/lib/hosted-target/bounds.mjs +7 -0
  151. package/lib/hosted-target/capsule-error-response.cjs +76 -0
  152. package/lib/hosted-target/capsule-error-response.d.cts +2 -0
  153. package/lib/hosted-target/capsule-error-response.d.mts +2 -0
  154. package/lib/hosted-target/capsule-error-response.d.ts +2 -0
  155. package/lib/hosted-target/capsule-error-response.mjs +73 -0
  156. package/lib/hosted-target/errors.cjs +88 -0
  157. package/lib/hosted-target/errors.d.cts +36 -0
  158. package/lib/hosted-target/errors.d.mts +36 -0
  159. package/lib/hosted-target/errors.d.ts +36 -0
  160. package/lib/hosted-target/errors.mjs +75 -0
  161. package/lib/hosted-target/index.cjs +16 -0
  162. package/lib/hosted-target/index.d.cts +3 -0
  163. package/lib/hosted-target/index.d.mts +3 -0
  164. package/lib/hosted-target/index.d.ts +3 -0
  165. package/lib/hosted-target/index.mjs +2 -0
  166. package/lib/hosted-target/response-validation.cjs +169 -0
  167. package/lib/hosted-target/response-validation.d.cts +5 -0
  168. package/lib/hosted-target/response-validation.d.mts +5 -0
  169. package/lib/hosted-target/response-validation.d.ts +5 -0
  170. package/lib/hosted-target/response-validation.mjs +163 -0
  171. package/lib/hosted-target/retry-executor.cjs +51 -0
  172. package/lib/hosted-target/retry-executor.d.cts +8 -0
  173. package/lib/hosted-target/retry-executor.d.mts +8 -0
  174. package/lib/hosted-target/retry-executor.d.ts +8 -0
  175. package/lib/hosted-target/retry-executor.mjs +48 -0
  176. package/lib/hosted-target/retry.cjs +78 -0
  177. package/lib/hosted-target/retry.d.cts +9 -0
  178. package/lib/hosted-target/retry.d.mts +9 -0
  179. package/lib/hosted-target/retry.d.ts +9 -0
  180. package/lib/hosted-target/retry.mjs +73 -0
  181. package/lib/hosted-target/target-adapter.cjs +10 -0
  182. package/lib/hosted-target/target-adapter.d.cts +3 -0
  183. package/lib/hosted-target/target-adapter.d.mts +3 -0
  184. package/lib/hosted-target/target-adapter.d.ts +3 -0
  185. package/lib/hosted-target/target-adapter.mjs +7 -0
  186. package/lib/hosted-target/types.cjs +4 -0
  187. package/lib/hosted-target/types.d.cts +50 -0
  188. package/lib/hosted-target/types.d.mts +50 -0
  189. package/lib/hosted-target/types.d.ts +50 -0
  190. package/lib/hosted-target/types.mjs +1 -0
  191. package/lib/hosted-target/zero-cloud-v1-adapter.cjs +185 -0
  192. package/lib/hosted-target/zero-cloud-v1-adapter.d.cts +13 -0
  193. package/lib/hosted-target/zero-cloud-v1-adapter.d.mts +13 -0
  194. package/lib/hosted-target/zero-cloud-v1-adapter.d.ts +13 -0
  195. package/lib/hosted-target/zero-cloud-v1-adapter.mjs +181 -0
  196. package/lib/start-cluster.js +3 -3
  197. package/lib/target/bounded-response.cjs +51 -0
  198. package/lib/target/bounded-response.d.cts +1 -0
  199. package/lib/target/bounded-response.d.mts +1 -0
  200. package/lib/target/bounded-response.d.ts +1 -0
  201. package/lib/target/bounded-response.js +51 -0
  202. package/lib/target/bounded-response.mjs +48 -0
  203. package/lib/target/credential-lock.js +1 -3
  204. package/lib/target/credential-store.js +9 -4
  205. package/lib/target/device-flow.cjs +213 -0
  206. package/lib/target/device-flow.d.cts +54 -0
  207. package/lib/target/device-flow.d.mts +54 -0
  208. package/lib/target/device-flow.d.ts +26 -14
  209. package/lib/target/device-flow.js +162 -58
  210. package/lib/target/device-flow.mjs +203 -0
  211. package/lib/target/discovery-errors.cjs +10 -0
  212. package/lib/target/discovery-errors.d.cts +3 -0
  213. package/lib/target/discovery-errors.d.mts +3 -0
  214. package/lib/target/discovery-errors.d.ts +3 -0
  215. package/lib/target/discovery-errors.js +10 -0
  216. package/lib/target/discovery-errors.mjs +6 -0
  217. package/lib/target/discovery-sections.cjs +191 -0
  218. package/lib/target/discovery-sections.d.cts +52 -0
  219. package/lib/target/discovery-sections.d.mts +52 -0
  220. package/lib/target/discovery-sections.d.ts +52 -0
  221. package/lib/target/discovery-sections.js +191 -0
  222. package/lib/target/discovery-sections.mjs +179 -0
  223. package/lib/target/discovery-validation.cjs +109 -0
  224. package/lib/target/discovery-validation.d.cts +28 -0
  225. package/lib/target/discovery-validation.d.mts +28 -0
  226. package/lib/target/discovery-validation.d.ts +28 -0
  227. package/lib/target/discovery-validation.js +109 -0
  228. package/lib/target/discovery-validation.mjs +99 -0
  229. package/lib/target/discovery.cjs +112 -0
  230. package/lib/target/discovery.d.cts +74 -0
  231. package/lib/target/discovery.d.mts +74 -0
  232. package/lib/target/discovery.d.ts +67 -5
  233. package/lib/target/discovery.js +94 -79
  234. package/lib/target/discovery.mjs +105 -0
  235. package/lib/target/index.d.ts +6 -6
  236. package/lib/target/index.js +36 -36
  237. package/lib/target/oauth-http.d.ts +2 -0
  238. package/lib/target/oauth-http.js +25 -0
  239. package/lib/target/refresh-exchange.d.ts +11 -0
  240. package/lib/target/refresh-exchange.js +24 -0
  241. package/lib/target/refresh-revocation.d.ts +8 -0
  242. package/lib/target/refresh-revocation.js +19 -0
  243. package/lib/target/route-template.cjs +85 -0
  244. package/lib/target/route-template.d.cts +7 -0
  245. package/lib/target/route-template.d.mts +7 -0
  246. package/lib/target/route-template.d.ts +7 -0
  247. package/lib/target/route-template.js +85 -0
  248. package/lib/target/route-template.mjs +81 -0
  249. package/lib/target/session-errors.d.ts +4 -0
  250. package/lib/target/session-errors.js +12 -0
  251. package/lib/target/session-verification.d.ts +10 -0
  252. package/lib/target/session-verification.js +42 -0
  253. package/lib/target/target-registry.d.ts +7 -3
  254. package/lib/target/target-registry.js +41 -10
  255. package/lib/target/target-session-manager.d.ts +48 -0
  256. package/lib/target/target-session-manager.js +226 -0
  257. package/lib/target/target-session.d.ts +39 -32
  258. package/lib/target/target-session.js +63 -151
  259. package/lib/target/token-response.cjs +51 -0
  260. package/lib/target/token-response.d.cts +7 -0
  261. package/lib/target/token-response.d.mts +7 -0
  262. package/lib/target/token-response.d.ts +7 -0
  263. package/lib/target/token-response.js +51 -0
  264. package/lib/target/token-response.mjs +48 -0
  265. package/package.json +14 -7
  266. package/protocol/openengine-cluster/v1/worker.schema.json +171 -9
  267. package/scripts/build-cluster.js +23 -3
  268. package/scripts/opcore-introduced-check.js +0 -2
  269. package/src/agent-cli-provider/adapters/codex.ts +0 -1
  270. package/src/agent-cli-provider/contract-actions.ts +9 -5
  271. package/src/agent-cli-provider/contract-invoke.ts +3 -2
  272. package/src/agent-cli-provider/contract-support.ts +12 -6
  273. package/src/agent-cli-provider/contract.ts +6 -1
  274. package/src/agent-cli-provider/index.ts +1 -0
  275. package/src/agent-cli-provider/provider-registry.ts +4 -0
  276. package/src/agent-cli-provider/single-agent-runtime.ts +32 -45
  277. package/src/cluster/client.ts +42 -15
  278. package/src/cluster/connection-state.ts +33 -0
  279. package/src/cluster/connection-types.ts +28 -0
  280. package/src/cluster/connection.ts +37 -68
  281. package/src/cluster/errors.ts +5 -0
  282. package/src/cluster/index.ts +3 -1
  283. package/src/cluster/json-source.ts +1 -0
  284. package/src/cluster/payload-value.ts +1 -0
  285. package/src/cluster/socket.ts +13 -0
  286. package/src/cluster/subscriptions.ts +7 -2
  287. package/src/cluster/validators.ts +1 -0
  288. package/src/cluster/ws.d.ts +1 -1
  289. package/src/hosted-session/authority.ts +77 -0
  290. package/src/hosted-session/coordinator.ts +113 -56
  291. package/src/hosted-session/errors.ts +21 -0
  292. package/src/hosted-session/index.ts +14 -2
  293. package/src/hosted-session/reconnecting-watch.ts +148 -0
  294. package/src/hosted-session/types.ts +22 -8
  295. package/src/hosted-target/access-url.ts +46 -0
  296. package/src/hosted-target/adapter-request.ts +28 -0
  297. package/src/hosted-target/adapter-types.ts +39 -0
  298. package/src/hosted-target/bounds.ts +1 -0
  299. package/src/hosted-target/capsule-error-response.ts +107 -0
  300. package/src/hosted-target/errors.ts +36 -35
  301. package/src/hosted-target/index.ts +10 -23
  302. package/src/hosted-target/response-validation.ts +170 -62
  303. package/src/hosted-target/retry-executor.ts +62 -0
  304. package/src/hosted-target/retry.ts +47 -11
  305. package/src/hosted-target/target-adapter.ts +12 -8
  306. package/src/hosted-target/types.ts +19 -18
  307. package/src/hosted-target/zero-cloud-v1-adapter.ts +229 -316
  308. package/src/isolation-manager.js +1 -16
  309. package/src/target/bounded-response.ts +68 -0
  310. package/src/target/credential-lock.ts +1 -3
  311. package/src/target/credential-store.ts +14 -10
  312. package/src/target/device-flow.ts +209 -85
  313. package/src/target/discovery-errors.ts +6 -0
  314. package/src/target/discovery-sections.ts +251 -0
  315. package/src/target/discovery-validation.ts +144 -0
  316. package/src/target/discovery.ts +163 -97
  317. package/src/target/index.ts +15 -11
  318. package/src/target/oauth-http.ts +27 -0
  319. package/src/target/refresh-exchange.ts +36 -0
  320. package/src/target/refresh-revocation.ts +29 -0
  321. package/src/target/route-template.ts +105 -0
  322. package/src/target/session-errors.ts +9 -0
  323. package/src/target/session-verification.ts +51 -0
  324. package/src/target/target-registry.ts +60 -27
  325. package/src/target/target-session-manager.ts +285 -0
  326. package/src/target/target-session.ts +105 -226
  327. package/src/target/token-response.ts +62 -0
  328. package/docker/zeroshot-oecp/Cargo.toml +0 -12
  329. package/docker/zeroshot-oecp/Dockerfile +0 -65
  330. package/docker/zeroshot-oecp/src/main.rs +0 -32
  331. package/lib/target/bounded-json.d.ts +0 -6
  332. package/lib/target/bounded-json.js +0 -43
  333. package/lib/target/hosted-run/client.d.ts +0 -26
  334. package/lib/target/hosted-run/client.js +0 -158
  335. package/lib/target/hosted-run/commands.d.ts +0 -4
  336. package/lib/target/hosted-run/commands.js +0 -113
  337. package/lib/target/hosted-run/contracts.d.ts +0 -49
  338. package/lib/target/hosted-run/input.d.ts +0 -5
  339. package/lib/target/hosted-run/input.js +0 -200
  340. package/lib/target/hosted-run.d.ts +0 -4
  341. package/lib/target/hosted-run.js +0 -12
  342. package/src/target/bounded-json.ts +0 -48
  343. package/src/target/hosted-run/client.ts +0 -198
  344. package/src/target/hosted-run/commands.ts +0 -140
  345. package/src/target/hosted-run/contracts.ts +0 -53
  346. package/src/target/hosted-run/input.ts +0 -199
  347. package/src/target/hosted-run.ts +0 -8
@@ -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';
@@ -1,86 +1,194 @@
1
- import { TargetProtocolError } from './errors.ts';
2
- import { KNOWN_CAPSULE_STATES } from './types.ts';
3
- import type { Capsule, CapsuleAccess, CapsuleLimits, CapsuleListPage } from './types.ts';
4
-
5
- export function assertRequiredFields(
6
- body: unknown,
7
- fields: readonly string[],
8
- context: string,
9
- ): asserts body is Record<string, unknown> {
10
- if (body === null || typeof body !== 'object') {
11
- throw new TargetProtocolError(`${context}: expected object, got ${typeof body}`);
1
+ import { TargetProtocolError } from './errors.js';
2
+ import { KNOWN_CAPSULE_STATES } from './types.js';
3
+ import type { Capsule, CapsuleAccess, CapsuleLimits, CapsuleListPage } from './types.js';
4
+
5
+ function closedObject(body: unknown, fields: readonly string[], context: string): Record<string, unknown> {
6
+ if (body === null || typeof body !== 'object' || Array.isArray(body)) {
7
+ throw new TargetProtocolError(`${context} response is malformed`);
12
8
  }
13
9
  const record = body as Record<string, unknown>;
14
- for (const field of fields) {
15
- if (record[field] === undefined || record[field] === null) {
16
- throw new TargetProtocolError(`${context}: missing required field "${field}"`);
17
- }
10
+ if (Object.keys(record).length !== fields.length || fields.some((field) => !(field in record))) {
11
+ throw new TargetProtocolError(`${context} response is malformed`);
18
12
  }
13
+ return record;
14
+ }
15
+
16
+ function nonempty(value: unknown): value is string {
17
+ return typeof value === 'string' && value.length > 0;
19
18
  }
20
19
 
21
- export function assertKnownEnum(value: string, known: readonly string[], field: string): void {
22
- if (!known.includes(value)) {
23
- // eslint-disable-next-line no-console
24
- console.warn(`Unknown ${field} value: "${value}". Known values: ${known.join(', ')}`);
20
+ type TimestampParts = {
21
+ readonly year: number;
22
+ readonly month: number;
23
+ readonly day: number;
24
+ readonly hour: number;
25
+ readonly minute: number;
26
+ readonly second: number;
27
+ readonly offsetHour: number;
28
+ readonly offsetMinute: number;
29
+ };
30
+
31
+ function decimal(value: string, length: number): number | null {
32
+ if (value.length !== length) return null;
33
+ for (const character of value) {
34
+ if (character < '0' || character > '9') return null;
25
35
  }
36
+ return Number(value);
26
37
  }
27
38
 
28
- export function assertCapsule(body: unknown): Capsule {
29
- assertRequiredFields(body, ['id', 'state', 'createdAt'], 'Capsule');
30
- const record = body as Record<string, unknown>;
31
- if (typeof record['id'] !== 'string') {
32
- throw new TargetProtocolError('Capsule: "id" must be a string');
39
+ function parseDate(value: string): Pick<TimestampParts, 'year' | 'month' | 'day'> | null {
40
+ const fields = value.split('-');
41
+ if (fields.length !== 3) return null;
42
+ const year = decimal(fields[0] ?? '', 4);
43
+ const month = decimal(fields[1] ?? '', 2);
44
+ const day = decimal(fields[2] ?? '', 2);
45
+ if (year === null || month === null || day === null) return null;
46
+ return { year, month, day };
47
+ }
48
+
49
+ function parseZone(value: string): {
50
+ readonly clock: string;
51
+ readonly offsetHour: number;
52
+ readonly offsetMinute: number;
53
+ } | null {
54
+ if (value.endsWith('Z')) {
55
+ return { clock: value.slice(0, -1), offsetHour: 0, offsetMinute: 0 };
33
56
  }
34
- if (typeof record['state'] !== 'string') {
35
- throw new TargetProtocolError('Capsule: "state" must be a string');
57
+ const marker = value.at(-6);
58
+ if ((marker !== '+' && marker !== '-') || value.at(-3) !== ':') return null;
59
+ const offsetHour = decimal(value.slice(-5, -3), 2);
60
+ const offsetMinute = decimal(value.slice(-2), 2);
61
+ if (offsetHour === null || offsetMinute === null) return null;
62
+ return { clock: value.slice(0, -6), offsetHour, offsetMinute };
63
+ }
64
+
65
+ function parseFractionalClock(value: string): string | null {
66
+ const fields = value.split('.');
67
+ if (fields.length > 2) return null;
68
+ const fraction = fields[1];
69
+ if (fraction !== undefined &&
70
+ (fraction.length === 0 || decimal(fraction, fraction.length) === null)) {
71
+ return null;
36
72
  }
37
- if (typeof record['createdAt'] !== 'string') {
38
- throw new TargetProtocolError('Capsule: "createdAt" must be a string');
73
+ return fields[0] ?? null;
74
+ }
75
+
76
+ function parseHms(value: string): {
77
+ readonly hour: number;
78
+ readonly minute: number;
79
+ readonly second: number;
80
+ } | null {
81
+ const fields = value.split(':');
82
+ if (fields.length !== 3) return null;
83
+ const hour = decimal(fields[0] ?? '', 2);
84
+ const minute = decimal(fields[1] ?? '', 2);
85
+ const second = decimal(fields[2] ?? '', 2);
86
+ return hour === null || minute === null || second === null ? null : { hour, minute, second };
87
+ }
88
+
89
+ function parseClock(value: string): Omit<TimestampParts, 'year' | 'month' | 'day'> | null {
90
+ const zone = parseZone(value);
91
+ if (zone === null) return null;
92
+ const clock = parseFractionalClock(zone.clock);
93
+ if (clock === null) return null;
94
+ const parts = parseHms(clock);
95
+ if (parts === null) return null;
96
+ return { ...parts, offsetHour: zone.offsetHour, offsetMinute: zone.offsetMinute };
97
+ }
98
+
99
+ function parseTimestamp(value: string): TimestampParts | null {
100
+ if (value.at(10) !== 'T') return null;
101
+ const date = parseDate(value.slice(0, 10));
102
+ const clock = parseClock(value.slice(11));
103
+ return date === null || clock === null ? null : { ...date, ...clock };
104
+ }
105
+
106
+ function validClock(parts: TimestampParts): boolean {
107
+ return parts.hour <= 23 && parts.minute <= 59 && parts.second <= 59 &&
108
+ parts.offsetHour <= 23 && parts.offsetMinute <= 59;
109
+ }
110
+
111
+ function validCalendar(parts: TimestampParts): boolean {
112
+ if (parts.month < 1 || parts.month > 12) return false;
113
+ const leap = parts.year % 4 === 0 && (parts.year % 100 !== 0 || parts.year % 400 === 0);
114
+ const days = [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
115
+ return parts.day >= 1 && parts.day <= (days[parts.month - 1] ?? 0);
116
+ }
117
+
118
+ function timestamp(value: unknown): value is string {
119
+ if (!nonempty(value)) return false;
120
+ const parts = parseTimestamp(value);
121
+ return parts !== null &&
122
+ validClock(parts) &&
123
+ validCalendar(parts) &&
124
+ Number.isFinite(Date.parse(value));
125
+ }
126
+
127
+ function uint(value: unknown): value is number {
128
+ return Number.isSafeInteger(value) && (value as number) >= 0;
129
+ }
130
+
131
+ export function assertCapsule(body: unknown): Capsule {
132
+ const value = closedObject(body, ['capsule_id', 'state', 'label', 'created_at'], 'Capsule');
133
+ if (
134
+ !nonempty(value.capsule_id) ||
135
+ typeof value.state !== 'string' ||
136
+ !KNOWN_CAPSULE_STATES.includes(value.state as Capsule['state']) ||
137
+ (value.label !== null && typeof value.label !== 'string') ||
138
+ !timestamp(value.created_at)
139
+ ) {
140
+ throw new TargetProtocolError('Capsule response is malformed');
39
141
  }
40
- assertKnownEnum(record['state'] as string, KNOWN_CAPSULE_STATES, 'CapsuleState');
41
- return record as unknown as Capsule;
142
+ return Object.freeze({
143
+ id: value.capsule_id,
144
+ state: value.state as Capsule['state'],
145
+ label: value.label as string | null,
146
+ createdAt: value.created_at,
147
+ });
42
148
  }
43
149
 
44
150
  export function assertCapsuleAccess(body: unknown): CapsuleAccess {
45
- assertRequiredFields(body, ['endpoint', 'token', 'expiresAt'], 'CapsuleAccess');
46
- const record = body as Record<string, unknown>;
47
- if (typeof record['endpoint'] !== 'string') {
48
- throw new TargetProtocolError('CapsuleAccess: "endpoint" must be a string');
49
- }
50
- if (typeof record['token'] !== 'string') {
51
- throw new TargetProtocolError('CapsuleAccess: "token" must be a string');
151
+ const value = closedObject(
152
+ body,
153
+ ['protocol', 'websocket_url', 'access_token', 'token_type', 'expires_at'],
154
+ 'CapsuleAccess',
155
+ );
156
+ if (
157
+ value.protocol !== 'openengine.cluster/v1' ||
158
+ !nonempty(value.websocket_url) ||
159
+ !nonempty(value.access_token) ||
160
+ value.token_type !== 'Bearer' ||
161
+ !timestamp(value.expires_at)
162
+ ) {
163
+ throw new TargetProtocolError('CapsuleAccess response is malformed');
52
164
  }
53
- if (typeof record['expiresAt'] !== 'string') {
54
- throw new TargetProtocolError('CapsuleAccess: "expiresAt" must be a string');
55
- }
56
- return record as unknown as CapsuleAccess;
165
+ return Object.freeze({
166
+ protocol: 'openengine.cluster/v1',
167
+ websocketUrl: value.websocket_url,
168
+ accessToken: value.access_token,
169
+ tokenType: 'Bearer',
170
+ expiresAt: value.expires_at,
171
+ });
57
172
  }
58
173
 
59
174
  export function assertCapsuleLimits(body: unknown): CapsuleLimits {
60
- assertRequiredFields(body, ['maxConcurrent', 'maxPerHour'], 'CapsuleLimits');
61
- const record = body as Record<string, unknown>;
62
- if (typeof record['maxConcurrent'] !== 'number') {
63
- throw new TargetProtocolError('CapsuleLimits: "maxConcurrent" must be a number');
175
+ const value = closedObject(body, ['active_capsules', 'max_active_capsules'], 'CapsuleLimits');
176
+ if (!uint(value.active_capsules) || (value.max_active_capsules !== null && !uint(value.max_active_capsules))) {
177
+ throw new TargetProtocolError('CapsuleLimits response is malformed');
64
178
  }
65
- if (typeof record['maxPerHour'] !== 'number') {
66
- throw new TargetProtocolError('CapsuleLimits: "maxPerHour" must be a number');
67
- }
68
- return record as unknown as CapsuleLimits;
179
+ return Object.freeze({
180
+ activeCapsules: value.active_capsules,
181
+ maxActiveCapsules: value.max_active_capsules as number | null,
182
+ });
69
183
  }
70
184
 
71
185
  export function assertCapsuleListPage(body: unknown): CapsuleListPage {
72
- assertRequiredFields(body, ['items'], 'CapsuleListPage');
73
- const record = body as Record<string, unknown>;
74
- if (!Array.isArray(record['items'])) {
75
- throw new TargetProtocolError('CapsuleListPage: "items" must be an array');
76
- }
77
- const items = (record['items'] as unknown[]).map((item) => assertCapsule(item));
78
- const cursor = record['cursor'];
79
- if (cursor !== undefined && cursor !== null && typeof cursor !== 'string') {
80
- throw new TargetProtocolError('CapsuleListPage: "cursor" must be a string if present');
81
- }
82
- if (typeof cursor === 'string') {
83
- return { items, cursor };
186
+ const value = closedObject(body, ['capsules', 'next_cursor'], 'CapsulePage');
187
+ if (!Array.isArray(value.capsules) || (value.next_cursor !== null && typeof value.next_cursor !== 'string')) {
188
+ throw new TargetProtocolError('CapsulePage response is malformed');
84
189
  }
85
- return { items };
190
+ return Object.freeze({
191
+ capsules: Object.freeze(value.capsules.map((item) => assertCapsule(item))),
192
+ nextCursor: value.next_cursor as string | null,
193
+ });
86
194
  }
@@ -0,0 +1,62 @@
1
+ import { MAX_RETRY_ELAPSED_MS } from './bounds.js';
2
+ import { TargetAdapterError } from './errors.js';
3
+ import type { Clock, RetryPolicy } from './types.js';
4
+
5
+ export type TargetOperation = 'allocate' | 'list' | 'inspect' | 'terminate' | 'limits' | 'access';
6
+
7
+ function throwIfAborted(signal?: AbortSignal): void {
8
+ if (signal?.aborted) {
9
+ throw signal.reason ?? new globalThis.DOMException('The operation was aborted', 'AbortError');
10
+ }
11
+ }
12
+
13
+ async function wait(delayMs: number, signal?: AbortSignal): Promise<void> {
14
+ throwIfAborted(signal);
15
+ if (delayMs <= 0) return;
16
+ await new Promise<void>((resolve, reject) => {
17
+ const timer = setTimeout(resolve, delayMs);
18
+ signal?.addEventListener('abort', () => {
19
+ clearTimeout(timer);
20
+ reject(signal.reason ?? new globalThis.DOMException('The operation was aborted', 'AbortError'));
21
+ }, { once: true });
22
+ });
23
+ }
24
+
25
+ type RetryContext = {
26
+ readonly clock: Clock;
27
+ readonly policy: RetryPolicy;
28
+ };
29
+ function retryableError(value: unknown): value is TargetAdapterError {
30
+ return value instanceof TargetAdapterError && value.retryable;
31
+ }
32
+
33
+ function validRetryDelay(retry: boolean, delayMs: number, remaining: number): boolean {
34
+ return retry && Number.isFinite(delayMs) && delayMs >= 0 && delayMs < remaining;
35
+ }
36
+
37
+
38
+ export async function withTargetRetry<T>(
39
+ operation: TargetOperation,
40
+ effect: () => Promise<T>,
41
+ signal: AbortSignal | undefined,
42
+ context: RetryContext,
43
+ ): Promise<T> {
44
+ const retrySafe = operation !== 'access';
45
+ const started = context.clock.now();
46
+ let attempt = 0;
47
+ while (true) {
48
+ throwIfAborted(signal);
49
+ try {
50
+ return await effect();
51
+ } catch (error) {
52
+ throwIfAborted(signal);
53
+ if (!retrySafe || !retryableError(error)) throw error;
54
+ attempt += 1;
55
+ const elapsed = context.clock.now() - started;
56
+ const decision = context.policy.shouldRetry(attempt, elapsed, error);
57
+ const remaining = MAX_RETRY_ELAPSED_MS - elapsed;
58
+ if (!validRetryDelay(decision.retry, decision.delayMs, remaining)) throw error;
59
+ await wait(decision.delayMs, signal);
60
+ }
61
+ }
62
+ }
@@ -1,13 +1,45 @@
1
- import { MAX_RETRY_ATTEMPTS, MAX_RETRY_ELAPSED_MS } from './bounds.ts';
2
- import type { TargetAdapterError } from './errors.ts';
3
- import { TargetAuthError, TargetRateLimitError } from './errors.ts';
4
- import type { Clock, RetryPolicy } from './types.ts';
1
+ import { MAX_RETRY_ATTEMPTS, MAX_RETRY_ELAPSED_MS } from './bounds.js';
2
+ import type { TargetAdapterError } from './errors.js';
3
+ import { TargetAuthError, TargetRateLimitError, TargetServerError } from './errors.js';
4
+ import type { Clock, RetryPolicy } from './types.js';
5
+ const IMF_WEEKDAYS = new Set(['Mon,', 'Tue,', 'Wed,', 'Thu,', 'Fri,', 'Sat,', 'Sun,']);
6
+ const IMF_MONTHS = new Set([
7
+ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
8
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',
9
+ ]);
10
+
11
+ function fixedDigits(value: string, length: number): boolean {
12
+ if (value.length !== length) return false;
13
+ for (const character of value) {
14
+ if (character < '0' || character > '9') return false;
15
+ }
16
+ return true;
17
+ }
18
+
19
+ function validImfDate(weekday: string, day: string, month: string, year: string): boolean {
20
+ return IMF_WEEKDAYS.has(weekday) &&
21
+ fixedDigits(day, 2) &&
22
+ IMF_MONTHS.has(month) &&
23
+ fixedDigits(year, 4);
24
+ }
25
+
26
+ function validImfTime(value: string): boolean {
27
+ const parts = value.split(':');
28
+ return parts.length === 3 && parts.every((part) => fixedDigits(part, 2));
29
+ }
30
+
31
+ function isImfFixdate(value: string): boolean {
32
+ const parts = value.split(' ');
33
+ if (parts.length !== 6) return false;
34
+ const [weekday = '', day = '', month = '', year = '', time = '', zone = ''] = parts;
35
+ return validImfDate(weekday, day, month, year) && validImfTime(time) && zone === 'GMT';
36
+ }
5
37
 
6
38
  export class DefaultRetryPolicy implements RetryPolicy {
7
39
  shouldRetry(
8
40
  attempt: number,
9
41
  elapsed: number,
10
- error: TargetAdapterError,
42
+ error: TargetAdapterError
11
43
  ): { retry: boolean; delayMs: number } {
12
44
  if (error instanceof TargetAuthError) return { retry: false, delayMs: 0 };
13
45
  if (!error.retryable) return { retry: false, delayMs: 0 };
@@ -15,7 +47,8 @@ export class DefaultRetryPolicy implements RetryPolicy {
15
47
  if (elapsed >= MAX_RETRY_ELAPSED_MS) return { retry: false, delayMs: 0 };
16
48
 
17
49
  const requestedDelay =
18
- error instanceof TargetRateLimitError && error.retryAfterMs !== undefined
50
+ (error instanceof TargetRateLimitError || error instanceof TargetServerError) &&
51
+ error.retryAfterMs !== undefined
19
52
  ? Math.max(0, error.retryAfterMs)
20
53
  : Math.min(1000 * Math.pow(2, attempt), 10_000);
21
54
  const remaining = MAX_RETRY_ELAPSED_MS - elapsed;
@@ -33,14 +66,17 @@ export function parseRetryAfter(header: string | null, clock: Clock): number | n
33
66
  const trimmed = header.trim();
34
67
  if (trimmed.length === 0) return null;
35
68
 
36
- const numericSeconds = Number(trimmed);
37
- if (Number.isFinite(numericSeconds) && numericSeconds >= 0) {
38
- return Math.ceil(numericSeconds * 1000);
69
+ if (/^\d+$/.test(trimmed)) {
70
+ const delayMs = Number(trimmed) * 1000;
71
+ return Number.isSafeInteger(delayMs) ? delayMs : null;
39
72
  }
40
73
 
74
+ if (!isImfFixdate(trimmed)) {
75
+ return null;
76
+ }
41
77
  const date = Date.parse(trimmed);
42
- if (Number.isNaN(date)) return null;
78
+ if (!Number.isFinite(date) || new Date(date).toUTCString() !== trimmed) return null;
43
79
 
44
80
  const delayMs = date - clock.now();
45
- return delayMs > 0 ? Math.ceil(delayMs) : 0;
81
+ return delayMs > 0 ? delayMs : 0;
46
82
  }
@@ -1,10 +1,14 @@
1
- import type { AllocateRequest, Capsule, CapsuleAccess, CapsuleLimits, CapsuleListPage } from './types.ts';
1
+ import { ZeroCloudV1TargetAdapter } from './zero-cloud-v1-adapter.js';
2
+ import type { CreateTargetAdapterOptions, TargetAdapter } from './adapter-types.js';
3
+ export type {
4
+ CreateTargetAdapterOptions,
5
+ CredentialInstallCapability,
6
+ TargetAdapter,
7
+ } from './adapter-types.js';
2
8
 
3
- export interface TargetAdapter {
4
- allocate(req: AllocateRequest, signal?: AbortSignal): Promise<Capsule>;
5
- list(cursor?: string, signal?: AbortSignal): Promise<CapsuleListPage>;
6
- inspect(capsuleId: string, signal?: AbortSignal): Promise<Capsule>;
7
- terminate(capsuleId: string, signal?: AbortSignal): Promise<void>;
8
- limits(signal?: AbortSignal): Promise<CapsuleLimits>;
9
- access(capsuleId: string, signal?: AbortSignal): Promise<CapsuleAccess>;
9
+ export function createTargetAdapter(options: CreateTargetAdapterOptions): TargetAdapter {
10
+ if (options.descriptor.adapter.majorVersion !== 1) {
11
+ throw new Error('Unsupported hosted target adapter version');
12
+ }
13
+ return new ZeroCloudV1TargetAdapter(options);
10
14
  }
@@ -1,44 +1,49 @@
1
- import type { TargetAdapterError } from './errors.ts';
1
+ import type { TargetAdapterError } from './errors.js';
2
2
 
3
3
  export interface TargetAccessTokenProvider {
4
4
  getAccessToken(signal?: AbortSignal): Promise<string>;
5
5
  }
6
6
 
7
- export type CapsuleState = 'provisioning' | 'running' | 'stopping' | 'terminated' | 'failed' | (string & {});
8
-
9
- export const KNOWN_CAPSULE_STATES = ['provisioning', 'running', 'stopping', 'terminated', 'failed'] as const;
7
+ export type CapsuleState = 'provisioning' | 'ready' | 'terminating' | 'terminated' | 'failed';
8
+ export const KNOWN_CAPSULE_STATES = ['provisioning', 'ready', 'terminating', 'terminated', 'failed'] as const;
10
9
 
11
10
  export interface Capsule {
12
11
  readonly id: string;
13
12
  readonly state: CapsuleState;
13
+ readonly label: string | null;
14
14
  readonly createdAt: string;
15
- readonly [key: string]: unknown;
16
15
  }
17
16
 
18
17
  export interface CapsuleAccess {
19
- readonly endpoint: string;
20
- readonly token: string;
18
+ readonly protocol: 'openengine.cluster/v1';
19
+ readonly websocketUrl: string;
20
+ readonly accessToken: string;
21
+ readonly tokenType: 'Bearer';
21
22
  readonly expiresAt: string;
22
23
  }
23
24
 
24
25
  export interface CapsuleListPage {
25
- readonly items: readonly Capsule[];
26
- readonly cursor?: string;
26
+ readonly capsules: readonly Capsule[];
27
+ readonly nextCursor: string | null;
27
28
  }
28
29
 
29
30
  export interface CapsuleLimits {
30
- readonly maxConcurrent: number;
31
- readonly maxPerHour: number;
32
- readonly [key: string]: unknown;
31
+ readonly activeCapsules: number;
32
+ readonly maxActiveCapsules: number | null;
33
33
  }
34
34
 
35
35
  export interface AllocateRequest {
36
36
  readonly idempotencyKey: string;
37
- readonly profile: string;
37
+ readonly label?: string;
38
+ readonly size?: 'tiny' | 'small' | 'standard' | 'large';
39
+ }
40
+ export interface ListRequest {
41
+ readonly cursor?: string;
42
+ readonly limit?: number;
38
43
  }
39
44
 
40
45
  export interface HttpTransport {
41
- fetch(url: string, init: RequestInit & { redirect: 'error' }): Promise<Response>;
46
+ fetch(url: string, init: RequestInit & { redirect: 'manual' }): Promise<Response>;
42
47
  }
43
48
 
44
49
  export interface Clock {
@@ -52,7 +57,3 @@ export interface RetryPolicy {
52
57
  error: TargetAdapterError,
53
58
  ): { retry: boolean; delayMs: number };
54
59
  }
55
-
56
- export interface TargetDiscovery {
57
- readonly capsuleV1: string;
58
- }