@aexhq/sdk 0.46.4-canary → 0.50.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 (337) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +38 -0
  3. package/README.md +23 -31
  4. package/dist/client/aex.d.ts +33 -0
  5. package/dist/client/aex.js +98 -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 +25 -0
  14. package/dist/downloads/download.js +53 -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 +81 -0
  18. package/dist/generated/errors.js.map +1 -0
  19. package/dist/generated/resources.d.ts +730 -0
  20. package/dist/generated/resources.js +606 -0
  21. package/dist/generated/resources.js.map +1 -0
  22. package/dist/generated/routes.d.ts +42 -0
  23. package/dist/generated/routes.js +2101 -0
  24. package/dist/generated/routes.js.map +1 -0
  25. package/dist/index.d.ts +20 -50
  26. package/dist/index.js +11 -62
  27. package/dist/index.js.map +1 -1
  28. package/dist/observations/stream.d.ts +1 -0
  29. package/dist/observations/stream.js +18 -0
  30. package/dist/observations/stream.js.map +1 -0
  31. package/dist/transport/errors.d.ts +60 -0
  32. package/dist/transport/errors.js +107 -0
  33. package/dist/transport/errors.js.map +1 -0
  34. package/dist/transport/pagination.d.ts +8 -0
  35. package/dist/transport/pagination.js +34 -0
  36. package/dist/transport/pagination.js.map +1 -0
  37. package/dist/transport/retry.d.ts +21 -0
  38. package/dist/transport/retry.js +37 -0
  39. package/dist/transport/retry.js.map +1 -0
  40. package/dist/transport/transport.d.ts +25 -0
  41. package/dist/transport/transport.js +28 -0
  42. package/dist/transport/transport.js.map +1 -0
  43. package/package.json +63 -30
  44. package/dist/_contracts/account-operations.d.ts +0 -101
  45. package/dist/_contracts/account-operations.js +0 -242
  46. package/dist/_contracts/account-types.d.ts +0 -461
  47. package/dist/_contracts/account-types.js +0 -1
  48. package/dist/_contracts/api-key.d.ts +0 -61
  49. package/dist/_contracts/api-key.js +0 -101
  50. package/dist/_contracts/api-routes.d.ts +0 -20
  51. package/dist/_contracts/api-routes.js +0 -109
  52. package/dist/_contracts/archive-limits.d.ts +0 -3
  53. package/dist/_contracts/archive-limits.js +0 -23
  54. package/dist/_contracts/asset-authoring.d.ts +0 -22
  55. package/dist/_contracts/asset-authoring.js +0 -106
  56. package/dist/_contracts/asset-bundle.d.ts +0 -64
  57. package/dist/_contracts/asset-bundle.js +0 -263
  58. package/dist/_contracts/asset-upload-helper.d.ts +0 -31
  59. package/dist/_contracts/asset-upload-helper.js +0 -84
  60. package/dist/_contracts/billing-admission.d.ts +0 -29
  61. package/dist/_contracts/billing-admission.js +0 -28
  62. package/dist/_contracts/bundle-manifest.d.ts +0 -89
  63. package/dist/_contracts/bundle-manifest.js +0 -158
  64. package/dist/_contracts/canonical-sha256.d.ts +0 -8
  65. package/dist/_contracts/canonical-sha256.js +0 -8
  66. package/dist/_contracts/connection-ticket.d.ts +0 -22
  67. package/dist/_contracts/connection-ticket.js +0 -54
  68. package/dist/_contracts/continuation-event.d.ts +0 -31
  69. package/dist/_contracts/continuation-event.js +0 -6
  70. package/dist/_contracts/contract-parse-error.d.ts +0 -12
  71. package/dist/_contracts/contract-parse-error.js +0 -51
  72. package/dist/_contracts/error-codes.d.ts +0 -26
  73. package/dist/_contracts/error-codes.js +0 -116
  74. package/dist/_contracts/error-factory.d.ts +0 -32
  75. package/dist/_contracts/error-factory.js +0 -174
  76. package/dist/_contracts/event-envelope.d.ts +0 -471
  77. package/dist/_contracts/event-envelope.js +0 -501
  78. package/dist/_contracts/event-stream-client.d.ts +0 -122
  79. package/dist/_contracts/event-stream-client.js +0 -445
  80. package/dist/_contracts/event-view.d.ts +0 -44
  81. package/dist/_contracts/event-view.js +0 -69
  82. package/dist/_contracts/failure-class.d.ts +0 -29
  83. package/dist/_contracts/failure-class.js +0 -73
  84. package/dist/_contracts/http.d.ts +0 -135
  85. package/dist/_contracts/http.js +0 -434
  86. package/dist/_contracts/ids.d.ts +0 -66
  87. package/dist/_contracts/ids.js +0 -119
  88. package/dist/_contracts/index.d.ts +0 -42
  89. package/dist/_contracts/index.js +0 -52
  90. package/dist/_contracts/internal.d.ts +0 -55
  91. package/dist/_contracts/internal.js +0 -113
  92. package/dist/_contracts/models.d.ts +0 -30
  93. package/dist/_contracts/models.js +0 -28
  94. package/dist/_contracts/operation-core.d.ts +0 -36
  95. package/dist/_contracts/operation-core.js +0 -70
  96. package/dist/_contracts/operations.d.ts +0 -218
  97. package/dist/_contracts/operations.js +0 -1496
  98. package/dist/_contracts/otlp-projection.d.ts +0 -78
  99. package/dist/_contracts/otlp-projection.js +0 -171
  100. package/dist/_contracts/post-hook.d.ts +0 -31
  101. package/dist/_contracts/post-hook.js +0 -61
  102. package/dist/_contracts/provider-fault.d.ts +0 -34
  103. package/dist/_contracts/provider-fault.js +0 -68
  104. package/dist/_contracts/retry-core.d.ts +0 -29
  105. package/dist/_contracts/retry-core.js +0 -79
  106. package/dist/_contracts/runner-event.d.ts +0 -117
  107. package/dist/_contracts/runner-event.js +0 -172
  108. package/dist/_contracts/runtime-kind.d.ts +0 -60
  109. package/dist/_contracts/runtime-kind.js +0 -70
  110. package/dist/_contracts/runtime-manifest.d.ts +0 -121
  111. package/dist/_contracts/runtime-manifest.js +0 -83
  112. package/dist/_contracts/runtime-security-profile.d.ts +0 -26
  113. package/dist/_contracts/runtime-security-profile.js +0 -73
  114. package/dist/_contracts/runtime-sizes.d.ts +0 -104
  115. package/dist/_contracts/runtime-sizes.js +0 -111
  116. package/dist/_contracts/runtime-types.d.ts +0 -618
  117. package/dist/_contracts/runtime-types.js +0 -58
  118. package/dist/_contracts/schemas/asset-bundle.d.ts +0 -70
  119. package/dist/_contracts/schemas/asset-bundle.js +0 -107
  120. package/dist/_contracts/schemas/asset-ref.d.ts +0 -61
  121. package/dist/_contracts/schemas/asset-ref.js +0 -118
  122. package/dist/_contracts/schemas/bundle-manifest.d.ts +0 -66
  123. package/dist/_contracts/schemas/bundle-manifest.js +0 -77
  124. package/dist/_contracts/schemas/index.d.ts +0 -32
  125. package/dist/_contracts/schemas/index.js +0 -30
  126. package/dist/_contracts/schemas/mcp-server.d.ts +0 -99
  127. package/dist/_contracts/schemas/mcp-server.js +0 -209
  128. package/dist/_contracts/schemas/models.d.ts +0 -29
  129. package/dist/_contracts/schemas/models.js +0 -51
  130. package/dist/_contracts/schemas/numeric.d.ts +0 -18
  131. package/dist/_contracts/schemas/numeric.js +0 -28
  132. package/dist/_contracts/schemas/post-hook.d.ts +0 -45
  133. package/dist/_contracts/schemas/post-hook.js +0 -68
  134. package/dist/_contracts/schemas/response-assets.d.ts +0 -75
  135. package/dist/_contracts/schemas/response-assets.js +0 -81
  136. package/dist/_contracts/schemas/response-billing.d.ts +0 -208
  137. package/dist/_contracts/schemas/response-billing.js +0 -139
  138. package/dist/_contracts/schemas/response-common.d.ts +0 -132
  139. package/dist/_contracts/schemas/response-common.js +0 -162
  140. package/dist/_contracts/schemas/response-identity.d.ts +0 -648
  141. package/dist/_contracts/schemas/response-identity.js +0 -131
  142. package/dist/_contracts/schemas/response-mcp-servers.d.ts +0 -51
  143. package/dist/_contracts/schemas/response-mcp-servers.js +0 -32
  144. package/dist/_contracts/schemas/response-secrets.d.ts +0 -50
  145. package/dist/_contracts/schemas/response-secrets.js +0 -32
  146. package/dist/_contracts/schemas/response-sessions-internal.d.ts +0 -200
  147. package/dist/_contracts/schemas/response-sessions-internal.js +0 -142
  148. package/dist/_contracts/schemas/response-sessions.d.ts +0 -1598
  149. package/dist/_contracts/schemas/response-sessions.js +0 -377
  150. package/dist/_contracts/schemas/response-webhooks.d.ts +0 -76
  151. package/dist/_contracts/schemas/response-webhooks.js +0 -42
  152. package/dist/_contracts/schemas/response-workspace.d.ts +0 -225
  153. package/dist/_contracts/schemas/response-workspace.js +0 -99
  154. package/dist/_contracts/schemas/runtime-kind.d.ts +0 -31
  155. package/dist/_contracts/schemas/runtime-kind.js +0 -29
  156. package/dist/_contracts/schemas/runtime-security-profile.d.ts +0 -28
  157. package/dist/_contracts/schemas/runtime-security-profile.js +0 -26
  158. package/dist/_contracts/schemas/runtime-sizes.d.ts +0 -70
  159. package/dist/_contracts/schemas/runtime-sizes.js +0 -127
  160. package/dist/_contracts/schemas/session-limits.d.ts +0 -34
  161. package/dist/_contracts/schemas/session-limits.js +0 -39
  162. package/dist/_contracts/schemas/session-machine.d.ts +0 -23
  163. package/dist/_contracts/schemas/session-machine.js +0 -24
  164. package/dist/_contracts/schemas/session-request-config.d.ts +0 -58
  165. package/dist/_contracts/schemas/session-request-config.js +0 -134
  166. package/dist/_contracts/schemas/session-webhook.d.ts +0 -11
  167. package/dist/_contracts/schemas/session-webhook.js +0 -38
  168. package/dist/_contracts/schemas/side-effect-audit.d.ts +0 -98
  169. package/dist/_contracts/schemas/side-effect-audit.js +0 -102
  170. package/dist/_contracts/schemas/submission-assets.d.ts +0 -117
  171. package/dist/_contracts/schemas/submission-assets.js +0 -147
  172. package/dist/_contracts/schemas/submission-body.d.ts +0 -251
  173. package/dist/_contracts/schemas/submission-body.js +0 -378
  174. package/dist/_contracts/schemas/submission-environment.d.ts +0 -79
  175. package/dist/_contracts/schemas/submission-environment.js +0 -179
  176. package/dist/_contracts/schemas/submission-request.d.ts +0 -158
  177. package/dist/_contracts/schemas/submission-request.js +0 -49
  178. package/dist/_contracts/schemas/submission-secrets.d.ts +0 -47
  179. package/dist/_contracts/schemas/submission-secrets.js +0 -108
  180. package/dist/_contracts/schemas/wire.d.ts +0 -118
  181. package/dist/_contracts/schemas/wire.js +0 -171
  182. package/dist/_contracts/schemas/workspace-resources.d.ts +0 -50
  183. package/dist/_contracts/schemas/workspace-resources.js +0 -87
  184. package/dist/_contracts/sdk-errors.d.ts +0 -212
  185. package/dist/_contracts/sdk-errors.js +0 -313
  186. package/dist/_contracts/sdk-secrets.d.ts +0 -67
  187. package/dist/_contracts/sdk-secrets.js +0 -427
  188. package/dist/_contracts/session-archive.d.ts +0 -16
  189. package/dist/_contracts/session-archive.js +0 -92
  190. package/dist/_contracts/session-artifacts.d.ts +0 -189
  191. package/dist/_contracts/session-artifacts.js +0 -264
  192. package/dist/_contracts/session-config.d.ts +0 -373
  193. package/dist/_contracts/session-config.js +0 -562
  194. package/dist/_contracts/session-cost-types.d.ts +0 -211
  195. package/dist/_contracts/session-cost-types.js +0 -69
  196. package/dist/_contracts/session-cost.d.ts +0 -8
  197. package/dist/_contracts/session-cost.js +0 -582
  198. package/dist/_contracts/session-custody.d.ts +0 -165
  199. package/dist/_contracts/session-custody.js +0 -345
  200. package/dist/_contracts/session-file-query.d.ts +0 -14
  201. package/dist/_contracts/session-file-query.js +0 -178
  202. package/dist/_contracts/session-record.d.ts +0 -112
  203. package/dist/_contracts/session-record.js +0 -165
  204. package/dist/_contracts/session-retention.d.ts +0 -201
  205. package/dist/_contracts/session-retention.js +0 -450
  206. package/dist/_contracts/side-effect-audit.d.ts +0 -126
  207. package/dist/_contracts/side-effect-audit.js +0 -520
  208. package/dist/_contracts/sse.d.ts +0 -74
  209. package/dist/_contracts/sse.js +0 -227
  210. package/dist/_contracts/stable.d.ts +0 -45
  211. package/dist/_contracts/stable.js +0 -62
  212. package/dist/_contracts/status.d.ts +0 -25
  213. package/dist/_contracts/status.js +0 -57
  214. package/dist/_contracts/submission-limits.d.ts +0 -61
  215. package/dist/_contracts/submission-limits.js +0 -60
  216. package/dist/_contracts/submission.d.ts +0 -547
  217. package/dist/_contracts/submission.js +0 -812
  218. package/dist/_contracts/suggest.d.ts +0 -15
  219. package/dist/_contracts/suggest.js +0 -53
  220. package/dist/_contracts/testing/response-bindings.d.ts +0 -45
  221. package/dist/_contracts/testing/response-bindings.js +0 -256
  222. package/dist/_contracts/testing/wire-conformance-entry.d.ts +0 -10
  223. package/dist/_contracts/testing/wire-conformance-entry.js +0 -8
  224. package/dist/_contracts/testing/wire-conformance.d.ts +0 -169
  225. package/dist/_contracts/testing/wire-conformance.js +0 -276
  226. package/dist/_contracts/turn-trace.d.ts +0 -28
  227. package/dist/_contracts/turn-trace.js +0 -1
  228. package/dist/_contracts/unknown-field-error.d.ts +0 -13
  229. package/dist/_contracts/unknown-field-error.js +0 -21
  230. package/dist/_contracts/value-guards.d.ts +0 -20
  231. package/dist/_contracts/value-guards.js +0 -34
  232. package/dist/_contracts/webhook-verify.d.ts +0 -34
  233. package/dist/_contracts/webhook-verify.js +0 -93
  234. package/dist/_contracts/wire-observer.d.ts +0 -49
  235. package/dist/_contracts/wire-observer.js +0 -34
  236. package/dist/_contracts/workflow-status.d.ts +0 -7
  237. package/dist/_contracts/workflow-status.js +0 -43
  238. package/dist/_contracts/workspace-resources.d.ts +0 -98
  239. package/dist/_contracts/workspace-resources.js +0 -39
  240. package/dist/archive-limits.d.ts +0 -1
  241. package/dist/archive-limits.js +0 -2
  242. package/dist/archive-limits.js.map +0 -1
  243. package/dist/asset-upload.d.ts +0 -47
  244. package/dist/asset-upload.js +0 -269
  245. package/dist/asset-upload.js.map +0 -1
  246. package/dist/bundle.d.ts +0 -9
  247. package/dist/bundle.js +0 -20
  248. package/dist/bundle.js.map +0 -1
  249. package/dist/canonical-zip.d.ts +0 -68
  250. package/dist/canonical-zip.js +0 -355
  251. package/dist/canonical-zip.js.map +0 -1
  252. package/dist/cli.mjs +0 -12048
  253. package/dist/cli.mjs.sha256 +0 -1
  254. package/dist/client-types.d.ts +0 -192
  255. package/dist/client-types.js +0 -2
  256. package/dist/client-types.js.map +0 -1
  257. package/dist/client.d.ts +0 -464
  258. package/dist/client.js +0 -1207
  259. package/dist/client.js.map +0 -1
  260. package/dist/event-projection.d.ts +0 -22
  261. package/dist/event-projection.js +0 -380
  262. package/dist/event-projection.js.map +0 -1
  263. package/dist/fetch-archive.d.ts +0 -16
  264. package/dist/fetch-archive.js +0 -252
  265. package/dist/fetch-archive.js.map +0 -1
  266. package/dist/file.d.ts +0 -96
  267. package/dist/file.js +0 -272
  268. package/dist/file.js.map +0 -1
  269. package/dist/instructions.d.ts +0 -20
  270. package/dist/instructions.js +0 -40
  271. package/dist/instructions.js.map +0 -1
  272. package/dist/legacy-session-provider-fault.d.ts +0 -7
  273. package/dist/legacy-session-provider-fault.js +0 -38
  274. package/dist/legacy-session-provider-fault.js.map +0 -1
  275. package/dist/mcp-server.d.ts +0 -84
  276. package/dist/mcp-server.js +0 -117
  277. package/dist/mcp-server.js.map +0 -1
  278. package/dist/node-fs.d.ts +0 -29
  279. package/dist/node-fs.js +0 -19
  280. package/dist/node-fs.js.map +0 -1
  281. package/dist/node-walk.d.ts +0 -69
  282. package/dist/node-walk.js +0 -151
  283. package/dist/node-walk.js.map +0 -1
  284. package/dist/path-basename.d.ts +0 -5
  285. package/dist/path-basename.js +0 -9
  286. package/dist/path-basename.js.map +0 -1
  287. package/dist/retry.d.ts +0 -70
  288. package/dist/retry.js +0 -155
  289. package/dist/retry.js.map +0 -1
  290. package/dist/secret.d.ts +0 -65
  291. package/dist/secret.js +0 -110
  292. package/dist/secret.js.map +0 -1
  293. package/dist/session-validate.d.ts +0 -100
  294. package/dist/session-validate.js +0 -303
  295. package/dist/session-validate.js.map +0 -1
  296. package/dist/skill.d.ts +0 -99
  297. package/dist/skill.js +0 -169
  298. package/dist/skill.js.map +0 -1
  299. package/dist/submission-wire.d.ts +0 -13
  300. package/dist/submission-wire.js +0 -69
  301. package/dist/submission-wire.js.map +0 -1
  302. package/dist/tool.d.ts +0 -41
  303. package/dist/tool.js +0 -76
  304. package/dist/tool.js.map +0 -1
  305. package/dist/version.d.ts +0 -9
  306. package/dist/version.js +0 -10
  307. package/dist/version.js.map +0 -1
  308. package/docs/authentication.md +0 -125
  309. package/docs/billing.md +0 -164
  310. package/docs/cleanup.md +0 -27
  311. package/docs/concepts/agent-tools.md +0 -47
  312. package/docs/concepts/composition.md +0 -60
  313. package/docs/concepts/providers-and-runtimes.md +0 -121
  314. package/docs/concepts/sessions.md +0 -51
  315. package/docs/concepts/subagents.md +0 -35
  316. package/docs/credentials.md +0 -116
  317. package/docs/defaults.md +0 -51
  318. package/docs/errors.md +0 -258
  319. package/docs/events.md +0 -143
  320. package/docs/files.md +0 -130
  321. package/docs/limits-and-quotas.md +0 -114
  322. package/docs/limits.md +0 -51
  323. package/docs/mcp.md +0 -47
  324. package/docs/networking.md +0 -114
  325. package/docs/provider-runtime-capabilities.md +0 -32
  326. package/docs/public-surface.json +0 -73
  327. package/docs/quickstart.md +0 -135
  328. package/docs/release.md +0 -44
  329. package/docs/retries.md +0 -108
  330. package/docs/secrets.md +0 -141
  331. package/docs/session-config.md +0 -51
  332. package/docs/session-record.md +0 -58
  333. package/docs/skills.md +0 -65
  334. package/docs/telemetry.md +0 -66
  335. package/docs/testing.md +0 -35
  336. package/docs/vision-skills.md +0 -94
  337. 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
- }