@aexhq/sdk 0.30.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -9
- package/dist/_contracts/connection-ticket.d.ts +1 -1
- package/dist/_contracts/connection-ticket.js +1 -1
- package/dist/_contracts/event-envelope.d.ts +5 -8
- package/dist/_contracts/event-envelope.js +5 -6
- package/dist/_contracts/event-stream-client.d.ts +1 -1
- package/dist/_contracts/http.js +1 -1
- package/dist/_contracts/operations.d.ts +2 -47
- package/dist/_contracts/operations.js +7 -112
- package/dist/_contracts/provider-support.d.ts +48 -138
- package/dist/_contracts/provider-support.js +10 -41
- package/dist/_contracts/proxy-protocol.d.ts +7 -7
- package/dist/_contracts/proxy-protocol.js +8 -8
- package/dist/_contracts/run-config.d.ts +7 -20
- package/dist/_contracts/run-config.js +8 -46
- package/dist/_contracts/run-cost.d.ts +1 -5
- package/dist/_contracts/run-cost.js +0 -8
- package/dist/_contracts/run-custody.d.ts +4 -6
- package/dist/_contracts/run-custody.js +0 -8
- package/dist/_contracts/run-unit.d.ts +1 -1
- package/dist/_contracts/run-unit.js +2 -2
- package/dist/_contracts/runner-event.d.ts +1 -1
- package/dist/_contracts/runner-event.js +1 -1
- package/dist/_contracts/runtime-manifest.d.ts +13 -26
- package/dist/_contracts/runtime-manifest.js +6 -35
- package/dist/_contracts/runtime-types.d.ts +1 -1
- package/dist/_contracts/sdk-secrets.js +4 -4
- package/dist/_contracts/side-effect-audit.d.ts +2 -4
- package/dist/_contracts/side-effect-audit.js +2 -4
- package/dist/_contracts/status.d.ts +1 -1
- package/dist/_contracts/status.js +1 -1
- package/dist/_contracts/submission.d.ts +5 -126
- package/dist/_contracts/submission.js +10 -182
- package/dist/_contracts/webhook-verify.d.ts +1 -1
- package/dist/_contracts/webhook-verify.js +1 -1
- package/dist/asset-upload.d.ts +4 -10
- package/dist/asset-upload.js +4 -47
- package/dist/asset-upload.js.map +1 -1
- package/dist/cli.mjs +19 -193
- package/dist/cli.mjs.sha256 +1 -1
- package/dist/client.d.ts +8 -69
- package/dist/client.js +21 -98
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -4
- package/dist/index.js.map +1 -1
- package/dist/skill.d.ts +1 -1
- package/dist/skill.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/cleanup.md +2 -2
- package/docs/concepts/agent-tools.md +2 -2
- package/docs/concepts/composition.md +1 -1
- package/docs/concepts/providers-and-runtimes.md +2 -4
- package/docs/concepts/runs.md +3 -6
- package/docs/credentials.md +2 -5
- package/docs/defaults.md +22 -22
- package/docs/limits-and-quotas.md +40 -40
- package/docs/limits.md +1 -1
- package/docs/networking.md +2 -2
- package/docs/outputs.md +1 -1
- package/docs/provider-runtime-capabilities.md +36 -64
- package/docs/public-surface.json +2 -3
- package/docs/quickstart.md +18 -6
- package/docs/run-config.md +3 -4
- package/docs/secrets.md +7 -5
- package/docs/skills.md +4 -12
- package/docs/vision-skills.md +1 -1
- package/package.json +2 -2
|
@@ -5,9 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* - `SkillRef` is the wire-level reference to a skill. Public run
|
|
7
7
|
* configs use storage-neutral `kind:"asset"` refs produced by the SDK
|
|
8
|
-
* upload path or by workspace catalog records.
|
|
9
|
-
* in the parser for wire compatibility, but the managed runtime rejects
|
|
10
|
-
* them at submission time.
|
|
8
|
+
* upload path or by workspace catalog records.
|
|
11
9
|
*
|
|
12
10
|
* - `McpServerRef` is the non-secret part of an MCP server declaration:
|
|
13
11
|
* `name` and `url`. Bearer / cookie / per-request headers travel in
|
|
@@ -30,7 +28,6 @@
|
|
|
30
28
|
* Keep this as the public source of truth for the SDK/CLI composition
|
|
31
29
|
* boundary.
|
|
32
30
|
*/
|
|
33
|
-
import { parseRegion, } from "./submission.js";
|
|
34
31
|
import { parseRunModel } from "./models.js";
|
|
35
32
|
import { parsePostHook } from "./post-hook.js";
|
|
36
33
|
// ---------------------------------------------------------------------------
|
|
@@ -89,9 +86,6 @@ export const SKILL_BUNDLE_LIMITS = {
|
|
|
89
86
|
};
|
|
90
87
|
/** Content-hash format: `sha256:<64 lowercase hex>`. */
|
|
91
88
|
export const INLINE_CONTENT_HASH_PATTERN = /^sha256:[0-9a-f]{64}$/;
|
|
92
|
-
export function isProviderSkillRef(ref) {
|
|
93
|
-
return ref.kind === "provider";
|
|
94
|
-
}
|
|
95
89
|
export function isAssetRef(ref) {
|
|
96
90
|
return ref.kind === "asset";
|
|
97
91
|
}
|
|
@@ -146,10 +140,8 @@ export function assertValidMountPath(value, field) {
|
|
|
146
140
|
}
|
|
147
141
|
}
|
|
148
142
|
/**
|
|
149
|
-
* Parse a `SkillRef` from untrusted input.
|
|
150
|
-
*
|
|
151
|
-
* `kind: "asset"` and `kind: "provider"` are valid; all other historical
|
|
152
|
-
* wire shapes (including storage-specific refs) are rejected.
|
|
143
|
+
* Parse a `SkillRef` from untrusted input. Only asset-backed skill refs are
|
|
144
|
+
* accepted on the public surface.
|
|
153
145
|
*/
|
|
154
146
|
export function parseSkillRef(input, path) {
|
|
155
147
|
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
@@ -157,35 +149,10 @@ export function parseSkillRef(input, path) {
|
|
|
157
149
|
}
|
|
158
150
|
const record = input;
|
|
159
151
|
const kind = record.kind;
|
|
160
|
-
if (kind === "provider") {
|
|
161
|
-
for (const key of Object.keys(record)) {
|
|
162
|
-
if (key !== "kind" && key !== "vendor" && key !== "skillId" && key !== "version") {
|
|
163
|
-
throw new Error(`${path} contains unexpected field for provider SkillRef: ${key}`);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
const vendor = record.vendor;
|
|
167
|
-
if (vendor !== "anthropic" && vendor !== "custom") {
|
|
168
|
-
throw new Error(`${path}.vendor must be 'anthropic' or 'custom'`);
|
|
169
|
-
}
|
|
170
|
-
const skillId = record.skillId;
|
|
171
|
-
if (typeof skillId !== "string" || skillId.length === 0 || skillId.length > 256) {
|
|
172
|
-
throw new Error(`${path}.skillId must be a non-empty string (<= 256 chars)`);
|
|
173
|
-
}
|
|
174
|
-
const version = record.version;
|
|
175
|
-
if (version !== undefined && (typeof version !== "string" || version.length === 0 || version.length > 64)) {
|
|
176
|
-
throw new Error(`${path}.version, when provided, must be a non-empty string (<= 64 chars)`);
|
|
177
|
-
}
|
|
178
|
-
return {
|
|
179
|
-
kind: "provider",
|
|
180
|
-
vendor,
|
|
181
|
-
skillId,
|
|
182
|
-
...(version !== undefined ? { version } : {})
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
152
|
if (kind === "asset") {
|
|
186
153
|
return parseAssetRefFields(record, path);
|
|
187
154
|
}
|
|
188
|
-
throw new Error(`${path}.kind must be '
|
|
155
|
+
throw new Error(`${path}.kind must be 'asset'`);
|
|
189
156
|
}
|
|
190
157
|
/**
|
|
191
158
|
* Common parser for any `kind: "asset"` ref (skill / agentsMd / file).
|
|
@@ -434,11 +401,9 @@ export function parseMcpServerRef(input, path) {
|
|
|
434
401
|
if (parsed.username !== "" || parsed.password !== "") {
|
|
435
402
|
throw new Error(`${path}.url must not contain userinfo (username/password); use secrets.mcpServers[].headers for auth`);
|
|
436
403
|
}
|
|
437
|
-
// SSRF guard at the parser boundary (C4) — the
|
|
438
|
-
// relies on this validation
|
|
439
|
-
//
|
|
440
|
-
// arbitrary non-443 ports on https. Each branch below maps to a
|
|
441
|
-
// c4-worker-ssrf.regression test case.
|
|
404
|
+
// SSRF guard at the parser boundary (C4) — the platform MCP proxy
|
|
405
|
+
// relies on this validation. Each branch below maps to an
|
|
406
|
+
// SSRF regression test case.
|
|
442
407
|
const ssrfDenial = denyReasonForMcpHost(parsed);
|
|
443
408
|
if (ssrfDenial !== null) {
|
|
444
409
|
throw new Error(`${path}.url ${ssrfDenial}`);
|
|
@@ -559,7 +524,7 @@ function denyReasonForV4(host) {
|
|
|
559
524
|
* when the URL is acceptable. Hostnames are lowercased; numeric ranges
|
|
560
525
|
* are checked literally so the catch covers both names ("localhost") and
|
|
561
526
|
* IP literals ("127.0.0.1") symmetrically. The numeric-range checks
|
|
562
|
-
* delegate to {@link denyReasonForHostIp} (shared with the
|
|
527
|
+
* delegate to {@link denyReasonForHostIp} (shared with the platform proxy).
|
|
563
528
|
*
|
|
564
529
|
* Surface tracked by server-side SSRF regression coverage.
|
|
565
530
|
*/
|
|
@@ -651,7 +616,6 @@ export function parseRunRequestConfig(input) {
|
|
|
651
616
|
"mcpServers",
|
|
652
617
|
"environment",
|
|
653
618
|
"runtimeSize",
|
|
654
|
-
"region",
|
|
655
619
|
"timeout",
|
|
656
620
|
"postHook",
|
|
657
621
|
"proxyEndpoints",
|
|
@@ -670,7 +634,6 @@ export function parseRunRequestConfig(input) {
|
|
|
670
634
|
const prompt = parseRunRequestConfigPrompt(record.prompt);
|
|
671
635
|
const skills = parseRunRequestConfigSkills(record.skills);
|
|
672
636
|
const mcpServers = parseRunRequestConfigMcpServers(record.mcpServers);
|
|
673
|
-
const region = parseRegion(record.region);
|
|
674
637
|
const postHook = parsePostHook(record.postHook, "run request config postHook");
|
|
675
638
|
return {
|
|
676
639
|
model,
|
|
@@ -688,7 +651,6 @@ export function parseRunRequestConfig(input) {
|
|
|
688
651
|
...(record.runtimeSize !== undefined
|
|
689
652
|
? { runtimeSize: record.runtimeSize }
|
|
690
653
|
: {}),
|
|
691
|
-
...(region !== undefined ? { region } : {}),
|
|
692
654
|
...(record.timeout !== undefined
|
|
693
655
|
? { timeout: record.timeout }
|
|
694
656
|
: {}),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RunProvider } from "./submission.js";
|
|
2
2
|
export declare const RUN_COST_TELEMETRY_SCHEMA_VERSION = 1;
|
|
3
3
|
export declare const RUN_USAGE_SAMPLE_SCHEMA_VERSION = 1;
|
|
4
4
|
export declare const RUN_COST_SUMMARY_STATUSES: readonly ["pending", "partial", "complete", "unavailable", "not_applicable"];
|
|
@@ -23,9 +23,7 @@ export interface RunUsageSample {
|
|
|
23
23
|
readonly quantity: number;
|
|
24
24
|
readonly source: RunUsageSampleSource;
|
|
25
25
|
readonly provider?: RunProvider | string;
|
|
26
|
-
readonly runtime?: RuntimeKind | string;
|
|
27
26
|
readonly model?: string;
|
|
28
|
-
readonly credentialMode?: CredentialMode;
|
|
29
27
|
readonly recordedAt?: string;
|
|
30
28
|
}
|
|
31
29
|
export type RunUsageSampleInput = Omit<RunUsageSample, "schemaVersion" | "unit"> & {
|
|
@@ -104,7 +102,6 @@ export interface RunCostTelemetry {
|
|
|
104
102
|
readonly schemaVersion: typeof RUN_COST_TELEMETRY_SCHEMA_VERSION;
|
|
105
103
|
readonly runId?: string;
|
|
106
104
|
readonly provider?: RunProvider | string;
|
|
107
|
-
readonly runtime?: RuntimeKind | string;
|
|
108
105
|
readonly recordedAt?: string;
|
|
109
106
|
readonly status?: RunCostSummaryStatus;
|
|
110
107
|
readonly sourceSummary?: RunCostSourceSummary;
|
|
@@ -132,7 +129,6 @@ export type RunCostTelemetryInput = Omit<RunCostTelemetry, "schemaVersion">;
|
|
|
132
129
|
export interface RunCostTelemetryFromUsageSamplesInput {
|
|
133
130
|
readonly runId?: string;
|
|
134
131
|
readonly provider?: RunProvider | string;
|
|
135
|
-
readonly runtime?: RuntimeKind | string;
|
|
136
132
|
readonly recordedAt?: string;
|
|
137
133
|
readonly status?: RunCostSummaryStatus;
|
|
138
134
|
readonly samples: readonly RunUsageSampleInput[];
|
|
@@ -113,9 +113,7 @@ export function buildRunUsageSample(input) {
|
|
|
113
113
|
quantity: nonNegativeFinite(input.quantity, "quantity"),
|
|
114
114
|
source: normalizeUsageSampleSource(input.source),
|
|
115
115
|
...(input.provider ? { provider: input.provider } : {}),
|
|
116
|
-
...(input.runtime ? { runtime: input.runtime } : {}),
|
|
117
116
|
...(input.model ? { model: input.model } : {}),
|
|
118
|
-
...(input.credentialMode ? { credentialMode: input.credentialMode } : {}),
|
|
119
117
|
...(input.recordedAt ? { recordedAt: input.recordedAt } : {})
|
|
120
118
|
});
|
|
121
119
|
}
|
|
@@ -124,7 +122,6 @@ export function buildRunCostTelemetry(input) {
|
|
|
124
122
|
schemaVersion: RUN_COST_TELEMETRY_SCHEMA_VERSION,
|
|
125
123
|
...(input.runId ? { runId: input.runId } : {}),
|
|
126
124
|
...(input.provider ? { provider: input.provider } : {}),
|
|
127
|
-
...(input.runtime ? { runtime: input.runtime } : {}),
|
|
128
125
|
...(input.recordedAt ? { recordedAt: input.recordedAt } : {}),
|
|
129
126
|
...(input.status ? { status: normalizeSummaryStatus(input.status) } : {}),
|
|
130
127
|
...(input.sourceSummary ? { sourceSummary: normalizeSourceSummary(input.sourceSummary) } : {}),
|
|
@@ -148,8 +145,6 @@ export function buildRunCostTelemetryFromUsageSamples(input) {
|
|
|
148
145
|
telemetry.runId = input.runId;
|
|
149
146
|
if (input.provider)
|
|
150
147
|
telemetry.provider = input.provider;
|
|
151
|
-
if (input.runtime)
|
|
152
|
-
telemetry.runtime = input.runtime;
|
|
153
148
|
if (input.recordedAt)
|
|
154
149
|
telemetry.recordedAt = input.recordedAt;
|
|
155
150
|
if (input.status)
|
|
@@ -288,7 +283,6 @@ export function mergeRunCostTelemetry(base, next) {
|
|
|
288
283
|
const merged = {};
|
|
289
284
|
const runId = patch.runId ?? base.runId;
|
|
290
285
|
const provider = patch.provider ?? base.provider;
|
|
291
|
-
const runtime = patch.runtime ?? base.runtime;
|
|
292
286
|
const recordedAt = patch.recordedAt ?? base.recordedAt;
|
|
293
287
|
const status = patch.status ?? base.status;
|
|
294
288
|
const sourceSummary = mergeSourceSummary(base.sourceSummary, patch.sourceSummary);
|
|
@@ -308,8 +302,6 @@ export function mergeRunCostTelemetry(base, next) {
|
|
|
308
302
|
merged.runId = runId;
|
|
309
303
|
if (provider)
|
|
310
304
|
merged.provider = provider;
|
|
311
|
-
if (runtime)
|
|
312
|
-
merged.runtime = runtime;
|
|
313
305
|
if (recordedAt)
|
|
314
306
|
merged.recordedAt = recordedAt;
|
|
315
307
|
if (status)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RunStatus } from "./status.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { RunProvider } from "./submission.js";
|
|
3
3
|
export declare const CUSTODY_MANIFEST_SCHEMA_VERSION = 1;
|
|
4
4
|
export declare const CUSTODY_REDACTION_SCANNER_VERSION = 1;
|
|
5
5
|
export declare const CUSTODY_MANIFEST_KIND = "aex.custody_manifest.v1";
|
|
@@ -7,15 +7,15 @@ export declare const CUSTODY_MANIFEST_CONTENT_TYPE = "application/json; charset=
|
|
|
7
7
|
export declare const CUSTODY_MANIFEST_RUN_REL_PATH = "metadata/custody.json";
|
|
8
8
|
export declare const CUSTODY_SECRET_CLASSES: readonly ["provider_api_key", "mcp_credential", "proxy_endpoint_auth", "runner_bearer", "managed_system_credential"];
|
|
9
9
|
export type CustodySecretClass = (typeof CUSTODY_SECRET_CLASSES)[number];
|
|
10
|
-
export declare const CUSTODY_RESOURCE_CLASSES: readonly ["runtime_machine", "
|
|
10
|
+
export declare const CUSTODY_RESOURCE_CLASSES: readonly ["runtime_machine", "proxy_token", "execution_secret", "event_archive", "run_output", "run_log", "run_asset"];
|
|
11
11
|
export type CustodyResourceClass = (typeof CUSTODY_RESOURCE_CLASSES)[number];
|
|
12
|
-
export declare const CUSTODY_EXPOSURE_SURFACES: readonly ["aex_vault", "aex_kv", "host_env", "host_file", "
|
|
12
|
+
export declare const CUSTODY_EXPOSURE_SURFACES: readonly ["aex_vault", "aex_kv", "host_env", "host_file", "dashboard_proxy", "api_provider_proxy", "api_mcp_proxy", "run_artifact_store", "coordinator_event_archive"];
|
|
13
13
|
export type CustodyExposureSurface = (typeof CUSTODY_EXPOSURE_SURFACES)[number];
|
|
14
14
|
export declare const CUSTODY_EXPOSURE_ACCESS_KINDS: readonly ["stored", "injected", "proxied", "replicated", "observed", "unknown"];
|
|
15
15
|
export type CustodyExposureAccessKind = (typeof CUSTODY_EXPOSURE_ACCESS_KINDS)[number];
|
|
16
16
|
export declare const CUSTODY_EXPOSURE_STATUSES: readonly ["exposed", "revoked", "retained", "failed", "not_applicable"];
|
|
17
17
|
export type CustodyExposureStatus = (typeof CUSTODY_EXPOSURE_STATUSES)[number];
|
|
18
|
-
export declare const CUSTODY_DISPOSITION_STATUSES: readonly ["destroyed", "revoked", "not_found", "
|
|
18
|
+
export declare const CUSTODY_DISPOSITION_STATUSES: readonly ["destroyed", "revoked", "not_found", "retained_by_policy", "cleanup_failed", "parked_for_operator", "pending", "not_applicable"];
|
|
19
19
|
export type CustodyDispositionStatus = (typeof CUSTODY_DISPOSITION_STATUSES)[number];
|
|
20
20
|
export declare const CUSTODY_CLEANUP_STATUSES: readonly ["succeeded", "partial", "failed", "retained", "pending"];
|
|
21
21
|
export type CustodyCleanupStatus = (typeof CUSTODY_CLEANUP_STATUSES)[number];
|
|
@@ -27,9 +27,7 @@ export interface CustodyManifestRunV1 {
|
|
|
27
27
|
readonly runId: string;
|
|
28
28
|
readonly workspaceId: string;
|
|
29
29
|
readonly provider: RunProvider | string;
|
|
30
|
-
readonly runtime: RuntimeKind | string;
|
|
31
30
|
readonly terminalStatus: RunStatus | string;
|
|
32
|
-
readonly credentialMode?: CredentialMode;
|
|
33
31
|
readonly createdAt?: string;
|
|
34
32
|
readonly terminalAt?: string;
|
|
35
33
|
}
|
|
@@ -12,9 +12,6 @@ export const CUSTODY_SECRET_CLASSES = [
|
|
|
12
12
|
];
|
|
13
13
|
export const CUSTODY_RESOURCE_CLASSES = [
|
|
14
14
|
"runtime_machine",
|
|
15
|
-
"native_provider_session",
|
|
16
|
-
"native_provider_resource",
|
|
17
|
-
"provider_asset",
|
|
18
15
|
"proxy_token",
|
|
19
16
|
"execution_secret",
|
|
20
17
|
"event_archive",
|
|
@@ -27,8 +24,6 @@ export const CUSTODY_EXPOSURE_SURFACES = [
|
|
|
27
24
|
"aex_kv",
|
|
28
25
|
"host_env",
|
|
29
26
|
"host_file",
|
|
30
|
-
"provider_vault",
|
|
31
|
-
"provider_session",
|
|
32
27
|
"dashboard_proxy",
|
|
33
28
|
"api_provider_proxy",
|
|
34
29
|
"api_mcp_proxy",
|
|
@@ -54,7 +49,6 @@ export const CUSTODY_DISPOSITION_STATUSES = [
|
|
|
54
49
|
"destroyed",
|
|
55
50
|
"revoked",
|
|
56
51
|
"not_found",
|
|
57
|
-
"provider_delete_confirmed",
|
|
58
52
|
"retained_by_policy",
|
|
59
53
|
"cleanup_failed",
|
|
60
54
|
"parked_for_operator",
|
|
@@ -179,9 +173,7 @@ function normalizeRun(input) {
|
|
|
179
173
|
runId: assertSafeIdentifier(input.runId, "run.runId"),
|
|
180
174
|
workspaceId: assertSafeIdentifier(input.workspaceId, "run.workspaceId"),
|
|
181
175
|
provider: assertSafeMetadataString(input.provider, "run.provider"),
|
|
182
|
-
runtime: assertSafeMetadataString(input.runtime, "run.runtime"),
|
|
183
176
|
terminalStatus: assertSafeMetadataString(input.terminalStatus, "run.terminalStatus"),
|
|
184
|
-
...(input.credentialMode ? { credentialMode: input.credentialMode } : {}),
|
|
185
177
|
...(input.createdAt ? { createdAt: assertTimestamp(input.createdAt, "run.createdAt") } : {}),
|
|
186
178
|
...(input.terminalAt ? { terminalAt: assertTimestamp(input.terminalAt, "run.terminalAt") } : {})
|
|
187
179
|
});
|
|
@@ -183,7 +183,7 @@ export interface RunUnit {
|
|
|
183
183
|
/**
|
|
184
184
|
* Parse a legacy run snapshot jsonb payload into the typed flat
|
|
185
185
|
* submission. Never throws on minor unknown keys so we can
|
|
186
|
-
* forward-compat with
|
|
186
|
+
* forward-compat with hosted API enrichment.
|
|
187
187
|
*
|
|
188
188
|
* Returns a typed shape even for malformed snapshots by falling back to the
|
|
189
189
|
* default public model and empty collection defaults, because the dashboard
|
|
@@ -28,7 +28,7 @@ import { PLATFORM_PACKAGE_ECOSYSTEMS } from "./submission.js";
|
|
|
28
28
|
/**
|
|
29
29
|
* Parse a legacy run snapshot jsonb payload into the typed flat
|
|
30
30
|
* submission. Never throws on minor unknown keys so we can
|
|
31
|
-
* forward-compat with
|
|
31
|
+
* forward-compat with hosted API enrichment.
|
|
32
32
|
*
|
|
33
33
|
* Returns a typed shape even for malformed snapshots by falling back to the
|
|
34
34
|
* default public model and empty collection defaults, because the dashboard
|
|
@@ -160,7 +160,7 @@ function toSkillRefArray(value) {
|
|
|
160
160
|
}
|
|
161
161
|
catch {
|
|
162
162
|
// Skip malformed entries rather than failing the whole detail
|
|
163
|
-
// read.
|
|
163
|
+
// read. Hosted API enrichment may add fields we don't recognise.
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
166
|
return out;
|
|
@@ -74,7 +74,7 @@ export interface RunnerEventBatch {
|
|
|
74
74
|
}
|
|
75
75
|
/**
|
|
76
76
|
* Maximum number of events per batch. Bounds the size of the body
|
|
77
|
-
* api.aex.dev accepts and the size of the downstream Postgres /
|
|
77
|
+
* api.aex.dev accepts and the size of the downstream Postgres / metadata-store
|
|
78
78
|
* write. Larger streams are split into multiple batches; the runner is
|
|
79
79
|
* responsible for chunking.
|
|
80
80
|
*/
|
|
@@ -55,7 +55,7 @@ export const RUNNER_EVENT_KINDS = [
|
|
|
55
55
|
];
|
|
56
56
|
/**
|
|
57
57
|
* Maximum number of events per batch. Bounds the size of the body
|
|
58
|
-
* api.aex.dev accepts and the size of the downstream Postgres /
|
|
58
|
+
* api.aex.dev accepts and the size of the downstream Postgres / metadata-store
|
|
59
59
|
* write. Larger streams are split into multiple batches; the runner is
|
|
60
60
|
* responsible for chunking.
|
|
61
61
|
*/
|
|
@@ -1,30 +1,23 @@
|
|
|
1
|
+
import type { RunProvider } from "./submission.js";
|
|
1
2
|
/**
|
|
2
|
-
* Runtime manifest: the per-run
|
|
3
|
+
* Runtime manifest: the per-run description of where
|
|
3
4
|
* aex places things inside the agent container, plus the merged
|
|
4
5
|
* env-var bag delivered via `RUNTIME.env` / `RUNTIME.json`.
|
|
5
6
|
*
|
|
6
7
|
* The hosted API computes a manifest at submitRun-response time
|
|
7
|
-
*
|
|
8
|
-
*
|
|
8
|
+
* from the validated submission via {@link buildRuntimeManifest} and
|
|
9
|
+
* echoes it on the wire as
|
|
9
10
|
* `Run.runtimeManifest`, so caller code (anyone rendering catalog markdown
|
|
10
11
|
* pre-submission, or resolving aex's in-container path strings) doesn't
|
|
11
12
|
* have to guess.
|
|
12
13
|
* The managed runtime materialises the actual `RUNTIME.env` / `RUNTIME.json`
|
|
13
|
-
* files in-container from the same
|
|
14
|
+
* files in-container from the same envVars inputs, so the
|
|
14
15
|
* SDK-side view and the in-container view describe the same layout.
|
|
15
16
|
*
|
|
16
17
|
* Manifest values are derived, never persisted separately — the source
|
|
17
18
|
* of truth for the customer half remains `submission.environment.envVars`
|
|
18
|
-
* on the run row; the aex half is constant for a given
|
|
19
|
-
* provider+SDK-version pair.
|
|
19
|
+
* on the run row; the aex half is constant for a given SDK version.
|
|
20
20
|
*/
|
|
21
|
-
/**
|
|
22
|
-
* Set of providers whose runtime contract aex models. Today only
|
|
23
|
-
* `"anthropic"` ships; the field is on the manifest so forward-compat
|
|
24
|
-
* consumers can branch on it without us having to silently change
|
|
25
|
-
* what `runtimeManifest` means when we add a second provider.
|
|
26
|
-
*/
|
|
27
|
-
export type RuntimeProvider = "anthropic";
|
|
28
21
|
/**
|
|
29
22
|
* The in-container paths the agent and skill code reference at
|
|
30
23
|
* runtime. All fields are absolute, all reflect Anthropic Managed
|
|
@@ -37,8 +30,8 @@ export type RuntimeProvider = "anthropic";
|
|
|
37
30
|
* under `/mnt/session/uploads/`.
|
|
38
31
|
*/
|
|
39
32
|
export interface RuntimeManifest {
|
|
40
|
-
readonly provider:
|
|
41
|
-
/** Where
|
|
33
|
+
readonly provider: RunProvider | string;
|
|
34
|
+
/** Where skill bundles auto-discover in the managed runner. */
|
|
42
35
|
readonly skillsRoot: string;
|
|
43
36
|
/** Parent dir of File mounts: `<filesRoot>/<f_id>/<rel-path>`. */
|
|
44
37
|
readonly filesRoot: string;
|
|
@@ -79,12 +72,12 @@ export interface MountedFileManifest {
|
|
|
79
72
|
readonly mountPath: string;
|
|
80
73
|
}
|
|
81
74
|
/**
|
|
82
|
-
* Managed-runner container paths. Kept here so the BFF,
|
|
75
|
+
* Managed-runner container paths. Kept here so the BFF, hosted API, and
|
|
83
76
|
* in-container bridge render identical values; runtime bootstrap constants are
|
|
84
77
|
* validated against these by a regression test
|
|
85
78
|
* (`packages/contracts/test/runtime-manifest.test.ts`).
|
|
86
79
|
*/
|
|
87
|
-
declare const
|
|
80
|
+
declare const RUNTIME_PATHS: Readonly<{
|
|
88
81
|
readonly skillsRoot: "/workspace/skills";
|
|
89
82
|
readonly filesRoot: "/mnt/session/uploads/aex/files";
|
|
90
83
|
readonly assetsRoot: "/mnt/session/uploads/aex/assets";
|
|
@@ -94,15 +87,9 @@ declare const ANTHROPIC_PATHS: Readonly<{
|
|
|
94
87
|
readonly runtimeJson: "/mnt/session/uploads/aex/RUNTIME.json";
|
|
95
88
|
readonly runtimeEnv: "/mnt/session/uploads/aex/RUNTIME.env";
|
|
96
89
|
}>;
|
|
97
|
-
|
|
98
|
-
* Container paths exposed for a given provider. Today only
|
|
99
|
-
* `"anthropic"` is recognised; calling with anything else throws so
|
|
100
|
-
* forward-compat surfaces the missing provider entry instead of
|
|
101
|
-
* silently emitting Anthropic paths.
|
|
102
|
-
*/
|
|
103
|
-
export declare function runtimePathsFor(provider: RuntimeProvider): typeof ANTHROPIC_PATHS;
|
|
90
|
+
export declare function runtimePaths(): typeof RUNTIME_PATHS;
|
|
104
91
|
export interface BuildRuntimeManifestInput {
|
|
105
|
-
readonly provider:
|
|
92
|
+
readonly provider: RunProvider | string;
|
|
106
93
|
/**
|
|
107
94
|
* Customer-supplied `environment.envVars` from the validated
|
|
108
95
|
* submission. Keys with the reserved `AEX_` prefix are
|
|
@@ -124,7 +111,7 @@ export interface BuildRuntimeManifestInput {
|
|
|
124
111
|
/**
|
|
125
112
|
* Build the runtime manifest for a single submission. Pure function:
|
|
126
113
|
* same input → same output → safe to call from the BFF response path
|
|
127
|
-
* and from the
|
|
114
|
+
* and from the hosted bootstrap path with identical results.
|
|
128
115
|
*/
|
|
129
116
|
export declare function buildRuntimeManifest(input: BuildRuntimeManifestInput): RuntimeManifest;
|
|
130
117
|
export {};
|
|
@@ -1,30 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* aex places things inside the agent container, plus the merged
|
|
4
|
-
* env-var bag delivered via `RUNTIME.env` / `RUNTIME.json`.
|
|
5
|
-
*
|
|
6
|
-
* The hosted API computes a manifest at submitRun-response time
|
|
7
|
-
* (from the validated submission + the chosen provider) via
|
|
8
|
-
* {@link buildRuntimeManifest} and echoes it on the wire as
|
|
9
|
-
* `Run.runtimeManifest`, so caller code (anyone rendering catalog markdown
|
|
10
|
-
* pre-submission, or resolving aex's in-container path strings) doesn't
|
|
11
|
-
* have to guess.
|
|
12
|
-
* The managed runtime materialises the actual `RUNTIME.env` / `RUNTIME.json`
|
|
13
|
-
* files in-container from the same provider + envVars inputs, so the
|
|
14
|
-
* SDK-side view and the in-container view describe the same layout.
|
|
15
|
-
*
|
|
16
|
-
* Manifest values are derived, never persisted separately — the source
|
|
17
|
-
* of truth for the customer half remains `submission.environment.envVars`
|
|
18
|
-
* on the run row; the aex half is constant for a given
|
|
19
|
-
* provider+SDK-version pair.
|
|
20
|
-
*/
|
|
21
|
-
/**
|
|
22
|
-
* Managed-runner container paths. Kept here so the BFF, worker, and
|
|
2
|
+
* Managed-runner container paths. Kept here so the BFF, hosted API, and
|
|
23
3
|
* in-container bridge render identical values; runtime bootstrap constants are
|
|
24
4
|
* validated against these by a regression test
|
|
25
5
|
* (`packages/contracts/test/runtime-manifest.test.ts`).
|
|
26
6
|
*/
|
|
27
|
-
const
|
|
7
|
+
const RUNTIME_PATHS = Object.freeze({
|
|
28
8
|
skillsRoot: "/workspace/skills",
|
|
29
9
|
filesRoot: "/mnt/session/uploads/aex/files",
|
|
30
10
|
assetsRoot: "/mnt/session/uploads/aex/assets",
|
|
@@ -34,17 +14,8 @@ const ANTHROPIC_PATHS = Object.freeze({
|
|
|
34
14
|
runtimeJson: "/mnt/session/uploads/aex/RUNTIME.json",
|
|
35
15
|
runtimeEnv: "/mnt/session/uploads/aex/RUNTIME.env"
|
|
36
16
|
});
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
* `"anthropic"` is recognised; calling with anything else throws so
|
|
40
|
-
* forward-compat surfaces the missing provider entry instead of
|
|
41
|
-
* silently emitting Anthropic paths.
|
|
42
|
-
*/
|
|
43
|
-
export function runtimePathsFor(provider) {
|
|
44
|
-
if (provider === "anthropic") {
|
|
45
|
-
return ANTHROPIC_PATHS;
|
|
46
|
-
}
|
|
47
|
-
throw new Error(`Unknown runtime provider: ${provider}`);
|
|
17
|
+
export function runtimePaths() {
|
|
18
|
+
return RUNTIME_PATHS;
|
|
48
19
|
}
|
|
49
20
|
/**
|
|
50
21
|
* Reserved env-var prefix for aex-set runtime keys. Mirrors the
|
|
@@ -63,10 +34,10 @@ const DEFAULT_FILE_MOUNT_PATH = "/workspace";
|
|
|
63
34
|
/**
|
|
64
35
|
* Build the runtime manifest for a single submission. Pure function:
|
|
65
36
|
* same input → same output → safe to call from the BFF response path
|
|
66
|
-
* and from the
|
|
37
|
+
* and from the hosted bootstrap path with identical results.
|
|
67
38
|
*/
|
|
68
39
|
export function buildRuntimeManifest(input) {
|
|
69
|
-
const paths =
|
|
40
|
+
const paths = runtimePaths();
|
|
70
41
|
const aexEnvVars = {
|
|
71
42
|
AEX_PROVIDER: input.provider,
|
|
72
43
|
AEX_CLI: paths.aexCli,
|
|
@@ -130,7 +130,7 @@ export interface RunEvent {
|
|
|
130
130
|
readonly recordedAt?: string;
|
|
131
131
|
/** Which sub-stream this record rides — `"event"` (typed) or `"log"`. Absent ⇒ `"event"`. */
|
|
132
132
|
readonly channel?: import("./event-envelope.js").AexEventChannel;
|
|
133
|
-
/** Coarse origin classifier
|
|
133
|
+
/** Coarse origin classifier. See {@link AexEventSource}. */
|
|
134
134
|
readonly source?: import("./event-envelope.js").AexEventSource;
|
|
135
135
|
/** Per-source monotonic counter assigned at the source (carried, not re-ordered). */
|
|
136
136
|
readonly sourceSeq?: number;
|
|
@@ -3,8 +3,8 @@ import { Transform } from "node:stream";
|
|
|
3
3
|
* Value-AGNOSTIC secret patterns: each matches a SHAPE, not a known value.
|
|
4
4
|
* Correctness must not depend on seeding the redactor with the literal
|
|
5
5
|
* secret — the two real leaks this project hit were a database password that
|
|
6
|
-
* survived a naive `sed` mask (as a substring) and an Anthropic key
|
|
7
|
-
*
|
|
6
|
+
* survived a naive `sed` mask (as a substring) and an Anthropic key surfaced in
|
|
7
|
+
* a deploy CLI's describe output that the harness NEVER loaded. A value-seeded
|
|
8
8
|
* redactor is blind to both; these patterns catch them by form.
|
|
9
9
|
*
|
|
10
10
|
* Ordering matters: structured shapes (connection strings, auth headers, JWT)
|
|
@@ -42,7 +42,7 @@ const REDACTED = "[REDACTED]";
|
|
|
42
42
|
* The candidate run deliberately EXCLUDES `_`: secrets are contiguous opaque
|
|
43
43
|
* runs, whereas `SCREAMING_SNAKE_CASE` env names and `snake_case` identifiers
|
|
44
44
|
* are `_`-separated words — excluding `_` breaks those into sub-24 fragments so
|
|
45
|
-
* they are never eaten
|
|
45
|
+
* they are never eaten. The
|
|
46
46
|
* class-diversity gate (≥2 of lower/upper/digit) then keeps the remaining
|
|
47
47
|
* single-class runs (all-lowercase module paths like `internal/modules/esm`)
|
|
48
48
|
* while still catching mixed-case/alnum secret blobs. Entropy alone cannot
|
|
@@ -55,7 +55,7 @@ const MIN_CHAR_CLASSES = 2;
|
|
|
55
55
|
* A mixed-case run with no digit and < this length is treated as a benign
|
|
56
56
|
* identifier, not a secret. Real opaque secrets are alnum-mixed (carry a
|
|
57
57
|
* digit) or very long; digit-free camelCase identifiers like
|
|
58
|
-
* `asyncRunEntryPointWithESMLoader` / `
|
|
58
|
+
* `asyncRunEntryPointWithESMLoader` / `getReadableStreamController` (which
|
|
59
59
|
* appear in stack traces the diagnostic bundle captures) are 24–39 chars and
|
|
60
60
|
* digit-free — eating them would gut debuggability. The length escape hatch
|
|
61
61
|
* still catches the rare long digit-free secret.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RunProvider } from "./submission.js";
|
|
2
2
|
export declare const SIDE_EFFECT_AUDIT_SCHEMA_VERSION = 1;
|
|
3
3
|
export declare const SIDE_EFFECT_AUDIT_REDACTION_SCANNER_VERSION = 1;
|
|
4
4
|
export declare const SIDE_EFFECT_AUDIT_KIND = "aex.side_effect_audit.v1";
|
|
@@ -6,7 +6,7 @@ export declare const SIDE_EFFECT_AUDIT_ACTIONS: readonly ["run.submit.accepted",
|
|
|
6
6
|
export type SideEffectAuditAction = (typeof SIDE_EFFECT_AUDIT_ACTIONS)[number];
|
|
7
7
|
export declare const SIDE_EFFECT_AUDIT_ACTOR_PRINCIPAL_TYPES: readonly ["user", "api_token", "system", "runtime"];
|
|
8
8
|
export type SideEffectAuditActorPrincipalType = (typeof SIDE_EFFECT_AUDIT_ACTOR_PRINCIPAL_TYPES)[number];
|
|
9
|
-
export declare const SIDE_EFFECT_AUDIT_SOURCE_PLANES: readonly ["dashboard", "
|
|
9
|
+
export declare const SIDE_EFFECT_AUDIT_SOURCE_PLANES: readonly ["dashboard", "api", "runtime", "system"];
|
|
10
10
|
export type SideEffectAuditSourcePlane = (typeof SIDE_EFFECT_AUDIT_SOURCE_PLANES)[number];
|
|
11
11
|
export declare const SIDE_EFFECT_AUDIT_AUTHENTICATION_KINDS: readonly ["dashboard_auth", "api_token", "runner_token", "system"];
|
|
12
12
|
export type SideEffectAuditAuthenticationKind = (typeof SIDE_EFFECT_AUDIT_AUTHENTICATION_KINDS)[number];
|
|
@@ -56,8 +56,6 @@ export interface SideEffectAuditStatusMetadataV1 {
|
|
|
56
56
|
}
|
|
57
57
|
export interface SideEffectAuditDimensionsMetadataV1 {
|
|
58
58
|
readonly provider?: RunProvider | string;
|
|
59
|
-
readonly runtime?: RuntimeKind | string;
|
|
60
|
-
readonly credentialMode?: CredentialMode;
|
|
61
59
|
readonly namespace?: "metadata" | "events" | "logs" | "outputs" | "archive";
|
|
62
60
|
readonly method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
63
61
|
readonly surface?: string;
|
|
@@ -36,7 +36,7 @@ export const SIDE_EFFECT_AUDIT_ACTOR_PRINCIPAL_TYPES = [
|
|
|
36
36
|
];
|
|
37
37
|
export const SIDE_EFFECT_AUDIT_SOURCE_PLANES = [
|
|
38
38
|
"dashboard",
|
|
39
|
-
"
|
|
39
|
+
"api",
|
|
40
40
|
"runtime",
|
|
41
41
|
"system"
|
|
42
42
|
];
|
|
@@ -306,11 +306,9 @@ function normalizeTimestamps(input) {
|
|
|
306
306
|
return Object.freeze(out);
|
|
307
307
|
}
|
|
308
308
|
function normalizeDimensions(input) {
|
|
309
|
-
assertSupportedNestedKeys(input, ["provider", "
|
|
309
|
+
assertSupportedNestedKeys(input, ["provider", "namespace", "method", "surface"], "metadata.dimensions");
|
|
310
310
|
return Object.freeze({
|
|
311
311
|
...(input.provider ? { provider: assertSafeMetadataString(input.provider, "metadata.dimensions.provider") } : {}),
|
|
312
|
-
...(input.runtime ? { runtime: assertSafeMetadataString(input.runtime, "metadata.dimensions.runtime") } : {}),
|
|
313
|
-
...(input.credentialMode ? { credentialMode: input.credentialMode } : {}),
|
|
314
312
|
...(input.namespace ? { namespace: input.namespace } : {}),
|
|
315
313
|
...(input.method ? { method: input.method } : {}),
|
|
316
314
|
...(input.surface ? { surface: assertSafeMetadataString(input.surface, "metadata.dimensions.surface") } : {})
|
|
@@ -8,7 +8,7 @@ export declare function isTerminalRunStatus(status: RunStatus): boolean;
|
|
|
8
8
|
* `markRunTerminal` (and that a `run/terminal` event carries). This is a
|
|
9
9
|
* STRICT SUBSET of {@link TERMINAL_RUN_STATUSES}: the read-terminal set also
|
|
10
10
|
* includes `cleanup_failed`, which the funnel never writes as an outcome.
|
|
11
|
-
* The
|
|
11
|
+
* The platform lifecycle `TerminalRunStatus` and the workflow `TerminalOutcome` both
|
|
12
12
|
* derive from this so the four call sites can't drift.
|
|
13
13
|
*/
|
|
14
14
|
export declare const RUN_TERMINAL_OUTCOMES: readonly ["succeeded", "failed", "timed_out", "cancelled"];
|
|
@@ -32,7 +32,7 @@ export function isTerminalRunStatus(status) {
|
|
|
32
32
|
* `markRunTerminal` (and that a `run/terminal` event carries). This is a
|
|
33
33
|
* STRICT SUBSET of {@link TERMINAL_RUN_STATUSES}: the read-terminal set also
|
|
34
34
|
* includes `cleanup_failed`, which the funnel never writes as an outcome.
|
|
35
|
-
* The
|
|
35
|
+
* The platform lifecycle `TerminalRunStatus` and the workflow `TerminalOutcome` both
|
|
36
36
|
* derive from this so the four call sites can't drift.
|
|
37
37
|
*/
|
|
38
38
|
export const RUN_TERMINAL_OUTCOMES = [
|