@aexhq/sdk 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/README.md +14 -14
- package/dist/_contracts/connection-ticket.d.ts +8 -7
- package/dist/_contracts/connection-ticket.js +20 -14
- package/dist/_contracts/event-envelope.d.ts +17 -18
- package/dist/_contracts/event-envelope.js +10 -11
- package/dist/_contracts/managed-key.d.ts +27 -1
- package/dist/_contracts/managed-key.js +75 -4
- package/dist/_contracts/operations.d.ts +9 -20
- package/dist/_contracts/operations.js +33 -82
- package/dist/_contracts/proxy-protocol.d.ts +35 -2
- package/dist/_contracts/proxy-protocol.js +34 -1
- package/dist/_contracts/run-artifacts.d.ts +12 -10
- package/dist/_contracts/run-artifacts.js +13 -11
- package/dist/_contracts/run-config.d.ts +7 -0
- package/dist/_contracts/run-config.js +93 -24
- package/dist/_contracts/run-custody.d.ts +3 -3
- package/dist/_contracts/run-custody.js +5 -5
- package/dist/_contracts/run-record.d.ts +5 -17
- package/dist/_contracts/run-record.js +4 -15
- package/dist/_contracts/run-retention.d.ts +2 -2
- package/dist/_contracts/run-retention.js +3 -3
- package/dist/_contracts/run-unit.d.ts +4 -5
- package/dist/_contracts/runner-event.d.ts +7 -8
- package/dist/_contracts/runner-event.js +7 -8
- package/dist/_contracts/side-effect-audit.d.ts +2 -2
- package/dist/_contracts/side-effect-audit.js +3 -3
- package/dist/_contracts/stable.d.ts +1 -1
- package/dist/_contracts/stable.js +1 -1
- package/dist/_contracts/submission.d.ts +15 -11
- package/dist/_contracts/submission.js +18 -14
- package/dist/cli.mjs +127 -127
- package/dist/cli.mjs.sha256 +1 -1
- package/dist/client.d.ts +14 -58
- package/dist/client.js +304 -168
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/cleanup.md +4 -4
- package/docs/credentials.md +5 -5
- package/docs/events.md +5 -5
- package/docs/outputs.md +23 -25
- package/docs/product-boundaries.md +5 -5
- package/docs/provider-runtime-capabilities.md +1 -1
- package/docs/quickstart.md +12 -12
- package/docs/run-config.md +1 -1
- package/docs/run-record.md +6 -9
- package/docs/skills.md +23 -25
- package/package.json +2 -2
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/client.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { HttpClient, type AexEvent, type AgentsMdRecord, type CredentialMode, type DebugSink, type FetchLike, type FileRecord, type Output, type PlatformSubmission, type PlatformInlineSecrets, type PlatformProxyEndpoint, type PlatformProxyEndpointAuth, type Run, type RunEvent, type RunProvider, type RunUnit, type RuntimeSize, type RuntimeKind, type SignedOutputLink, type Skill as SkillRecord, type WhoAmI } from "./_contracts/index.js";
|
|
1
|
+
import { HttpClient, type AexEvent, type AgentsMdRecord, type CredentialMode, type DebugSink, type FetchLike, type FileRecord, type Output, type OutputMode, type PlatformSubmission, type PlatformInlineSecrets, type PlatformProxyEndpoint, type PlatformProxyEndpointAuth, type Run, type RunEvent, type RunProvider, type RunUnit, type RuntimeSize, type RuntimeKind, type SignedOutputLink, type Skill as SkillRecord, type WhoAmI } from "./_contracts/index.js";
|
|
2
2
|
import { AgentsMd } from "./agents-md.js";
|
|
3
3
|
import { File } from "./file.js";
|
|
4
4
|
import { McpServer } from "./mcp-server.js";
|
|
5
5
|
import { ProxyEndpoint } from "./proxy-endpoint.js";
|
|
6
6
|
import { Skill } from "./skill.js";
|
|
7
|
-
export interface
|
|
7
|
+
export interface AgentExecutorOptions {
|
|
8
8
|
/** Workspace-scoped SDK API token. */
|
|
9
9
|
readonly apiToken: string;
|
|
10
10
|
/**
|
|
@@ -117,6 +117,12 @@ export interface SubmitRunOptions {
|
|
|
117
117
|
* entries, deduplicated server-side.
|
|
118
118
|
*/
|
|
119
119
|
readonly builtins?: readonly string[];
|
|
120
|
+
/**
|
|
121
|
+
* Assistant-output granularity. `"buffered"` (default) delivers one event per
|
|
122
|
+
* assistant message; `"stream"` delivers per-token text deltas for live
|
|
123
|
+
* typing UIs.
|
|
124
|
+
*/
|
|
125
|
+
readonly outputMode?: OutputMode;
|
|
120
126
|
readonly secrets: PlatformInlineSecrets;
|
|
121
127
|
readonly idempotencyKey?: string;
|
|
122
128
|
readonly signal?: AbortSignal;
|
|
@@ -148,34 +154,6 @@ export type OutputFileSelector = Output | OutputFileIdSelector | OutputFilePathS
|
|
|
148
154
|
export interface OutputDownloadOptions {
|
|
149
155
|
readonly to?: string;
|
|
150
156
|
}
|
|
151
|
-
/**
|
|
152
|
-
* One captured debug artifact returned by {@link AexClient.getRunDebugLogs}.
|
|
153
|
-
*
|
|
154
|
-
* - `filename` is the path under `runs/{runId}/logs/` — leading
|
|
155
|
-
* `runtime/` for runtime logs and `host/` for host logs.
|
|
156
|
-
* - `text` is populated when the content type looks textual
|
|
157
|
-
* (`text/*`, `application/json`); decoded as UTF-8.
|
|
158
|
-
* - `bytesBase64` is always present so a caller that wants raw bytes
|
|
159
|
-
* (e.g. piping into a file) can use it uniformly across textual
|
|
160
|
-
* and binary artifacts.
|
|
161
|
-
*/
|
|
162
|
-
export interface RunDebugLog {
|
|
163
|
-
readonly filename: string;
|
|
164
|
-
readonly sizeBytes: number;
|
|
165
|
-
readonly contentType: string;
|
|
166
|
-
readonly createdAt: string;
|
|
167
|
-
readonly text?: string;
|
|
168
|
-
readonly bytesBase64: string;
|
|
169
|
-
}
|
|
170
|
-
export interface RunDebugLogError {
|
|
171
|
-
readonly filename: string;
|
|
172
|
-
readonly message: string;
|
|
173
|
-
}
|
|
174
|
-
export interface RunDebugLogs {
|
|
175
|
-
readonly runId: string;
|
|
176
|
-
readonly logs: ReadonlyArray<RunDebugLog>;
|
|
177
|
-
readonly errors: ReadonlyArray<RunDebugLogError>;
|
|
178
|
-
}
|
|
179
157
|
/**
|
|
180
158
|
* Workspace skill admin operations exposed under `client.skills`.
|
|
181
159
|
*
|
|
@@ -283,12 +261,12 @@ export declare class FilesClient {
|
|
|
283
261
|
* `client.whoami()` if you want to introspect which workspace the
|
|
284
262
|
* token resolves to.
|
|
285
263
|
*/
|
|
286
|
-
export declare class
|
|
264
|
+
export declare class AgentExecutor {
|
|
287
265
|
#private;
|
|
288
266
|
readonly skills: SkillsClient;
|
|
289
267
|
readonly agentsMd: AgentsMdClient;
|
|
290
268
|
readonly files: FilesClient;
|
|
291
|
-
constructor(options:
|
|
269
|
+
constructor(options: AgentExecutorOptions);
|
|
292
270
|
/**
|
|
293
271
|
* Internal: forwards to `SkillsClient._uploadSkillBundle`. NOT part of
|
|
294
272
|
* the public API.
|
|
@@ -406,25 +384,6 @@ export declare class AexClient {
|
|
|
406
384
|
downloadOutput(runId: string, options?: OutputDownloadOptions): Promise<Uint8Array>;
|
|
407
385
|
downloadOutput(runId: string, selector: undefined, options?: OutputDownloadOptions): Promise<Uint8Array>;
|
|
408
386
|
downloadOutput(runId: string, selector: OutputFileSelector, options?: OutputDownloadOptions): Promise<Uint8Array>;
|
|
409
|
-
/**
|
|
410
|
-
* Bundle the per-run debug artifacts aex captures automatically:
|
|
411
|
-
*
|
|
412
|
-
* - `runtime/{stdout,stderr,args}.log` — runtime process diagnostics.
|
|
413
|
-
* - `host/...` — managed host logs when the platform includes them.
|
|
414
|
-
* These all live in the run's `logs` namespace (`runs/<id>/logs/`).
|
|
415
|
-
* Each is downloaded through the gated `/logs/:id/download` endpoint,
|
|
416
|
-
* decoded as UTF-8 text when the content type looks textual, and
|
|
417
|
-
* surfaced as raw bytes (base64) otherwise. The call is best-effort: a
|
|
418
|
-
* download failure for one file does not block the others; the failing
|
|
419
|
-
* entry lands in `errors` with the underlying message.
|
|
420
|
-
*
|
|
421
|
-
* Use this when a run failed or behaved oddly and you want all the
|
|
422
|
-
* post-mortem material in one round-trip — no need to wire
|
|
423
|
-
* `listOutputs` + `createOutputLink` by hand.
|
|
424
|
-
*/
|
|
425
|
-
getRunDebugLogs(runId: string): Promise<RunDebugLogs>;
|
|
426
|
-
/** Short alias for `getRunDebugLogs`. */
|
|
427
|
-
debugLogs(runId: string): Promise<RunDebugLogs>;
|
|
428
387
|
cancelRun(runId: string): Promise<void>;
|
|
429
388
|
/** Short alias for `cancelRun`. */
|
|
430
389
|
cancel(runId: string): Promise<void>;
|
|
@@ -439,19 +398,16 @@ export declare class AexClient {
|
|
|
439
398
|
deleteWorkspaceAsset(hash: string): Promise<void>;
|
|
440
399
|
whoami(): Promise<WhoAmI>;
|
|
441
400
|
/**
|
|
442
|
-
* Download EVERYTHING about a run as one zip, assembled client-side
|
|
401
|
+
* Download EVERYTHING public about a run as one zip, assembled client-side
|
|
443
402
|
* from the public read endpoints (`getRun` + `listEvents` +
|
|
444
|
-
* `listOutputs` + per-output `/download`). Organised into the
|
|
445
|
-
*
|
|
446
|
-
*
|
|
447
|
-
* diagnostics), plus a `manifest.json`. Pass `to` to also write the
|
|
403
|
+
* `listOutputs` + per-output `/download`). Organised into the namespace
|
|
404
|
+
* folders `metadata/`, `events/`, and `outputs/`, plus a `manifest.json`.
|
|
405
|
+
* Pass `to` to also write the
|
|
448
406
|
* bytes to a file path while still returning the bytes.
|
|
449
407
|
*/
|
|
450
408
|
download(runId: string, options?: OutputDownloadOptions): Promise<Uint8Array>;
|
|
451
409
|
/** Download only the run's deliverables (the `outputs` namespace) as a zip. */
|
|
452
410
|
downloadOutputs(runId: string, options?: OutputDownloadOptions): Promise<Uint8Array>;
|
|
453
|
-
/** Download only the platform diagnostics (the `logs` namespace) as a zip. */
|
|
454
|
-
downloadLogs(runId: string, options?: OutputDownloadOptions): Promise<Uint8Array>;
|
|
455
411
|
/** Download only the indexed event archive (the `events` namespace) as a zip. */
|
|
456
412
|
downloadEvents(runId: string, options?: OutputDownloadOptions): Promise<Uint8Array>;
|
|
457
413
|
/** Download only the run record (the `metadata` namespace) as a zip. */
|