@aexhq/sdk 0.46.5-canary → 0.51.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 (346) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +38 -0
  3. package/README.md +54 -29
  4. package/dist/client/aex.d.ts +33 -0
  5. package/dist/client/aex.js +108 -0
  6. package/dist/client/aex.js.map +1 -0
  7. package/dist/client/credentials.d.ts +25 -0
  8. package/dist/client/credentials.js +97 -0
  9. package/dist/client/credentials.js.map +1 -0
  10. package/dist/client/routing.d.ts +7 -0
  11. package/dist/client/routing.js +29 -0
  12. package/dist/client/routing.js.map +1 -0
  13. package/dist/downloads/download.d.ts +18 -0
  14. package/dist/downloads/download.js +67 -0
  15. package/dist/downloads/download.js.map +1 -0
  16. package/dist/generated/errors.d.ts +12 -0
  17. package/dist/generated/errors.js +82 -0
  18. package/dist/generated/errors.js.map +1 -0
  19. package/dist/generated/models.d.ts +1392 -0
  20. package/dist/generated/models.js +62 -0
  21. package/dist/generated/models.js.map +1 -0
  22. package/dist/generated/resources.d.ts +710 -0
  23. package/dist/generated/resources.js +582 -0
  24. package/dist/generated/resources.js.map +1 -0
  25. package/dist/generated/routes.d.ts +44 -0
  26. package/dist/generated/routes.js +1905 -0
  27. package/dist/generated/routes.js.map +1 -0
  28. package/dist/index.d.ts +21 -50
  29. package/dist/index.js +14 -62
  30. package/dist/index.js.map +1 -1
  31. package/dist/node/session-file-limits.d.ts +4 -0
  32. package/dist/node/session-file-limits.js +7 -0
  33. package/dist/node/session-file-limits.js.map +1 -0
  34. package/dist/node/session-files.d.ts +80 -0
  35. package/dist/node/session-files.js +254 -0
  36. package/dist/node/session-files.js.map +1 -0
  37. package/dist/observations/stream.d.ts +1 -0
  38. package/dist/observations/stream.js +18 -0
  39. package/dist/observations/stream.js.map +1 -0
  40. package/dist/transport/errors.d.ts +60 -0
  41. package/dist/transport/errors.js +107 -0
  42. package/dist/transport/errors.js.map +1 -0
  43. package/dist/transport/pagination.d.ts +8 -0
  44. package/dist/transport/pagination.js +34 -0
  45. package/dist/transport/pagination.js.map +1 -0
  46. package/dist/transport/retry.d.ts +21 -0
  47. package/dist/transport/retry.js +37 -0
  48. package/dist/transport/retry.js.map +1 -0
  49. package/dist/transport/transport.d.ts +25 -0
  50. package/dist/transport/transport.js +33 -0
  51. package/dist/transport/transport.js.map +1 -0
  52. package/package.json +67 -30
  53. package/dist/_contracts/account-operations.d.ts +0 -101
  54. package/dist/_contracts/account-operations.js +0 -242
  55. package/dist/_contracts/account-types.d.ts +0 -461
  56. package/dist/_contracts/account-types.js +0 -1
  57. package/dist/_contracts/api-key.d.ts +0 -61
  58. package/dist/_contracts/api-key.js +0 -101
  59. package/dist/_contracts/api-routes.d.ts +0 -20
  60. package/dist/_contracts/api-routes.js +0 -109
  61. package/dist/_contracts/archive-limits.d.ts +0 -3
  62. package/dist/_contracts/archive-limits.js +0 -23
  63. package/dist/_contracts/asset-authoring.d.ts +0 -22
  64. package/dist/_contracts/asset-authoring.js +0 -106
  65. package/dist/_contracts/asset-bundle.d.ts +0 -64
  66. package/dist/_contracts/asset-bundle.js +0 -263
  67. package/dist/_contracts/asset-upload-helper.d.ts +0 -31
  68. package/dist/_contracts/asset-upload-helper.js +0 -84
  69. package/dist/_contracts/billing-admission.d.ts +0 -29
  70. package/dist/_contracts/billing-admission.js +0 -28
  71. package/dist/_contracts/bundle-manifest.d.ts +0 -89
  72. package/dist/_contracts/bundle-manifest.js +0 -158
  73. package/dist/_contracts/canonical-sha256.d.ts +0 -8
  74. package/dist/_contracts/canonical-sha256.js +0 -8
  75. package/dist/_contracts/connection-ticket.d.ts +0 -22
  76. package/dist/_contracts/connection-ticket.js +0 -54
  77. package/dist/_contracts/continuation-event.d.ts +0 -31
  78. package/dist/_contracts/continuation-event.js +0 -6
  79. package/dist/_contracts/contract-parse-error.d.ts +0 -12
  80. package/dist/_contracts/contract-parse-error.js +0 -51
  81. package/dist/_contracts/error-codes.d.ts +0 -26
  82. package/dist/_contracts/error-codes.js +0 -116
  83. package/dist/_contracts/error-factory.d.ts +0 -32
  84. package/dist/_contracts/error-factory.js +0 -174
  85. package/dist/_contracts/event-envelope.d.ts +0 -471
  86. package/dist/_contracts/event-envelope.js +0 -501
  87. package/dist/_contracts/event-stream-client.d.ts +0 -122
  88. package/dist/_contracts/event-stream-client.js +0 -445
  89. package/dist/_contracts/event-view.d.ts +0 -44
  90. package/dist/_contracts/event-view.js +0 -69
  91. package/dist/_contracts/failure-class.d.ts +0 -29
  92. package/dist/_contracts/failure-class.js +0 -73
  93. package/dist/_contracts/http.d.ts +0 -135
  94. package/dist/_contracts/http.js +0 -434
  95. package/dist/_contracts/ids.d.ts +0 -66
  96. package/dist/_contracts/ids.js +0 -119
  97. package/dist/_contracts/index.d.ts +0 -42
  98. package/dist/_contracts/index.js +0 -52
  99. package/dist/_contracts/internal.d.ts +0 -55
  100. package/dist/_contracts/internal.js +0 -113
  101. package/dist/_contracts/models.d.ts +0 -30
  102. package/dist/_contracts/models.js +0 -28
  103. package/dist/_contracts/operation-core.d.ts +0 -36
  104. package/dist/_contracts/operation-core.js +0 -70
  105. package/dist/_contracts/operations.d.ts +0 -218
  106. package/dist/_contracts/operations.js +0 -1496
  107. package/dist/_contracts/otlp-projection.d.ts +0 -78
  108. package/dist/_contracts/otlp-projection.js +0 -171
  109. package/dist/_contracts/post-hook.d.ts +0 -31
  110. package/dist/_contracts/post-hook.js +0 -61
  111. package/dist/_contracts/provider-fault.d.ts +0 -34
  112. package/dist/_contracts/provider-fault.js +0 -68
  113. package/dist/_contracts/retry-core.d.ts +0 -29
  114. package/dist/_contracts/retry-core.js +0 -79
  115. package/dist/_contracts/runner-event.d.ts +0 -117
  116. package/dist/_contracts/runner-event.js +0 -172
  117. package/dist/_contracts/runtime-kind.d.ts +0 -60
  118. package/dist/_contracts/runtime-kind.js +0 -70
  119. package/dist/_contracts/runtime-manifest.d.ts +0 -121
  120. package/dist/_contracts/runtime-manifest.js +0 -83
  121. package/dist/_contracts/runtime-security-profile.d.ts +0 -26
  122. package/dist/_contracts/runtime-security-profile.js +0 -73
  123. package/dist/_contracts/runtime-sizes.d.ts +0 -104
  124. package/dist/_contracts/runtime-sizes.js +0 -111
  125. package/dist/_contracts/runtime-types.d.ts +0 -618
  126. package/dist/_contracts/runtime-types.js +0 -58
  127. package/dist/_contracts/schemas/asset-bundle.d.ts +0 -70
  128. package/dist/_contracts/schemas/asset-bundle.js +0 -107
  129. package/dist/_contracts/schemas/asset-ref.d.ts +0 -61
  130. package/dist/_contracts/schemas/asset-ref.js +0 -118
  131. package/dist/_contracts/schemas/bundle-manifest.d.ts +0 -66
  132. package/dist/_contracts/schemas/bundle-manifest.js +0 -77
  133. package/dist/_contracts/schemas/index.d.ts +0 -32
  134. package/dist/_contracts/schemas/index.js +0 -30
  135. package/dist/_contracts/schemas/mcp-server.d.ts +0 -99
  136. package/dist/_contracts/schemas/mcp-server.js +0 -209
  137. package/dist/_contracts/schemas/models.d.ts +0 -29
  138. package/dist/_contracts/schemas/models.js +0 -51
  139. package/dist/_contracts/schemas/numeric.d.ts +0 -18
  140. package/dist/_contracts/schemas/numeric.js +0 -28
  141. package/dist/_contracts/schemas/post-hook.d.ts +0 -45
  142. package/dist/_contracts/schemas/post-hook.js +0 -68
  143. package/dist/_contracts/schemas/response-assets.d.ts +0 -75
  144. package/dist/_contracts/schemas/response-assets.js +0 -81
  145. package/dist/_contracts/schemas/response-billing.d.ts +0 -208
  146. package/dist/_contracts/schemas/response-billing.js +0 -139
  147. package/dist/_contracts/schemas/response-common.d.ts +0 -132
  148. package/dist/_contracts/schemas/response-common.js +0 -162
  149. package/dist/_contracts/schemas/response-identity.d.ts +0 -648
  150. package/dist/_contracts/schemas/response-identity.js +0 -131
  151. package/dist/_contracts/schemas/response-mcp-servers.d.ts +0 -51
  152. package/dist/_contracts/schemas/response-mcp-servers.js +0 -32
  153. package/dist/_contracts/schemas/response-secrets.d.ts +0 -50
  154. package/dist/_contracts/schemas/response-secrets.js +0 -32
  155. package/dist/_contracts/schemas/response-sessions-internal.d.ts +0 -200
  156. package/dist/_contracts/schemas/response-sessions-internal.js +0 -142
  157. package/dist/_contracts/schemas/response-sessions.d.ts +0 -1598
  158. package/dist/_contracts/schemas/response-sessions.js +0 -377
  159. package/dist/_contracts/schemas/response-webhooks.d.ts +0 -76
  160. package/dist/_contracts/schemas/response-webhooks.js +0 -42
  161. package/dist/_contracts/schemas/response-workspace.d.ts +0 -225
  162. package/dist/_contracts/schemas/response-workspace.js +0 -99
  163. package/dist/_contracts/schemas/runtime-kind.d.ts +0 -31
  164. package/dist/_contracts/schemas/runtime-kind.js +0 -29
  165. package/dist/_contracts/schemas/runtime-security-profile.d.ts +0 -28
  166. package/dist/_contracts/schemas/runtime-security-profile.js +0 -26
  167. package/dist/_contracts/schemas/runtime-sizes.d.ts +0 -70
  168. package/dist/_contracts/schemas/runtime-sizes.js +0 -127
  169. package/dist/_contracts/schemas/session-limits.d.ts +0 -34
  170. package/dist/_contracts/schemas/session-limits.js +0 -39
  171. package/dist/_contracts/schemas/session-machine.d.ts +0 -23
  172. package/dist/_contracts/schemas/session-machine.js +0 -24
  173. package/dist/_contracts/schemas/session-request-config.d.ts +0 -58
  174. package/dist/_contracts/schemas/session-request-config.js +0 -134
  175. package/dist/_contracts/schemas/session-webhook.d.ts +0 -11
  176. package/dist/_contracts/schemas/session-webhook.js +0 -38
  177. package/dist/_contracts/schemas/side-effect-audit.d.ts +0 -98
  178. package/dist/_contracts/schemas/side-effect-audit.js +0 -102
  179. package/dist/_contracts/schemas/submission-assets.d.ts +0 -117
  180. package/dist/_contracts/schemas/submission-assets.js +0 -147
  181. package/dist/_contracts/schemas/submission-body.d.ts +0 -251
  182. package/dist/_contracts/schemas/submission-body.js +0 -378
  183. package/dist/_contracts/schemas/submission-environment.d.ts +0 -79
  184. package/dist/_contracts/schemas/submission-environment.js +0 -179
  185. package/dist/_contracts/schemas/submission-request.d.ts +0 -158
  186. package/dist/_contracts/schemas/submission-request.js +0 -49
  187. package/dist/_contracts/schemas/submission-secrets.d.ts +0 -47
  188. package/dist/_contracts/schemas/submission-secrets.js +0 -108
  189. package/dist/_contracts/schemas/wire.d.ts +0 -118
  190. package/dist/_contracts/schemas/wire.js +0 -171
  191. package/dist/_contracts/schemas/workspace-resources.d.ts +0 -50
  192. package/dist/_contracts/schemas/workspace-resources.js +0 -87
  193. package/dist/_contracts/sdk-errors.d.ts +0 -212
  194. package/dist/_contracts/sdk-errors.js +0 -313
  195. package/dist/_contracts/sdk-secrets.d.ts +0 -67
  196. package/dist/_contracts/sdk-secrets.js +0 -427
  197. package/dist/_contracts/session-archive.d.ts +0 -16
  198. package/dist/_contracts/session-archive.js +0 -92
  199. package/dist/_contracts/session-artifacts.d.ts +0 -189
  200. package/dist/_contracts/session-artifacts.js +0 -264
  201. package/dist/_contracts/session-config.d.ts +0 -373
  202. package/dist/_contracts/session-config.js +0 -562
  203. package/dist/_contracts/session-cost-types.d.ts +0 -211
  204. package/dist/_contracts/session-cost-types.js +0 -69
  205. package/dist/_contracts/session-cost.d.ts +0 -8
  206. package/dist/_contracts/session-cost.js +0 -582
  207. package/dist/_contracts/session-custody.d.ts +0 -165
  208. package/dist/_contracts/session-custody.js +0 -345
  209. package/dist/_contracts/session-file-query.d.ts +0 -14
  210. package/dist/_contracts/session-file-query.js +0 -178
  211. package/dist/_contracts/session-record.d.ts +0 -112
  212. package/dist/_contracts/session-record.js +0 -165
  213. package/dist/_contracts/session-retention.d.ts +0 -201
  214. package/dist/_contracts/session-retention.js +0 -450
  215. package/dist/_contracts/side-effect-audit.d.ts +0 -126
  216. package/dist/_contracts/side-effect-audit.js +0 -520
  217. package/dist/_contracts/sse.d.ts +0 -74
  218. package/dist/_contracts/sse.js +0 -227
  219. package/dist/_contracts/stable.d.ts +0 -45
  220. package/dist/_contracts/stable.js +0 -62
  221. package/dist/_contracts/status.d.ts +0 -25
  222. package/dist/_contracts/status.js +0 -57
  223. package/dist/_contracts/submission-limits.d.ts +0 -61
  224. package/dist/_contracts/submission-limits.js +0 -60
  225. package/dist/_contracts/submission.d.ts +0 -547
  226. package/dist/_contracts/submission.js +0 -812
  227. package/dist/_contracts/suggest.d.ts +0 -15
  228. package/dist/_contracts/suggest.js +0 -53
  229. package/dist/_contracts/testing/response-bindings.d.ts +0 -45
  230. package/dist/_contracts/testing/response-bindings.js +0 -256
  231. package/dist/_contracts/testing/wire-conformance-entry.d.ts +0 -10
  232. package/dist/_contracts/testing/wire-conformance-entry.js +0 -8
  233. package/dist/_contracts/testing/wire-conformance.d.ts +0 -169
  234. package/dist/_contracts/testing/wire-conformance.js +0 -276
  235. package/dist/_contracts/turn-trace.d.ts +0 -28
  236. package/dist/_contracts/turn-trace.js +0 -1
  237. package/dist/_contracts/unknown-field-error.d.ts +0 -13
  238. package/dist/_contracts/unknown-field-error.js +0 -21
  239. package/dist/_contracts/value-guards.d.ts +0 -20
  240. package/dist/_contracts/value-guards.js +0 -34
  241. package/dist/_contracts/webhook-verify.d.ts +0 -34
  242. package/dist/_contracts/webhook-verify.js +0 -93
  243. package/dist/_contracts/wire-observer.d.ts +0 -49
  244. package/dist/_contracts/wire-observer.js +0 -34
  245. package/dist/_contracts/workflow-status.d.ts +0 -7
  246. package/dist/_contracts/workflow-status.js +0 -43
  247. package/dist/_contracts/workspace-resources.d.ts +0 -98
  248. package/dist/_contracts/workspace-resources.js +0 -39
  249. package/dist/archive-limits.d.ts +0 -1
  250. package/dist/archive-limits.js +0 -2
  251. package/dist/archive-limits.js.map +0 -1
  252. package/dist/asset-upload.d.ts +0 -47
  253. package/dist/asset-upload.js +0 -269
  254. package/dist/asset-upload.js.map +0 -1
  255. package/dist/bundle.d.ts +0 -9
  256. package/dist/bundle.js +0 -20
  257. package/dist/bundle.js.map +0 -1
  258. package/dist/canonical-zip.d.ts +0 -68
  259. package/dist/canonical-zip.js +0 -355
  260. package/dist/canonical-zip.js.map +0 -1
  261. package/dist/cli.mjs +0 -12048
  262. package/dist/cli.mjs.sha256 +0 -1
  263. package/dist/client-types.d.ts +0 -192
  264. package/dist/client-types.js +0 -2
  265. package/dist/client-types.js.map +0 -1
  266. package/dist/client.d.ts +0 -464
  267. package/dist/client.js +0 -1207
  268. package/dist/client.js.map +0 -1
  269. package/dist/event-projection.d.ts +0 -22
  270. package/dist/event-projection.js +0 -380
  271. package/dist/event-projection.js.map +0 -1
  272. package/dist/fetch-archive.d.ts +0 -16
  273. package/dist/fetch-archive.js +0 -252
  274. package/dist/fetch-archive.js.map +0 -1
  275. package/dist/file.d.ts +0 -96
  276. package/dist/file.js +0 -272
  277. package/dist/file.js.map +0 -1
  278. package/dist/instructions.d.ts +0 -20
  279. package/dist/instructions.js +0 -40
  280. package/dist/instructions.js.map +0 -1
  281. package/dist/legacy-session-provider-fault.d.ts +0 -7
  282. package/dist/legacy-session-provider-fault.js +0 -38
  283. package/dist/legacy-session-provider-fault.js.map +0 -1
  284. package/dist/mcp-server.d.ts +0 -84
  285. package/dist/mcp-server.js +0 -117
  286. package/dist/mcp-server.js.map +0 -1
  287. package/dist/node-fs.d.ts +0 -29
  288. package/dist/node-fs.js +0 -19
  289. package/dist/node-fs.js.map +0 -1
  290. package/dist/node-walk.d.ts +0 -69
  291. package/dist/node-walk.js +0 -151
  292. package/dist/node-walk.js.map +0 -1
  293. package/dist/path-basename.d.ts +0 -5
  294. package/dist/path-basename.js +0 -9
  295. package/dist/path-basename.js.map +0 -1
  296. package/dist/retry.d.ts +0 -70
  297. package/dist/retry.js +0 -155
  298. package/dist/retry.js.map +0 -1
  299. package/dist/secret.d.ts +0 -65
  300. package/dist/secret.js +0 -110
  301. package/dist/secret.js.map +0 -1
  302. package/dist/session-validate.d.ts +0 -100
  303. package/dist/session-validate.js +0 -303
  304. package/dist/session-validate.js.map +0 -1
  305. package/dist/skill.d.ts +0 -99
  306. package/dist/skill.js +0 -169
  307. package/dist/skill.js.map +0 -1
  308. package/dist/submission-wire.d.ts +0 -13
  309. package/dist/submission-wire.js +0 -69
  310. package/dist/submission-wire.js.map +0 -1
  311. package/dist/tool.d.ts +0 -41
  312. package/dist/tool.js +0 -76
  313. package/dist/tool.js.map +0 -1
  314. package/dist/version.d.ts +0 -9
  315. package/dist/version.js +0 -10
  316. package/dist/version.js.map +0 -1
  317. package/docs/authentication.md +0 -125
  318. package/docs/billing.md +0 -164
  319. package/docs/cleanup.md +0 -27
  320. package/docs/concepts/agent-tools.md +0 -47
  321. package/docs/concepts/composition.md +0 -60
  322. package/docs/concepts/providers-and-runtimes.md +0 -121
  323. package/docs/concepts/sessions.md +0 -51
  324. package/docs/concepts/subagents.md +0 -35
  325. package/docs/credentials.md +0 -116
  326. package/docs/defaults.md +0 -51
  327. package/docs/errors.md +0 -258
  328. package/docs/events.md +0 -143
  329. package/docs/files.md +0 -130
  330. package/docs/limits-and-quotas.md +0 -114
  331. package/docs/limits.md +0 -51
  332. package/docs/mcp.md +0 -47
  333. package/docs/networking.md +0 -114
  334. package/docs/provider-runtime-capabilities.md +0 -32
  335. package/docs/public-surface.json +0 -73
  336. package/docs/quickstart.md +0 -135
  337. package/docs/release.md +0 -44
  338. package/docs/retries.md +0 -108
  339. package/docs/secrets.md +0 -141
  340. package/docs/session-config.md +0 -51
  341. package/docs/session-record.md +0 -58
  342. package/docs/skills.md +0 -65
  343. package/docs/telemetry.md +0 -66
  344. package/docs/testing.md +0 -35
  345. package/docs/vision-skills.md +0 -94
  346. package/docs/webhooks.md +0 -143
