@aexhq/sdk 0.40.4 → 0.40.6

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 (77) hide show
  1. package/README.md +159 -159
  2. package/dist/_contracts/api-key.js +0 -1
  3. package/dist/_contracts/bundle-manifest.js +0 -1
  4. package/dist/_contracts/connection-ticket.js +0 -1
  5. package/dist/_contracts/error-codes.js +0 -1
  6. package/dist/_contracts/error-factory.js +0 -1
  7. package/dist/_contracts/event-envelope.js +0 -1
  8. package/dist/_contracts/event-stream-client.js +0 -1
  9. package/dist/_contracts/event-view.js +0 -1
  10. package/dist/_contracts/http.js +0 -1
  11. package/dist/_contracts/index.js +0 -1
  12. package/dist/_contracts/internal.d.ts +36 -0
  13. package/dist/_contracts/internal.js +155 -6
  14. package/dist/_contracts/models.js +0 -1
  15. package/dist/_contracts/operations.js +1 -2
  16. package/dist/_contracts/post-hook.js +0 -1
  17. package/dist/_contracts/provider-support.js +0 -1
  18. package/dist/_contracts/run-artifacts.js +0 -1
  19. package/dist/_contracts/run-config.js +0 -1
  20. package/dist/_contracts/run-cost.js +0 -1
  21. package/dist/_contracts/run-custody.js +0 -1
  22. package/dist/_contracts/run-record.js +0 -1
  23. package/dist/_contracts/run-retention.js +0 -1
  24. package/dist/_contracts/run-trace.js +0 -1
  25. package/dist/_contracts/run-unit.js +0 -1
  26. package/dist/_contracts/runner-event.js +0 -1
  27. package/dist/_contracts/runtime-manifest.js +0 -1
  28. package/dist/_contracts/runtime-security-profile.js +0 -1
  29. package/dist/_contracts/runtime-sizes.js +0 -1
  30. package/dist/_contracts/runtime-types.js +0 -1
  31. package/dist/_contracts/sdk-errors.js +0 -1
  32. package/dist/_contracts/sdk-secrets.js +0 -1
  33. package/dist/_contracts/side-effect-audit.js +0 -1
  34. package/dist/_contracts/sse.js +0 -0
  35. package/dist/_contracts/stable.js +0 -1
  36. package/dist/_contracts/status.js +0 -1
  37. package/dist/_contracts/submission.js +0 -1
  38. package/dist/_contracts/suggest.js +0 -1
  39. package/dist/_contracts/webhook-verify.js +0 -1
  40. package/dist/asset-upload.d.ts +3 -43
  41. package/dist/asset-upload.js +1 -109
  42. package/dist/asset-upload.js.map +1 -1
  43. package/dist/cli.mjs +354 -781
  44. package/dist/cli.mjs.sha256 +1 -1
  45. package/dist/fetch-archive.js +76 -16
  46. package/dist/fetch-archive.js.map +1 -1
  47. package/dist/version.d.ts +1 -1
  48. package/dist/version.js +1 -1
  49. package/docs/authentication.md +125 -125
  50. package/docs/billing.md +118 -118
  51. package/docs/concepts/agent-tools.md +66 -66
  52. package/docs/concepts/composition.md +37 -37
  53. package/docs/concepts/providers-and-runtimes.md +54 -54
  54. package/docs/concepts/runs.md +49 -49
  55. package/docs/concepts/subagents.md +88 -88
  56. package/docs/credentials.md +125 -125
  57. package/docs/defaults.md +64 -64
  58. package/docs/errors.md +196 -196
  59. package/docs/events.md +243 -243
  60. package/docs/limits-and-quotas.md +144 -144
  61. package/docs/limits.md +50 -50
  62. package/docs/mcp.md +44 -44
  63. package/docs/networking.md +163 -163
  64. package/docs/outputs.md +267 -267
  65. package/docs/public-surface.json +77 -77
  66. package/docs/quickstart.md +119 -119
  67. package/docs/release.md +38 -38
  68. package/docs/retries.md +129 -129
  69. package/docs/run-config.md +58 -58
  70. package/docs/run-record.md +55 -55
  71. package/docs/secrets.md +125 -130
  72. package/docs/testing.md +35 -35
  73. package/docs/vision-skills.md +91 -91
  74. package/docs/webhooks.md +127 -131
  75. package/examples/feature-tour.ts +282 -282
  76. package/examples/spike-settle-latency.ts +125 -125
  77. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -7,7 +7,7 @@ var __export = (target, all) => {
7
7
 
8
8
  // dist/cli.js
9
9
  import { readFile, writeFile, readdir, stat, mkdir, chmod, rm } from "node:fs/promises";
10
- import { resolve as resolvePath5, join, dirname as dirname2 } from "node:path";
10
+ import { resolve as resolvePath4, join, dirname } from "node:path";
11
11
  import { homedir } from "node:os";
12
12
 
13
13
  // ../contracts/dist/provider-support.js
@@ -1489,12 +1489,12 @@ function namespace(name, description) {
1489
1489
  description
1490
1490
  });
1491
1491
  }
