@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.
- package/README.md +159 -159
- package/dist/_contracts/api-key.js +0 -1
- package/dist/_contracts/bundle-manifest.js +0 -1
- package/dist/_contracts/connection-ticket.js +0 -1
- package/dist/_contracts/error-codes.js +0 -1
- package/dist/_contracts/error-factory.js +0 -1
- package/dist/_contracts/event-envelope.js +0 -1
- package/dist/_contracts/event-stream-client.js +0 -1
- package/dist/_contracts/event-view.js +0 -1
- package/dist/_contracts/http.js +0 -1
- package/dist/_contracts/index.js +0 -1
- package/dist/_contracts/internal.d.ts +36 -0
- package/dist/_contracts/internal.js +155 -6
- package/dist/_contracts/models.js +0 -1
- package/dist/_contracts/operations.js +1 -2
- package/dist/_contracts/post-hook.js +0 -1
- package/dist/_contracts/provider-support.js +0 -1
- package/dist/_contracts/run-artifacts.js +0 -1
- package/dist/_contracts/run-config.js +0 -1
- package/dist/_contracts/run-cost.js +0 -1
- package/dist/_contracts/run-custody.js +0 -1
- package/dist/_contracts/run-record.js +0 -1
- package/dist/_contracts/run-retention.js +0 -1
- package/dist/_contracts/run-trace.js +0 -1
- package/dist/_contracts/run-unit.js +0 -1
- package/dist/_contracts/runner-event.js +0 -1
- package/dist/_contracts/runtime-manifest.js +0 -1
- package/dist/_contracts/runtime-security-profile.js +0 -1
- package/dist/_contracts/runtime-sizes.js +0 -1
- package/dist/_contracts/runtime-types.js +0 -1
- package/dist/_contracts/sdk-errors.js +0 -1
- package/dist/_contracts/sdk-secrets.js +0 -1
- package/dist/_contracts/side-effect-audit.js +0 -1
- package/dist/_contracts/sse.js +0 -0
- package/dist/_contracts/stable.js +0 -1
- package/dist/_contracts/status.js +0 -1
- package/dist/_contracts/submission.js +0 -1
- package/dist/_contracts/suggest.js +0 -1
- package/dist/_contracts/webhook-verify.js +0 -1
- package/dist/asset-upload.d.ts +3 -43
- package/dist/asset-upload.js +1 -109
- package/dist/asset-upload.js.map +1 -1
- package/dist/cli.mjs +354 -781
- package/dist/cli.mjs.sha256 +1 -1
- package/dist/fetch-archive.js +76 -16
- package/dist/fetch-archive.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/authentication.md +125 -125
- package/docs/billing.md +118 -118
- package/docs/concepts/agent-tools.md +66 -66
- package/docs/concepts/composition.md +37 -37
- package/docs/concepts/providers-and-runtimes.md +54 -54
- package/docs/concepts/runs.md +49 -49
- package/docs/concepts/subagents.md +88 -88
- package/docs/credentials.md +125 -125
- package/docs/defaults.md +64 -64
- package/docs/errors.md +196 -196
- package/docs/events.md +243 -243
- package/docs/limits-and-quotas.md +144 -144
- package/docs/limits.md +50 -50
- package/docs/mcp.md +44 -44
- package/docs/networking.md +163 -163
- package/docs/outputs.md +267 -267
- package/docs/public-surface.json +77 -77
- package/docs/quickstart.md +119 -119
- package/docs/release.md +38 -38
- package/docs/retries.md +129 -129
- package/docs/run-config.md +58 -58
- package/docs/run-record.md +55 -55
- package/docs/secrets.md +125 -130
- package/docs/testing.md +35 -35
- package/docs/vision-skills.md +91 -91
- package/docs/webhooks.md +127 -131
- package/examples/feature-tour.ts +282 -282
- package/examples/spike-settle-latency.ts +125 -125
- 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
|
|
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,
|
|
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
|
|
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
|
|
1823
|
+
const status = detailRecord?.httpStatus ?? detailRecord?.status;
|
|
1824
1824
|
const apiCode = detailRecord?.apiCode;
|
|
1825
|
-
this.status = typeof
|
|
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(
|
|
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 =
|
|
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(
|
|
2007
|
-
if (
|
|
2006
|
+
function kindForStatus(status) {
|
|
2007
|
+
if (status === 401 || status === 403)
|
|
2008
2008
|
return "auth";
|
|
2009
|
-
if (
|
|
2009
|
+
if (status === 404)
|
|
2010
2010
|
return "not_found";
|
|
2011
|
-
if (
|
|
2011
|
+
if (status === 409)
|
|
2012
2012
|
return "idempotency";
|
|
2013
|
-
if (
|
|
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,
|
|
2124
|
-
this.#debug?.(`[aex] ${(method ?? "GET").toUpperCase()} ${url.pathname} -> ${
|
|
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
|
|
2242
|
-
if (obj.error === "session_busy" && typeof
|
|
2243
|
-
return `session_busy (session status: ${
|
|
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(
|
|
3902
|
-
return
|
|
3901
|
+
function isSessionParked2(status) {
|
|
3902
|
+
return status === "idle" || status === "suspended" || status === "error" || TERMINAL_STATUSES.has(status);
|
|
3903
3903
|
}
|
|
3904
|
-
function isSessionOk(
|
|
3905
|
-
return
|
|
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(
|
|
4014
|
-
if (
|
|
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 (
|
|
4026
|
+
if (status === 401)
|
|
4017
4027
|
return "check --api-key, or run `aex login`";
|
|
4018
|
-
if (
|
|
4028
|
+
if (status === 403)
|
|
4019
4029
|
return "token lacks permission for this workspace/action";
|
|
4020
|
-
if (
|
|
4030
|
+
if (status === 404)
|
|
4021
4031
|
return "no such run/resource \u2014 verify the id";
|
|
4022
|
-
if (
|
|
4032
|
+
if (status === 429)
|
|
4023
4033
|
return "rate limited \u2014 retry with backoff";
|
|
4024
|
-
if (
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
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
|
|
5022
|
+
return bufferToHex2(digest);
|
|
4917
5023
|
}
|
|
4918
|
-
function
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
7680
|
-
if (costUsd !== void 0 ||
|
|
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 (
|
|
7685
|
-
parts.push(`in=${
|
|
7686
|
-
if (
|
|
7687
|
-
parts.push(`out=${
|
|
7688
|
-
if (
|
|
7689
|
-
parts.push(`total=${
|
|
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 =
|
|
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(
|
|
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),
|