@@ -1,50 +0,0 @@
1
- /**
2
- * Schemas for persisted workspace resource references.
3
- *
4
- * Two independent gates live here:
5
- *
6
- * - {@link workspaceResourceNameSchema} — the directly-supplied resource *name*
7
- * grammar. Validation only: an accepted name is stored verbatim, so there is
8
- * deliberately no normaliser to pair with it (no trim, no case folding).
9
- * - {@link pinnedWorkspaceResourceSchema} — the immutable identity quartet every
10
- * submitted resource carries, plus the `assetId`/`contentHash` agreement.
11
- *
12
- * **Both are factories over the wire grammars rather than owners of them.** The
13
- * name patterns are supplied because there are two of them with deliberately
14
- * separate identities (`workspace-resources.ts`), and the digest pattern is
15
- * supplied because `canonical-sha256.ts` is the single declaring site for that
16
- * grammar and `workspace-resources.ts` is its declared consumer — an invariant
17
- * `canonical-sha256-ownership.test.ts` enforces. Threading them in keeps this
18
- * module about *shape* and leaves grammar ownership where it already is.
19
- *
20
- * Neither schema is strict. `assertPinnedWorkspaceResource` is handed a fully
21
- * projected `WorkspaceResourceRef` — `kind`, `name`, `mountPath`, and friends
22
- * ride along — and rejecting those would break every caller. Unknown-key
23
- * rejection for the resource objects themselves is the submission parser's job,
24
- * one level up, where the per-kind key list actually exists.
25
- */
26
- import * as z from "zod/mini";
27
- /**
28
- * A directly supplied resource name: matches `pattern`, and never contains the
29
- * reserved `__` separator.
30
- *
31
- * The envelope failure and the type failure share one message because the
32
- * ladder this replaces collapsed them (`typeof value !== "string" || !pattern.test(value)`),
33
- * and `abort` keeps the separator complaint from firing on a name that never
34
- * cleared the envelope.
35
- */
36
- export declare function workspaceResourceNameSchema(path: string, pattern: RegExp): z.ZodMiniString<string>;
37
- /**
38
- * The immutable identity fields common to every submitted workspace resource.
39
- *
40
- * Field order is the order the sequential assertions this replaces ran in, and
41
- * `errorFromZod` reports the shallowest issue, so a field complaint still wins
42
- * over the `assetId`/`contentHash` agreement — which Zod only evaluates once
43
- * every field has parsed (measured), exactly as the original ladder did.
44
- */
45
- export declare function pinnedWorkspaceResourceSchema(path: string, digestPattern: RegExp): z.ZodMiniObject<{
46
- resourceId: z.ZodMiniString<string>;
47
- version: z.ZodMiniNumber<number>;
48
- assetId: z.ZodMiniString<string>;
49
- contentHash: z.ZodMiniString<string>;
50
- }, z.core.$strip>;
@@ -1,87 +0,0 @@
1
- /**
2
- * Schemas for persisted workspace resource references.
3
- *
4
- * Two independent gates live here:
5
- *
6
- * - {@link workspaceResourceNameSchema} — the directly-supplied resource *name*
7
- * grammar. Validation only: an accepted name is stored verbatim, so there is
8
- * deliberately no normaliser to pair with it (no trim, no case folding).
9
- * - {@link pinnedWorkspaceResourceSchema} — the immutable identity quartet every
10
- * submitted resource carries, plus the `assetId`/`contentHash` agreement.
11
- *
12
- * **Both are factories over the wire grammars rather than owners of them.** The
13
- * name patterns are supplied because there are two of them with deliberately
14
- * separate identities (`workspace-resources.ts`), and the digest pattern is
15
- * supplied because `canonical-sha256.ts` is the single declaring site for that
16
- * grammar and `workspace-resources.ts` is its declared consumer — an invariant
17
- * `canonical-sha256-ownership.test.ts` enforces. Threading them in keeps this
18
- * module about *shape* and leaves grammar ownership where it already is.
19
- *
20
- * Neither schema is strict. `assertPinnedWorkspaceResource` is handed a fully
21
- * projected `WorkspaceResourceRef` — `kind`, `name`, `mountPath`, and friends
22
- * ride along — and rejecting those would break every caller. Unknown-key
23
- * rejection for the resource objects themselves is the submission parser's job,
24
- * one level up, where the per-kind key list actually exists.
25
- */
26
- import * as z from "zod/mini";
27
- import { idPattern } from "../ids.js";
28
- /**
29
- * Opaque logical resource id minted by the platform.
30
- *
31
- * Sourced from the id owner rather than re-declared: `scripts/validate/id-format-parity.test.ts`
32
- * fails on any `^<prefix>_` literal outside `ids.ts`, because eight hand-copies of the
33
- * workspace-id pattern had already drifted (one lacked the `/i` flag the others carried,
34
- * so the same id passed everywhere and threw at the telemetry boundary).
35
- */
36
- const WORKSPACE_RESOURCE_ID_PATTERN = idPattern("resource");
37
- /** Bytes prefix stripped from a canonical digest to derive the asset id. */
38
- const DIGEST_PREFIX = "sha256:";
39
- /**
40
- * A directly supplied resource name: matches `pattern`, and never contains the
41
- * reserved `__` separator.
42
- *
43
- * The envelope failure and the type failure share one message because the
44
- * ladder this replaces collapsed them (`typeof value !== "string" || !pattern.test(value)`),
45
- * and `abort` keeps the separator complaint from firing on a name that never
46
- * cleared the envelope.
47
- */
48
- export function workspaceResourceNameSchema(path, pattern) {
49
- const envelope = `${path} must match ${pattern.source}`;
50
- return z.string({ error: envelope }).check(z.refine((value) => pattern.test(value), { error: envelope, abort: true }), z.refine((value) => !value.includes("__"), {
51
- error: `${path} must not contain "__"`,
52
- abort: true
53
- }));
54
- }
55
- /**
56
- * The immutable identity fields common to every submitted workspace resource.
57
- *
58
- * Field order is the order the sequential assertions this replaces ran in, and
59
- * `errorFromZod` reports the shallowest issue, so a field complaint still wins
60
- * over the `assetId`/`contentHash` agreement — which Zod only evaluates once
61
- * every field has parsed (measured), exactly as the original ladder did.
62
- */
63
- export function pinnedWorkspaceResourceSchema(path, digestPattern) {
64
- const resourceId = `${path}.resourceId must match wres_<32 lowercase hex>`;
65
- const version = `${path}.version must be a positive integer`;
66
- const assetId = `${path}.assetId must be a non-empty string`;
67
- const contentHash = `${path}.contentHash must be a sha256 digest`;
68
- return z
69
- .object({
70
- resourceId: z.string({ error: resourceId }).check(z.refine((value) => WORKSPACE_RESOURCE_ID_PATTERN.test(value), {
71
- error: resourceId,
72
- abort: true
73
- })),
74
- version: z.number({ error: version }).check(z.refine((value) => Number.isSafeInteger(value) && value >= 1, {
75
- error: version,
76
- abort: true
77
- })),
78
- assetId: z
79
- .string({ error: assetId })
80
- .check(z.minLength(1, { error: assetId, abort: true })),
81
- contentHash: z.string({ error: contentHash }).check(z.refine((value) => digestPattern.test(value), {
82
- error: contentHash,
83
- abort: true
84
- }))
85
- })
86
- .check(z.refine((value) => value.assetId === `asset_${value.contentHash.slice(DIGEST_PREFIX.length)}`, { error: `${path}.assetId must identify the same bytes as contentHash` }));
87
- }
@@ -1,212 +0,0 @@
1
- import { type AexApiErrorCode } from "./error-codes.js";
2
- import type { ProviderFault } from "./provider-fault.js";
3
- export type AexErrorCode = "SESSION_CONFIG_INVALID" | "CREDENTIAL_INVALID" | "PROVIDER_ERROR" | "SESSION_STATE_ERROR" | "CLEANUP_ERROR" | "RUNTIME_UNSUPPORTED" | "API_ERROR" | "NETWORK_ERROR";
4
- export declare class AexError extends Error {
5
- readonly code: AexErrorCode;
6
- readonly details?: unknown;
7
- constructor(code: AexErrorCode, message: string, details?: unknown, options?: {
8
- readonly cause?: unknown;
9
- });
10
- }
11
- export interface SessionConfigValidationDetails {
12
- /** Stable public field path; human error prose is not a branching contract. */
13
- readonly field: string;
14
- }
15
- export declare class SessionConfigValidationError extends AexError {
16
- readonly details: SessionConfigValidationDetails;
17
- /**
18
- * `code` and `details.field` are the stable machine contract. An optional
19
- * cause is best-effort diagnostic context and must not be used for branching.
20
- */
21
- constructor(message: string, details: SessionConfigValidationDetails, options?: {
22
- readonly cause?: unknown;
23
- });
24
- }
25
- export declare class CredentialValidationError extends AexError {
26
- constructor(message: string, details?: unknown);
27
- }
28
- export declare class ProviderError extends AexError {
29
- readonly status: number | undefined;
30
- constructor(message: string, options?: {
31
- status?: number;
32
- details?: unknown;
33
- });
34
- }
35
- export declare class SessionStateError extends AexError {
36
- /**
37
- * HTTP status from a wrapped API rejection, when this state error is a
38
- * bounded client-side interpretation of that rejection.
39
- */
40
- readonly status: number | undefined;
41
- /** Stable API code from a wrapped API rejection, when available. */
42
- readonly apiCode: AexApiErrorCode | undefined;
43
- /** Request id from a wrapped API rejection, when available. */
44
- readonly requestId: string | undefined;
45
- constructor(message: string, details?: unknown, options?: {
46
- readonly cause?: unknown;
47
- });
48
- }
49
- export declare class CleanupError extends AexError {
50
- constructor(message: string, details?: unknown);
51
- }
52
- /**
53
- * Thrown by SDK and CLI operations when the hosted aex API returns a non-2xx
54
- * response. Carries the HTTP status, the redacted parsed body, the server's
55
- * STABLE {@link AexApiErrorCode} (when present), and a `requestId` for support.
56
- * Construct via {@link import("./error-factory.js").apiErrorFromResponse} — the
57
- * single wire→exception mapping — which dispatches to a typed subclass
58
- * ({@link AexAuthError} / {@link AexIdempotencyConflictError} /
59
- * {@link AexNotFoundError} / {@link AexRateLimitError}).
60
- */
61
- export declare class AexApiError extends AexError {
62
- readonly status: number;
63
- readonly body: unknown;
64
- /** The server's stable error code, when the body carried a known one. */
65
- readonly apiCode: AexApiErrorCode | undefined;
66
- /** Request id (body `requestId` or a response header) for support correlation. */
67
- readonly requestId: string | undefined;
68
- constructor(status: number, message: string, body: unknown, options?: {
69
- readonly apiCode?: AexApiErrorCode | undefined;
70
- readonly requestId?: string | undefined;
71
- readonly cause?: unknown;
72
- });
73
- }
74
- /** Shared construction shape for the typed {@link AexApiError} subclasses. */
75
- export interface AexApiErrorInit {
76
- readonly status: number;
77
- readonly message: string;
78
- readonly body: unknown;
79
- readonly apiCode?: AexApiErrorCode | undefined;
80
- readonly requestId?: string | undefined;
81
- readonly cause?: unknown;
82
- }
83
- /** 401/403 auth failure (token invalid/revoked/expired, forbidden, insufficient scope). */
84
- export declare class AexAuthError extends AexApiError {
85
- /** The scope the endpoint required, when the server named it (insufficient_scope). */
86
- readonly requiredScope: string | undefined;
87
- constructor(init: AexApiErrorInit & {
88
- readonly requiredScope?: string | undefined;
89
- });
90
- }
91
- /** 409 — the idempotency key was reused with a different request body. */
92
- export declare class AexIdempotencyConflictError extends AexApiError {
93
- constructor(init: AexApiErrorInit);
94
- }
95
- /** 404 — the requested resource was not found. */
96
- export declare class AexNotFoundError extends AexApiError {
97
- constructor(init: AexApiErrorInit);
98
- }
99
- /** Construction shape for {@link AexRateLimitError}. */
100
- export type AexRateLimitErrorInit = Omit<AexApiErrorInit, "message" | "body"> & {
101
- /** Omitted when the retry policy builds the error: a fixed, non-leaky summary is generated. */
102
- readonly message?: string;
103
- readonly body?: unknown;
104
- /** Suggested backoff (ms), when the server advertised one (Retry-After). */
105
- readonly retryAfterMs?: number | undefined;
106
- /** How many transport attempts were made before giving up. Defaults to `1`. */
107
- readonly attempts?: number;
108
- /** Whether the throttle came from the aex API plane or the upstream provider. */
109
- readonly source?: "api" | "provider";
110
- /** The upstream provider fault, when the throttle originated there. */
111
- readonly providerFault?: ProviderFault;
112
- };
113
- /**
114
- * 429 / 503 / 529 — the workspace hit a rate/concurrency limit, or an upstream
115
- * provider said "slow down"; retry after a backoff.
116
- *
117
- * ONE class for both producers: the wire→exception factory
118
- * (`apiErrorFromResponse`) and the shared HTTP retry policy, so `isRateLimited`
119
- * recognises both with no split-brain. When the retry policy raises it, `message`
120
- * is a fixed non-leaky summary (never an echo of the raw body, which is still
121
- * available redacted on `.body`) and `attempts` / `source` / `providerFault`
122
- * carry the retry-layer detail.
123
- */
124
- export declare class AexRateLimitError extends AexApiError {
125
- /** Suggested backoff (ms), when the server advertised one (Retry-After). */
126
- readonly retryAfterMs: number | undefined;
127
- /** How many attempts were made before giving up; `1` for a single-shot rejection. */
128
- readonly attempts: number;
129
- /** Whether the throttle came from the aex API plane or the upstream provider. */
130
- readonly source: "api" | "provider";
131
- /** The upstream provider fault, when the throttle originated there. */
132
- readonly providerFault?: ProviderFault;
133
- constructor(init: AexRateLimitErrorInit);
134
- }
135
- /**
136
- * 410 (WS4) — the session's CONTENT (events, messages, files, manifest,
137
- * archive, event stream) was deleted after its retention window; only the
138
- * session RECORD (metadata) remains. Carries the `sessionId`, when the content
139
- * was `purgedAt`, and what triggered it (`deletedBy`). Every content read AND
140
- * `session…stream()` surface it via the one wire→exception factory. Narrow with
141
- * {@link isContentDeleted}; check `session.dataState === "metadata_only"` first
142
- * to avoid the round-trip.
143
- */
144
- export declare class ContentDeletedError extends AexApiError {
145
- /** The session whose content was deleted. */
146
- readonly sessionId: string | undefined;
147
- /** When the content was purged (ISO 8601), when the server reported it. */
148
- readonly purgedAt: string | undefined;
149
- /** What triggered the purge: retention-window elapse or an explicit user delete. */
150
- readonly deletedBy: "retention" | "user" | undefined;
151
- constructor(init: AexApiErrorInit & {
152
- readonly sessionId?: string | undefined;
153
- readonly purgedAt?: string | undefined;
154
- readonly deletedBy?: "retention" | "user" | undefined;
155
- });
156
- }
157
- /** True for a 401/403 authentication/authorization failure. */
158
- export declare function isAuthError(err: unknown): err is AexAuthError;
159
- /** True for a 403 whose cause is a missing scope (`insufficient_scope`). */
160
- export declare function isInsufficientScope(err: unknown): boolean;
161
- /** True for a 409 idempotency-key reuse conflict. */
162
- export declare function isIdempotencyConflict(err: unknown): err is AexIdempotencyConflictError;
163
- /** True for a 404 not-found error. */
164
- export declare function isNotFound(err: unknown): err is AexNotFoundError;
165
- /** True for a 429 rate/concurrency-limit error. */
166
- export declare function isRateLimited(err: unknown): err is AexRateLimitError;
167
- /** True for a 410 whose session content was deleted after its retention window. */
168
- export declare function isContentDeleted(err: unknown): err is ContentDeletedError;
169
- /**
170
- * Thrown when a BFF-bound request fails BEFORE any HTTP response exists — DNS
171
- * failure, connection refused, TLS error, socket reset. Wraps the raw fetch
172
- * rejection (whose undici form is a bare `TypeError: fetch failed` with the
173
- * useful code hidden on `cause.code`) into a message that names the request
174
- * and the transport failure, e.g.
175
- * `POST api.aex.dev/api/assets/presign failed: ECONNREFUSED (connect ECONNREFUSED 127.0.0.1:443)`.
176
- * The original rejection is preserved on `cause`.
177
- */
178
- export declare class AexNetworkError extends AexError {
179
- readonly method: string;
180
- /** Request host — never carries credentials or the query string. */
181
- readonly host: string;
182
- readonly path: string;
183
- /** Transport failure code (e.g. `ECONNREFUSED`), when detectable. */
184
- readonly causeCode: string | undefined;
185
- /** Attempts made when a retry layer exhausted its budget; `1` otherwise. */
186
- readonly attempts: number;
187
- /** Total elapsed time (ms) across all attempts, when the retry layer set it. */
188
- readonly elapsedMs: number | undefined;
189
- constructor(args: {
190
- readonly method: string;
191
- readonly host: string;
192
- readonly path: string;
193
- readonly cause: unknown;
194
- /** Set by the retry layer when it gave up: appended to the message. */
195
- readonly attempts?: number;
196
- readonly elapsedMs?: number;
197
- });
198
- }
199
- /**
200
- * Best-effort transport error code (`ECONNREFUSED`, `ENOTFOUND`, …): checks
201
- * `err.code`, then a bounded native `cause` chain (where undici and database
202
- * drivers hide it), then falls back to an `E…`-shaped token in the outer
203
- * message. Five inspected values matches the platform diagnostic boundary and
204
- * prevents malformed/cyclic cause graphs from becoming unbounded work.
205
- */
206
- export declare function extractErrorCode(err: unknown): string | undefined;
207
- /**
208
- * Redact a URL down to protocol + host + path: credentials become
209
- * `[redacted]@` and any query string becomes `?[redacted]` (presigned URLs
210
- * carry signatures there). Tolerates unparseable input.
211
- */
212
- export declare function redactUrl(url: string): string;
@@ -1,313 +0,0 @@
1
- import { redactSecrets } from "./sdk-secrets.js";
2
- import { isAexApiErrorCode } from "./error-codes.js";
3
- export class AexError extends Error {
4
- code;
5
- details;
6
- constructor(code, message, details, options) {
7
- super(redactSecrets(message), options?.cause === undefined ? undefined : { cause: options.cause });
8
- this.name = this.constructor.name;
9
- this.code = code;
10
- this.details = details === undefined ? undefined : redactSecrets(details);
11
- }
12
- }
13
- export class SessionConfigValidationError extends AexError {
14
- /**
15
- * `code` and `details.field` are the stable machine contract. An optional
16
- * cause is best-effort diagnostic context and must not be used for branching.
17
- */
18
- constructor(message, details, options) {
19
- super("SESSION_CONFIG_INVALID", message, Object.freeze({ field: details.field }), options?.cause === undefined ? undefined : { cause: options.cause });
20
- }
21
- }
22
- export class CredentialValidationError extends AexError {
23
- constructor(message, details) {
24
- super("CREDENTIAL_INVALID", message, details);
25
- }
26
- }
27
- export class ProviderError extends AexError {
28
- status;
29
- constructor(message, options = {}) {
30
- super("PROVIDER_ERROR", message, options.details);
31
- this.status = options.status;
32
- }
33
- }
34
- export class SessionStateError extends AexError {
35
- /**
36
- * HTTP status from a wrapped API rejection, when this state error is a
37
- * bounded client-side interpretation of that rejection.
38
- */
39
- status;
40
- /** Stable API code from a wrapped API rejection, when available. */
41
- apiCode;
42
- /** Request id from a wrapped API rejection, when available. */
43
- requestId;
44
- constructor(message, details, options) {
45
- const detailRecord = details && typeof details === "object" && !Array.isArray(details)
46
- ? details
47
- : undefined;
48
- const cause = options?.cause ?? detailRecord?.cause;
49
- super("SESSION_STATE_ERROR", message, details, cause === undefined ? undefined : { cause });
50
- const status = detailRecord?.httpStatus ?? detailRecord?.status;
51
- const apiCode = detailRecord?.apiCode;
52
- this.status = typeof status === "number" ? status : undefined;
53
- this.apiCode = isAexApiErrorCode(apiCode) ? apiCode : undefined;
54
- this.requestId = typeof detailRecord?.requestId === "string" ? detailRecord.requestId : undefined;
55
- }
56
- }
57
- export class CleanupError extends AexError {
58
- constructor(message, details) {
59
- super("CLEANUP_ERROR", message, details);
60
- }
61
- }
62
- /**
63
- * Thrown by SDK and CLI operations when the hosted aex API returns a non-2xx
64
- * response. Carries the HTTP status, the redacted parsed body, the server's
65
- * STABLE {@link AexApiErrorCode} (when present), and a `requestId` for support.
66
- * Construct via {@link import("./error-factory.js").apiErrorFromResponse} — the
67
- * single wire→exception mapping — which dispatches to a typed subclass
68
- * ({@link AexAuthError} / {@link AexIdempotencyConflictError} /
69
- * {@link AexNotFoundError} / {@link AexRateLimitError}).
70
- */
71
- export class AexApiError extends AexError {
72
- status;
73
- body;
74
- /** The server's stable error code, when the body carried a known one. */
75
- apiCode;
76
- /** Request id (body `requestId` or a response header) for support correlation. */
77
- requestId;
78
- constructor(status, message, body, options) {
79
- super("API_ERROR", message, body, options?.cause === undefined ? undefined : { cause: options.cause });
80
- this.status = status;
81
- this.body = redactSecrets(body);
82
- this.apiCode = options?.apiCode;
83
- this.requestId = options?.requestId;
84
- }
85
- }
86
- /** 401/403 auth failure (token invalid/revoked/expired, forbidden, insufficient scope). */
87
- export class AexAuthError extends AexApiError {
88
- /** The scope the endpoint required, when the server named it (insufficient_scope). */
89
- requiredScope;
90
- constructor(init) {
91
- super(init.status, init.message, init.body, {
92
- apiCode: init.apiCode,
93
- requestId: init.requestId,
94
- cause: init.cause
95
- });
96
- this.requiredScope = init.requiredScope;
97
- }
98
- }
99
- /** 409 — the idempotency key was reused with a different request body. */
100
- export class AexIdempotencyConflictError extends AexApiError {
101
- constructor(init) {
102
- super(init.status, init.message, init.body, {
103
- apiCode: init.apiCode,
104
- requestId: init.requestId,
105
- cause: init.cause
106
- });
107
- }
108
- }
109
- /** 404 — the requested resource was not found. */
110
- export class AexNotFoundError extends AexApiError {
111
- constructor(init) {
112
- super(init.status, init.message, init.body, {
113
- apiCode: init.apiCode,
114
- requestId: init.requestId,
115
- cause: init.cause
116
- });
117
- }
118
- }
119
- /**
120
- * 429 / 503 / 529 — the workspace hit a rate/concurrency limit, or an upstream
121
- * provider said "slow down"; retry after a backoff.
122
- *
123
- * ONE class for both producers: the wire→exception factory
124
- * (`apiErrorFromResponse`) and the shared HTTP retry policy, so `isRateLimited`
125
- * recognises both with no split-brain. When the retry policy raises it, `message`
126
- * is a fixed non-leaky summary (never an echo of the raw body, which is still
127
- * available redacted on `.body`) and `attempts` / `source` / `providerFault`
128
- * carry the retry-layer detail.
129
- */
130
- export class AexRateLimitError extends AexApiError {
131
- /** Suggested backoff (ms), when the server advertised one (Retry-After). */
132
- retryAfterMs;
133
- /** How many attempts were made before giving up; `1` for a single-shot rejection. */
134
- attempts;
135
- /** Whether the throttle came from the aex API plane or the upstream provider. */
136
- source;
137
- /** The upstream provider fault, when the throttle originated there. */
138
- providerFault;
139
- constructor(init) {
140
- const attempts = init.attempts ?? 1;
141
- const source = init.source ?? "api";
142
- super(init.status, init.message ?? throttleSummary(init.status, attempts, source, init.retryAfterMs), init.body, {
143
- apiCode: init.apiCode,
144
- requestId: init.requestId,
145
- cause: init.cause
146
- });
147
- this.retryAfterMs = init.retryAfterMs;
148
- this.attempts = attempts;
149
- this.source = source;
150
- if (init.providerFault !== undefined)
151
- this.providerFault = init.providerFault;
152
- }
153
- }
154
- /** Fixed, non-leaky throttle summary — never echoes the server's error body. */
155
- function throttleSummary(status, attempts, source, retryAfterMs) {
156
- const who = source === "provider" ? "upstream provider" : "aex API";
157
- const label = status === 529 ? "overloaded" : "rate limit reached";
158
- const attemptsLabel = `${attempts} attempt${attempts === 1 ? "" : "s"}`;
159
- const wait = retryAfterMs !== undefined ? `; retry after ~${Math.ceil(retryAfterMs / 1000)}s` : "";
160
- return `${who} ${label} (HTTP ${status}) after ${attemptsLabel}${wait}`;
161
- }
162
- /**
163
- * 410 (WS4) — the session's CONTENT (events, messages, files, manifest,
164
- * archive, event stream) was deleted after its retention window; only the
165
- * session RECORD (metadata) remains. Carries the `sessionId`, when the content
166
- * was `purgedAt`, and what triggered it (`deletedBy`). Every content read AND
167
- * `session…stream()` surface it via the one wire→exception factory. Narrow with
168
- * {@link isContentDeleted}; check `session.dataState === "metadata_only"` first
169
- * to avoid the round-trip.
170
- */
171
- export class ContentDeletedError extends AexApiError {
172
- /** The session whose content was deleted. */
173
- sessionId;
174
- /** When the content was purged (ISO 8601), when the server reported it. */
175
- purgedAt;
176
- /** What triggered the purge: retention-window elapse or an explicit user delete. */
177
- deletedBy;
178
- constructor(init) {
179
- super(init.status, init.message, init.body, {
180
- apiCode: init.apiCode,
181
- requestId: init.requestId,
182
- cause: init.cause
183
- });
184
- this.sessionId = init.sessionId;
185
- this.purgedAt = init.purgedAt;
186
- this.deletedBy = init.deletedBy;
187
- }
188
- }
189
- /** True for a 401/403 authentication/authorization failure. */
190
- export function isAuthError(err) {
191
- return err instanceof AexAuthError;
192
- }
193
- /** True for a 403 whose cause is a missing scope (`insufficient_scope`). */
194
- export function isInsufficientScope(err) {
195
- return err instanceof AexAuthError && err.apiCode === "insufficient_scope";
196
- }
197
- /** True for a 409 idempotency-key reuse conflict. */
198
- export function isIdempotencyConflict(err) {
199
- return err instanceof AexIdempotencyConflictError;
200
- }
201
- /** True for a 404 not-found error. */
202
- export function isNotFound(err) {
203
- return err instanceof AexNotFoundError;
204
- }
205
- /** True for a 429 rate/concurrency-limit error. */
206
- export function isRateLimited(err) {
207
- return err instanceof AexRateLimitError;
208
- }
209
- /** True for a 410 whose session content was deleted after its retention window. */
210
- export function isContentDeleted(err) {
211
- return err instanceof ContentDeletedError;
212
- }
213
- /**
214
- * Thrown when a BFF-bound request fails BEFORE any HTTP response exists — DNS
215
- * failure, connection refused, TLS error, socket reset. Wraps the raw fetch
216
- * rejection (whose undici form is a bare `TypeError: fetch failed` with the
217
- * useful code hidden on `cause.code`) into a message that names the request
218
- * and the transport failure, e.g.
219
- * `POST api.aex.dev/api/assets/presign failed: ECONNREFUSED (connect ECONNREFUSED 127.0.0.1:443)`.
220
- * The original rejection is preserved on `cause`.
221
- */
222
- export class AexNetworkError extends AexError {
223
- method;
224
- /** Request host — never carries credentials or the query string. */
225
- host;
226
- path;
227
- /** Transport failure code (e.g. `ECONNREFUSED`), when detectable. */
228
- causeCode;
229
- /** Attempts made when a retry layer exhausted its budget; `1` otherwise. */
230
- attempts;
231
- /** Total elapsed time (ms) across all attempts, when the retry layer set it. */
232
- elapsedMs;
233
- constructor(args) {
234
- const causeCode = extractErrorCode(args.cause);
235
- super("NETWORK_ERROR", networkErrorMessage(args, causeCode), { method: args.method, host: args.host, path: args.path, ...(causeCode ? { code: causeCode } : {}) }, { cause: args.cause });
236
- this.method = args.method;
237
- this.host = args.host;
238
- this.path = args.path;
239
- this.causeCode = causeCode;
240
- this.attempts = args.attempts ?? 1;
241
- this.elapsedMs = args.elapsedMs;
242
- }
243
- }
244
- function networkErrorMessage(args, causeCode) {
245
- const target = args.host ? `${args.host}${args.path}` : "request";
246
- const detail = shortCauseMessage(args.cause, causeCode);
247
- const suffix = args.attempts === undefined
248
- ? ""
249
- : ` after ${args.attempts} attempt${args.attempts === 1 ? "" : "s"} over ${args.elapsedMs ?? 0}ms`;
250
- let message = `${args.method} ${target} failed`;
251
- if (causeCode)
252
- message += `: ${causeCode}`;
253
- if (detail)
254
- message += causeCode ? ` (${detail})` : `: ${detail}`;
255
- return message + suffix;
256
- }
257
- /** The innermost useful message off the rejection, URL-redacted and bounded. */
258
- function shortCauseMessage(cause, causeCode) {
259
- const nested = cause instanceof Error && cause.cause instanceof Error ? cause.cause : cause;
260
- const message = nested instanceof Error ? nested.message || nested.name : typeof nested === "string" ? nested : undefined;
261
- if (!message || message === causeCode)
262
- return undefined;
263
- return message.replace(/https?:\/\/[^\s<>"'`]+/g, (raw) => redactUrl(raw)).slice(0, 200);
264
- }
265
- /**
266
- * Best-effort transport error code (`ECONNREFUSED`, `ENOTFOUND`, …): checks
267
- * `err.code`, then a bounded native `cause` chain (where undici and database
268
- * drivers hide it), then falls back to an `E…`-shaped token in the outer
269
- * message. Five inspected values matches the platform diagnostic boundary and
270
- * prevents malformed/cyclic cause graphs from becoming unbounded work.
271
- */
272
- export function extractErrorCode(err) {
273
- let current = err;
274
- for (let depth = 0; depth < 5 && current && typeof current === "object"; depth += 1) {
275
- const code = stringProperty(current, "code");
276
- if (code)
277
- return code;
278
- current = current.cause;
279
- }
280
- const match = /\bE[A-Z0-9_]+\b/.exec(errorMessageOf(err));
281
- return match?.[0];
282
- }
283
- /**
284
- * Redact a URL down to protocol + host + path: credentials become
285
- * `[redacted]@` and any query string becomes `?[redacted]` (presigned URLs
286
- * carry signatures there). Tolerates unparseable input.
287
- */
288
- export function redactUrl(url) {
289
- try {
290
- const parsed = new URL(url);
291
- const auth = parsed.username || parsed.password ? "[redacted]@" : "";
292
- const query = parsed.search ? "?[redacted]" : "";
293
- return `${parsed.protocol}//${auth}${parsed.host}${parsed.pathname}${query}`;
294
- }
295
- catch {
296
- const withoutAuth = url.replace(/\/\/[^/?#\s]+@/, "//[redacted]@");
297
- const queryStart = withoutAuth.indexOf("?");
298
- return queryStart === -1 ? withoutAuth : `${withoutAuth.slice(0, queryStart)}?[redacted]`;
299
- }
300
- }
301
- function errorMessageOf(err) {
302
- if (err instanceof Error)
303
- return err.message || err.name;
304
- if (typeof err === "string")
305
- return err;
306
- return String(err);
307
- }
308
- function stringProperty(value, key) {
309
- if (!value || typeof value !== "object")
310
- return undefined;
311
- const prop = value[key];
312
- return typeof prop === "string" && prop.length > 0 ? prop : undefined;
313
- }