@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,67 +0,0 @@
1
- import { Transform } from "node:stream";
2
- export type PublicSafeStructuralReason = "forbidden_field_name" | "uninspectable_value";
3
- export type PublicSafeSecretReason = "bearer_token" | "provider_key" | "signed_url" | "object_store_key" | "vault_id" | "private_resource_handle" | "high_entropy_token";
4
- export interface PublicSafeFinding<Reason extends string> {
5
- readonly path: string;
6
- readonly reason: Reason | PublicSafeStructuralReason;
7
- readonly valueLength?: number;
8
- }
9
- export interface PublicSafeStringPattern<Reason extends string> {
10
- readonly reason: Reason;
11
- readonly regex: RegExp;
12
- readonly accept?: (match: string) => boolean;
13
- }
14
- export interface PublicSafePatternMatch<Reason extends string> {
15
- readonly reason: Reason;
16
- readonly path: string;
17
- readonly value: string;
18
- readonly match: string;
19
- }
20
- export interface PublicSafeScannerConfig<Reason extends string> {
21
- readonly patterns: readonly PublicSafeStringPattern<Reason>[];
22
- readonly isForbiddenFieldName: (key: string, path: string) => boolean;
23
- readonly isPatternExempt?: (match: PublicSafePatternMatch<Reason>) => boolean;
24
- readonly maxDepth?: number;
25
- readonly maxVisitedValues?: number;
26
- }
27
- /** The only bare content identity the platform mints. */
28
- export declare function isPlatformContentDigest(candidate: string): boolean;
29
- export declare function looksHighEntropySecret(value: string): boolean;
30
- export declare function publicSafeCharClassCount(value: string): number;
31
- export declare function publicSafeShannonBits(value: string): number;
32
- export declare const PUBLIC_SAFE_SECRET_PATTERNS: readonly PublicSafeStringPattern<Exclude<PublicSafeSecretReason, "private_resource_handle">>[];
33
- /** Extra entropy policy for consumers whose identifier slots admit `_`. */
34
- export declare function underscoredHighEntropyPattern(): PublicSafeStringPattern<"high_entropy_token">;
35
- export declare function privateResourceHandlePattern(keywords: readonly string[], separators?: "_:-" | "_:"): PublicSafeStringPattern<"private_resource_handle">;
36
- export declare function createForbiddenFieldNamePredicate(names: readonly string[]): (key: string, path: string) => boolean;
37
- export declare function scanPublicSafePayload<Reason extends string>(input: unknown, config: PublicSafeScannerConfig<Reason>): readonly PublicSafeFinding<Reason>[];
38
- export declare class SecretString {
39
- #private;
40
- constructor(value: string, label?: string);
41
- unwrap(): string;
42
- toString(): string;
43
- toJSON(): string;
44
- }
45
- export declare function redactSecrets<T>(value: T): T;
46
- /**
47
- * Redact every secret-shaped run in `input`.
48
- *
49
- * `known` is an OPTIONAL belt-and-suspenders set of literal values to also mask
50
- * (e.g. creds the caller happens to have loaded). Correctness does NOT depend on
51
- * it — every shape above is caught with or without seeding — but masking known
52
- * values first removes any residual substring of a value the shapes split.
53
- */
54
- export declare function redactString(input: string, known?: Iterable<string>): string;
55
- export declare function containsSecretLikeValue(input: string): boolean;
56
- /**
57
- * A line-buffered `Transform` that redacts secrets BEFORE bytes touch disk or
58
- * console. Pipe a child process's stdout/stderr through it
59
- * (`child.stdout.pipe(createRedactingStream()).pipe(process.stdout)`) so a
60
- * secret can never be written and "cleaned up after"; the secret you didn't
61
- * recognise is the one already on disk.
62
- *
63
- * Buffers by line so a secret split across a chunk boundary is still redacted:
64
- * a partial trailing line is held until the next chunk (or `flush`) completes
65
- * it. `known` is forwarded to `redactString` for optional value seeding.
66
- */
67
- export declare function createRedactingStream(known?: Iterable<string>): Transform;
@@ -1,427 +0,0 @@
1
- import { Transform } from "node:stream";
2
- const DEFAULT_MAX_DEPTH = 64;
3
- const DEFAULT_MAX_VISITED_VALUES = 100_000;
4
- const ENTROPY_BITS_PER_CHAR = 3.0;
5
- const MIN_CHAR_CLASSES = 2;
6
- const HIGH_ENTROPY_NO_DIGIT_MIN_LEN = 40;
7
- /** The only bare content identity the platform mints. */
8
- export function isPlatformContentDigest(candidate) {
9
- return /^[0-9a-f]{64}$/.test(candidate);
10
- }
11
- export function looksHighEntropySecret(value) {
12
- return value.split("-").some(isOpaqueSecretRun);
13
- }
14
- export function publicSafeCharClassCount(value) {
15
- let count = 0;
16
- if (/[a-z]/.test(value))
17
- count++;
18
- if (/[A-Z]/.test(value))
19
- count++;
20
- if (/[0-9]/.test(value))
21
- count++;
22
- return count;
23
- }
24
- export function publicSafeShannonBits(value) {
25
- if (value.length === 0)
26
- return 0;
27
- const counts = new Map();
28
- for (const char of value) {
29
- counts.set(char, (counts.get(char) ?? 0) + 1);
30
- }
31
- let bits = 0;
32
- for (const count of counts.values()) {
33
- const probability = count / value.length;
34
- bits -= probability * Math.log2(probability);
35
- }
36
- return bits;
37
- }
38
- function isOpaqueSecretRun(value) {
39
- if (publicSafeCharClassCount(value) < MIN_CHAR_CLASSES)
40
- return false;
41
- if (publicSafeShannonBits(value) < ENTROPY_BITS_PER_CHAR)
42
- return false;
43
- return /[0-9]/.test(value) || value.length >= HIGH_ENTROPY_NO_DIGIT_MIN_LEN;
44
- }
45
- export const PUBLIC_SAFE_SECRET_PATTERNS = Object.freeze([
46
- Object.freeze({
47
- reason: "bearer_token",
48
- regex: /\b(Bearer)\s+[A-Za-z0-9._~+/=-]{8,}/i
49
- }),
50
- Object.freeze({
51
- reason: "provider_key",
52
- regex: /\b(?:sk-[A-Za-z0-9_-]{16,}|xox[baprs]-[A-Za-z0-9-]{8,}|AIza[A-Za-z0-9_-]{8,})/i
53
- }),
54
- Object.freeze({
55
- reason: "signed_url",
56
- regex: /\bhttps?:\/\/[^\s"'<>]*(?:X-Amz-Signature|X-Amz-Credential|X-Amz-Algorithm|AWSAccessKeyId|X-Goog-Signature|X-Goog-Credential|[?&]sig=)[^\s"'<>]*/i
57
- }),
58
- Object.freeze({
59
- reason: "object_store_key",
60
- regex: /(^|[\s"'`])(?:sessions|assets)\/[^?<#\s"'`]+/i
61
- }),
62
- Object.freeze({
63
- reason: "vault_id",
64
- regex: /\b(?:vault|vlt|secret)[_:-][A-Za-z0-9][A-Za-z0-9_-]{7,}\b/i
65
- }),
66
- Object.freeze({
67
- reason: "high_entropy_token",
68
- regex: /\b[A-Za-z0-9-]{40,}\b/,
69
- accept: looksHighEntropySecret
70
- })
71
- ]);
72
- /** Extra entropy policy for consumers whose identifier slots admit `_`. */
73
- export function underscoredHighEntropyPattern() {
74
- return Object.freeze({
75
- reason: "high_entropy_token",
76
- regex: /\b[A-Za-z0-9-]{3,}_[A-Za-z0-9_-]{36,}\b/,
77
- accept: (match) => looksHighEntropySecret(match.replaceAll("_", "-"))
78
- });
79
- }
80
- export function privateResourceHandlePattern(keywords, separators = "_:-") {
81
- const source = keywords.map(escapePublicSafeRegex).join("|");
82
- return Object.freeze({
83
- reason: "private_resource_handle",
84
- regex: new RegExp(`\\b(?:${source})[${separators}][A-Za-z0-9][A-Za-z0-9_-]{7,}\\b`, "i"),
85
- accept: isMintedResourceHandle
86
- });
87
- }
88
- function isMintedResourceHandle(match) {
89
- const separatorIndex = match.search(/[_:-]/);
90
- return separatorIndex >= 0 && /\d/.test(match.slice(separatorIndex + 1));
91
- }
92
- function escapePublicSafeRegex(value) {
93
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
94
- }
95
- export function createForbiddenFieldNamePredicate(names) {
96
- const normalized = new Set(names.map((name) => name.toLowerCase()));
97
- return (key) => normalized.has(key.toLowerCase());
98
- }
99
- export function scanPublicSafePayload(input, config) {
100
- const findings = [];
101
- const seen = new WeakSet();
102
- const stack = [
103
- { value: input, path: "$", depth: 0 }
104
- ];
105
- const maxDepth = config.maxDepth ?? DEFAULT_MAX_DEPTH;
106
- const maxVisitedValues = config.maxVisitedValues ?? DEFAULT_MAX_VISITED_VALUES;
107
- let visited = 0;
108
- while (stack.length > 0) {
109
- const current = stack.pop();
110
- visited++;
111
- if (visited > maxVisitedValues || current.depth > maxDepth) {
112
- findings.push(freezePublicSafeFinding({ path: current.path, reason: "uninspectable_value" }));
113
- continue;
114
- }
115
- if (typeof current.value === "string") {
116
- scanPublicSafeString(current.value, current.path, config, findings);
117
- continue;
118
- }
119
- if (current.value === null || typeof current.value !== "object")
120
- continue;
121
- if (seen.has(current.value)) {
122
- findings.push(freezePublicSafeFinding({ path: current.path, reason: "uninspectable_value" }));
123
- continue;
124
- }
125
- seen.add(current.value);
126
- let keys;
127
- try {
128
- keys = Object.keys(current.value);
129
- }
130
- catch {
131
- findings.push(freezePublicSafeFinding({ path: current.path, reason: "uninspectable_value" }));
132
- continue;
133
- }
134
- const children = [];
135
- for (const key of keys) {
136
- const childPath = Array.isArray(current.value) && /^\d+$/.test(key)
137
- ? `${current.path}[${key}]`
138
- : `${current.path}.${key}`;
139
- let forbidden = false;
140
- try {
141
- forbidden = config.isForbiddenFieldName(key, childPath);
142
- }
143
- catch {
144
- findings.push(freezePublicSafeFinding({ path: childPath, reason: "uninspectable_value" }));
145
- }
146
- if (forbidden) {
147
- findings.push(freezePublicSafeFinding({ path: childPath, reason: "forbidden_field_name" }));
148
- }
149
- let descriptor;
150
- try {
151
- descriptor = Object.getOwnPropertyDescriptor(current.value, key);
152
- }
153
- catch {
154
- findings.push(freezePublicSafeFinding({ path: childPath, reason: "uninspectable_value" }));
155
- continue;
156
- }
157
- if (!descriptor || !("value" in descriptor)) {
158
- findings.push(freezePublicSafeFinding({ path: childPath, reason: "uninspectable_value" }));
159
- continue;
160
- }
161
- children.push({ value: descriptor.value, path: childPath, depth: current.depth + 1 });
162
- }
163
- for (let index = children.length - 1; index >= 0; index--)
164
- stack.push(children[index]);
165
- }
166
- return Object.freeze(findings);
167
- }
168
- function scanPublicSafeString(value, path, config, findings) {
169
- for (const pattern of config.patterns) {
170
- let matches;
171
- try {
172
- matches = matchingPublicSafeSequences(pattern, value);
173
- }
174
- catch {
175
- findings.push(freezePublicSafeFinding({ path, reason: "uninspectable_value" }));
176
- continue;
177
- }
178
- for (const match of matches) {
179
- let exempt = false;
180
- try {
181
- exempt = config.isPatternExempt?.({ reason: pattern.reason, path, value, match }) ?? false;
182
- }
183
- catch {
184
- findings.push(freezePublicSafeFinding({ path, reason: "uninspectable_value" }));
185
- break;
186
- }
187
- if (!exempt) {
188
- findings.push(freezePublicSafeFinding({ path, reason: pattern.reason, valueLength: value.length }));
189
- break;
190
- }
191
- }
192
- }
193
- }
194
- function matchingPublicSafeSequences(pattern, value) {
195
- const flags = pattern.regex.flags.includes("g") ? pattern.regex.flags : `${pattern.regex.flags}g`;
196
- const regex = new RegExp(pattern.regex.source, flags);
197
- const matches = [];
198
- let match;
199
- while ((match = regex.exec(value)) !== null) {
200
- if (!pattern.accept || pattern.accept(match[0]))
201
- matches.push(match[0]);
202
- if (match.index === regex.lastIndex)
203
- regex.lastIndex++;
204
- }
205
- return matches;
206
- }
207
- function freezePublicSafeFinding(finding) {
208
- return Object.freeze(finding);
209
- }
210
- /**
211
- * Value-AGNOSTIC secret patterns: each matches a SHAPE, not a known value.
212
- * Correctness must not depend on seeding the redactor with the literal
213
- * secret — the two real leaks this project hit were a database password that
214
- * survived a naive `sed` mask (as a substring) and an Anthropic key surfaced in
215
- * a deploy CLI's describe output that the harness NEVER loaded. A value-seeded
216
- * redactor is blind to both; these patterns catch them by form.
217
- *
218
- * Ordering matters: structured shapes (connection strings, auth headers, JWT)
219
- * come BEFORE the generic key/entropy catch-alls so the more descriptive
220
- * `[REDACTED …]` label wins on overlapping matches.
221
- */
222
- const SECRET_PATTERNS = [
223
- // postgres / postgresql connection strings — redact the whole URI so the
224
- // embedded password can never survive as a substring (the `sed`-mask leak).
225
- /\bpostgres(?:ql)?:\/\/[^\s"']+/gi,
226
- // aex workspace / proxy tokens: apt_… / ant_….
227
- /\b(?:apt|ant)_[A-Za-z0-9_-]{16,}/g,
228
- // aex self-describing workspace API key (one-time reveal from createWorkspace /
229
- // createApiKey): aex_<plane>_<region>_<workspaceId>_<secret>_<crc>. Anchored on
230
- // the full 6-part shape so the whole key masks as one label (the entropy
231
- // catch-all would otherwise redact only its dense segments, leaving the
232
- // `aex_<plane>_<region>_` prefix behind). Never matches `api.aex.dev`.
233
- /\baex_(?:dev|prd)_[a-z0-9]+_[a-z0-9]+_[A-Za-z0-9]+_[a-z0-9]+/gi,
234
- // aex account PAT (control-plane): aexu_<opaque>. Distinct prefix from the
235
- // workspace-key family so a PAT masks by shape even when short.
236
- /\baexu_[A-Za-z0-9_-]{16,}/g,
237
- // AWS access key id + secret access key shapes.
238
- /\b(?:AKIA|ASIA)[A-Z0-9]{16}\b/g,
239
- /\baws_secret_access_key["'\s:=]+[A-Za-z0-9/+=]{40}/gi,
240
- // JWT-shaped: header.payload.signature, each base64url, header starts `eyJ`.
241
- /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/g,
242
- // Keyword-introduced secret assignments (bearer/token/api_key/…).
243
- /(?:bearer|token|api[_-]?key|access[_-]?token|refresh[_-]?token|client[_-]?secret)["'\s:=]+[A-Za-z0-9_\-./+=]{12,}/gi
244
- ];
245
- const SDK_SHARED_SECRET_PATTERNS = PUBLIC_SAFE_SECRET_PATTERNS.filter((pattern) => pattern.reason === "bearer_token" ||
246
- pattern.reason === "provider_key" ||
247
- pattern.reason === "signed_url");
248
- const REDACTED = "[REDACTED]";
249
- /**
250
- * Generic high-entropy token catch-all, applied AFTER the named patterns.
251
- * Catches the secret nobody recognised: any long base64url/hex-ish run that is
252
- * BOTH high-entropy AND character-class-diverse.
253
- *
254
- * The candidate run deliberately EXCLUDES `_`: secrets are contiguous opaque
255
- * runs, whereas `SCREAMING_SNAKE_CASE` env names and `snake_case` identifiers
256
- * are `_`-separated words — excluding `_` breaks those into sub-24 fragments so
257
- * they are never eaten. The
258
- * class-diversity gate (≥2 of lower/upper/digit) then keeps the remaining
259
- * single-class runs (all-lowercase module paths like `internal/modules/esm`)
260
- * while still catching mixed-case/alnum secret blobs. Entropy alone cannot
261
- * separate these — `the_quick…` (4.16) out-scores a real key prefix.
262
- */
263
- const HIGH_ENTROPY_CANDIDATE = /[A-Za-z0-9+/=-]{24,}/g;
264
- /**
265
- * A mixed-case run with no digit and < this length is treated as a benign
266
- * identifier, not a secret. Real opaque secrets are alnum-mixed (carry a
267
- * digit) or very long; digit-free camelCase identifiers like
268
- * `asyncEntryPointWithESMLoader` / `getReadableStreamController` (which
269
- * appear in stack traces the diagnostic bundle captures) are 24–39 chars and
270
- * digit-free — eating them would gut debuggability. The length escape hatch
271
- * still catches the rare long digit-free secret.
272
- */
273
- /**
274
- * Canonical aex session-id hex: exactly 32 lowercase hex chars directly preceded
275
- * by `ses_`. The HIGH_ENTROPY_CANDIDATE class excludes `_`, so the candidate
276
- * candidate for a session id is the bare hex — dense enough to trip the entropy gate.
277
- * Masking it destroys the ONE identifier every error message needs for
278
- * traceability (`cancel via aex.sessions.open("ses_[REDACTED]")` is useless
279
- * guidance). A session id is not a credential: it grants nothing without the
280
- * bearer token. Mirrors the platform-side redactor's canonical-id exemption.
281
- */
282
- function isCanonicalSessionIdHex(input, matchStart, match) {
283
- if (!/^[0-9a-f]{32}$/.test(match))
284
- return false;
285
- return input.slice(Math.max(0, matchStart - 4), matchStart) === "ses_";
286
- }
287
- export class SecretString {
288
- #value;
289
- constructor(value, label = "secret") {
290
- if (!value) {
291
- throw new Error(`${label} is required`);
292
- }
293
- this.#value = value;
294
- }
295
- unwrap() {
296
- return this.#value;
297
- }
298
- toString() {
299
- return REDACTED;
300
- }
301
- toJSON() {
302
- return REDACTED;
303
- }
304
- }
305
- export function redactSecrets(value) {
306
- if (typeof value === "string") {
307
- return redactString(value);
308
- }
309
- if (Array.isArray(value)) {
310
- return value.map((item) => redactSecrets(item));
311
- }
312
- if (value && typeof value === "object") {
313
- const out = {};
314
- for (const [key, item] of Object.entries(value)) {
315
- if (isSecretKey(key)) {
316
- out[key] = REDACTED;
317
- }
318
- else {
319
- out[key] = redactSecrets(item);
320
- }
321
- }
322
- return out;
323
- }
324
- return value;
325
- }
326
- /**
327
- * Redact every secret-shaped run in `input`.
328
- *
329
- * `known` is an OPTIONAL belt-and-suspenders set of literal values to also mask
330
- * (e.g. creds the caller happens to have loaded). Correctness does NOT depend on
331
- * it — every shape above is caught with or without seeding — but masking known
332
- * values first removes any residual substring of a value the shapes split.
333
- */
334
- export function redactString(input, known = []) {
335
- let out = input;
336
- for (const value of known) {
337
- if (value && value.length >= 4) {
338
- out = out.split(value).join(REDACTED);
339
- }
340
- }
341
- out = SDK_SHARED_SECRET_PATTERNS.reduce((current, pattern) => current.replace(new RegExp(pattern.regex.source, pattern.regex.flags.includes("g")
342
- ? pattern.regex.flags
343
- : `${pattern.regex.flags}g`), (match, captured) => typeof captured === "string" ? `${captured} ${REDACTED}` : REDACTED), out);
344
- out = SECRET_PATTERNS.reduce((current, pattern) => current.replace(pattern, (match, captured) => typeof captured === "string" ? `${captured} ${REDACTED}` : REDACTED), out);
345
- return out.replace(HIGH_ENTROPY_CANDIDATE, (match, offset, whole) => !isCanonicalSessionIdHex(whole, offset, match) &&
346
- !isPlatformContentDigest(match) &&
347
- looksHighEntropySecret(match)
348
- ? REDACTED
349
- : match);
350
- }
351
- export function containsSecretLikeValue(input) {
352
- if ([...SECRET_PATTERNS, ...SDK_SHARED_SECRET_PATTERNS.map((pattern) => pattern.regex)].some((pattern) => {
353
- pattern.lastIndex = 0;
354
- return pattern.test(input);
355
- })) {
356
- return true;
357
- }
358
- HIGH_ENTROPY_CANDIDATE.lastIndex = 0;
359
- let candidate;
360
- while ((candidate = HIGH_ENTROPY_CANDIDATE.exec(input)) !== null) {
361
- if (isCanonicalSessionIdHex(input, candidate.index, candidate[0])) {
362
- continue;
363
- }
364
- if (isPlatformContentDigest(candidate[0])) {
365
- continue;
366
- }
367
- if (looksHighEntropySecret(candidate[0])) {
368
- return true;
369
- }
370
- }
371
- return false;
372
- }
373
- /**
374
- * A line-buffered `Transform` that redacts secrets BEFORE bytes touch disk or
375
- * console. Pipe a child process's stdout/stderr through it
376
- * (`child.stdout.pipe(createRedactingStream()).pipe(process.stdout)`) so a
377
- * secret can never be written and "cleaned up after"; the secret you didn't
378
- * recognise is the one already on disk.
379
- *
380
- * Buffers by line so a secret split across a chunk boundary is still redacted:
381
- * a partial trailing line is held until the next chunk (or `flush`) completes
382
- * it. `known` is forwarded to `redactString` for optional value seeding.
383
- */
384
- export function createRedactingStream(known = []) {
385
- const knownValues = [...known];
386
- let carry = "";
387
- return new Transform({
388
- transform(chunk, _encoding, callback) {
389
- carry += chunk.toString();
390
- const lastNewline = carry.lastIndexOf("\n");
391
- if (lastNewline === -1) {
392
- callback();
393
- return;
394
- }
395
- const ready = carry.slice(0, lastNewline + 1);
396
- carry = carry.slice(lastNewline + 1);
397
- callback(null, redactString(ready, knownValues));
398
- },
399
- flush(callback) {
400
- if (carry === "") {
401
- callback();
402
- return;
403
- }
404
- const tail = carry;
405
- carry = "";
406
- callback(null, redactString(tail, knownValues));
407
- }
408
- });
409
- }
410
- /**
411
- * Wire keys that contain a secret-looking word but name a QUANTITY, not a
412
- * credential. Same argument as the canonical-session-id exemption above: masking
413
- * them destroys the one number the message exists to carry, and the value grants
414
- * nothing to whoever reads it.
415
- *
416
- * `llm_token_usd` is the free model-usage allowance dimension. It is the field a
417
- * `402 insufficient_credits` body is read for — "$0.00 of $2.00 left this month"
418
- * — and the substring `token` in a dimension name is a coincidence of the
419
- * metering vocabulary, not a credential. The name is fixed by the hosted
420
- * allowance schema, so it cannot be spelled around on the client.
421
- */
422
- const NON_SECRET_KEYS = new Set(["llm_token_usd"]);
423
- function isSecretKey(key) {
424
- if (NON_SECRET_KEYS.has(key))
425
- return false;
426
- return /(?:api[_-]?key|authorization|token|secret|password|credential)/i.test(key);
427
- }
@@ -1,16 +0,0 @@
1
- import type { AexEvent } from "./event-envelope.js";
2
- import { type SessionRecordArchiveEntryForRedactionV1, type SessionRecordArtifactSummaryV1, type SessionRecordDownloadErrorV1 } from "./session-record.js";
3
- import type { Session } from "./runtime-types.js";
4
- export interface SessionArchiveEntry extends SessionRecordArchiveEntryForRedactionV1 {
5
- readonly path: string;
6
- readonly bytes: Uint8Array;
7
- }
8
- export interface CollectedSessionArchiveArtifacts {
9
- readonly entries: readonly SessionArchiveEntry[];
10
- readonly captured: readonly SessionRecordArtifactSummaryV1[];
11
- readonly errors: readonly SessionRecordDownloadErrorV1[];
12
- }
13
- export declare function buildSessionArchive(sessionId: string, session: Session, events: readonly AexEvent[], files: CollectedSessionArchiveArtifacts): Uint8Array;
14
- export declare function buildSessionFilesArchive(sessionId: string, files: CollectedSessionArchiveArtifacts): Uint8Array;
15
- export declare function buildSessionEventsArchive(sessionId: string, events: readonly AexEvent[]): Uint8Array;
16
- export declare function buildSessionMetadataArchive(sessionId: string, session: Session): Uint8Array;
@@ -1,92 +0,0 @@
1
- import { strToU8, zipSync } from "fflate";
2
- import { isRecord } from "./value-guards.js";
3
- import { assertSessionRecordArchivePublicSafeV1, buildSessionRecordDownloadManifestV1 } from "./session-record.js";
4
- export function buildSessionArchive(sessionId, session, events, files) {
5
- const submissionSnapshot = extractSubmissionSnapshot(session);
6
- const costTelemetry = extractCostTelemetry(session);
7
- const manifest = buildSessionRecordDownloadManifestV1({
8
- sessionId,
9
- sessionFiles: files.captured,
10
- errors: files.errors,
11
- typedEventCount: events.length,
12
- ...(submissionSnapshot ? { submission: { status: "present" } } : {}),
13
- ...(costTelemetry ? { cost: { status: "present" } } : {})
14
- });
15
- return zipEntries([
16
- jsonEntry("metadata/session.json", session),
17
- ...(submissionSnapshot ? [jsonEntry("metadata/submission.json", submissionSnapshot)] : []),
18
- ...(costTelemetry ? [jsonEntry("metadata/cost.json", costTelemetry)] : []),
19
- jsonlEntry("events/events.jsonl", events),
20
- ...files.entries,
21
- jsonEntry("manifest.json", manifest)
22
- ]);
23
- }
24
- export function buildSessionFilesArchive(sessionId, files) {
25
- return zipEntries([
26
- ...files.entries,
27
- jsonEntry("manifest.json", {
28
- sessionId,
29
- namespace: "files",
30
- files: files.captured,
31
- errors: files.errors
32
- })
33
- ]);
34
- }
35
- export function buildSessionEventsArchive(sessionId, events) {
36
- return zipEntries([
37
- jsonlEntry("events.jsonl", events),
38
- jsonEntry("manifest.json", {
39
- sessionId,
40
- namespace: "events",
41
- files: [{ path: "events.jsonl", role: "typed_events", status: "present", recordCount: events.length }],
42
- errors: []
43
- })
44
- ]);
45
- }
46
- export function buildSessionMetadataArchive(sessionId, session) {
47
- return zipEntries([
48
- jsonEntry("session.json", session),
49
- jsonEntry("manifest.json", {
50
- sessionId,
51
- namespace: "metadata",
52
- files: [{ path: "session.json", role: "session_metadata", status: "present" }],
53
- errors: []
54
- })
55
- ]);
56
- }
57
- function zipEntries(entries) {
58
- assertSessionRecordArchivePublicSafeV1(entries);
59
- const files = {};
60
- for (const entry of entries) {
61
- files[entry.path] = [entry.bytes, { mtime: ZIP_EPOCH }];
62
- }
63
- return zipSync(files);
64
- }
65
- /** Fixed ZIP timestamp: session archives must not depend on the wall clock. */
66
- const ZIP_EPOCH = new Date(Date.UTC(1980, 0, 1));
67
- function jsonEntry(path, value) {
68
- return {
69
- path,
70
- bytes: strToU8(JSON.stringify(value, null, 2)),
71
- contentType: "application/json; charset=utf-8"
72
- };
73
- }
74
- function jsonlEntry(path, events) {
75
- return {
76
- path,
77
- bytes: strToU8(events.map((event) => JSON.stringify(event)).join("\n")),
78
- contentType: "application/jsonl; charset=utf-8"
79
- };
80
- }
81
- function extractSubmissionSnapshot(session) {
82
- const raw = session.submission;
83
- if (!isRecord(raw) || raw.kind !== "submission" || !isRecord(raw.submission)) {
84
- return undefined;
85
- }
86
- return {
87
- submission: raw.submission
88
- };
89
- }
90
- function extractCostTelemetry(session) {
91
- return session.costTelemetry;
92
- }