1492
- function file(namespaceName, path, role, status2, extra) {
1492
+ function file(namespaceName, path, role, status, extra) {
1493
1493
  return Object.freeze({
1494
1494
  namespace: namespaceName,
1495
1495
  path,
1496
1496
  role,
1497
- status: status2,
1497
+ status,
1498
1498
  ...extra?.recordCount !== void 0 ? { recordCount: extra.recordCount } : {}
1499
1499
  });
1500
1500
  }
@@ -1820,9 +1820,9 @@ var RunStateError = class extends AexError {
1820
1820
  const detailRecord = details && typeof details === "object" && !Array.isArray(details) ? details : void 0;
1821
1821
  const cause = options?.cause ?? detailRecord?.cause;
1822
1822
  super("RUN_STATE_ERROR", message, details, cause === void 0 ? void 0 : { cause });
1823
- const status2 = detailRecord?.httpStatus ?? detailRecord?.status;
1823
+ const status = detailRecord?.httpStatus ?? detailRecord?.status;
1824
1824
  const apiCode = detailRecord?.apiCode;
1825
- this.status = typeof status2 === "number" ? status2 : void 0;
1825
+ this.status = typeof status === "number" ? status : void 0;
1826
1826
  this.apiCode = isAexApiErrorCode(apiCode) ? apiCode : void 0;
1827
1827
  this.requestId = typeof detailRecord?.requestId === "string" ? detailRecord.requestId : void 0;
1828
1828
  }
@@ -1834,9 +1834,9 @@ var AexApiError = class extends AexError {
1834
1834
  apiCode;
1835
1835
  /** Request id (body `requestId` or a response header) for support correlation. */
1836
1836
  requestId;
1837
- constructor(status2, message, body, options) {
1837
+ constructor(status, message, body, options) {
1838
1838
  super("API_ERROR", message, body, options?.cause === void 0 ? void 0 : { cause: options.cause });
1839
- this.status = status2;
1839
+ this.status = status;
1840
1840
  this.body = redactSecrets(body);
1841
1841
  this.apiCode = options?.apiCode;
1842
1842
  this.requestId = options?.requestId;
@@ -2003,14 +2003,14 @@ function apiErrorKindForCode(code) {
2003
2003
  return "generic";
2004
2004
  }
2005
2005
  }
2006
- function kindForStatus(status2) {
2007
- if (status2 === 401 || status2 === 403)
2006
+ function kindForStatus(status) {
2007
+ if (status === 401 || status === 403)
2008
2008
  return "auth";
2009
- if (status2 === 404)
2009
+ if (status === 404)
2010
2010
  return "not_found";
2011
- if (status2 === 409)
2011
+ if (status === 409)
2012
2012
  return "idempotency";
2013
- if (status2 === 429)
2013
+ if (status === 429)
2014
2014
  return "rate_limit";
2015
2015
  return "generic";
2016
2016
  }
@@ -2120,8 +2120,8 @@ var HttpClient = class {
2120
2120
  this.#debug = options.debug;
2121
2121
  }
2122
2122
  /** Emit a redacted round-trip trace (no auth header, body, or query). */
2123
- #trace(method, url, status2, startedMs) {
2124
- this.#debug?.(`[aex] ${(method ?? "GET").toUpperCase()} ${url.pathname} -> ${status2} ${Date.now() - startedMs}ms`);
2123
+ #trace(method, url, status, startedMs) {
2124
+ this.#debug?.(`[aex] ${(method ?? "GET").toUpperCase()} ${url.pathname} -> ${status} ${Date.now() - startedMs}ms`);
2125
2125
  }
2126
2126
  async request(path, init = {}, query = {}) {
2127
2127
  const url = new URL(path.replace(/^\//, ""), this.#baseUrl);
@@ -2238,9 +2238,9 @@ function extractErrorMessage(body) {
2238
2238
  if (body && typeof body === "object") {
2239
2239
  const obj = body;
2240
2240
  if (typeof obj.error === "string") {
2241
- const status2 = body.status;
2242
- if (obj.error === "session_busy" && typeof status2 === "string") {
2243
- return `session_busy (session status: ${status2})`;
2241
+ const status = body.status;
2242
+ if (obj.error === "session_busy" && typeof status === "string") {
2243
+ return `session_busy (session status: ${status})`;
2244
2244
  }
2245
2245
  if (typeof obj.message === "string" && obj.message.length > 0 && obj.message !== obj.error) {
2246
2246
  return `${obj.error}: ${obj.message}`;
@@ -3375,7 +3375,7 @@ async function readCappedText(response, maxBytes) {
3375
3375
  });
3376
3376
  }
3377
3377
  const merged = concatBytes(chunks).subarray(0, maxBytes);
3378
- const truncated = declared !== void 0 ? declared > maxBytes : sawMore;
3378
+ const truncated = declared !== void 0 ? declared > maxBytes : read > maxBytes || sawMore;
3379
3379
  const totalBytes = declared ?? read;
3380
3380
  return { text: decoder.decode(merged), truncated, totalBytes };
3381
3381
  }
@@ -3898,11 +3898,11 @@ var USAGE_ERR = { code: 2 };
3898
3898
  var RUNTIME_ERR = { code: 1 };
3899
3899
  var TIMEOUT_ERR = { code: 3 };
3900
3900
  var TERMINAL_STATUSES = new Set(TERMINAL_RUN_STATUSES);
3901
- function isSessionParked2(status2) {
3902
- return status2 === "idle" || status2 === "suspended" || status2 === "error" || TERMINAL_STATUSES.has(status2);
3901
+ function isSessionParked2(status) {
3902
+ return status === "idle" || status === "suspended" || status === "error" || TERMINAL_STATUSES.has(status);
3903
3903
  }
3904
- function isSessionOk(status2) {
3905
- return status2 === "idle" || status2 === "suspended" || status2 === "succeeded";
3904
+ function isSessionOk(status) {
3905
+ return status === "idle" || status === "suspended" || status === "succeeded";
3906
3906
  }
3907
3907
  function extractCommonHostFlags(argv) {
3908
3908
  let apiKey = null;
@@ -3944,6 +3944,16 @@ function extractCommonHostFlags(argv) {
3944
3944
  }
3945
3945
  return { ok: true, flags: { apiKey, aexUrl, debug: debug2, json, rest } };
3946
3946
  }
3947
+ function rejectUnknownFlags(io2, rest, usage) {
3948
+ const unknown = rest.find((arg) => arg.startsWith("--"));
3949
+ if (unknown === void 0)
3950
+ return null;
3951
+ io2.stderr(`unknown flag: ${unknown}
3952
+ `);
3953
+ io2.stderr(`${usage}
3954
+ `);
3955
+ return USAGE_ERR;
3956
+ }
3947
3957
  async function resolveCommonHostFlags(io2, argv) {
3948
3958
  const extracted = extractCommonHostFlags(argv);
3949
3959
  if (!extracted.ok)
@@ -4010,18 +4020,18 @@ function describeErrorBody(body) {
4010
4020
  const redacted = redactSecrets(text);
4011
4021
  return redacted.length > 400 ? `${redacted.slice(0, 400)}\u2026 (truncated)` : redacted;
4012
4022
  }
4013
- function remedyForStatus(status2) {
4014
- if (status2 === 400)
4023
+ function remedyForStatus(status) {
4024
+ if (status === 400)
4015
4025
  return "malformed request \u2014 if this is an auth failure, check --api-key or run `aex login`";
4016
- if (status2 === 401)
4026
+ if (status === 401)
4017
4027
  return "check --api-key, or run `aex login`";
4018
- if (status2 === 403)
4028
+ if (status === 403)
4019
4029
  return "token lacks permission for this workspace/action";
4020
- if (status2 === 404)
4030
+ if (status === 404)
4021
4031
  return "no such run/resource \u2014 verify the id";
4022
- if (status2 === 429)
4032
+ if (status === 429)
4023
4033
  return "rate limited \u2014 retry with backoff";
4024
- if (status2 >= 500)
4034
+ if (status >= 500)
4025
4035
  return "server error \u2014 retry; re-run with --debug to capture the request trace";
4026
4036
  return void 0;
4027
4037
  }
@@ -4425,11 +4435,6 @@ var CLI_VERBS = [
4425
4435
  name: "runtime-sizes",
4426
4436
  summary: "List managed runtime presets (no token needed).",
4427
4437
  usage: ["aex runtime-sizes list [--json]"]
4428
- },
4429
- {
4430
- name: "debug",
4431
- summary: "Operator: read the AWS plane directly (AWS creds, not --api-key).",
4432
- usage: ["aex debug <run-id> [--plane dev|prd] [--region eu-west-2] [--cloudwatch] [--with-outputs]"]
4433
4438
  }
4434
4439
  ];
4435
4440
  var VERB_BY_NAME = new Map(CLI_VERBS.map((v) => [v.name, v]));
@@ -4451,6 +4456,147 @@ function renderVerbHelp(spec) {
4451
4456
  // dist/host/run-cmd.js
4452
4457
  import { resolve as resolvePath } from "node:path";
4453
4458
 
4459
+ // ../contracts/dist/post-hook.js
4460
+ var DEFAULT_POST_HOOK_TIMEOUT_MS = 5 * 60 * 1e3;
4461
+
4462
+ // ../contracts/dist/internal.js
4463
+ var DIRECT_UPLOAD_MAX_ATTEMPTS = 3;
4464
+ async function uploadAsset(args) {
4465
+ const expected = args.hash.startsWith("sha256:") ? args.hash.slice("sha256:".length) : args.hash;
4466
+ const actual = await computeSha256Hex(args.bytes);
4467
+ if (actual !== expected) {
4468
+ throw new Error(`uploadAsset: client-side hash mismatch: computed sha256:${actual} but caller declared ${args.hash}. Aborting to avoid uploading corrupted data.`);
4469
+ }
4470
+ const contentHashHeader = `sha256:${actual}`;
4471
+ const presign = await args.http.request("/assets/presign", {
4472
+ method: "POST",
4473
+ headers: { "content-type": "application/json" },
4474
+ body: JSON.stringify({ hash: contentHashHeader, sizeBytes: args.bytes.byteLength })
4475
+ });
4476
+ if (presign.exists) {
4477
+ const contentHash2 = presign.contentHash ?? contentHashHeader;
4478
+ return {
4479
+ assetId: presign.assetId ?? assetIdFromContentHash(contentHash2),
4480
+ contentHash: contentHash2,
4481
+ sizeBytes: presign.sizeBytes ?? args.bytes.byteLength,
4482
+ exists: true
4483
+ };
4484
+ }
4485
+ if (!presign.uploadUrl) {
4486
+ throw new Error("uploadAsset: presign returned no uploadUrl and exists:false");
4487
+ }
4488
+ const doFetch = args.fetch ?? globalThis.fetch;
4489
+ const putHeaders = {
4490
+ "content-type": args.contentType ?? "application/zip",
4491
+ ...presign.requiredHeaders ?? {}
4492
+ };
4493
+ await putWithRetry(doFetch, presign.uploadUrl, {
4494
+ method: "PUT",
4495
+ headers: putHeaders,
4496
+ body: args.bytes
4497
+ });
4498
+ const fin = await args.http.request("/assets/finalize", {
4499
+ method: "POST",
4500
+ headers: { "content-type": "application/json" },
4501
+ body: JSON.stringify({ hash: contentHashHeader, sizeBytes: args.bytes.byteLength })
4502
+ });
4503
+ const contentHash = fin.contentHash ?? presign.contentHash ?? contentHashHeader;
4504
+ return {
4505
+ assetId: fin.assetId ?? presign.assetId ?? assetIdFromContentHash(contentHash),
4506
+ contentHash,
4507
+ sizeBytes: fin.sizeBytes ?? args.bytes.byteLength,
4508
+ exists: false
4509
+ };
4510
+ }
4511
+ async function computeSha256Hex(bytes) {
4512
+ const subtle = globalThis.crypto?.subtle;
4513
+ if (!subtle) {
4514
+ throw new Error("uploadAsset: globalThis.crypto.subtle is not available; Bun, Node 18+, or a Web-Crypto-capable runtime is required");
4515
+ }
4516
+ const digest = await subtle.digest("SHA-256", bytes);
4517
+ return bufferToHex(digest);
4518
+ }
4519
+ function assetIdFromContentHash(contentHash) {
4520
+ const hex = contentHash.startsWith("sha256:") ? contentHash.slice("sha256:".length) : contentHash;
4521
+ return `asset_${hex}`;
4522
+ }
4523
+ async function putWithRetry(fetchImpl, uploadUrl, init) {
4524
+ for (let attempt = 1; attempt <= DIRECT_UPLOAD_MAX_ATTEMPTS; attempt++) {
4525
+ let response;
4526
+ try {
4527
+ response = await fetchImpl(uploadUrl, init);
4528
+ } catch (err2) {
4529
+ if (attempt < DIRECT_UPLOAD_MAX_ATTEMPTS && isRetryableUploadError(err2)) {
4530
+ continue;
4531
+ }
4532
+ throw directUploadNetworkError(uploadUrl, err2, attempt);
4533
+ }
4534
+ if (response.ok)
4535
+ return;
4536
+ if (attempt < DIRECT_UPLOAD_MAX_ATTEMPTS && isRetryableUploadStatus(response.status)) {
4537
+ await response.text().catch(() => "");
4538
+ continue;
4539
+ }
4540
+ const detail = await response.text().catch(() => "");
4541
+ throw directUploadResponseError(uploadUrl, response.status, detail, attempt);
4542
+ }
4543
+ }
4544
+ function isRetryableUploadStatus(status) {
4545
+ return status === 408 || status === 425 || status === 429 || status >= 500 && status <= 599;
4546
+ }
4547
+ function isRetryableUploadError(err2) {
4548
+ if (isNamedError(err2, "AbortError"))
4549
+ return false;
4550
+ return true;
4551
+ }
4552
+ function directUploadNetworkError(uploadUrl, err2, attempts) {
4553
+ const safeUrl = redactUrl(uploadUrl);
4554
+ const code = extractErrorCode(err2);
4555
+ const detail = sanitizeUploadText(errorMessage(err2)).slice(0, 500);
4556
+ return new Error(`uploadAsset: direct upload PUT failed for ${safeUrl} after ${attemptsLabel(attempts)}` + (code ? ` (${code})` : "") + (detail ? `: ${detail}` : ""));
4557
+ }
4558
+ function directUploadResponseError(uploadUrl, status, detail, attempts) {
4559
+ const safeUrl = redactUrl(uploadUrl);
4560
+ const safeDetail = sanitizeUploadText(detail).slice(0, 500);
4561
+ return new Error(`uploadAsset: direct upload PUT failed for ${safeUrl} with status ${status}` + (attempts > 1 ? ` after ${attemptsLabel(attempts)}` : "") + (safeDetail ? `: ${safeDetail}` : ""));
4562
+ }
4563
+ function attemptsLabel(attempts) {
4564
+ return attempts === 1 ? "1 attempt" : `${attempts} attempts`;
4565
+ }
4566
+ function errorMessage(err2) {
4567
+ if (err2 instanceof Error)
4568
+ return err2.message || err2.name;
4569
+ if (typeof err2 === "string")
4570
+ return err2;
4571
+ return String(err2);
4572
+ }
4573
+ function isNamedError(err2, name) {
4574
+ return stringProperty2(err2, "name") === name;
4575
+ }
4576
+ function stringProperty2(value, key) {
4577
+ if (!value || typeof value !== "object")
4578
+ return void 0;
4579
+ const prop = value[key];
4580
+ return typeof prop === "string" && prop.length > 0 ? prop : void 0;
4581
+ }
4582
+ function sanitizeUploadText(text) {
4583
+ return text.replace(/https?:\/\/[^\s<>"'`]+/g, (raw) => redactUrlPreservingTrailingPunctuation(raw)).replace(/\b(?:X-Amz-(?:Algorithm|Credential|Date|Expires|Security-Token|Signature|SignedHeaders)|AWSAccessKeyId|Signature|Credential|Security-Token|AccessKeyId|SecretAccessKey|SessionToken)=([^&\s<>"'`]+)/gi, "[redacted]").replace(/\bAKIA[0-9A-Z]{8,}\b/g, "[redacted]");
4584
+ }
4585
+ function redactUrlPreservingTrailingPunctuation(raw) {
4586
+ const trailing = raw.match(/[),.;:!?]+$/)?.[0] ?? "";
4587
+ const candidate = trailing ? raw.slice(0, -trailing.length) : raw;
4588
+ return `${redactUrl(candidate)}${trailing}`;
4589
+ }
4590
+ function bufferToHex(buffer) {
4591
+ const view = new Uint8Array(buffer);
4592
+ let out = "";
4593
+ for (let i2 = 0; i2 < view.length; i2++) {
4594
+ const byte = view[i2];
4595
+ out += byte.toString(16).padStart(2, "0");
4596
+ }
4597
+ return out;
4598
+ }
4599
+
4454
4600
  // dist/host/run-submit.js
4455
4601
  var TEXT = new TextEncoder();
4456
4602
  var ZIP_EPOCH = new Date(Date.UTC(1980, 0, 1));
@@ -4615,7 +4761,7 @@ async function prepareTools(http, fetchImpl, tools) {
4615
4761
  }
4616
4762
  return { kind: "builtin", name: entry };
4617
4763
  }
4618
- const uploaded = await uploadAsset(http, fetchImpl, {
4764
+ const uploaded = await stageAsset(http, fetchImpl, {
4619
4765
  bytes: entry.bytes,
4620
4766
  hash: entry.ref.contentHash,
4621
4767
  contentType: "application/zip"
@@ -4650,7 +4796,7 @@ async function prepareSkills(http, fetchImpl, skills) {
4650
4796
  seen.add(skill.name);
4651
4797
  }
4652
4798
  return mapWithConcurrency(skills, UPLOAD_CONCURRENCY, async (skill) => {
4653
- await uploadAsset(http, fetchImpl, { bytes: skill.bytes, hash: skill.contentHash, contentType: "application/zip" });
4799
+ await stageAsset(http, fetchImpl, { bytes: skill.bytes, hash: skill.contentHash, contentType: "application/zip" });
4654
4800
  await operations_exports.upsertSkill(http, {
4655
4801
  name: skill.name,
4656
4802
  contentHash: skill.contentHash,
@@ -4662,7 +4808,7 @@ async function prepareSkills(http, fetchImpl, skills) {
4662
4808
  }
4663
4809
  async function prepareAgentsMd(http, fetchImpl, agentsMds) {
4664
4810
  return mapWithConcurrency(agentsMds, UPLOAD_CONCURRENCY, async (entry) => {
4665
- const uploaded = await uploadAsset(http, fetchImpl, {
4811
+ const uploaded = await stageAsset(http, fetchImpl, {
4666
4812
  bytes: entry.bytes,
4667
4813
  hash: entry.contentHash,
4668
4814
  contentType: "application/zip"
@@ -4672,7 +4818,7 @@ async function prepareAgentsMd(http, fetchImpl, agentsMds) {
4672
4818
  }
4673
4819
  async function prepareFiles(http, fetchImpl, files) {
4674
4820
  return mapWithConcurrency(files, UPLOAD_CONCURRENCY, async (entry) => {
4675
- const uploaded = await uploadAsset(http, fetchImpl, {
4821
+ const uploaded = await stageAsset(http, fetchImpl, {
4676
4822
  bytes: entry.bytes,
4677
4823
  hash: entry.contentHash,
4678
4824
  contentType: "application/zip"
@@ -4701,54 +4847,14 @@ function sessionEnvironmentForWire(environment) {
4701
4847
  };
4702
4848
  return Object.keys(out).length === 0 ? void 0 : out;
4703
4849
  }
4704
- async function uploadAsset(http, fetchImpl, args) {
4705
- const expected = args.hash.startsWith("sha256:") ? args.hash.slice("sha256:".length) : args.hash;
4706
- const actual = await sha256Hex(args.bytes);
4707
- if (actual !== expected) {
4708
- throw new Error(`uploadAsset: client-side hash mismatch: computed sha256:${actual} but caller declared ${args.hash}`);
4709
- }
4710
- const contentHash = `sha256:${actual}`;
4711
- const presign = await http.request("/assets/presign", {
4712
- method: "POST",
4713
- headers: { "content-type": "application/json" },
4714
- body: JSON.stringify({ hash: contentHash, sizeBytes: args.bytes.byteLength })
4715
- });
4716
- if (presign.exists) {
4717
- const storedHash2 = presign.contentHash ?? contentHash;
4718
- return {
4719
- assetId: presign.assetId ?? assetIdFromContentHash(storedHash2),
4720
- contentHash: storedHash2,
4721
- sizeBytes: presign.sizeBytes ?? args.bytes.byteLength,
4722
- exists: true
4723
- };
4724
- }
4725
- if (!presign.uploadUrl) {
4726
- throw new Error("uploadAsset: presign returned no uploadUrl and exists:false");
4727
- }
4728
- const doFetch = fetchImpl ?? globalThis.fetch;
4729
- const put = await doFetch(presign.uploadUrl, {
4730
- method: "PUT",
4731
- headers: {
4732
- "content-type": args.contentType ?? "application/zip",
4733
- ...presign.requiredHeaders ?? {}
4734
- },
4735
- body: args.bytes
4736
- });
4737
- if (!put.ok) {
4738
- throw new Error(`uploadAsset: direct upload PUT failed with status ${put.status}`);
4739
- }
4740
- const fin = await http.request("/assets/finalize", {
4741
- method: "POST",
4742
- headers: { "content-type": "application/json" },
4743
- body: JSON.stringify({ hash: contentHash, sizeBytes: args.bytes.byteLength })
4850
+ async function stageAsset(http, fetchImpl, args) {
4851
+ return uploadAsset({
4852
+ http,
4853
+ bytes: args.bytes,
4854
+ hash: args.hash,
4855
+ ...args.contentType !== void 0 ? { contentType: args.contentType } : {},
4856
+ ...fetchImpl !== void 0 ? { fetch: fetchImpl } : {}
4744
4857
  });
4745
- const storedHash = fin.contentHash ?? presign.contentHash ?? contentHash;
4746
- return {
4747
- assetId: fin.assetId ?? presign.assetId ?? assetIdFromContentHash(storedHash),
4748
- contentHash: storedHash,
4749
- sizeBytes: fin.sizeBytes ?? args.bytes.byteLength,
4750
- exists: false
4751
- };
4752
4858
  }
4753
4859
  function bundleSkillFiles(files) {
4754
4860
  const collected = collectBundleFiles("Skill bundle", files, true);
@@ -4913,9 +5019,9 @@ async function sha256Hex(bytes) {
4913
5019
  const view = new Uint8Array(bytes.byteLength);
4914
5020
  view.set(bytes);
4915
5021
  const digest = await subtle.digest("SHA-256", view.buffer);
4916
- return bufferToHex(digest);
5022
+ return bufferToHex2(digest);
4917
5023
  }
4918
- function bufferToHex(buffer) {
5024
+ function bufferToHex2(buffer) {
4919
5025
  const view = new Uint8Array(buffer);
4920
5026
  let out = "";
4921
5027
  for (const byte of view) {
@@ -4923,10 +5029,6 @@ function bufferToHex(buffer) {
4923
5029
  }
4924
5030
  return out;
4925
5031
  }
4926
- function assetIdFromContentHash(contentHash) {
4927
- const hex = contentHash.startsWith("sha256:") ? contentHash.slice("sha256:".length) : contentHash;
4928
- return `asset_${hex}`;
4929
- }
4930
5032
  async function mapWithConcurrency(items, limit, fn) {
4931
5033
  const out = new Array(items.length);
4932
5034
  let next = 0;
@@ -5642,9 +5744,14 @@ async function runStatusCmd(io2, argv) {
5642
5744
  `);
5643
5745
  return USAGE_ERR;
5644
5746
  }
5645
- const positional = common.rest.filter((arg) => !arg.startsWith("--"));
5747
+ const usage = "usage: aex status <session-id> [common flags]";
5748
+ const unknown = rejectUnknownFlags(io2, common.rest, usage);
5749
+ if (unknown)
5750
+ return unknown;
5751
+ const positional = common.rest;
5646
5752
  if (positional.length !== 1) {
5647
- io2.stderr("usage: aex status <session-id> [common flags]\n");
5753
+ io2.stderr(`${usage}
5754
+ `);
5648
5755
  return USAGE_ERR;
5649
5756
  }
5650
5757
  const sessionId = positional[0];
@@ -5673,9 +5780,14 @@ async function runDeliveriesCmd(io2, argv) {
5673
5780
  `);
5674
5781
  return USAGE_ERR;
5675
5782
  }
5676
- const positional = common.rest.filter((arg) => !arg.startsWith("--"));
5783
+ const usage = "usage: aex deliveries <session-id> [common flags]";
5784
+ const unknown = rejectUnknownFlags(io2, common.rest, usage);
5785
+ if (unknown)
5786
+ return unknown;
5787
+ const positional = common.rest;
5677
5788
  if (positional.length !== 1) {
5678
- io2.stderr("usage: aex deliveries <session-id> [common flags]\n");
5789
+ io2.stderr(`${usage}
5790
+ `);
5679
5791
  return USAGE_ERR;
5680
5792
  }
5681
5793
  const sessionId = positional[0];
@@ -5727,9 +5839,14 @@ async function runWaitCmd(io2, argv) {
5727
5839
  }
5728
5840
  intervalMs = parsed.ms;
5729
5841
  }
5730
- const positional = intervalFlag.remaining.filter((arg) => !arg.startsWith("--"));
5842
+ const usage = "usage: aex wait <session-id> [--timeout <dur>] [--interval <dur>] [common flags]";
5843
+ const unknown = rejectUnknownFlags(io2, intervalFlag.remaining, usage);
5844
+ if (unknown)
5845
+ return unknown;
5846
+ const positional = intervalFlag.remaining;
5731
5847
  if (positional.length !== 1) {
5732
- io2.stderr("usage: aex wait <session-id> [--timeout <dur>] [--interval <dur>] [common flags]\n");
5848
+ io2.stderr(`${usage}
5849
+ `);
5733
5850
  return USAGE_ERR;
5734
5851
  }
5735
5852
  const sessionId = positional[0];
@@ -5786,9 +5903,14 @@ async function runEventsCmd(io2, argv) {
5786
5903
  }
5787
5904
  timeoutMs = parsed.ms;
5788
5905
  }
5789
- const positional = timeoutFlag.remaining.filter((arg) => !arg.startsWith("--"));
5906
+ const usage = "usage: aex events <session-id> [--follow] [--timeout <dur>] [common flags]";
5907
+ const unknown = rejectUnknownFlags(io2, timeoutFlag.remaining, usage);
5908
+ if (unknown)
5909
+ return unknown;
5910
+ const positional = timeoutFlag.remaining;
5790
5911
  if (positional.length !== 1) {
5791
- io2.stderr("usage: aex events <session-id> [--follow] [--timeout <dur>] [common flags]\n");
5912
+ io2.stderr(`${usage}
5913
+ `);
5792
5914
  return USAGE_ERR;
5793
5915
  }
5794
5916
  const sessionId = positional[0];
@@ -5881,9 +6003,14 @@ async function runOutputsCmd(io2, argv) {
5881
6003
  }
5882
6004
  }
5883
6005
  async function outputsList(io2, http, args) {
5884
- const positional = args.filter((a) => !a.startsWith("--"));
6006
+ const usage = "usage: aex outputs <session-id> [common flags]";
6007
+ const unknown = rejectUnknownFlags(io2, args, usage);
6008
+ if (unknown)
6009
+ return unknown;
6010
+ const positional = args;
5885
6011
  if (positional.length !== 1) {
5886
- io2.stderr("usage: aex outputs <session-id> [common flags]\n");
6012
+ io2.stderr(`${usage}
6013
+ `);
5887
6014
  return USAGE_ERR;
5888
6015
  }
5889
6016
  const sessionId = positional[0];
@@ -5897,9 +6024,14 @@ async function outputsList(io2, http, args) {
5897
6024
  }
5898
6025
  }
5899
6026
  async function outputsRead(io2, http, args) {
5900
- const positional = args.filter((a) => !a.startsWith("--"));
6027
+ const usage = "usage: aex outputs read <session-id> <path> [common flags]";
6028
+ const unknown = rejectUnknownFlags(io2, args, usage);
6029
+ if (unknown)
6030
+ return unknown;
6031
+ const positional = args;
5901
6032
  if (positional.length !== 2) {
5902
- io2.stderr("usage: aex outputs read <session-id> <path> [common flags]\n");
6033
+ io2.stderr(`${usage}
6034
+ `);
5903
6035
  return USAGE_ERR;
5904
6036
  }
5905
6037
  const [sessionId, selector] = positional;
@@ -5919,9 +6051,14 @@ async function outputsDownload(io2, http, args, flags) {
5919
6051
  return USAGE_ERR;
5920
6052
  }
5921
6053
  void flags;
5922
- const positional = outFlag.remaining.filter((a) => !a.startsWith("--"));
6054
+ const usage = "usage: aex outputs download <session-id> <path> [--out file] [common flags]";
6055
+ const unknown = rejectUnknownFlags(io2, outFlag.remaining, usage);
6056
+ if (unknown)
6057
+ return unknown;
6058
+ const positional = outFlag.remaining;
5923
6059
  if (positional.length !== 2) {
5924
- io2.stderr("usage: aex outputs download <session-id> <path> [--out file] [common flags]\n");
6060
+ io2.stderr(`${usage}
6061
+ `);
5925
6062
  return USAGE_ERR;
5926
6063
  }
5927
6064
  const [sessionId, selector] = positional;
@@ -5941,9 +6078,14 @@ async function outputsDownload(io2, http, args, flags) {
5941
6078
  return SUCCESS;
5942
6079
  }
5943
6080
  async function outputsLink(io2, http, args) {
5944
- const positional = args.filter((a) => !a.startsWith("--"));
6081
+ const usage = "usage: aex outputs link <session-id> <path> [common flags]";
6082
+ const unknown = rejectUnknownFlags(io2, args, usage);
6083
+ if (unknown)
6084
+ return unknown;
6085
+ const positional = args;
5945
6086
  if (positional.length !== 2) {
5946
- io2.stderr("usage: aex outputs link <session-id> <path> [common flags]\n");
6087
+ io2.stderr(`${usage}
6088
+ `);
5947
6089
  return USAGE_ERR;
5948
6090
  }
5949
6091
  const [sessionId, selector] = positional;
@@ -5966,9 +6108,14 @@ async function outputsFind(io2, http, args) {
5966
6108
  `);
5967
6109
  return USAGE_ERR;
5968
6110
  }
5969
- const positional = contentType.remaining.filter((a) => !a.startsWith("--"));
6111
+ const usage = "usage: aex outputs find <session-id> [--name S] [--ext E] [--type T] [--content-type CT] [common flags]";
6112
+ const unknown = rejectUnknownFlags(io2, contentType.remaining, usage);
6113
+ if (unknown)
6114
+ return unknown;
6115
+ const positional = contentType.remaining;
5970
6116
  if (positional.length !== 1) {
5971
- io2.stderr("usage: aex outputs find <session-id> [--name S] [--ext E] [--type T] [--content-type CT] [common flags]\n");
6117
+ io2.stderr(`${usage}
6118
+ `);
5972
6119
  return USAGE_ERR;
5973
6120
  }
5974
6121
  const sessionId = positional[0];
@@ -5997,6 +6144,17 @@ async function outputsSearch(io2, http, args) {
5997
6144
  const err2 = query.error ?? name.error ?? ext.error ?? contentType.error ?? limit.error ?? runIds.error;
5998
6145
  if (err2) {
5999
6146
  io2.stderr(`${err2}
6147
+ `);
6148
+ return USAGE_ERR;
6149
+ }
6150
+ const usage = "usage: aex outputs search [--query S] [--name S] [--ext E] [--content-type CT] [--run-id ID] [--limit N] [common flags]";
6151
+ const unknown = rejectUnknownFlags(io2, runIds.remaining, usage);
6152
+ if (unknown)
6153
+ return unknown;
6154
+ if (runIds.remaining.length > 0) {
6155
+ io2.stderr(`unexpected arguments: ${runIds.remaining.join(" ")}
6156
+ `);
6157
+ io2.stderr(`${usage}
6000
6158
  `);
6001
6159
  return USAGE_ERR;
6002
6160
  }
@@ -6129,9 +6287,14 @@ async function runDownloadCmd(io2, argv) {
6129
6287
  return USAGE_ERR;
6130
6288
  }
6131
6289
  const namespace2 = onlyFlag.value;
6132
- const positional = onlyFlag.remaining.filter((arg) => !arg.startsWith("--"));
6290
+ const usage = "usage: aex download <session-id> [--only outputs|events|metadata] [--out path] [common flags]";
6291
+ const unknown = rejectUnknownFlags(io2, onlyFlag.remaining, usage);
6292
+ if (unknown)
6293
+ return unknown;
6294
+ const positional = onlyFlag.remaining;
6133
6295
  if (positional.length !== 1) {
6134
- io2.stderr("usage: aex download <session-id> [--only outputs|events|metadata] [--out path] [common flags]\n");
6296
+ io2.stderr(`${usage}
6297
+ `);
6135
6298
  return USAGE_ERR;
6136
6299
  }
6137
6300
  const sessionId = positional[0];
@@ -6175,9 +6338,14 @@ async function runCancelCmd(io2, argv) {
6175
6338
  `);
6176
6339
  return USAGE_ERR;
6177
6340
  }
6178
- const positional = common.rest.filter((arg) => !arg.startsWith("--"));
6341
+ const usage = "usage: aex cancel <session-id> [common flags]";
6342
+ const unknown = rejectUnknownFlags(io2, common.rest, usage);
6343
+ if (unknown)
6344
+ return unknown;
6345
+ const positional = common.rest;
6179
6346
  if (positional.length !== 1) {
6180
- io2.stderr("usage: aex cancel <session-id> [common flags]\n");
6347
+ io2.stderr(`${usage}
6348
+ `);
6181
6349
  return USAGE_ERR;
6182
6350
  }
6183
6351
  const sessionId = positional[0];
@@ -6206,9 +6374,14 @@ async function runDeleteCmd(io2, argv) {
6206
6374
  `);
6207
6375
  return USAGE_ERR;
6208
6376
  }
6209
- const positional = common.rest.filter((arg) => !arg.startsWith("--"));
6377
+ const usage = "usage: aex delete <session-id> [common flags]";
6378
+ const unknown = rejectUnknownFlags(io2, common.rest, usage);
6379
+ if (unknown)
6380
+ return unknown;
6381
+ const positional = common.rest;
6210
6382
  if (positional.length !== 1) {
6211
- io2.stderr("usage: aex delete <session-id> [common flags]\n");
6383
+ io2.stderr(`${usage}
6384
+ `);
6212
6385
  return USAGE_ERR;
6213
6386
  }
6214
6387
  const sessionId = positional[0];
@@ -6237,9 +6410,14 @@ async function runDeleteAssetCmd(io2, argv) {
6237
6410
  `);
6238
6411
  return USAGE_ERR;
6239
6412
  }
6240
- const positional = common.rest.filter((arg) => !arg.startsWith("--"));
6413
+ const usage = "usage: aex delete-asset <hash> [common flags]";
6414
+ const unknown = rejectUnknownFlags(io2, common.rest, usage);
6415
+ if (unknown)
6416
+ return unknown;
6417
+ const positional = common.rest;
6241
6418
  if (positional.length !== 1) {
6242
- io2.stderr("usage: aex delete-asset <hash> [common flags]\n");
6419
+ io2.stderr(`${usage}
6420
+ `);
6243
6421
  return USAGE_ERR;
6244
6422
  }
6245
6423
  const hash = positional[0];
@@ -6565,645 +6743,6 @@ async function runSessionsCmd(io2, argv) {
6565
6743
  }
6566
6744
  }
6567
6745
 
6568
- // dist/host/debug.js
6569
- import { dirname, resolve as resolvePath4 } from "node:path";
6570
- function status(source, state, opts = {}) {
6571
- return {
6572
- source,
6573
- state,
6574
- ...opts.detail !== void 0 ? { detail: opts.detail } : {},
6575
- ...opts.count !== void 0 ? { count: opts.count } : {}
6576
- };
6577
- }
6578
- function seqOf(v) {
6579
- if (typeof v === "number" && Number.isFinite(v))
6580
- return v;
6581
- if (typeof v === "string" && /^\d+$/.test(v))
6582
- return Number(v);
6583
- return Number.POSITIVE_INFINITY;
6584
- }
6585
- function sortJournal(events) {
6586
- return events.map((e, i2) => ({ e, i: i2 })).sort((a, b) => {
6587
- const d = seqOf(a.e.seq) - seqOf(b.e.seq);
6588
- return d !== 0 ? d : a.i - b.i;
6589
- }).map((x2) => x2.e);
6590
- }
6591
- function parseNdjson(text) {
6592
- const out = [];
6593
- for (const line of text.split("\n")) {
6594
- const trimmed = line.trim();
6595
- if (!trimmed)
6596
- continue;
6597
- try {
6598
- const parsed = JSON.parse(trimmed);
6599
- if (parsed && typeof parsed === "object")
6600
- out.push(parsed);
6601
- } catch {
6602
- }
6603
- }
6604
- return out;
6605
- }
6606
- var CHILD_ID_KEYS = ["childRunId", "subagentRunId", "spawnedRunId", "child_run_id", "subagent_run_id"];
6607
- function extractChildRunIds(events, selfRunId) {
6608
- const ids = /* @__PURE__ */ new Set();
6609
- const scan = (node) => {
6610
- if (!node || typeof node !== "object")
6611
- return;
6612
- if (Array.isArray(node)) {
6613
- for (const v of node)
6614
- scan(v);
6615
- return;
6616
- }
6617
- const rec = node;
6618
- for (const k of CHILD_ID_KEYS) {
6619
- const v = rec[k];
6620
- if (typeof v === "string" && v && v !== selfRunId)
6621
- ids.add(v);
6622
- }
6623
- for (const v of Object.values(rec))
6624
- scan(v);
6625
- };
6626
- for (const e of events)
6627
- scan(e);
6628
- return [...ids];
6629
- }
6630
- function parseJsonObj(text) {
6631
- if (!text)
6632
- return {};
6633
- try {
6634
- const parsed = JSON.parse(text);
6635
- return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
6636
- } catch {
6637
- return {};
6638
- }
6639
- }
6640
- function pickStr(obj, keys) {
6641
- for (const k of keys) {
6642
- const v = obj[k];
6643
- if (typeof v === "string" && v)
6644
- return v;
6645
- }
6646
- return null;
6647
- }
6648
- function pickTime(obj, keys) {
6649
- for (const k of keys) {
6650
- const v = obj[k];
6651
- if (typeof v === "string" && v)
6652
- return v;
6653
- if (typeof v === "number" && Number.isFinite(v))
6654
- return new Date(v).toISOString();
6655
- }
6656
- return null;
6657
- }
6658
- function extractRunMeta(settleText, bootText) {
6659
- const settle = parseJsonObj(settleText);
6660
- const boot = parseJsonObj(bootText);
6661
- return {
6662
- status: pickStr(settle, ["status", "runStatus", "outcome", "state", "terminalStatus"]) ?? pickStr(boot, ["status"]),
6663
- startedAt: pickTime(boot, ["startedAt", "createdAt", "bootAt", "queuedAt"]) ?? pickTime(settle, ["startedAt", "createdAt"]),
6664
- endedAt: pickTime(settle, ["endedAt", "finishedAt", "terminalAt", "settledAt", "completedAt", "ts"])
6665
- };
6666
- }
6667
- function renderIndexMd(m, depth = 0) {
6668
- const lines = [];
6669
- const h = "#".repeat(Math.min(depth + 1, 6));
6670
- const sub = "#".repeat(Math.min(depth + 2, 6));
6671
- lines.push(`${h} aex debug bundle \u2014 ${m.runId}`, "");
6672
- lines.push(`- generated: ${m.generatedAt}`);
6673
- lines.push(`- plane / region: ${m.plane} / ${m.region}`);
6674
- lines.push(`- run status: ${m.runStatus ?? "unknown"}`);
6675
- lines.push(`- started: ${m.startedAt ?? "?"} ended: ${m.endedAt ?? "?"}`);
6676
- lines.push(`- journal: ${m.journalSource} (${m.journalEventCount} events)`);
6677
- lines.push(`- outputs bucket: ${m.outputsBucket}`, "");
6678
- lines.push(`${sub} sources`, "");
6679
- lines.push("| source | state | detail | count |");
6680
- lines.push("|---|---|---|---|");
6681
- for (const s of m.sources) {
6682
- lines.push(`| ${s.source} | ${s.state} | ${(s.detail ?? "").replace(/\|/g, "\\|")} | ${s.count ?? ""} |`);
6683
- }
6684
- lines.push("");
6685
- if (m.childRunIds.length > 0) {
6686
- lines.push(`${sub} child runs (${m.childRunIds.length})`, "");
6687
- for (const c of m.childRunIds)
6688
- lines.push(`- ${c} \u2192 children/${c}/`);
6689
- lines.push("");
6690
- for (const cm of m.children)
6691
- lines.push(renderIndexMd(cm, depth + 1), "");
6692
- }
6693
- return lines.join("\n");
6694
- }
6695
- async function assembleBundle(opts) {
6696
- const flags = { cloudwatch: opts.cloudwatch, withOutputs: opts.withOutputs, sinceMs: opts.sinceMs };
6697
- return assembleOne(opts.runId, opts.targets, opts.sources, flags, opts.visited ?? /* @__PURE__ */ new Set());
6698
- }
6699
- async function safeGetText(sources, bucket, key) {
6700
- try {
6701
- return await sources.getObjectText(bucket, key);
6702
- } catch {
6703
- return null;
6704
- }
6705
- }
6706
- async function assembleOne(runId, targets, sources, flags, visited) {
6707
- visited.add(runId);
6708
- const files = [];
6709
- const statuses = [];
6710
- const prefix = `runs/${runId}/`;
6711
- let listing = [];
6712
- let s3Error = null;
6713
- try {
6714
- listing = await sources.listObjects(targets.outputsBucket, prefix);
6715
- } catch (err2) {
6716
- s3Error = err2.message ?? "list failed";
6717
- }
6718
- files.push({
6719
- path: "s3-listing.ndjson",
6720
- content: ndjsonOf(listing.map((i2) => ({ key: i2.key, sizeBytes: i2.sizeBytes })))
6721
- });
6722
- const outputsListing = [];
6723
- let sealedPresent = false;
6724
- let sealedSize = 0;
6725
- let settleText = null;
6726
- let bootText = null;
6727
- for (const item of listing) {
6728
- if (!item.key.startsWith(prefix))
6729
- continue;
6730
- const rel = item.key.slice(prefix.length);
6731
- if (rel === "")
6732
- continue;
6733
- if (rel === "secrets.sealed") {
6734
- sealedPresent = true;
6735
- sealedSize = item.sizeBytes;
6736
- continue;
6737
- }
6738
- if (rel.startsWith("outputs/")) {
6739
- outputsListing.push(item);
6740
- if (flags.withOutputs) {
6741
- const body = await safeGetText(sources, targets.outputsBucket, item.key);
6742
- if (body !== null)
6743
- files.push({ path: rel, content: body });
6744
- }
6745
- continue;
6746
- }
6747
- if (rel.startsWith("assets/") || rel.startsWith("session/backup/"))
6748
- continue;
6749
- if (/\.(json|ndjson|txt|log)$/.test(rel)) {
6750
- const body = await safeGetText(sources, targets.outputsBucket, item.key);
6751
- if (body !== null) {
6752
- files.push({ path: rel, content: body });
6753
- if (rel === "settle.json")
6754
- settleText = body;
6755
- if (rel === "boot.json" || rel === "session/boot.json")
6756
- bootText = body;
6757
- }
6758
- }
6759
- }
6760
- files.push({
6761
- path: "outputs/_listing.ndjson",
6762
- content: ndjsonOf(outputsListing.map((i2) => ({ key: i2.key, sizeBytes: i2.sizeBytes })))
6763
- });
6764
- if (s3Error)
6765
- statuses.push(status("s3", "error", { detail: s3Error }));
6766
- else if (listing.length === 0) {
6767
- statuses.push(status("s3", "missing", { detail: `no objects under s3://${targets.outputsBucket}/${prefix}` }));
6768
- } else
6769
- statuses.push(status("s3", "present", { count: listing.length }));
6770
- statuses.push(sealedPresent ? status("secrets.sealed", "present", { detail: `${sealedSize} bytes (not downloaded)` }) : status("secrets.sealed", "missing", { detail: "absent" }));
6771
- const meta = extractRunMeta(settleText, bootText);
6772
- let journalSource = "none";
6773
- let events = [];
6774
- let ddbRows = null;
6775
- let ddbError = null;
6776
- try {
6777
- ddbRows = await sources.queryEvents(targets.eventsTable, runId);
6778
- } catch (err2) {
6779
- ddbError = err2.message ?? "query failed";
6780
- }
6781
- if (ddbRows && ddbRows.length > 0) {
6782
- events = sortJournal(ddbRows);
6783
- journalSource = "ddb";
6784
- } else {
6785
- const archiveText = await safeGetText(sources, targets.eventsArchiveBucket, `${runId}/log.ndjson`);
6786
- if (archiveText) {
6787
- events = sortJournal(parseNdjson(archiveText));
6788
- if (events.length > 0)
6789
- journalSource = "events-archive";
6790
- }
6791
- }
6792
- files.push({ path: "journal.ndjson", content: ndjsonOf(events) });
6793
- if (journalSource === "none") {
6794
- statuses.push(status("journal", "missing", {
6795
- detail: ddbError ? `ddb error: ${ddbError}; no events-archive fallback` : "empty in DDB and no events-archive/<runId>/log.ndjson (TTL-expired?)"
6796
- }));
6797
- } else {
6798
- statuses.push(status("journal", "present", { detail: `source=${journalSource}`, count: events.length }));
6799
- }
6800
- if (!targets.account) {
6801
- statuses.push(status("sfn", "skipped", { detail: "no account id (pass --account or grant s3:ListBuckets) \u2014 cannot build execution ARN" }));
6802
- } else {
6803
- const arn = `arn:${targets.partition}:states:${targets.region}:${targets.account}:execution:${targets.stateMachineName}:${runId}`;
6804
- let history = null;
6805
- let sfnError = null;
6806
- try {
6807
- history = await sources.getExecutionHistory(arn);
6808
- } catch (err2) {
6809
- sfnError = err2.message ?? "GetExecutionHistory failed";
6810
- }
6811
- if (history) {
6812
- files.push({ path: "sfn-history.json", content: JSON.stringify({ executionArn: arn, events: history }, null, 2) });
6813
- statuses.push(status("sfn", history.length > 0 ? "present" : "empty", { count: history.length }));
6814
- } else {
6815
- statuses.push(status("sfn", sfnError ? "error" : "missing", {
6816
- detail: sfnError ?? "execution not found (expired or never ran)"
6817
- }));
6818
- }
6819
- }
6820
- if (flags.cloudwatch) {
6821
- const endMs = toMs(meta.endedAt) ?? Date.now();
6822
- const startMs = toMs(meta.startedAt) ?? endMs - flags.sinceMs;
6823
- for (const [label, group] of Object.entries(targets.logGroups)) {
6824
- let res;
6825
- try {
6826
- res = await sources.filterLogs(group, runId, startMs, endMs);
6827
- } catch (err2) {
6828
- res = { kind: "error", message: err2.message ?? "FilterLogEvents failed" };
6829
- }
6830
- const src = `cloudwatch:${label}`;
6831
- if (res.kind === "events") {
6832
- files.push({ path: `cloudwatch/${label}.ndjson`, content: ndjsonOf(res.events) });
6833
- statuses.push(status(src, res.events.length > 0 ? "present" : "empty", { count: res.events.length }));
6834
- } else if (res.kind === "empty") {
6835
- statuses.push(status(src, "empty", { detail: `no events in window for ${group}` }));
6836
- } else if (res.kind === "expired") {
6837
- statuses.push(status(src, "expired", { detail: `log group ${group} not found / retention expired` }));
6838
- } else {
6839
- statuses.push(status(src, "error", { detail: res.message }));
6840
- }
6841
- }
6842
- } else {
6843
- statuses.push(status("cloudwatch", "skipped", { detail: "pass --cloudwatch to fetch (fresh runs only)" }));
6844
- }
6845
- const childRunIds = extractChildRunIds(events, runId).filter((id) => !visited.has(id));
6846
- const children = [];
6847
- for (const childId of childRunIds) {
6848
- if (visited.has(childId))
6849
- continue;
6850
- const childBundle = await assembleOne(childId, targets, sources, flags, visited);
6851
- for (const f of childBundle.files)
6852
- files.push({ path: `children/${childId}/${f.path}`, content: f.content });
6853
- children.push(childBundle.manifest);
6854
- }
6855
- const manifest = {
6856
- runId,
6857
- generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
6858
- plane: targets.plane,
6859
- region: targets.region,
6860
- outputsBucket: targets.outputsBucket,
6861
- eventsArchiveBucket: targets.eventsArchiveBucket,
6862
- runStatus: meta.status,
6863
- startedAt: meta.startedAt,
6864
- endedAt: meta.endedAt,
6865
- journalSource,
6866
- journalEventCount: events.length,
6867
- childRunIds,
6868
- sources: statuses,
6869
- children
6870
- };
6871
- files.push({ path: "manifest.json", content: JSON.stringify(manifest, null, 2) });
6872
- files.push({ path: "index.md", content: renderIndexMd(manifest) });
6873
- return { files, manifest };
6874
- }
6875
- function ndjsonOf(rows) {
6876
- return rows.length === 0 ? "" : rows.map((r) => JSON.stringify(r)).join("\n") + "\n";
6877
- }
6878
- function toMs(iso) {
6879
- if (!iso)
6880
- return null;
6881
- const ms = Date.parse(iso);
6882
- return Number.isFinite(ms) ? ms : null;
6883
- }
6884
- async function writeDebugBundle(io2, baseDir, bundle) {
6885
- const encoder3 = new TextEncoder();
6886
- for (const file2 of bundle.files) {
6887
- const abs = resolvePath4(baseDir, file2.path);
6888
- if (io2.mkdirp)
6889
- await io2.mkdirp(dirname(abs));
6890
- await io2.writeFile(abs, encoder3.encode(file2.content));
6891
- }
6892
- }
6893
- async function loadModule(pkg) {
6894
- try {
6895
- return await import(pkg);
6896
- } catch (err2) {
6897
- throw new Error(`aex debug needs the AWS SDK v3 package "${pkg}". Install it (e.g. \`npm i ${pkg}\`) and retry. (${err2.message})`);
6898
- }
6899
- }
6900
- function isNotFound(err2) {
6901
- const name = err2?.name ?? "";
6902
- return /NotFound|NoSuchKey|NoSuchBucket|ResourceNotFound|ExecutionDoesNotExist/i.test(name);
6903
- }
6904
- function partitionForRegion(region) {
6905
- if (region.startsWith("cn-"))
6906
- return "aws-cn";
6907
- if (region.startsWith("us-gov-"))
6908
- return "aws-us-gov";
6909
- return "aws";
6910
- }
6911
- function unmarshallAttr(av) {
6912
- if ("S" in av)
6913
- return av.S;
6914
- if ("N" in av)
6915
- return Number(av.N);
6916
- if ("BOOL" in av)
6917
- return av.BOOL;
6918
- if ("NULL" in av)
6919
- return null;
6920
- if ("M" in av) {
6921
- const m = av.M;
6922
- const out = {};
6923
- for (const [k, v] of Object.entries(m))
6924
- out[k] = unmarshallAttr(v);
6925
- return out;
6926
- }
6927
- if ("L" in av)
6928
- return av.L.map(unmarshallAttr);
6929
- if ("SS" in av)
6930
- return av.SS;
6931
- if ("NS" in av)
6932
- return av.NS.map(Number);
6933
- if ("B" in av)
6934
- return av.B;
6935
- return av;
6936
- }
6937
- function unmarshallItem(item) {
6938
- const out = {};
6939
- for (const [k, v] of Object.entries(item))
6940
- out[k] = unmarshallAttr(v);
6941
- return out;
6942
- }
6943
- function makeAwsSources(region) {
6944
- const clients = /* @__PURE__ */ new Map();
6945
- const modules = /* @__PURE__ */ new Map();
6946
- async function mod(pkg) {
6947
- let m = modules.get(pkg);
6948
- if (!m) {
6949
- m = await loadModule(pkg);
6950
- modules.set(pkg, m);
6951
- }
6952
- return m;
6953
- }
6954
- async function client(pkg, ctorName) {
6955
- let c = clients.get(pkg);
6956
- if (!c) {
6957
- const m = await mod(pkg);
6958
- const Ctor = m[ctorName];
6959
- c = new Ctor({ region });
6960
- clients.set(pkg, c);
6961
- }
6962
- return c;
6963
- }
6964
- async function listBuckets() {
6965
- const m = await mod("@aws-sdk/client-s3");
6966
- const c = await client("@aws-sdk/client-s3", "S3Client");
6967
- const Cmd = m.ListBucketsCommand;
6968
- const out = await c.send(new Cmd({}));
6969
- const buckets = out.Buckets ?? [];
6970
- return buckets.map((b) => b.Name ?? "").filter((n) => n !== "");
6971
- }
6972
- return {
6973
- async resolveTargets(plane, regionArg, accountHint) {
6974
- const prefix = `aex-${plane}-${regionArg}`;
6975
- let account = accountHint;
6976
- let outputsBucket = account ? `${prefix}-outputs-${account}` : "";
6977
- let eventsArchiveBucket = account ? `${prefix}-events-archive-${account}` : "";
6978
- if (!account) {
6979
- const names = await listBuckets();
6980
- const out = names.find((n) => n.startsWith(`${prefix}-outputs-`));
6981
- const arch = names.find((n) => n.startsWith(`${prefix}-events-archive-`));
6982
- if (out) {
6983
- outputsBucket = out;
6984
- account = out.slice(`${prefix}-outputs-`.length) || null;
6985
- }
6986
- if (arch)
6987
- eventsArchiveBucket = arch;
6988
- }
6989
- if (!outputsBucket)
6990
- outputsBucket = `${prefix}-outputs-${account ?? "unknown"}`;
6991
- if (!eventsArchiveBucket)
6992
- eventsArchiveBucket = `${prefix}-events-archive-${account ?? "unknown"}`;
6993
- return {
6994
- plane,
6995
- region: regionArg,
6996
- partition: partitionForRegion(regionArg),
6997
- account: account ?? null,
6998
- outputsBucket,
6999
- eventsArchiveBucket,
7000
- eventsTable: `${prefix}-events`,
7001
- stateMachineName: `${prefix}-sfn`,
7002
- logGroups: {
7003
- api: `/aws/lambda/${prefix}-api`,
7004
- sfn: `/aws/states/${prefix}-run`,
7005
- brain: `/aws/ecs/${prefix}-brain`,
7006
- egress: `/aws/ecs/${prefix}-egress`
7007
- }
7008
- };
7009
- },
7010
- async listObjects(bucket, keyPrefix) {
7011
- const m = await mod("@aws-sdk/client-s3");
7012
- const c = await client("@aws-sdk/client-s3", "S3Client");
7013
- const Cmd = m.ListObjectsV2Command;
7014
- const items = [];
7015
- let token;
7016
- do {
7017
- const out = await c.send(new Cmd({ Bucket: bucket, Prefix: keyPrefix, ...token ? { ContinuationToken: token } : {} }));
7018
- const contents = out.Contents ?? [];
7019
- for (const o of contents)
7020
- if (o.Key)
7021
- items.push({ key: o.Key, sizeBytes: o.Size ?? 0 });
7022
- token = out.IsTruncated ? out.NextContinuationToken : void 0;
7023
- } while (token);
7024
- return items;
7025
- },
7026
- async getObjectText(bucket, key) {
7027
- const m = await mod("@aws-sdk/client-s3");
7028
- const c = await client("@aws-sdk/client-s3", "S3Client");
7029
- const Cmd = m.GetObjectCommand;
7030
- try {
7031
- const out = await c.send(new Cmd({ Bucket: bucket, Key: key }));
7032
- const body = out.Body;
7033
- if (body?.transformToString)
7034
- return await body.transformToString();
7035
- return null;
7036
- } catch (err2) {
7037
- if (isNotFound(err2))
7038
- return null;
7039
- throw err2;
7040
- }
7041
- },
7042
- async queryEvents(table, runId) {
7043
- try {
7044
- const m = await mod("@aws-sdk/client-dynamodb");
7045
- const c = await client("@aws-sdk/client-dynamodb", "DynamoDBClient");
7046
- const Cmd = m.QueryCommand;
7047
- const items = [];
7048
- let startKey;
7049
- do {
7050
- const out = await c.send(new Cmd({
7051
- TableName: table,
7052
- KeyConditionExpression: "runId = :r",
7053
- ExpressionAttributeValues: { ":r": { S: runId } },
7054
- ScanIndexForward: true,
7055
- ...startKey ? { ExclusiveStartKey: startKey } : {}
7056
- }));
7057
- const rows = out.Items ?? [];
7058
- for (const r of rows)
7059
- items.push(unmarshallItem(r));
7060
- startKey = out.LastEvaluatedKey;
7061
- } while (startKey);
7062
- return items;
7063
- } catch (err2) {
7064
- if (isNotFound(err2))
7065
- return null;
7066
- return null;
7067
- }
7068
- },
7069
- async getExecutionHistory(executionArn) {
7070
- try {
7071
- const m = await mod("@aws-sdk/client-sfn");
7072
- const c = await client("@aws-sdk/client-sfn", "SFNClient");
7073
- const Cmd = m.GetExecutionHistoryCommand;
7074
- const events = [];
7075
- let token;
7076
- do {
7077
- const out = await c.send(new Cmd({ executionArn, maxResults: 1e3, includeExecutionData: true, ...token ? { nextToken: token } : {} }));
7078
- const page = out.events ?? [];
7079
- events.push(...page);
7080
- token = out.nextToken;
7081
- } while (token);
7082
- return events;
7083
- } catch (err2) {
7084
- if (isNotFound(err2))
7085
- return null;
7086
- throw err2;
7087
- }
7088
- },
7089
- async filterLogs(logGroup, runId, startMs, endMs) {
7090
- try {
7091
- const m = await mod("@aws-sdk/client-cloudwatch-logs");
7092
- const c = await client("@aws-sdk/client-cloudwatch-logs", "CloudWatchLogsClient");
7093
- const Cmd = m.FilterLogEventsCommand;
7094
- const events = [];
7095
- let token;
7096
- let pages = 0;
7097
- do {
7098
- const out = await c.send(new Cmd({
7099
- logGroupName: logGroup,
7100
- startTime: startMs,
7101
- endTime: endMs,
7102
- filterPattern: `"${runId}"`,
7103
- ...token ? { nextToken: token } : {}
7104
- }));
7105
- const page = out.events ?? [];
7106
- events.push(...page);
7107
- token = out.nextToken;
7108
- } while (token && ++pages < 10);
7109
- return events.length > 0 ? { kind: "events", events } : { kind: "empty" };
7110
- } catch (err2) {
7111
- if (isNotFound(err2))
7112
- return { kind: "expired" };
7113
- return { kind: "error", message: err2.message ?? "FilterLogEvents failed" };
7114
- }
7115
- }
7116
- };
7117
- }
7118
- var USAGE = "usage: aex debug <run-id> [--plane dev|prd] [--region eu-west-2] [--out dir] [--account <id>] [--cloudwatch] [--since <dur>] [--with-outputs]\n operator command \u2014 uses the standard AWS SDK credential chain (env/profile), NOT --api-key\n";
7119
- async function runDebugCmd(io2, argv) {
7120
- if (await refuseInsideManagedRun(io2, "debug"))
7121
- return USAGE_ERR;
7122
- const planeF = takeOptionFlag(argv, "--plane");
7123
- const regionF = takeOptionFlag(planeF.remaining, "--region");
7124
- const outF = takeOptionFlag(regionF.remaining, "--out");
7125
- const accountF = takeOptionFlag(outF.remaining, "--account");
7126
- const sinceF = takeOptionFlag(accountF.remaining, "--since");
7127
- const cwF = takeBooleanFlag(sinceF.remaining, "--cloudwatch");
7128
- const woF = takeBooleanFlag(cwF.remaining, "--with-outputs");
7129
- const rest = woF.remaining;
7130
- const unknownFlags = rest.filter((a) => a.startsWith("--"));
7131
- if (unknownFlags.length > 0) {
7132
- io2.stderr(`unknown flag(s): ${unknownFlags.join(", ")}
7133
- ${USAGE}`);
7134
- return USAGE_ERR;
7135
- }
7136
- const positional = rest.filter((a) => !a.startsWith("--"));
7137
- if (positional.length !== 1) {
7138
- io2.stderr(USAGE);
7139
- return USAGE_ERR;
7140
- }
7141
- const runId = positional[0];
7142
- const plane = planeF.value ?? "dev";
7143
- if (plane !== "dev" && plane !== "prd") {
7144
- io2.stderr(`--plane must be one of: dev, prd (got "${plane}")
7145
- `);
7146
- return USAGE_ERR;
7147
- }
7148
- const region = regionF.value ?? "eu-west-2";
7149
- let sinceMs = 24 * 60 * 60 * 1e3;
7150
- if (sinceF.value !== void 0) {
7151
- const d = parseDuration(sinceF.value);
7152
- if (d.error || d.ms === null) {
7153
- io2.stderr(`--since: ${d.error ?? "invalid duration"}
7154
- `);
7155
- return USAGE_ERR;
7156
- }
7157
- sinceMs = d.ms;
7158
- }
7159
- const outDir = resolvePath4(io2.cwd(), outF.value ?? `aex-debug-${runId}`);
7160
- const client = makeAwsSources(region);
7161
- let targets;
7162
- try {
7163
- targets = await client.resolveTargets(plane, region, accountF.value ?? null);
7164
- } catch (err2) {
7165
- io2.stderr(JSON.stringify({
7166
- error: "debug_resolve_failed",
7167
- message: err2.message ?? "failed to resolve plane targets",
7168
- hint: "check AWS credentials (env/profile) or pass --account <id>"
7169
- }) + "\n");
7170
- return RUNTIME_ERR;
7171
- }
7172
- let bundle;
7173
- try {
7174
- bundle = await assembleBundle({
7175
- runId,
7176
- targets,
7177
- sources: client,
7178
- cloudwatch: cwF.present,
7179
- withOutputs: woF.present,
7180
- sinceMs
7181
- });
7182
- } catch (err2) {
7183
- io2.stderr(JSON.stringify({ error: "debug_assemble_failed", message: err2.message ?? "assembly failed" }) + "\n");
7184
- return RUNTIME_ERR;
7185
- }
7186
- try {
7187
- await writeDebugBundle(io2, outDir, bundle);
7188
- } catch (err2) {
7189
- io2.stderr(JSON.stringify({ error: "debug_write_failed", message: err2.message ?? "write failed", outDir }) + "\n");
7190
- return RUNTIME_ERR;
7191
- }
7192
- io2.stdout(JSON.stringify({
7193
- runId,
7194
- plane,
7195
- region,
7196
- outDir,
7197
- fileCount: bundle.files.length,
7198
- runStatus: bundle.manifest.runStatus,
7199
- journalSource: bundle.manifest.journalSource,
7200
- journalEventCount: bundle.manifest.journalEventCount,
7201
- childRunIds: bundle.manifest.childRunIds,
7202
- sources: bundle.manifest.sources
7203
- }, null, 2) + "\n");
7204
- return SUCCESS;
7205
- }
7206
-
7207
6746
  // dist/host/auth-cmd.js
7208
6747
  async function runLoginCmd(io2, argv) {
7209
6748
  if (await refuseInsideManagedRun(io2, "login"))
@@ -7218,14 +6757,19 @@ async function runLoginCmd(io2, argv) {
7218
6757
  return USAGE_ERR;
7219
6758
  }
7220
6759
  const { apiKey, aexUrl, debug: debug2, rest } = extracted.flags;
7221
- const positional = rest.filter((a) => !a.startsWith("--"));
6760
+ const loginUsage = "usage: aex login --api-key <token> [--aex-url <url>]";
6761
+ const unknown = rejectUnknownFlags(io2, rest, loginUsage);
6762
+ if (unknown)
6763
+ return unknown;
6764
+ const positional = rest;
7222
6765
  if (positional.length > 0) {
7223
6766
  io2.stderr(`unexpected arguments: ${positional.join(" ")}
7224
6767
  `);
7225
6768
  return USAGE_ERR;
7226
6769
  }
7227
6770
  if (!apiKey) {
7228
- io2.stderr("usage: aex login --api-key <token> [--aex-url <url>]\n");
6771
+ io2.stderr(`${loginUsage}
6772
+ `);
7229
6773
  return USAGE_ERR;
7230
6774
  }
7231
6775
  const resolvedUrl = aexUrl ?? AEX_DEFAULT_BASE_URL;
@@ -7267,6 +6811,17 @@ async function runLogoutCmd(io2, argv) {
7267
6811
  const extracted = extractCommonHostFlags(argv);
7268
6812
  if (!extracted.ok) {
7269
6813
  io2.stderr(`${extracted.reason}
6814
+ `);
6815
+ return USAGE_ERR;
6816
+ }
6817
+ const logoutUsage = "usage: aex logout";
6818
+ const unknown = rejectUnknownFlags(io2, extracted.flags.rest, logoutUsage);
6819
+ if (unknown)
6820
+ return unknown;
6821
+ if (extracted.flags.rest.length > 0) {
6822
+ io2.stderr(`unexpected arguments: ${extracted.flags.rest.join(" ")}
6823
+ `);
6824
+ io2.stderr(`${logoutUsage}
7270
6825
  `);
7271
6826
  return USAGE_ERR;
7272
6827
  }
@@ -7283,6 +6838,17 @@ async function runAuthStatusCmd(io2, argv) {
7283
6838
  const extracted = extractCommonHostFlags(argv);
7284
6839
  if (!extracted.ok) {
7285
6840
  io2.stderr(`${extracted.reason}
6841
+ `);
6842
+ return USAGE_ERR;
6843
+ }
6844
+ const authUsage = "usage: aex auth status";
6845
+ const unknown = rejectUnknownFlags(io2, extracted.flags.rest, authUsage);
6846
+ if (unknown)
6847
+ return unknown;
6848
+ if (extracted.flags.rest.length > 0) {
6849
+ io2.stderr(`unexpected arguments: ${extracted.flags.rest.join(" ")}
6850
+ `);
6851
+ io2.stderr(`${authUsage}
7286
6852
  `);
7287
6853
  return USAGE_ERR;
7288
6854
  }
@@ -7380,11 +6946,14 @@ function stripListSubcommand(argv) {
7380
6946
  return argv[0] === "list" ? argv.slice(1) : argv;
7381
6947
  }
7382
6948
  function hasUnknown(io2, rest, verb) {
7383
- const stray = rest.filter((a) => !a.startsWith("--"));
6949
+ const usage = `usage: aex ${verb} list [--json]`;
6950
+ if (rejectUnknownFlags(io2, rest, usage))
6951
+ return true;
6952
+ const stray = rest;
7384
6953
  if (stray.length > 0) {
7385
- io2.stderr(`usage: aex ${verb} list [--json]
7386
- `);
7387
6954
  io2.stderr(`unexpected arguments: ${stray.join(" ")}
6955
+ `);
6956
+ io2.stderr(`${usage}
7388
6957
  `);
7389
6958
  return true;
7390
6959
  }
@@ -7432,9 +7001,14 @@ async function runTailCmd(io2, argv) {
7432
7001
  }
7433
7002
  timeoutMs = parsed.ms;
7434
7003
  }
7435
- const positional = timeoutFlag.remaining.filter((a) => !a.startsWith("--"));
7004
+ const usage = "usage: aex tail <session-id> [--json] [--filter <type|source>] [--logs] [--from <seq>] [--settle] [--timeout <dur>] [common flags]";
7005
+ const unknown = rejectUnknownFlags(io2, timeoutFlag.remaining, usage);
7006
+ if (unknown)
7007
+ return unknown;
7008
+ const positional = timeoutFlag.remaining;
7436
7009
  if (positional.length !== 1) {
7437
- io2.stderr("usage: aex tail <session-id> [--json] [--filter <type|source>] [--logs] [--from <seq>] [--settle] [--timeout <dur>] [common flags]\n");
7010
+ io2.stderr(`${usage}
7011
+ `);
7438
7012
  return USAGE_ERR;
7439
7013
  }
7440
7014
  const sessionId = positional[0];
@@ -7574,9 +7148,14 @@ async function runInspectCmd(io2, argv) {
7574
7148
  }
7575
7149
  timeoutMs = parsed.ms;
7576
7150
  }
7577
- const positional = timeoutFlag.remaining.filter((a) => !a.startsWith("--"));
7151
+ const usage = "usage: aex inspect <session-id> [--json] [--filter <type|source>] [--logs] [--timeout <dur>] [common flags]";
7152
+ const unknown = rejectUnknownFlags(io2, timeoutFlag.remaining, usage);
7153
+ if (unknown)
7154
+ return unknown;
7155
+ const positional = timeoutFlag.remaining;
7578
7156
  if (positional.length !== 1) {
7579
- io2.stderr("usage: aex inspect <session-id> [--json] [--filter <type|source>] [--logs] [--timeout <dur>] [common flags]\n");
7157
+ io2.stderr(`${usage}
7158
+ `);
7580
7159
  return USAGE_ERR;
7581
7160
  }
7582
7161
  const sessionId = positional[0];
@@ -7676,17 +7255,17 @@ async function runInspectCmd(io2, argv) {
7676
7255
  `);
7677
7256
  }
7678
7257
  const costUsd = finalSession.costUsd;
7679
- const usage = finalSession.usage;
7680
- if (costUsd !== void 0 || usage) {
7258
+ const usage2 = finalSession.usage;
7259
+ if (costUsd !== void 0 || usage2) {
7681
7260
  const parts = [`status=${finalSession.status}`];
7682
7261
  if (costUsd !== void 0)
7683
7262
  parts.push(`costUsd=${costUsd}`);
7684
- if (usage?.inputTokens !== void 0)
7685
- parts.push(`in=${usage.inputTokens}`);
7686
- if (usage?.outputTokens !== void 0)
7687
- parts.push(`out=${usage.outputTokens}`);
7688
- if (usage?.totalTokens !== void 0)
7689
- parts.push(`total=${usage.totalTokens}`);
7263
+ if (usage2?.inputTokens !== void 0)
7264
+ parts.push(`in=${usage2.inputTokens}`);
7265
+ if (usage2?.outputTokens !== void 0)
7266
+ parts.push(`out=${usage2.outputTokens}`);
7267
+ if (usage2?.totalTokens !== void 0)
7268
+ parts.push(`total=${usage2.totalTokens}`);
7690
7269
  io2.stdout(`
7691
7270
  \u2014 ${parts.join(" \xB7 ")}
7692
7271
  `);
@@ -7772,8 +7351,6 @@ async function dispatch(io2, args) {
7772
7351
  return runToolsCmd(io2, rest);
7773
7352
  case "runtime-sizes":
7774
7353
  return runRuntimeSizesCmd(io2, rest);
7775
- case "debug":
7776
- return runDebugCmd(io2, rest);
7777
7354
  default:
7778
7355
  io2.stderr(`unknown subcommand: ${sub}
7779
7356
  `);
@@ -7812,7 +7389,6 @@ async function printGlobalHelp(io2) {
7812
7389
  io2.stdout(" aex providers list [--json] List providers + their models (no token needed)\n");
7813
7390
  io2.stdout(" aex tools list [--json] List builtin tools (all default; no token needed)\n");
7814
7391
  io2.stdout(" aex runtime-sizes list [--json] List managed runtime presets (no token needed)\n");
7815
- io2.stdout(" aex debug <run-id> [--plane dev|prd] [--region eu-west-2] [--cloudwatch] [--with-outputs] (operator; AWS creds)\n");
7816
7392
  io2.stdout(" aex --help\n\n");
7817
7393
  io2.stdout("Common flags on every host subcommand:\n");
7818
7394
  io2.stdout(" --api-key <token> REQUIRED \u2014 aex SDK API key (workspace is derived from it)\n");
@@ -7854,7 +7430,7 @@ async function walkDirectory(root) {
7854
7430
  async function visit(dir) {
7855
7431
  const entries = await readdir(dir, { withFileTypes: true });
7856
7432
  for (const entry of entries) {
7857
- const full = resolvePath5(dir, entry.name);
7433
+ const full = resolvePath4(dir, entry.name);
7858
7434
  if (entry.isDirectory()) {
7859
7435
  await visit(full);
7860
7436
  } else if (entry.isFile()) {
@@ -7903,7 +7479,7 @@ var configStore = {
7903
7479
  }
7904
7480
  },
7905
7481
  write: async (config) => {
7906
- await mkdir(dirname2(configPath), { recursive: true, mode: 448 });
7482
+ await mkdir(dirname(configPath), { recursive: true, mode: 448 });
7907
7483
  await writeFile(configPath, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
7908
7484
  try {
7909
7485
  await chmod(configPath, 384);
@@ -7920,9 +7496,6 @@ var webSocketFactory = typeof WebSocket === "undefined" ? void 0 : (url) => new
7920
7496
  var io = {
7921
7497
  readFile: (path) => readFile(path, "utf8"),
7922
7498
  writeFile: (path, data) => writeFile(path, data),
7923
- mkdirp: async (path) => {
7924
- await mkdir(path, { recursive: true });
7925
- },
7926
7499
  fetchImpl: fetch,
7927
7500
  stdout: (chunk) => process.stdout.write(chunk),
7928
7501
  stderr: (chunk) => process.stderr.write(chunk),