@aexhq/cli 0.13.6 → 0.13.8
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/dist/cli.mjs +127 -127
- package/dist/cli.mjs.sha256 +1 -1
- package/dist/host/download.js +5 -9
- package/dist/host/download.js.map +1 -1
- package/dist/proxy.js +58 -2
- package/dist/proxy.js.map +1 -1
- package/package.json +3 -3
- package/src/host/download.ts +6 -10
- package/src/proxy.ts +78 -3
- package/test/cli.test.ts +37 -2
- package/test/host.test.ts +15 -27
package/dist/cli.mjs
CHANGED
|
@@ -10,8 +10,14 @@ import { readFile as readFile2, writeFile, readdir as readdir2, stat as stat2 }
|
|
|
10
10
|
import { resolve as resolvePath4 } from "node:path";
|
|
11
11
|
|
|
12
12
|
// ../contracts/dist/proxy-protocol.js
|
|
13
|
-
var
|
|
13
|
+
var PROXY_PROTOCOL_VERSION_V2 = "2";
|
|
14
14
|
var PROXY_PROTOCOL_HEADER = "x-aex-proxy-protocol";
|
|
15
|
+
var PROXY_RESP_STATUS_HEADER = "x-aex-proxy-status";
|
|
16
|
+
var PROXY_RESP_MODE_HEADER = "x-aex-proxy-effective-mode";
|
|
17
|
+
var PROXY_RESP_TRUNCATED_HEADER = "x-aex-proxy-truncated";
|
|
18
|
+
var PROXY_RESP_REMAINING_CALLS_HEADER = "x-aex-proxy-remaining-calls";
|
|
19
|
+
var PROXY_RESP_REMAINING_BYTES_HEADER = "x-aex-proxy-remaining-bytes";
|
|
20
|
+
var PROXY_RESP_UPSTREAM_HEADERS_HEADER = "x-aex-proxy-upstream-headers";
|
|
15
21
|
var PROXY_METHOD_HEADER = "x-aex-method";
|
|
16
22
|
var PROXY_PATH_HEADER = "x-aex-path";
|
|
17
23
|
var PROXY_QUERY_HEADER = "x-aex-query";
|
|
@@ -114,6 +120,13 @@ var terminalRunStatuses = new Set(TERMINAL_RUN_STATUSES);
|
|
|
114
120
|
var SKILL_BUNDLE_LIMITS = {
|
|
115
121
|
/** Compressed (.zip) ceiling. */
|
|
116
122
|
maxCompressedBytes: 10 * 1024 * 1024,
|
|
123
|
+
/**
|
|
124
|
+
* Hard ceiling for the direct-to-storage (presigned PUT) upload path, where
|
|
125
|
+
* bytes never transit the hosted API so its memory/request-payload limits no
|
|
126
|
+
* longer cap the bundle. Kept well under the object store's 5 GiB single-PUT
|
|
127
|
+
* limit; objects above this would need S3 multipart, which is out of scope.
|
|
128
|
+
*/
|
|
129
|
+
maxBytes: 2 * 1024 * 1024 * 1024,
|
|
117
130
|
/** Sum of uncompressed file sizes. */
|
|
118
131
|
maxDecompressedBytes: 50 * 1024 * 1024,
|
|
119
132
|
/** Number of regular file entries (directories don't count). */
|
|
@@ -302,32 +315,63 @@ function rejectStdioMcpShape(record) {
|
|
|
302
315
|
}
|
|
303
316
|
}
|
|
304
317
|
}
|
|
305
|
-
function
|
|
306
|
-
const
|
|
307
|
-
if (
|
|
308
|
-
return
|
|
318
|
+
function denyReasonForHostIp(host) {
|
|
319
|
+
const mappedDotted = /^::(?:ffff:)?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/.exec(host);
|
|
320
|
+
if (mappedDotted) {
|
|
321
|
+
return denyReasonForV4(mappedDotted[1]);
|
|
309
322
|
}
|
|
310
|
-
|
|
311
|
-
|
|
323
|
+
const mappedHex = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(host);
|
|
324
|
+
if (mappedHex) {
|
|
325
|
+
const hi = Number.parseInt(mappedHex[1], 16);
|
|
326
|
+
const lo = Number.parseInt(mappedHex[2], 16);
|
|
327
|
+
const dotted = `${hi >> 8}.${hi & 255}.${lo >> 8}.${lo & 255}`;
|
|
328
|
+
return denyReasonForV4(dotted);
|
|
312
329
|
}
|
|
330
|
+
const v4 = denyReasonForV4(host);
|
|
331
|
+
if (v4)
|
|
332
|
+
return v4;
|
|
313
333
|
if (host === "::1" || host === "0:0:0:0:0:0:0:1") {
|
|
314
334
|
return "must not target loopback IPv6 (::1)";
|
|
315
335
|
}
|
|
316
336
|
if (/^fe[89ab][0-9a-f]?:/.test(host)) {
|
|
317
337
|
return "must not target link-local IPv6 (fe80::/10)";
|
|
318
338
|
}
|
|
319
|
-
if (/^
|
|
339
|
+
if (/^f[cd][0-9a-f]{0,2}:/.test(host)) {
|
|
340
|
+
return "must not target unique-local IPv6 (fc00::/7)";
|
|
341
|
+
}
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
function denyReasonForV4(host) {
|
|
345
|
+
if (!/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(host))
|
|
346
|
+
return null;
|
|
347
|
+
const octets = host.split(".").map((o) => Number.parseInt(o, 10));
|
|
348
|
+
if (octets.some((o) => o > 255))
|
|
349
|
+
return null;
|
|
350
|
+
const [a, b] = octets;
|
|
351
|
+
if (a === 127)
|
|
352
|
+
return "must not target loopback IPv4 (127.0.0.0/8)";
|
|
353
|
+
if (a === 169 && b === 254) {
|
|
320
354
|
return "must not target link-local IPv4 (169.254.0.0/16) \u2014 cloud metadata range";
|
|
321
355
|
}
|
|
322
|
-
if (
|
|
323
|
-
return "must not target
|
|
356
|
+
if (a === 100 && b >= 64 && b <= 127) {
|
|
357
|
+
return "must not target CGNAT IPv4 (100.64.0.0/10)";
|
|
324
358
|
}
|
|
325
|
-
if (
|
|
359
|
+
if (a === 10)
|
|
360
|
+
return "must not target RFC1918 IPv4 (10.0.0.0/8)";
|
|
361
|
+
if (a === 172 && b >= 16 && b <= 31)
|
|
326
362
|
return "must not target RFC1918 IPv4 (172.16.0.0/12)";
|
|
327
|
-
|
|
328
|
-
if (/^192\.168\.[0-9]+\.[0-9]+$/.test(host)) {
|
|
363
|
+
if (a === 192 && b === 168)
|
|
329
364
|
return "must not target RFC1918 IPv4 (192.168.0.0/16)";
|
|
365
|
+
return null;
|
|
366
|
+
}
|
|
367
|
+
function denyReasonForMcpHost(parsed) {
|
|
368
|
+
const host = parsed.hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
369
|
+
if (host === "localhost" || host.endsWith(".localhost")) {
|
|
370
|
+
return "must not target a loopback hostname";
|
|
330
371
|
}
|
|
372
|
+
const ipDenial = denyReasonForHostIp(host);
|
|
373
|
+
if (ipDenial)
|
|
374
|
+
return ipDenial;
|
|
331
375
|
if (parsed.protocol === "https:" && parsed.port !== "" && parsed.port !== "443") {
|
|
332
376
|
return `must use port 443 for https (got ${parsed.port})`;
|
|
333
377
|
}
|
|
@@ -544,7 +588,7 @@ var BLOCKED_MANAGED_KEY_POLICY_V1 = Object.freeze({
|
|
|
544
588
|
schemaVersion: MANAGED_KEY_POLICY_SCHEMA_VERSION,
|
|
545
589
|
credentialMode: "managed",
|
|
546
590
|
launchStage: "blocked",
|
|
547
|
-
|
|
591
|
+
privateImplementationAvailable: false,
|
|
548
592
|
billingRequired: true,
|
|
549
593
|
providers: Object.freeze([]),
|
|
550
594
|
runtimes: Object.freeze([]),
|
|
@@ -624,7 +668,7 @@ var forbiddenStringPatterns = Object.freeze([
|
|
|
624
668
|
regex: /\b(?:sk-(?:ant|proj|live|test|deepseek|openai)|xox[baprs]-|AIza)[A-Za-z0-9_-]{8,}/i
|
|
625
669
|
},
|
|
626
670
|
{ reason: "signed_url", regex: /[?&](?:X-Amz-Signature|X-Amz-Credential|X-Amz-Algorithm|AWSAccessKeyId)=/i },
|
|
627
|
-
{ reason: "
|
|
671
|
+
{ reason: "object_store_key", regex: /(^|[\s"'`])(?:runs|assets)\/[^?<#\s"'`]+/i },
|
|
628
672
|
{ reason: "vault_id", regex: /\b(?:vault|vlt|secret)[_:-][A-Za-z0-9][A-Za-z0-9_-]{7,}\b/i },
|
|
629
673
|
{
|
|
630
674
|
reason: "private_resource_handle",
|
|
@@ -633,7 +677,7 @@ var forbiddenStringPatterns = Object.freeze([
|
|
|
633
677
|
{ reason: "high_entropy_token", regex: /\b(?=[A-Za-z0-9_-]{40,}\b)(?=.*[A-Za-z])(?=.*\d)[A-Za-z0-9_-]{40,}\b/ }
|
|
634
678
|
]);
|
|
635
679
|
function isForbiddenCustodyFieldName(key) {
|
|
636
|
-
return /^(apiKey|secretValue|bearerHash|signedUrl|
|
|
680
|
+
return /^(apiKey|secretValue|bearerHash|signedUrl|objectStoreKey|objectKey|vaultId|providerResponseBody|responseBody|privateResourceHandle|resourceHandle|rawBody)$/i.test(key);
|
|
637
681
|
}
|
|
638
682
|
|
|
639
683
|
// ../contracts/dist/run-record.js
|
|
@@ -650,7 +694,6 @@ var RunRecordArchiveRedactionError = class extends Error {
|
|
|
650
694
|
};
|
|
651
695
|
function buildRunRecordDownloadManifestV1(input) {
|
|
652
696
|
const outputs = input.outputs.map((file2) => normalizeArtifactSummary(file2));
|
|
653
|
-
const logs = input.logs.map((file2) => normalizeArtifactSummary(file2));
|
|
654
697
|
const errors = (input.errors ?? []).map((error) => Object.freeze({ ...error }));
|
|
655
698
|
return Object.freeze({
|
|
656
699
|
schemaVersion: RUN_RECORD_MANIFEST_SCHEMA_VERSION,
|
|
@@ -658,9 +701,8 @@ function buildRunRecordDownloadManifestV1(input) {
|
|
|
658
701
|
runId: input.runId,
|
|
659
702
|
namespaces: Object.freeze([
|
|
660
703
|
namespace("metadata", "Run metadata, submission snapshot, custody, and cost files."),
|
|
661
|
-
namespace("events", "Typed event-channel exports
|
|
662
|
-
namespace("outputs", "Captured deliverables produced by the run.")
|
|
663
|
-
namespace("logs", "Platform diagnostics and runtime log artifacts.")
|
|
704
|
+
namespace("events", "Typed event-channel exports."),
|
|
705
|
+
namespace("outputs", "Captured deliverables produced by the run.")
|
|
664
706
|
]),
|
|
665
707
|
files: Object.freeze([
|
|
666
708
|
file("metadata", "metadata/run.json", "run_metadata", "present"),
|
|
@@ -670,14 +712,10 @@ function buildRunRecordDownloadManifestV1(input) {
|
|
|
670
712
|
file("events", "events/events.jsonl", "typed_events", "present", {
|
|
671
713
|
recordCount: input.typedEventCount ?? 0
|
|
672
714
|
}),
|
|
673
|
-
file("events", "events/logs.jsonl", "log_events", input.logEvents?.status ?? "unavailable", recordCountExtra(input.logEvents)),
|
|
674
|
-
file("events", "events/all.jsonl", "all_events", input.allEvents?.status ?? "unavailable", recordCountExtra(input.allEvents)),
|
|
675
715
|
file("events", "events/manifest.json", "coordinator_events_manifest", input.coordinatorEventsManifest?.status ?? "unavailable"),
|
|
676
|
-
...outputs.map((output) => artifactFile("outputs", "output", "outputs/", output))
|
|
677
|
-
...logs.map((log) => artifactFile("logs", "log", "logs/", log))
|
|
716
|
+
...outputs.map((output) => artifactFile("outputs", "output", "outputs/", output))
|
|
678
717
|
]),
|
|
679
718
|
outputs: Object.freeze(outputs),
|
|
680
|
-
logs: Object.freeze(logs),
|
|
681
719
|
errors: Object.freeze(errors)
|
|
682
720
|
});
|
|
683
721
|
}
|
|
@@ -698,9 +736,6 @@ function file(namespaceName, path, role, status, extra) {
|
|
|
698
736
|
...extra?.recordCount !== void 0 ? { recordCount: extra.recordCount } : {}
|
|
699
737
|
});
|
|
700
738
|
}
|
|
701
|
-
function recordCountExtra(input) {
|
|
702
|
-
return input?.status === "present" && input.recordCount !== void 0 ? { recordCount: input.recordCount } : void 0;
|
|
703
|
-
}
|
|
704
739
|
function artifactFile(namespaceName, role, prefix, artifact) {
|
|
705
740
|
return Object.freeze({
|
|
706
741
|
namespace: namespaceName,
|
|
@@ -767,7 +802,7 @@ function isAllowedArchiveHighEntropyField(entryPath, finding) {
|
|
|
767
802
|
if (finding.reason !== "high_entropy_token" || !entryPath.endsWith("manifest.json")) {
|
|
768
803
|
return false;
|
|
769
804
|
}
|
|
770
|
-
return /^\$(?:\.files\[\d+\]|\.outputs\[\d+\]
|
|
805
|
+
return /^\$(?:\.files\[\d+\]|\.outputs\[\d+\])\.id$/.test(finding.path);
|
|
771
806
|
}
|
|
772
807
|
function parseArchiveTextValues(path, text) {
|
|
773
808
|
if (/\.json$/i.test(path)) {
|
|
@@ -806,7 +841,7 @@ function formatArchiveFindingPaths(findings) {
|
|
|
806
841
|
// ../contracts/dist/run-retention.js
|
|
807
842
|
var forbiddenStringPatterns2 = Object.freeze([
|
|
808
843
|
{ reason: "signed_url", regex: /[?&](?:X-Amz-Signature|X-Amz-Credential|X-Amz-Algorithm|AWSAccessKeyId)=/i },
|
|
809
|
-
{ reason: "
|
|
844
|
+
{ reason: "object_store_key", regex: /(^|[\s"'`])(?:runs|assets)\/[^?<#\s"'`]+/i },
|
|
810
845
|
{ reason: "vault_id", regex: /\b(?:vault|vlt|secret)[_:-][A-Za-z0-9][A-Za-z0-9_-]{7,}\b/i },
|
|
811
846
|
{
|
|
812
847
|
reason: "private_resource_handle",
|
|
@@ -823,7 +858,7 @@ var forbiddenStringPatterns3 = Object.freeze([
|
|
|
823
858
|
regex: /\b(?:sk-(?:ant|proj|live|test|deepseek|openai)|xox[baprs]-|AIza)[A-Za-z0-9_-]{8,}/i
|
|
824
859
|
},
|
|
825
860
|
{ reason: "signed_url", regex: /[?&](?:X-Amz-Signature|X-Amz-Credential|X-Amz-Algorithm|AWSAccessKeyId)=/i },
|
|
826
|
-
{ reason: "
|
|
861
|
+
{ reason: "object_store_key", regex: /(^|[\s"'`])(?:runs|assets)\/[^?<#\s"'`]+/i },
|
|
827
862
|
{ reason: "vault_id", regex: /\b(?:vault|vlt|secret)[_:-][A-Za-z0-9][A-Za-z0-9_-]{7,}\b/i },
|
|
828
863
|
{
|
|
829
864
|
reason: "private_resource_handle",
|
|
@@ -1062,39 +1097,6 @@ function extractErrorMessage(body) {
|
|
|
1062
1097
|
return "aex API request failed";
|
|
1063
1098
|
}
|
|
1064
1099
|
|
|
1065
|
-
// ../contracts/dist/run-artifacts.js
|
|
1066
|
-
function runArtifactRel(rel) {
|
|
1067
|
-
if (rel.startsWith(".runtime-logs/"))
|
|
1068
|
-
return `runtime/${rel.slice(".runtime-logs/".length)}`;
|
|
1069
|
-
if (rel.startsWith("runtime/"))
|
|
1070
|
-
return rel;
|
|
1071
|
-
if (rel.startsWith(".host-logs/"))
|
|
1072
|
-
return `host/${rel.slice(".host-logs/".length)}`;
|
|
1073
|
-
if (rel.startsWith("host/"))
|
|
1074
|
-
return rel;
|
|
1075
|
-
if (rel.startsWith(".provider-proxy/"))
|
|
1076
|
-
return `provider-proxy/${rel.slice(".provider-proxy/".length)}`;
|
|
1077
|
-
if (rel.startsWith("provider-proxy/"))
|
|
1078
|
-
return rel;
|
|
1079
|
-
if (rel.startsWith(".control-plane/"))
|
|
1080
|
-
return `control-plane/${rel.slice(".control-plane/".length)}`;
|
|
1081
|
-
if (rel.startsWith("control-plane/"))
|
|
1082
|
-
return rel;
|
|
1083
|
-
if (rel.startsWith(".goose-logs/"))
|
|
1084
|
-
return `runtime/${rel.slice(".goose-logs/".length)}`;
|
|
1085
|
-
if (rel.startsWith("goose-logs/"))
|
|
1086
|
-
return `runtime/${rel.slice("goose-logs/".length)}`;
|
|
1087
|
-
if (rel.startsWith(".fly-logs/"))
|
|
1088
|
-
return `host/${rel.slice(".fly-logs/".length)}`;
|
|
1089
|
-
if (rel.startsWith("fly-logs/"))
|
|
1090
|
-
return `host/${rel.slice("fly-logs/".length)}`;
|
|
1091
|
-
if (rel.startsWith(".anthropic-debug/"))
|
|
1092
|
-
return `provider-proxy/${rel.slice(".anthropic-debug/".length)}`;
|
|
1093
|
-
if (rel.startsWith("anthropic-debug/"))
|
|
1094
|
-
return `provider-proxy/${rel.slice("anthropic-debug/".length)}`;
|
|
1095
|
-
return rel;
|
|
1096
|
-
}
|
|
1097
|
-
|
|
1098
1100
|
// ../contracts/dist/operations.js
|
|
1099
1101
|
var operations_exports = {};
|
|
1100
1102
|
__export(operations_exports, {
|
|
@@ -1111,7 +1113,6 @@ __export(operations_exports, {
|
|
|
1111
1113
|
deleteWorkspaceAsset: () => deleteWorkspaceAsset,
|
|
1112
1114
|
download: () => download,
|
|
1113
1115
|
downloadEvents: () => downloadEvents,
|
|
1114
|
-
downloadLogs: () => downloadLogs,
|
|
1115
1116
|
downloadMetadata: () => downloadMetadata,
|
|
1116
1117
|
downloadOutput: () => downloadOutput,
|
|
1117
1118
|
downloadOutputs: () => downloadOutputs,
|
|
@@ -1125,7 +1126,6 @@ __export(operations_exports, {
|
|
|
1125
1126
|
getSkill: () => getSkill,
|
|
1126
1127
|
listAgentsMd: () => listAgentsMd,
|
|
1127
1128
|
listFiles: () => listFiles,
|
|
1128
|
-
listLogs: () => listLogs,
|
|
1129
1129
|
listOutputs: () => listOutputs,
|
|
1130
1130
|
listRunEvents: () => listRunEvents,
|
|
1131
1131
|
listSkills: () => listSkills,
|
|
@@ -1860,10 +1860,20 @@ async function getRun(http, runId) {
|
|
|
1860
1860
|
async function getRunUnit(http, runId) {
|
|
1861
1861
|
return http.request(`/api/runs/${encodeURIComponent(runId)}`);
|
|
1862
1862
|
}
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
const
|
|
1866
|
-
|
|
1863
|
+
var LIST_EVENTS_PAGE_BUDGET = 1e3;
|
|
1864
|
+
async function listRunEvents(http, runId) {
|
|
1865
|
+
const path = `/api/runs/${encodeURIComponent(runId)}/events`;
|
|
1866
|
+
const all = [];
|
|
1867
|
+
let cursor;
|
|
1868
|
+
for (let page = 0; page < LIST_EVENTS_PAGE_BUDGET; page++) {
|
|
1869
|
+
const query = cursor !== void 0 ? { cursor: String(cursor) } : {};
|
|
1870
|
+
const result = await http.request(path, {}, query);
|
|
1871
|
+
all.push(...result.events);
|
|
1872
|
+
if (typeof result.nextCursor !== "number")
|
|
1873
|
+
break;
|
|
1874
|
+
cursor = result.nextCursor;
|
|
1875
|
+
}
|
|
1876
|
+
return all;
|
|
1867
1877
|
}
|
|
1868
1878
|
async function getCoordinatorTicket(http, runId) {
|
|
1869
1879
|
return http.request(`/api/runs/${encodeURIComponent(runId)}/events/ticket`, { method: "POST" });
|
|
@@ -1872,10 +1882,6 @@ async function listOutputs(http, runId) {
|
|
|
1872
1882
|
const result = await http.request(`/api/runs/${encodeURIComponent(runId)}/outputs`);
|
|
1873
1883
|
return result.outputs;
|
|
1874
1884
|
}
|
|
1875
|
-
async function listLogs(http, runId) {
|
|
1876
|
-
const result = await http.request(`/api/runs/${encodeURIComponent(runId)}/logs`);
|
|
1877
|
-
return result.logs.map((log) => typeof log.filename === "string" ? { ...log, filename: runArtifactRel(log.filename) } : log);
|
|
1878
|
-
}
|
|
1879
1885
|
async function createOutputLink(http, runId, outputId) {
|
|
1880
1886
|
return http.request(`/api/runs/${encodeURIComponent(runId)}/outputs/${encodeURIComponent(outputId)}/link`, { method: "POST" });
|
|
1881
1887
|
}
|
|
@@ -1939,7 +1945,7 @@ async function collectArtifactBytes(http, runId, items, zipPrefix, namespace2) {
|
|
|
1939
1945
|
path: `${zipPrefix}${rel}`,
|
|
1940
1946
|
bytes: new Uint8Array(await response.arrayBuffer()),
|
|
1941
1947
|
...item.contentType !== void 0 ? { contentType: item.contentType } : {},
|
|
1942
|
-
|
|
1948
|
+
customerContent: true
|
|
1943
1949
|
});
|
|
1944
1950
|
captured.push({
|
|
1945
1951
|
id: item.id,
|
|
@@ -1956,23 +1962,6 @@ async function collectArtifactBytes(http, runId, items, zipPrefix, namespace2) {
|
|
|
1956
1962
|
function eventsJsonl(events) {
|
|
1957
1963
|
return strToU8(events.map((event) => JSON.stringify(event)).join("\n"));
|
|
1958
1964
|
}
|
|
1959
|
-
async function tryListOptionalRunEvents(http, runId, channel) {
|
|
1960
|
-
try {
|
|
1961
|
-
const events = await listRunEvents(http, runId, { channel });
|
|
1962
|
-
if (channel === "log") {
|
|
1963
|
-
return events.length > 0 && events.every(isLogChannelEvent) ? { status: "present", events } : { status: "unavailable", events: [] };
|
|
1964
|
-
}
|
|
1965
|
-
return hasUnifiedStreamEvidence(events) ? { status: "present", events } : { status: "unavailable", events: [] };
|
|
1966
|
-
} catch {
|
|
1967
|
-
return { status: "unavailable", events: [] };
|
|
1968
|
-
}
|
|
1969
|
-
}
|
|
1970
|
-
function isLogChannelEvent(event) {
|
|
1971
|
-
return event.channel === "log";
|
|
1972
|
-
}
|
|
1973
|
-
function hasUnifiedStreamEvidence(events) {
|
|
1974
|
-
return events.some((event) => event.channel === "log" || event.channel === "event");
|
|
1975
|
-
}
|
|
1976
1965
|
function isPathSelector(selector) {
|
|
1977
1966
|
return Boolean(selector && typeof selector === "object" && "path" in selector);
|
|
1978
1967
|
}
|
|
@@ -1980,38 +1969,28 @@ function normalizeOutputLookupPath(path) {
|
|
|
1980
1969
|
return path.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
1981
1970
|
}
|
|
1982
1971
|
async function download(http, runId) {
|
|
1983
|
-
const [run, events,
|
|
1972
|
+
const [run, events, outputs] = await Promise.all([
|
|
1984
1973
|
getRun(http, runId),
|
|
1985
1974
|
listRunEvents(http, runId),
|
|
1986
|
-
|
|
1987
|
-
tryListOptionalRunEvents(http, runId, "all"),
|
|
1988
|
-
listOutputs(http, runId),
|
|
1989
|
-
listLogs(http, runId)
|
|
1975
|
+
listOutputs(http, runId)
|
|
1990
1976
|
]);
|
|
1991
1977
|
const out = await collectArtifactBytes(http, runId, outputs, "outputs/", "outputs");
|
|
1992
|
-
const logs = await collectArtifactBytes(http, runId, logItems, "logs/", "logs");
|
|
1993
1978
|
const submissionSnapshot = extractSubmissionSnapshot(run);
|
|
1994
1979
|
const costTelemetry = extractCostTelemetry(run);
|
|
1995
1980
|
const manifest = buildRunRecordDownloadManifestV1({
|
|
1996
1981
|
runId,
|
|
1997
1982
|
outputs: out.captured,
|
|
1998
|
-
|
|
1999
|
-
errors: [...out.errors, ...logs.errors],
|
|
1983
|
+
errors: out.errors,
|
|
2000
1984
|
typedEventCount: events.length,
|
|
2001
1985
|
...submissionSnapshot ? { submission: { status: "present" } } : {},
|
|
2002
|
-
...costTelemetry ? { cost: { status: "present" } } : {}
|
|
2003
|
-
logEvents: { status: logEvents.status, recordCount: logEvents.events.length },
|
|
2004
|
-
allEvents: { status: allEvents.status, recordCount: allEvents.events.length }
|
|
1986
|
+
...costTelemetry ? { cost: { status: "present" } } : {}
|
|
2005
1987
|
});
|
|
2006
1988
|
return zipEntries([
|
|
2007
1989
|
jsonEntry("metadata/run.json", run),
|
|
2008
1990
|
...submissionSnapshot ? [jsonEntry("metadata/submission.json", submissionSnapshot)] : [],
|
|
2009
1991
|
...costTelemetry ? [jsonEntry("metadata/cost.json", costTelemetry)] : [],
|
|
2010
1992
|
jsonlEntry("events/events.jsonl", events),
|
|
2011
|
-
...logEvents.status === "present" ? [jsonlEntry("events/logs.jsonl", logEvents.events)] : [],
|
|
2012
|
-
...allEvents.status === "present" ? [jsonlEntry("events/all.jsonl", allEvents.events)] : [],
|
|
2013
1993
|
...out.entries,
|
|
2014
|
-
...logs.entries,
|
|
2015
1994
|
jsonEntry("manifest.json", manifest)
|
|
2016
1995
|
]);
|
|
2017
1996
|
}
|
|
@@ -2023,25 +2002,9 @@ async function downloadOutputs(http, runId) {
|
|
|
2023
2002
|
jsonEntry("manifest.json", { runId, namespace: "outputs", outputs: captured, errors })
|
|
2024
2003
|
]);
|
|
2025
2004
|
}
|
|
2026
|
-
async function downloadLogs(http, runId) {
|
|
2027
|
-
const logItems = await listLogs(http, runId);
|
|
2028
|
-
const { entries, captured, errors } = await collectArtifactBytes(http, runId, logItems, "", "logs");
|
|
2029
|
-
return zipEntries([
|
|
2030
|
-
...entries,
|
|
2031
|
-
jsonEntry("manifest.json", { runId, namespace: "logs", logs: captured, errors })
|
|
2032
|
-
]);
|
|
2033
|
-
}
|
|
2034
2005
|
async function downloadEvents(http, runId) {
|
|
2035
|
-
const
|
|
2036
|
-
|
|
2037
|
-
tryListOptionalRunEvents(http, runId, "log"),
|
|
2038
|
-
tryListOptionalRunEvents(http, runId, "all")
|
|
2039
|
-
]);
|
|
2040
|
-
return zipEntries([
|
|
2041
|
-
jsonlEntry("events.jsonl", events),
|
|
2042
|
-
...logEvents.status === "present" ? [jsonlEntry("logs.jsonl", logEvents.events)] : [],
|
|
2043
|
-
...allEvents.status === "present" ? [jsonlEntry("all.jsonl", allEvents.events)] : []
|
|
2044
|
-
]);
|
|
2006
|
+
const events = await listRunEvents(http, runId);
|
|
2007
|
+
return zipEntries([jsonlEntry("events.jsonl", events)]);
|
|
2045
2008
|
}
|
|
2046
2009
|
async function downloadMetadata(http, runId) {
|
|
2047
2010
|
const run = await getRun(http, runId);
|
|
@@ -2742,7 +2705,7 @@ async function runProxy(io2, rest) {
|
|
|
2742
2705
|
const url = `${manifest.proxyBaseUrl.replace(/\/+$/, "")}/${encodeURIComponent(f.endpointName)}`;
|
|
2743
2706
|
const requestHeaders = new Headers();
|
|
2744
2707
|
requestHeaders.set("authorization", `Bearer ${token}`);
|
|
2745
|
-
requestHeaders.set(PROXY_PROTOCOL_HEADER,
|
|
2708
|
+
requestHeaders.set(PROXY_PROTOCOL_HEADER, PROXY_PROTOCOL_VERSION_V2);
|
|
2746
2709
|
requestHeaders.set(PROXY_METHOD_HEADER, f.method.toUpperCase());
|
|
2747
2710
|
requestHeaders.set(PROXY_PATH_HEADER, f.path);
|
|
2748
2711
|
if (f.query) {
|
|
@@ -2776,6 +2739,11 @@ async function runProxy(io2, rest) {
|
|
|
2776
2739
|
});
|
|
2777
2740
|
return RUNTIME_ERR;
|
|
2778
2741
|
}
|
|
2742
|
+
if (response.headers.get(PROXY_RESP_STATUS_HEADER) !== null) {
|
|
2743
|
+
const envelope = await readStreamedEnvelope(response, f.endpointName);
|
|
2744
|
+
io2.stdout(JSON.stringify(envelope) + "\n");
|
|
2745
|
+
return SUCCESS;
|
|
2746
|
+
}
|
|
2779
2747
|
const text = await response.text();
|
|
2780
2748
|
let parsedBody;
|
|
2781
2749
|
try {
|
|
@@ -2813,6 +2781,39 @@ async function resolveBody(io2, spec) {
|
|
|
2813
2781
|
function emitError(io2, body) {
|
|
2814
2782
|
io2.stderr(JSON.stringify(body) + "\n");
|
|
2815
2783
|
}
|
|
2784
|
+
async function readStreamedEnvelope(response, endpointName) {
|
|
2785
|
+
const effectiveResponseMode = response.headers.get(PROXY_RESP_MODE_HEADER) ?? "headers_only";
|
|
2786
|
+
const upstreamStatus = Number.parseInt(response.headers.get(PROXY_RESP_STATUS_HEADER) ?? "0", 10);
|
|
2787
|
+
const remainingCalls = Number.parseInt(response.headers.get(PROXY_RESP_REMAINING_CALLS_HEADER) ?? "0", 10);
|
|
2788
|
+
const remainingResponseBytes = Number.parseInt(response.headers.get(PROXY_RESP_REMAINING_BYTES_HEADER) ?? "0", 10);
|
|
2789
|
+
let upstreamHeaders = {};
|
|
2790
|
+
const rawHeaders = response.headers.get(PROXY_RESP_UPSTREAM_HEADERS_HEADER);
|
|
2791
|
+
if (rawHeaders) {
|
|
2792
|
+
try {
|
|
2793
|
+
const parsed = JSON.parse(rawHeaders);
|
|
2794
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
2795
|
+
upstreamHeaders = parsed;
|
|
2796
|
+
}
|
|
2797
|
+
} catch {
|
|
2798
|
+
}
|
|
2799
|
+
}
|
|
2800
|
+
const truncatedRaw = response.headers.get(PROXY_RESP_TRUNCATED_HEADER);
|
|
2801
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
2802
|
+
return {
|
|
2803
|
+
endpointName,
|
|
2804
|
+
upstreamStatus,
|
|
2805
|
+
upstreamHeaders,
|
|
2806
|
+
effectiveResponseMode,
|
|
2807
|
+
// The streamed path can't echo the request-side clamp decision (it
|
|
2808
|
+
// isn't carried back); the effective mode is authoritative for the
|
|
2809
|
+
// agent and matches what v1 surfaced for an un-clamped call.
|
|
2810
|
+
modeClamped: false,
|
|
2811
|
+
remainingCalls,
|
|
2812
|
+
remainingResponseBytes,
|
|
2813
|
+
...effectiveResponseMode === "full" && bytes.byteLength > 0 ? { upstreamBodyBase64: Buffer.from(bytes).toString("base64") } : {},
|
|
2814
|
+
...truncatedRaw === "true" ? { truncated: true } : {}
|
|
2815
|
+
};
|
|
2816
|
+
}
|
|
2816
2817
|
async function tryReadManifest(io2) {
|
|
2817
2818
|
try {
|
|
2818
2819
|
const raw = await io2.readFile(AEX_INDEX_PATH);
|
|
@@ -3814,7 +3815,6 @@ async function runOutputsCmd(io2, argv) {
|
|
|
3814
3815
|
import { resolve as resolvePath3 } from "node:path";
|
|
3815
3816
|
var NAMESPACE_DOWNLOADERS = {
|
|
3816
3817
|
outputs: operations_exports.downloadOutputs,
|
|
3817
|
-
logs: operations_exports.downloadLogs,
|
|
3818
3818
|
events: operations_exports.downloadEvents,
|
|
3819
3819
|
metadata: operations_exports.downloadMetadata
|
|
3820
3820
|
};
|
|
@@ -3847,7 +3847,7 @@ async function runDownloadCmd(io2, argv) {
|
|
|
3847
3847
|
const namespace2 = onlyFlag.value;
|
|
3848
3848
|
const positional = onlyFlag.remaining.filter((arg) => !arg.startsWith("--"));
|
|
3849
3849
|
if (positional.length !== 1) {
|
|
3850
|
-
io2.stderr("usage: aex download <run-id> [--only outputs|
|
|
3850
|
+
io2.stderr("usage: aex download <run-id> [--only outputs|events|metadata] [--out path] [common flags]\n");
|
|
3851
3851
|
return USAGE_ERR;
|
|
3852
3852
|
}
|
|
3853
3853
|
const runId = positional[0];
|
package/dist/cli.mjs.sha256
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
2e7ad715af0e691bcc91e7f403c611f03d6e9a1e0566889dd32fd4b956b71779 cli.mjs
|
package/dist/host/download.js
CHANGED
|
@@ -3,14 +3,11 @@
|
|
|
3
3
|
* a run's content as a zip, assembled client-side from the public read
|
|
4
4
|
* endpoints (no per-output id required).
|
|
5
5
|
*
|
|
6
|
-
* Without `--only`, downloads
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* serves channel opt-ins, `outputs/<rel>` (deliverables), `logs/<rel>`
|
|
10
|
-
* (the `.anthropic-debug/` / `.goose-logs/` / `.fly-logs/` diagnostics)
|
|
11
|
-
* — plus `manifest.json`.
|
|
6
|
+
* Without `--only`, downloads everything public — organised into
|
|
7
|
+
* `metadata/run.json`, typed `events/events.jsonl`, `outputs/<rel>`
|
|
8
|
+
* (deliverables), plus `manifest.json`.
|
|
12
9
|
*
|
|
13
|
-
* `--only outputs|
|
|
10
|
+
* `--only outputs|events|metadata` downloads just that one
|
|
14
11
|
* namespace (files at the zip root).
|
|
15
12
|
*
|
|
16
13
|
* `--out` resolves relative to the host CWD; if omitted the file is
|
|
@@ -22,7 +19,6 @@ import { operations } from "@aexhq/contracts";
|
|
|
22
19
|
import { SUCCESS, USAGE_ERR, emitJsonError, makeHttpClient, parseCommonHostFlags, refuseInsideManagedRun, takeFlagValue } from "./common.js";
|
|
23
20
|
const NAMESPACE_DOWNLOADERS = {
|
|
24
21
|
outputs: operations.downloadOutputs,
|
|
25
|
-
logs: operations.downloadLogs,
|
|
26
22
|
events: operations.downloadEvents,
|
|
27
23
|
metadata: operations.downloadMetadata
|
|
28
24
|
};
|
|
@@ -51,7 +47,7 @@ export async function runDownloadCmd(io, argv) {
|
|
|
51
47
|
const namespace = onlyFlag.value;
|
|
52
48
|
const positional = onlyFlag.remaining.filter((arg) => !arg.startsWith("--"));
|
|
53
49
|
if (positional.length !== 1) {
|
|
54
|
-
io.stderr("usage: aex download <run-id> [--only outputs|
|
|
50
|
+
io.stderr("usage: aex download <run-id> [--only outputs|events|metadata] [--out path] [common flags]\n");
|
|
55
51
|
return USAGE_ERR;
|
|
56
52
|
}
|
|
57
53
|
const runId = positional[0];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"download.js","sourceRoot":"","sources":["../../src/host/download.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"download.js","sourceRoot":"","sources":["../../src/host/download.ts"],"names":[],"mappings":"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"}
|
package/dist/proxy.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* This file was extracted from run.ts when the host-side subcommands
|
|
8
8
|
* (run/status/events/outputs/download/cancel/whoami) were added.
|
|
9
9
|
*/
|
|
10
|
-
import { PROXY_PROTOCOL_HEADER,
|
|
10
|
+
import { PROXY_PROTOCOL_HEADER, PROXY_PROTOCOL_VERSION_V2, PROXY_METHOD_HEADER, PROXY_PATH_HEADER, PROXY_QUERY_HEADER, PROXY_HEADERS_HEADER, PROXY_RESPONSE_MODE_HEADER, PROXY_RESPONSE_MODES, PROXY_RESP_MODE_HEADER, PROXY_RESP_REMAINING_BYTES_HEADER, PROXY_RESP_REMAINING_CALLS_HEADER, PROXY_RESP_STATUS_HEADER, PROXY_RESP_TRUNCATED_HEADER, PROXY_RESP_UPSTREAM_HEADERS_HEADER } from "@aexhq/contracts";
|
|
11
11
|
import { AEX_INDEX_PATH, AEX_RUN_TOKEN_PATH } from "./internal.js";
|
|
12
12
|
import { SUCCESS, USAGE_ERR, RUNTIME_ERR } from "./host/common.js";
|
|
13
13
|
function parseProxyFlags(rest) {
|
|
@@ -167,7 +167,7 @@ export async function runProxy(io, rest) {
|
|
|
167
167
|
const url = `${manifest.proxyBaseUrl.replace(/\/+$/, "")}/${encodeURIComponent(f.endpointName)}`;
|
|
168
168
|
const requestHeaders = new Headers();
|
|
169
169
|
requestHeaders.set("authorization", `Bearer ${token}`);
|
|
170
|
-
requestHeaders.set(PROXY_PROTOCOL_HEADER,
|
|
170
|
+
requestHeaders.set(PROXY_PROTOCOL_HEADER, PROXY_PROTOCOL_VERSION_V2);
|
|
171
171
|
requestHeaders.set(PROXY_METHOD_HEADER, f.method.toUpperCase());
|
|
172
172
|
requestHeaders.set(PROXY_PATH_HEADER, f.path);
|
|
173
173
|
if (f.query) {
|
|
@@ -202,6 +202,17 @@ export async function runProxy(io, rest) {
|
|
|
202
202
|
});
|
|
203
203
|
return RUNTIME_ERR;
|
|
204
204
|
}
|
|
205
|
+
// v2 streamed success: the Worker carries the envelope metadata in the
|
|
206
|
+
// x-aex-proxy-* response headers and streams the (already byte-capped)
|
|
207
|
+
// body. Reconstruct the same ProxyResponseEnvelope JSON the agent saw
|
|
208
|
+
// under v1 so the stdout contract is unchanged. A BFF-level error (e.g.
|
|
209
|
+
// unsupported_protocol, policy_denied) still returns a JSON error body
|
|
210
|
+
// with no status header, so it falls through to the JSON path below.
|
|
211
|
+
if (response.headers.get(PROXY_RESP_STATUS_HEADER) !== null) {
|
|
212
|
+
const envelope = await readStreamedEnvelope(response, f.endpointName);
|
|
213
|
+
io.stdout(JSON.stringify(envelope) + "\n");
|
|
214
|
+
return SUCCESS;
|
|
215
|
+
}
|
|
205
216
|
const text = await response.text();
|
|
206
217
|
let parsedBody;
|
|
207
218
|
try {
|
|
@@ -244,6 +255,51 @@ async function resolveBody(io, spec) {
|
|
|
244
255
|
function emitError(io, body) {
|
|
245
256
|
io.stderr(JSON.stringify(body) + "\n");
|
|
246
257
|
}
|
|
258
|
+
/**
|
|
259
|
+
* Reassemble a {@link ProxyResponseEnvelope} from a v2 streamed response.
|
|
260
|
+
* The Worker has already enforced the byte-cap, so reading the body to the
|
|
261
|
+
* end here is bounded by `maxResponseBytes` — the OOM risk lived on the
|
|
262
|
+
* Worker isolate, not in this per-call container process.
|
|
263
|
+
*/
|
|
264
|
+
async function readStreamedEnvelope(response, endpointName) {
|
|
265
|
+
const effectiveResponseMode = (response.headers.get(PROXY_RESP_MODE_HEADER) ??
|
|
266
|
+
"headers_only");
|
|
267
|
+
const upstreamStatus = Number.parseInt(response.headers.get(PROXY_RESP_STATUS_HEADER) ?? "0", 10);
|
|
268
|
+
const remainingCalls = Number.parseInt(response.headers.get(PROXY_RESP_REMAINING_CALLS_HEADER) ?? "0", 10);
|
|
269
|
+
const remainingResponseBytes = Number.parseInt(response.headers.get(PROXY_RESP_REMAINING_BYTES_HEADER) ?? "0", 10);
|
|
270
|
+
let upstreamHeaders = {};
|
|
271
|
+
const rawHeaders = response.headers.get(PROXY_RESP_UPSTREAM_HEADERS_HEADER);
|
|
272
|
+
if (rawHeaders) {
|
|
273
|
+
try {
|
|
274
|
+
const parsed = JSON.parse(rawHeaders);
|
|
275
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
276
|
+
upstreamHeaders = parsed;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
// The metadata header is Worker-controlled; a malformed value is a
|
|
281
|
+
// protocol bug, not agent input. Degrade to empty rather than crash.
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
const truncatedRaw = response.headers.get(PROXY_RESP_TRUNCATED_HEADER);
|
|
285
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
286
|
+
return {
|
|
287
|
+
endpointName,
|
|
288
|
+
upstreamStatus,
|
|
289
|
+
upstreamHeaders,
|
|
290
|
+
effectiveResponseMode,
|
|
291
|
+
// The streamed path can't echo the request-side clamp decision (it
|
|
292
|
+
// isn't carried back); the effective mode is authoritative for the
|
|
293
|
+
// agent and matches what v1 surfaced for an un-clamped call.
|
|
294
|
+
modeClamped: false,
|
|
295
|
+
remainingCalls,
|
|
296
|
+
remainingResponseBytes,
|
|
297
|
+
...(effectiveResponseMode === "full" && bytes.byteLength > 0
|
|
298
|
+
? { upstreamBodyBase64: Buffer.from(bytes).toString("base64") }
|
|
299
|
+
: {}),
|
|
300
|
+
...(truncatedRaw === "true" ? { truncated: true } : {})
|
|
301
|
+
};
|
|
302
|
+
}
|
|
247
303
|
export async function tryReadManifest(io) {
|
|
248
304
|
try {
|
|
249
305
|
const raw = await io.readFile(AEX_INDEX_PATH);
|
package/dist/proxy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,0BAA0B,EAC1B,oBAAoB,EACpB,sBAAsB,EACtB,iCAAiC,EACjC,iCAAiC,EACjC,wBAAwB,EACxB,2BAA2B,EAC3B,kCAAkC,EAKnC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAc,MAAM,eAAe,CAAC;AAC/E,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAoB,MAAM,kBAAkB,CAAC;AAarF,SAAS,eAAe,CAAC,IAAuB;IAC9C,IAAI,YAAY,GAAkB,IAAI,CAAC;IACvC,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,IAAI,GAAG,GAAG,CAAC;IACf,IAAI,KAAK,GAAkB,IAAI,CAAC;IAChC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC1C,IAAI,QAAQ,GAAkB,IAAI,CAAC;IACnC,IAAI,YAAY,GAAkB,IAAI,CAAC;IACvC,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACrB,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACrC,QAAQ,GAAG,IAAI,CAAC;YAChB,SAAS;QACX,CAAC;QACD,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;YACvB,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;YACvC,SAAS;QACX,CAAC;QACD,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YACrB,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;YACnC,SAAS;QACX,CAAC;QACD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;YACrC,SAAS;QACX,CAAC;QACD,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;YACvB,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;YACzC,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC3B,IAAI,EAAE,IAAI,CAAC;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,wCAAwC,EAAE,CAAC;YACpF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;YAC7D,SAAS;QACX,CAAC;QACD,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YACrB,QAAQ,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;YACvC,SAAS;QACX,CAAC;QACD,IAAI,GAAG,KAAK,iBAAiB,EAAE,CAAC;YAC9B,YAAY,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,iBAAiB,CAAC,CAAC;YACpD,SAAS;QACX,CAAC;QACD,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,GAAG,EAAE,EAAE,CAAC;QACvD,CAAC;QACD,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;YAC1B,YAAY,GAAG,GAAG,CAAC;YACnB,SAAS;QACX,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,mCAAmC,GAAG,EAAE,EAAE,CAAC;IACzE,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,CAAC;AAC/G,CAAC;AAED,SAAS,MAAM,CAAC,GAAsB,EAAE,GAAW,EAAE,IAAY;IAC/D,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IACnB,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;QACpB,MAAM,IAAI,aAAa,CAAC,GAAG,IAAI,mBAAmB,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,aAAc,SAAQ,KAAK;CAAG;AAEpC,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EAAS;IAC5C,EAAE,CAAC,MAAM,CAAC,uEAAuE,CAAC,CAAC;IACnF,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACtB,EAAE,CAAC,MAAM,CAAC,yCAAyC,CAAC,CAAC;IACrD,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACtB,EAAE,CAAC,MAAM,CAAC,yDAAyD,CAAC,CAAC;IACrE,EAAE,CAAC,MAAM,CAAC,+EAA+E,CAAC,CAAC;IAC3F,EAAE,CAAC,MAAM,CAAC,mFAAmF,CAAC,CAAC;IAC/F,EAAE,CAAC,MAAM,CAAC,+DAA+D,CAAC,CAAC;IAC3E,EAAE,CAAC,MAAM,CAAC,0FAA0F,CAAC,CAAC;IACtG,EAAE,CAAC,MAAM,CAAC,yFAAyF,CAAC,CAAC;IACrG,EAAE,CAAC,MAAM,CAAC,kDAAkD,CAAC,CAAC;IAC9D,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,EAAE,CAAC,CAAC;IAC3C,IAAI,QAAQ,IAAI,QAAQ,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,EAAE,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC;QACnC,KAAK,MAAM,EAAE,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;YACpC,EAAE,CAAC,MAAM,CACP,OAAO,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,YAAY,YAAY,EAAE,CAAC,aAAa,SAAS,CAC7I,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,EAAS,EAAE,IAAuB;IAC/D,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,aAAa,EAAE,CAAC;YACjC,EAAE,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;YAC9B,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,EAAE,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;QAChC,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;IACvB,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;QACf,OAAO,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC;QACpB,EAAE,CAAC,MAAM,CAAC,yBAAyB,CAAC,CAAC;QACrC,EAAE,CAAC,MAAM,CAAC,4CAA4C,CAAC,CAAC;QACxD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,CAAC,CAAC,YAAY,IAAI,CAAE,oBAA0C,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC;QAC5F,EAAE,CAAC,MAAM,CAAC,mCAAmC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClF,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,EAAE,CAAC,CAAC;IAC3C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,SAAS,CAAC,EAAE,EAAE;YACZ,KAAK,EAAE,gBAAgB;YACvB,OAAO,EAAE,mEAAmE;SAC7E,CAAC,CAAC;QACH,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;QAC3B,SAAS,CAAC,EAAE,EAAE;YACZ,KAAK,EAAE,oBAAoB;YAC3B,OAAO,EAAE,0CAA0C;YACnD,YAAY,EAAE,CAAC,CAAC,YAAY;SAC7B,CAAC,CAAC;QACH,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,IAAI,KAAa,CAAC;IAClB,IAAI,CAAC;QACH,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,SAAS,CAAC,EAAE,EAAE;YACZ,KAAK,EAAE,cAAc;YACrB,OAAO,EAAE,sDAAsD;SAChE,CAAC,CAAC;QACH,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC,CAAC;QACxE,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,IAAI,IAA4B,CAAC;IACjC,IAAI,CAAC,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC3C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,EAAE,CAAC,MAAM,CAAC,gCAAiC,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;YACtE,OAAO,WAAW,CAAC;QACrB,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAG,GAAG,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,kBAAkB,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC;IACjG,MAAM,cAAc,GAAG,IAAI,OAAO,EAAE,CAAC;IACrC,cAAc,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,KAAK,EAAE,CAAC,CAAC;IACvD,cAAc,CAAC,GAAG,CAAC,qBAAqB,EAAE,yBAAyB,CAAC,CAAC;IACrE,cAAc,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAChE,cAAc,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;QACZ,cAAc,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACvB,cAAc,CAAC,GAAG,CAAC,oBAAoB,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC1F,CAAC;IACD,IAAI,CAAC,CAAC,YAAY,EAAE,CAAC;QACnB,cAAc,CAAC,GAAG,CAAC,0BAA0B,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,cAAc,CAAC,GAAG,CAAC,gBAAgB,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,IAAI,GAAgB;QACxB,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,cAAc;QACvB,QAAQ,EAAE,QAAQ;KACnB,CAAC;IACF,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,SAAS,CAAC,EAAE,EAAE;YACZ,KAAK,EAAE,gBAAgB;YACvB,OAAO,EAAE,yBAA0B,GAAa,CAAC,OAAO,EAAE;YAC1D,YAAY,EAAE,CAAC,CAAC,YAAY;SAC7B,CAAC,CAAC;QACH,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,uEAAuE;IACvE,uEAAuE;IACvE,sEAAsE;IACtE,wEAAwE;IACxE,uEAAuE;IACvE,qEAAqE;IACrE,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,KAAK,IAAI,EAAE,CAAC;QAC5D,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,QAAQ,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;QACtE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;QAC3C,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,IAAI,UAAmB,CAAC;IACxB,IAAI,CAAC;QACH,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,8DAA8D;QAC9D,kEAAkE;QAClE,+DAA+D;QAC/D,qDAAqD;QACrD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/D,SAAS,CAAC,EAAE,EAAE;YACZ,KAAK,EAAE,gBAAgB;YACvB,OAAO,EAAE,0CAA0C,QAAQ,CAAC,MAAM,UAAU,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG;YACtG,YAAY,EAAE,CAAC,CAAC,YAAY;SAC7B,CAAC,CAAC;QACH,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,CAAC;QAC7C,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,EAAS,EAAE,IAAY;IAChD,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAC7C,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC3B,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACrC,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,SAAS,CAAC,EAAS,EAAE,IAAoB;IAChD,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;AACzC,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,oBAAoB,CACjC,QAAkB,EAClB,YAAoB;IAEpB,MAAM,qBAAqB,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;QACzE,cAAc,CAAsB,CAAC;IACvC,MAAM,cAAc,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;IAClG,MAAM,cAAc,GAAG,MAAM,CAAC,QAAQ,CACpC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,IAAI,GAAG,EAC9D,EAAE,CACH,CAAC;IACF,MAAM,sBAAsB,GAAG,MAAM,CAAC,QAAQ,CAC5C,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,IAAI,GAAG,EAC9D,EAAE,CACH,CAAC;IACF,IAAI,eAAe,GAA2B,EAAE,CAAC;IACjD,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAC5E,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACtC,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBACnE,eAAe,GAAG,MAAgC,CAAC;YACrD,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,mEAAmE;YACnE,qEAAqE;QACvE,CAAC;IACH,CAAC;IACD,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IACvE,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;IAE3D,OAAO;QACL,YAAY;QACZ,cAAc;QACd,eAAe;QACf,qBAAqB;QACrB,mEAAmE;QACnE,mEAAmE;QACnE,6DAA6D;QAC7D,WAAW,EAAE,KAAK;QAClB,cAAc;QACd,sBAAsB;QACtB,GAAG,CAAC,qBAAqB,KAAK,MAAM,IAAI,KAAK,CAAC,UAAU,GAAG,CAAC;YAC1D,CAAC,CAAC,EAAE,kBAAkB,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;YAC/D,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,YAAY,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACxD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EAAS;IAC7C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAmB,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aexhq/cli",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.8",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/aexhq/aex.git"
|
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"fflate": "^0.8.2",
|
|
30
|
-
"@aexhq/contracts": "0.13.
|
|
30
|
+
"@aexhq/contracts": "0.13.8"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"esbuild": "^0.28.0"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
|
-
"build": "tsc -p tsconfig.build.json && node ./scripts/finalize-bundle.mjs",
|
|
36
|
+
"build": "pnpm --filter @aexhq/contracts run build && tsc -p tsconfig.build.json && node ./scripts/finalize-bundle.mjs",
|
|
37
37
|
"lint": "tsc --noEmit -p tsconfig.json",
|
|
38
38
|
"pretest": "pnpm run build",
|
|
39
39
|
"test": "pnpm test:unit",
|
package/src/host/download.ts
CHANGED
|
@@ -3,14 +3,11 @@
|
|
|
3
3
|
* a run's content as a zip, assembled client-side from the public read
|
|
4
4
|
* endpoints (no per-output id required).
|
|
5
5
|
*
|
|
6
|
-
* Without `--only`, downloads
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* serves channel opt-ins, `outputs/<rel>` (deliverables), `logs/<rel>`
|
|
10
|
-
* (the `.anthropic-debug/` / `.goose-logs/` / `.fly-logs/` diagnostics)
|
|
11
|
-
* — plus `manifest.json`.
|
|
6
|
+
* Without `--only`, downloads everything public — organised into
|
|
7
|
+
* `metadata/run.json`, typed `events/events.jsonl`, `outputs/<rel>`
|
|
8
|
+
* (deliverables), plus `manifest.json`.
|
|
12
9
|
*
|
|
13
|
-
* `--only outputs|
|
|
10
|
+
* `--only outputs|events|metadata` downloads just that one
|
|
14
11
|
* namespace (files at the zip root).
|
|
15
12
|
*
|
|
16
13
|
* `--out` resolves relative to the host CWD; if omitted the file is
|
|
@@ -31,11 +28,10 @@ import {
|
|
|
31
28
|
takeFlagValue
|
|
32
29
|
} from "./common.js";
|
|
33
30
|
|
|
34
|
-
type Namespace = "outputs" | "
|
|
31
|
+
type Namespace = "outputs" | "events" | "metadata";
|
|
35
32
|
|
|
36
33
|
const NAMESPACE_DOWNLOADERS = {
|
|
37
34
|
outputs: operations.downloadOutputs,
|
|
38
|
-
logs: operations.downloadLogs,
|
|
39
35
|
events: operations.downloadEvents,
|
|
40
36
|
metadata: operations.downloadMetadata
|
|
41
37
|
} satisfies Record<Namespace, typeof operations.download>;
|
|
@@ -66,7 +62,7 @@ export async function runDownloadCmd(io: CliIO, argv: readonly string[]): Promis
|
|
|
66
62
|
|
|
67
63
|
const positional = onlyFlag.remaining.filter((arg) => !arg.startsWith("--"));
|
|
68
64
|
if (positional.length !== 1) {
|
|
69
|
-
io.stderr("usage: aex download <run-id> [--only outputs|
|
|
65
|
+
io.stderr("usage: aex download <run-id> [--only outputs|events|metadata] [--out path] [common flags]\n");
|
|
70
66
|
return USAGE_ERR;
|
|
71
67
|
}
|
|
72
68
|
const runId = positional[0]!;
|
package/src/proxy.ts
CHANGED
|
@@ -9,15 +9,23 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import {
|
|
11
11
|
PROXY_PROTOCOL_HEADER,
|
|
12
|
-
|
|
12
|
+
PROXY_PROTOCOL_VERSION_V2,
|
|
13
13
|
PROXY_METHOD_HEADER,
|
|
14
14
|
PROXY_PATH_HEADER,
|
|
15
15
|
PROXY_QUERY_HEADER,
|
|
16
16
|
PROXY_HEADERS_HEADER,
|
|
17
17
|
PROXY_RESPONSE_MODE_HEADER,
|
|
18
18
|
PROXY_RESPONSE_MODES,
|
|
19
|
+
PROXY_RESP_MODE_HEADER,
|
|
20
|
+
PROXY_RESP_REMAINING_BYTES_HEADER,
|
|
21
|
+
PROXY_RESP_REMAINING_CALLS_HEADER,
|
|
22
|
+
PROXY_RESP_STATUS_HEADER,
|
|
23
|
+
PROXY_RESP_TRUNCATED_HEADER,
|
|
24
|
+
PROXY_RESP_UPSTREAM_HEADERS_HEADER,
|
|
19
25
|
type ProxyErrorBody,
|
|
20
|
-
type ProxyIndexFile
|
|
26
|
+
type ProxyIndexFile,
|
|
27
|
+
type ProxyResponseEnvelope,
|
|
28
|
+
type ProxyResponseMode
|
|
21
29
|
} from "@aexhq/contracts";
|
|
22
30
|
import { AEX_INDEX_PATH, AEX_RUN_TOKEN_PATH, type CliIO } from "./internal.js";
|
|
23
31
|
import { SUCCESS, USAGE_ERR, RUNTIME_ERR, type CliExitCode } from "./host/common.js";
|
|
@@ -196,7 +204,7 @@ export async function runProxy(io: CliIO, rest: readonly string[]): Promise<CliE
|
|
|
196
204
|
const url = `${manifest.proxyBaseUrl.replace(/\/+$/, "")}/${encodeURIComponent(f.endpointName)}`;
|
|
197
205
|
const requestHeaders = new Headers();
|
|
198
206
|
requestHeaders.set("authorization", `Bearer ${token}`);
|
|
199
|
-
requestHeaders.set(PROXY_PROTOCOL_HEADER,
|
|
207
|
+
requestHeaders.set(PROXY_PROTOCOL_HEADER, PROXY_PROTOCOL_VERSION_V2);
|
|
200
208
|
requestHeaders.set(PROXY_METHOD_HEADER, f.method.toUpperCase());
|
|
201
209
|
requestHeaders.set(PROXY_PATH_HEADER, f.path);
|
|
202
210
|
if (f.query) {
|
|
@@ -233,6 +241,18 @@ export async function runProxy(io: CliIO, rest: readonly string[]): Promise<CliE
|
|
|
233
241
|
return RUNTIME_ERR;
|
|
234
242
|
}
|
|
235
243
|
|
|
244
|
+
// v2 streamed success: the Worker carries the envelope metadata in the
|
|
245
|
+
// x-aex-proxy-* response headers and streams the (already byte-capped)
|
|
246
|
+
// body. Reconstruct the same ProxyResponseEnvelope JSON the agent saw
|
|
247
|
+
// under v1 so the stdout contract is unchanged. A BFF-level error (e.g.
|
|
248
|
+
// unsupported_protocol, policy_denied) still returns a JSON error body
|
|
249
|
+
// with no status header, so it falls through to the JSON path below.
|
|
250
|
+
if (response.headers.get(PROXY_RESP_STATUS_HEADER) !== null) {
|
|
251
|
+
const envelope = await readStreamedEnvelope(response, f.endpointName);
|
|
252
|
+
io.stdout(JSON.stringify(envelope) + "\n");
|
|
253
|
+
return SUCCESS;
|
|
254
|
+
}
|
|
255
|
+
|
|
236
256
|
const text = await response.text();
|
|
237
257
|
let parsedBody: unknown;
|
|
238
258
|
try {
|
|
@@ -278,6 +298,61 @@ function emitError(io: CliIO, body: ProxyErrorBody): void {
|
|
|
278
298
|
io.stderr(JSON.stringify(body) + "\n");
|
|
279
299
|
}
|
|
280
300
|
|
|
301
|
+
/**
|
|
302
|
+
* Reassemble a {@link ProxyResponseEnvelope} from a v2 streamed response.
|
|
303
|
+
* The Worker has already enforced the byte-cap, so reading the body to the
|
|
304
|
+
* end here is bounded by `maxResponseBytes` — the OOM risk lived on the
|
|
305
|
+
* Worker isolate, not in this per-call container process.
|
|
306
|
+
*/
|
|
307
|
+
async function readStreamedEnvelope(
|
|
308
|
+
response: Response,
|
|
309
|
+
endpointName: string
|
|
310
|
+
): Promise<ProxyResponseEnvelope> {
|
|
311
|
+
const effectiveResponseMode = (response.headers.get(PROXY_RESP_MODE_HEADER) ??
|
|
312
|
+
"headers_only") as ProxyResponseMode;
|
|
313
|
+
const upstreamStatus = Number.parseInt(response.headers.get(PROXY_RESP_STATUS_HEADER) ?? "0", 10);
|
|
314
|
+
const remainingCalls = Number.parseInt(
|
|
315
|
+
response.headers.get(PROXY_RESP_REMAINING_CALLS_HEADER) ?? "0",
|
|
316
|
+
10
|
|
317
|
+
);
|
|
318
|
+
const remainingResponseBytes = Number.parseInt(
|
|
319
|
+
response.headers.get(PROXY_RESP_REMAINING_BYTES_HEADER) ?? "0",
|
|
320
|
+
10
|
|
321
|
+
);
|
|
322
|
+
let upstreamHeaders: Record<string, string> = {};
|
|
323
|
+
const rawHeaders = response.headers.get(PROXY_RESP_UPSTREAM_HEADERS_HEADER);
|
|
324
|
+
if (rawHeaders) {
|
|
325
|
+
try {
|
|
326
|
+
const parsed = JSON.parse(rawHeaders);
|
|
327
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
328
|
+
upstreamHeaders = parsed as Record<string, string>;
|
|
329
|
+
}
|
|
330
|
+
} catch {
|
|
331
|
+
// The metadata header is Worker-controlled; a malformed value is a
|
|
332
|
+
// protocol bug, not agent input. Degrade to empty rather than crash.
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const truncatedRaw = response.headers.get(PROXY_RESP_TRUNCATED_HEADER);
|
|
336
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
337
|
+
|
|
338
|
+
return {
|
|
339
|
+
endpointName,
|
|
340
|
+
upstreamStatus,
|
|
341
|
+
upstreamHeaders,
|
|
342
|
+
effectiveResponseMode,
|
|
343
|
+
// The streamed path can't echo the request-side clamp decision (it
|
|
344
|
+
// isn't carried back); the effective mode is authoritative for the
|
|
345
|
+
// agent and matches what v1 surfaced for an un-clamped call.
|
|
346
|
+
modeClamped: false,
|
|
347
|
+
remainingCalls,
|
|
348
|
+
remainingResponseBytes,
|
|
349
|
+
...(effectiveResponseMode === "full" && bytes.byteLength > 0
|
|
350
|
+
? { upstreamBodyBase64: Buffer.from(bytes).toString("base64") }
|
|
351
|
+
: {}),
|
|
352
|
+
...(truncatedRaw === "true" ? { truncated: true } : {})
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
281
356
|
export async function tryReadManifest(io: CliIO): Promise<ProxyIndexFile | null> {
|
|
282
357
|
try {
|
|
283
358
|
const raw = await io.readFile(AEX_INDEX_PATH);
|
package/test/cli.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from "vitest";
|
|
2
|
-
import { PROXY_PROTOCOL_VERSION } from "@aexhq/contracts";
|
|
2
|
+
import { PROXY_PROTOCOL_VERSION, PROXY_PROTOCOL_VERSION_V2 } from "@aexhq/contracts";
|
|
3
3
|
import { runCli } from "../src/run.js";
|
|
4
4
|
import { AEX_INDEX_PATH, AEX_RUN_TOKEN_PATH, type CliIO } from "../src/internal.js";
|
|
5
5
|
|
|
@@ -228,13 +228,48 @@ describe("aex proxy — successful call", () => {
|
|
|
228
228
|
expect(call.url).toBe("https://dash.example.com/api/runs/run-1/proxy/stripe");
|
|
229
229
|
const headers = new Headers((call.init as RequestInit).headers);
|
|
230
230
|
expect(headers.get("authorization")).toBe("Bearer bearer-xyz");
|
|
231
|
-
expect(headers.get("x-aex-proxy-protocol")).toBe(
|
|
231
|
+
expect(headers.get("x-aex-proxy-protocol")).toBe(PROXY_PROTOCOL_VERSION_V2);
|
|
232
232
|
expect(headers.get("x-aex-method")).toBe("POST");
|
|
233
233
|
expect(headers.get("x-aex-path")).toBe("/v1/refunds");
|
|
234
234
|
const body = JSON.parse(cap.stdout.trim());
|
|
235
235
|
expect(body.upstreamStatus).toBe(200);
|
|
236
236
|
});
|
|
237
237
|
|
|
238
|
+
it("reconstructs the envelope from a v2 streamed response (headers + raw body)", async () => {
|
|
239
|
+
const upstreamPayload = JSON.stringify({ streamed: true });
|
|
240
|
+
const cap = makeIo({
|
|
241
|
+
argv: ["proxy", "stripe", "--method", "POST", "--path", "/v1/refunds", "--response-mode", "full"],
|
|
242
|
+
files: {
|
|
243
|
+
[AEX_INDEX_PATH]: manifestJson({ endpoints: [{ name: "stripe", allowMethods: ["POST"] }] }),
|
|
244
|
+
[AEX_RUN_TOKEN_PATH]: "bearer-xyz"
|
|
245
|
+
},
|
|
246
|
+
// Mirror the Worker v2 streamed response: raw upstream body + the
|
|
247
|
+
// x-aex-proxy-* metadata headers (no JSON envelope, no base64).
|
|
248
|
+
fetchHandler: async () =>
|
|
249
|
+
new Response(upstreamPayload, {
|
|
250
|
+
status: 200,
|
|
251
|
+
headers: {
|
|
252
|
+
"x-aex-proxy-status": "200",
|
|
253
|
+
"x-aex-proxy-effective-mode": "full",
|
|
254
|
+
"x-aex-proxy-truncated": "false",
|
|
255
|
+
"x-aex-proxy-remaining-calls": "59",
|
|
256
|
+
"x-aex-proxy-remaining-bytes": "999000",
|
|
257
|
+
"x-aex-proxy-upstream-headers": JSON.stringify({ "content-type": "application/json" }),
|
|
258
|
+
"content-type": "application/octet-stream"
|
|
259
|
+
}
|
|
260
|
+
})
|
|
261
|
+
});
|
|
262
|
+
await runCli(cap.io);
|
|
263
|
+
expect(cap.exitCode).toBe(0);
|
|
264
|
+
const body = JSON.parse(cap.stdout.trim());
|
|
265
|
+
expect(body.upstreamStatus).toBe(200);
|
|
266
|
+
expect(body.effectiveResponseMode).toBe("full");
|
|
267
|
+
expect(body.remainingCalls).toBe(59);
|
|
268
|
+
expect(body.upstreamHeaders["content-type"]).toBe("application/json");
|
|
269
|
+
// Body round-trips through the same base64 field v1 used.
|
|
270
|
+
expect(Buffer.from(body.upstreamBodyBase64, "base64").toString("utf8")).toBe(upstreamPayload);
|
|
271
|
+
});
|
|
272
|
+
|
|
238
273
|
it("forwards --header K=V via the X-Aex-Headers JSON record", async () => {
|
|
239
274
|
let captured: Headers | null = null;
|
|
240
275
|
const cap = makeIo({
|
package/test/host.test.ts
CHANGED
|
@@ -446,9 +446,7 @@ describe("aex cancel + delete", () => {
|
|
|
446
446
|
|
|
447
447
|
describe("aex download", () => {
|
|
448
448
|
// Route the reads the download verbs fan out to: getRun + listEvents +
|
|
449
|
-
// listOutputs +
|
|
450
|
-
// deliverable (report.txt in the outputs namespace) and one legacy-named
|
|
451
|
-
// diagnostic in the logs namespace.
|
|
449
|
+
// listOutputs + per-output /download.
|
|
452
450
|
const json = (body: unknown) =>
|
|
453
451
|
new Response(JSON.stringify(body), { status: 200, headers: { "content-type": "application/json" } });
|
|
454
452
|
const wholeRunHandler =
|
|
@@ -458,19 +456,13 @@ describe("aex download", () => {
|
|
|
458
456
|
if (url.endsWith(`/api/runs/${runId}/outputs`)) {
|
|
459
457
|
return json({ outputs: [{ id: "o1", filename: "report.txt", sizeBytes: 5, contentType: "text/plain" }] });
|
|
460
458
|
}
|
|
461
|
-
if (url.endsWith(`/api/runs/${runId}/logs`)) {
|
|
462
|
-
return json({ logs: [{ id: "o2", filename: "goose-logs/stderr.log", sizeBytes: 3, contentType: "text/plain" }] });
|
|
463
|
-
}
|
|
464
459
|
if (url.endsWith(`/api/runs/${runId}/outputs/o1/download`)) {
|
|
465
460
|
return new Response(strToU8("hello").buffer, { status: 200, headers: { "content-type": "text/plain" } });
|
|
466
461
|
}
|
|
467
|
-
if (url.endsWith(`/api/runs/${runId}/logs/o2/download`)) {
|
|
468
|
-
return new Response(strToU8("err").buffer, { status: 200, headers: { "content-type": "text/plain" } });
|
|
469
|
-
}
|
|
470
462
|
return json({ id: runId, status: "succeeded" });
|
|
471
463
|
};
|
|
472
464
|
|
|
473
|
-
it("assembles the whole-run zip client-side
|
|
465
|
+
it("assembles the public whole-run zip client-side and writes it to --out", async () => {
|
|
474
466
|
const writes = new Map<string, Uint8Array>();
|
|
475
467
|
const cap = makeHostIo({
|
|
476
468
|
argv: ["download", "run-1", "--out", "run-1.zip", ...COMMON],
|
|
@@ -479,16 +471,14 @@ describe("aex download", () => {
|
|
|
479
471
|
});
|
|
480
472
|
await runCli(cap.io);
|
|
481
473
|
expect(cap.exitCode).toBe(0);
|
|
482
|
-
// getRun + events +
|
|
483
|
-
|
|
484
|
-
expect(cap.calls).toHaveLength(8);
|
|
474
|
+
// getRun + events + outputs + one per-output download.
|
|
475
|
+
expect(cap.calls).toHaveLength(4);
|
|
485
476
|
|
|
486
477
|
const writtenKey = [...writes.keys()][0]!;
|
|
487
478
|
expect(writtenKey).toMatch(/run-1\.zip$/);
|
|
488
479
|
const entries = unzipSync(writes.get(writtenKey)!);
|
|
489
480
|
expect(Object.keys(entries).sort()).toEqual([
|
|
490
481
|
"events/events.jsonl",
|
|
491
|
-
"logs/runtime/stderr.log",
|
|
492
482
|
"manifest.json",
|
|
493
483
|
"metadata/run.json",
|
|
494
484
|
"outputs/report.txt"
|
|
@@ -532,17 +522,15 @@ describe("aex download", () => {
|
|
|
532
522
|
expect((JSON.parse(cap.stdout.trim()) as { namespace: string }).namespace).toBe("outputs");
|
|
533
523
|
});
|
|
534
524
|
|
|
535
|
-
it("--only logs
|
|
536
|
-
const writes = new Map<string, Uint8Array>();
|
|
525
|
+
it("rejects --only logs with a usage error", async () => {
|
|
537
526
|
const cap = makeHostIo({
|
|
538
527
|
argv: ["download", "run-1", "--only", "logs", ...COMMON],
|
|
539
|
-
writes,
|
|
540
528
|
fetchHandler: wholeRunHandler("run-1")
|
|
541
529
|
});
|
|
542
530
|
await runCli(cap.io);
|
|
543
|
-
expect(cap.exitCode).toBe(
|
|
544
|
-
|
|
545
|
-
expect(
|
|
531
|
+
expect(cap.exitCode).toBe(2);
|
|
532
|
+
expect(cap.stderr).toContain("--only must be one of");
|
|
533
|
+
expect(cap.calls).toHaveLength(0);
|
|
546
534
|
});
|
|
547
535
|
|
|
548
536
|
it("--only metadata reads only the run record", async () => {
|
|
@@ -1031,14 +1019,14 @@ describe("aex skills", () => {
|
|
|
1031
1019
|
JSON.stringify({
|
|
1032
1020
|
ok: true,
|
|
1033
1021
|
skillId: "skl_cli_42",
|
|
1034
|
-
uploadUrl: "https://
|
|
1022
|
+
uploadUrl: "https://object-storage.example.test/bucket/assets/ws/hash?X-Amz-Signature=sig",
|
|
1035
1023
|
requiredHeaders: { "x-amz-checksum-sha256": "Y2hlY2tzdW0=" },
|
|
1036
1024
|
expiresInSeconds: 300
|
|
1037
1025
|
}),
|
|
1038
1026
|
{ status: 201, headers: { "content-type": "application/json" } }
|
|
1039
1027
|
);
|
|
1040
1028
|
}
|
|
1041
|
-
if (call.url.includes("
|
|
1029
|
+
if (call.url.includes("object-storage.example.test")) {
|
|
1042
1030
|
return new Response("", { status: 200 }); // object storage accepts the direct PUT
|
|
1043
1031
|
}
|
|
1044
1032
|
if (call.url.endsWith("/api/skills/skl_cli_42/finalize")) {
|
|
@@ -1058,11 +1046,11 @@ describe("aex skills", () => {
|
|
|
1058
1046
|
expect(cap.exitCode).toBe(0);
|
|
1059
1047
|
const urls = cap.calls.map((c) => c.url);
|
|
1060
1048
|
expect(urls).toContain("https://dash.example/api/skills/presign");
|
|
1061
|
-
expect(urls.some((u) => u.includes("
|
|
1049
|
+
expect(urls.some((u) => u.includes("object-storage.example.test"))).toBe(true);
|
|
1062
1050
|
expect(urls).toContain("https://dash.example/api/skills/skl_cli_42/finalize");
|
|
1063
|
-
const
|
|
1064
|
-
expect(
|
|
1065
|
-
expect((
|
|
1051
|
+
const storagePut = cap.calls.find((c) => c.url.includes("object-storage.example.test"))!;
|
|
1052
|
+
expect(storagePut.init.method).toBe("PUT");
|
|
1053
|
+
expect((storagePut.init.headers as Record<string, string>)["x-amz-checksum-sha256"]).toBe("Y2hlY2tzdW0=");
|
|
1066
1054
|
const printed = JSON.parse(cap.stdout.trim()) as { id: string; name: string };
|
|
1067
1055
|
expect(printed.id).toBe("skl_cli_42");
|
|
1068
1056
|
expect(printed.name).toBe("rules-cli");
|
|
@@ -1099,7 +1087,7 @@ describe("aex skills", () => {
|
|
|
1099
1087
|
const urls = cap.calls.map((c) => c.url);
|
|
1100
1088
|
expect(urls).toContain("https://dash.example/api/skills/presign");
|
|
1101
1089
|
expect(urls).toContain("https://dash.example/api/skills");
|
|
1102
|
-
expect(urls.some((u) => u.includes("
|
|
1090
|
+
expect(urls.some((u) => u.includes("object-storage.example.test"))).toBe(false);
|
|
1103
1091
|
const printed = JSON.parse(cap.stdout.trim()) as { id: string };
|
|
1104
1092
|
expect(printed.id).toBe("skl_fb");
|
|
1105
1093
|
} finally {
|