@aexhq/sdk 0.13.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +160 -0
- package/dist/_contracts/connection-ticket.d.ts +21 -0
- package/dist/_contracts/connection-ticket.js +49 -0
- package/dist/_contracts/event-envelope.d.ts +276 -0
- package/dist/_contracts/event-envelope.js +324 -0
- package/dist/_contracts/event-stream-client.d.ts +47 -0
- package/dist/_contracts/event-stream-client.js +141 -0
- package/dist/_contracts/http.d.ts +35 -0
- package/dist/_contracts/http.js +114 -0
- package/dist/_contracts/index.d.ts +28 -0
- package/dist/_contracts/index.js +29 -0
- package/dist/_contracts/managed-key.d.ts +74 -0
- package/dist/_contracts/managed-key.js +110 -0
- package/dist/_contracts/operations.d.ts +237 -0
- package/dist/_contracts/operations.js +632 -0
- package/dist/_contracts/provider-support.d.ts +220 -0
- package/dist/_contracts/provider-support.js +90 -0
- package/dist/_contracts/proxy-protocol.d.ts +257 -0
- package/dist/_contracts/proxy-protocol.js +234 -0
- package/dist/_contracts/proxy-validation.d.ts +19 -0
- package/dist/_contracts/proxy-validation.js +51 -0
- package/dist/_contracts/run-artifacts.d.ts +47 -0
- package/dist/_contracts/run-artifacts.js +101 -0
- package/dist/_contracts/run-config.d.ts +304 -0
- package/dist/_contracts/run-config.js +659 -0
- package/dist/_contracts/run-cost.d.ts +125 -0
- package/dist/_contracts/run-cost.js +616 -0
- package/dist/_contracts/run-custody.d.ts +226 -0
- package/dist/_contracts/run-custody.js +465 -0
- package/dist/_contracts/run-record.d.ts +127 -0
- package/dist/_contracts/run-record.js +177 -0
- package/dist/_contracts/run-retention.d.ts +213 -0
- package/dist/_contracts/run-retention.js +484 -0
- package/dist/_contracts/run-unit.d.ts +194 -0
- package/dist/_contracts/run-unit.js +215 -0
- package/dist/_contracts/runner-event.d.ts +114 -0
- package/dist/_contracts/runner-event.js +187 -0
- package/dist/_contracts/runtime-manifest.d.ts +106 -0
- package/dist/_contracts/runtime-manifest.js +98 -0
- package/dist/_contracts/runtime-security-profile.d.ts +27 -0
- package/dist/_contracts/runtime-security-profile.js +82 -0
- package/dist/_contracts/runtime-sizes.d.ts +144 -0
- package/dist/_contracts/runtime-sizes.js +136 -0
- package/dist/_contracts/runtime-types.d.ts +212 -0
- package/dist/_contracts/runtime-types.js +2 -0
- package/dist/_contracts/sdk-errors.d.ts +34 -0
- package/dist/_contracts/sdk-errors.js +52 -0
- package/dist/_contracts/sdk-secrets.d.ts +31 -0
- package/dist/_contracts/sdk-secrets.js +220 -0
- package/dist/_contracts/side-effect-audit.d.ts +129 -0
- package/dist/_contracts/side-effect-audit.js +494 -0
- package/dist/_contracts/sse.d.ts +74 -0
- package/dist/_contracts/sse.js +0 -0
- package/dist/_contracts/stable.d.ts +26 -0
- package/dist/_contracts/stable.js +44 -0
- package/dist/_contracts/status.d.ts +19 -0
- package/dist/_contracts/status.js +61 -0
- package/dist/_contracts/submission.d.ts +383 -0
- package/dist/_contracts/submission.js +1380 -0
- package/dist/agents-md.d.ts +46 -0
- package/dist/agents-md.js +83 -0
- package/dist/agents-md.js.map +1 -0
- package/dist/asset-upload.d.ts +66 -0
- package/dist/asset-upload.js +168 -0
- package/dist/asset-upload.js.map +1 -0
- package/dist/bundle.d.ts +33 -0
- package/dist/bundle.js +89 -0
- package/dist/bundle.js.map +1 -0
- package/dist/cli.mjs +4140 -0
- package/dist/cli.mjs.sha256 +1 -0
- package/dist/client.d.ts +460 -0
- package/dist/client.js +857 -0
- package/dist/client.js.map +1 -0
- package/dist/fetch-archive.d.ts +16 -0
- package/dist/fetch-archive.js +170 -0
- package/dist/fetch-archive.js.map +1 -0
- package/dist/file.d.ts +57 -0
- package/dist/file.js +153 -0
- package/dist/file.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server.d.ts +84 -0
- package/dist/mcp-server.js +114 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/node-fs.d.ts +12 -0
- package/dist/node-fs.js +44 -0
- package/dist/node-fs.js.map +1 -0
- package/dist/proxy-endpoint.d.ts +131 -0
- package/dist/proxy-endpoint.js +147 -0
- package/dist/proxy-endpoint.js.map +1 -0
- package/dist/skill.d.ts +117 -0
- package/dist/skill.js +169 -0
- package/dist/skill.js.map +1 -0
- package/dist/version.d.ts +9 -0
- package/dist/version.js +10 -0
- package/dist/version.js.map +1 -0
- package/docs/cleanup.md +38 -0
- package/docs/credentials.md +153 -0
- package/docs/events.md +76 -0
- package/docs/mcp.md +47 -0
- package/docs/outputs.md +157 -0
- package/docs/product-boundaries.md +57 -0
- package/docs/provider-runtime-capabilities.md +103 -0
- package/docs/quickstart.md +110 -0
- package/docs/release.md +99 -0
- package/docs/run-config.md +53 -0
- package/docs/run-record.md +39 -0
- package/docs/skills.md +139 -0
- package/docs/testing.md +29 -0
- package/package.json +47 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
// Wire format between the in-container runtime bridge (mounted at
|
|
2
|
+
// `/mnt/session/uploads/aex/aex`, invoked through `node`) and
|
|
3
|
+
// the dashboard BFF proxy route
|
|
4
|
+
// (`POST /api/runs/:runId/proxy/:endpointName`).
|
|
5
|
+
//
|
|
6
|
+
// This module is the single source of truth for the request shape, the
|
|
7
|
+
// response shape, the error-code enum, and the protocol version header.
|
|
8
|
+
// CLI and BFF both import from here; drift becomes a build-time type error.
|
|
9
|
+
//
|
|
10
|
+
/**
|
|
11
|
+
* Wire-protocol version. Bumped on any breaking change to the request or
|
|
12
|
+
* response shape. The CLI sends this in the `X-Aex-Proxy-Protocol`
|
|
13
|
+
* header on every request; the BFF rejects mismatches with HTTP 426
|
|
14
|
+
* `unsupported_protocol`.
|
|
15
|
+
*
|
|
16
|
+
* Bumps are coordinated: CLI and BFF release together, the worker
|
|
17
|
+
* bundles the matching CLI artifact, and the e2e suite runs both with
|
|
18
|
+
* the new version.
|
|
19
|
+
*/
|
|
20
|
+
export const PROXY_PROTOCOL_VERSION = "1";
|
|
21
|
+
export const PROXY_PROTOCOL_HEADER = "x-aex-proxy-protocol";
|
|
22
|
+
/**
|
|
23
|
+
* Default `User-Agent` the proxy attaches to every outbound request when
|
|
24
|
+
* the caller did not supply one via `allowHeaders`. Some upstreams reject
|
|
25
|
+
* requests that arrive without a meaningful UA — notably the Wikimedia
|
|
26
|
+
* family (Wikidata, Wikipedia, Wikimedia Commons), whose policy requires
|
|
27
|
+
* a contactable identifier and otherwise returns HTTP 403 with a
|
|
28
|
+
* `Please identify your user agent` body.
|
|
29
|
+
*
|
|
30
|
+
* Callers can override per request by listing `user-agent` in their
|
|
31
|
+
* endpoint's `allowHeaders` and setting it on the proxy call; the
|
|
32
|
+
* default only fires when nothing was forwarded.
|
|
33
|
+
*
|
|
34
|
+
* See <https://meta.wikimedia.org/wiki/User-Agent_policy>.
|
|
35
|
+
*/
|
|
36
|
+
export const PROXY_DEFAULT_USER_AGENT = "aex-proxy/1.0 (+https://aex.dev/contact)";
|
|
37
|
+
export const PROXY_METHOD_HEADER = "x-aex-method";
|
|
38
|
+
export const PROXY_PATH_HEADER = "x-aex-path";
|
|
39
|
+
export const PROXY_QUERY_HEADER = "x-aex-query";
|
|
40
|
+
export const PROXY_HEADERS_HEADER = "x-aex-headers";
|
|
41
|
+
export const PROXY_RESPONSE_MODE_HEADER = "x-aex-response-mode";
|
|
42
|
+
export const PROXY_ALLOWED_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"];
|
|
43
|
+
export const PROXY_RESPONSE_MODES = ["status_only", "headers_only", "full"];
|
|
44
|
+
/**
|
|
45
|
+
* Narrowing order: a request may only narrow below the policy ceiling.
|
|
46
|
+
* `status_only` is narrowest, `full` is widest. The BFF computes
|
|
47
|
+
* `narrowest(policyMode, headerMode)` and ignores escalation attempts,
|
|
48
|
+
* auditing them as `mode_clamped`.
|
|
49
|
+
*/
|
|
50
|
+
const RESPONSE_MODE_WIDTH = {
|
|
51
|
+
status_only: 0,
|
|
52
|
+
headers_only: 1,
|
|
53
|
+
full: 2
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Returns the narrower of the two response modes (lower width wins).
|
|
57
|
+
* Pure function so the CLI and BFF can both call it without import cycles.
|
|
58
|
+
*/
|
|
59
|
+
export function narrowResponseMode(policy, requested) {
|
|
60
|
+
return RESPONSE_MODE_WIDTH[requested] < RESPONSE_MODE_WIDTH[policy] ? requested : policy;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Error codes returned by the proxy route. Stable strings — the CLI
|
|
64
|
+
* matches against them in scripts. Adding a new code is non-breaking;
|
|
65
|
+
* removing or renaming an existing code requires a protocol bump.
|
|
66
|
+
*/
|
|
67
|
+
export const PROXY_ERROR_CODES = [
|
|
68
|
+
"unsupported_protocol",
|
|
69
|
+
"unauthorized",
|
|
70
|
+
"endpoint_not_found",
|
|
71
|
+
"policy_denied",
|
|
72
|
+
"rate_limited",
|
|
73
|
+
"budget_exceeded",
|
|
74
|
+
"ssrf_denied",
|
|
75
|
+
"upstream_timeout",
|
|
76
|
+
"upstream_error",
|
|
77
|
+
"exceeded_cap",
|
|
78
|
+
"bad_request",
|
|
79
|
+
"internal_error"
|
|
80
|
+
];
|
|
81
|
+
/**
|
|
82
|
+
* Default caps for a proxy endpoint when the submission doesn't specify
|
|
83
|
+
* one. Conservative on purpose. Lives in the protocol module (next to the
|
|
84
|
+
* index-file shape) so {@link buildProxyIndexFile} can fill every optional
|
|
85
|
+
* cap with a concrete value; the submission parser re-exports it.
|
|
86
|
+
*/
|
|
87
|
+
export const PROXY_ENDPOINT_DEFAULTS = {
|
|
88
|
+
allowHeaders: [],
|
|
89
|
+
responseMode: "headers_only",
|
|
90
|
+
maxRequestBytes: 64 * 1024,
|
|
91
|
+
maxResponseBytes: 1024 * 1024,
|
|
92
|
+
timeoutMs: 10_000,
|
|
93
|
+
perCallBudget: 60,
|
|
94
|
+
responseByteBudget: 1024 * 1024
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Build the per-run {@link ProxyIndexFile} mounted into the container at
|
|
98
|
+
* `/mnt/session/uploads/aex/index.json`. Pure: applies
|
|
99
|
+
* {@link PROXY_ENDPOINT_DEFAULTS} so every optional cap is concrete, and
|
|
100
|
+
* carries ONLY the non-secret endpoint policy — auth values never appear.
|
|
101
|
+
*
|
|
102
|
+
* ALWAYS emits a file (the always-on surface). With zero endpoints OR no
|
|
103
|
+
* `proxyPublicBaseUrl`, `proxyBaseUrl` is `null` and `endpoints` is `[]`.
|
|
104
|
+
* Otherwise `proxyBaseUrl` is `<trimmed base>/api/runs/<runId>/proxy`, the
|
|
105
|
+
* prefix the in-container runtime bridge appends `/<endpointName>` to (proxy.ts).
|
|
106
|
+
*/
|
|
107
|
+
export function buildProxyIndexFile(input) {
|
|
108
|
+
const endpoints = input.endpoints ?? [];
|
|
109
|
+
const base = input.proxyPublicBaseUrl?.trim() ?? "";
|
|
110
|
+
const haveBase = base.length > 0;
|
|
111
|
+
const proxyBaseUrl = endpoints.length > 0 && haveBase
|
|
112
|
+
? `${base.replace(/\/+$/, "")}/api/runs/${input.runId}/proxy`
|
|
113
|
+
: null;
|
|
114
|
+
return {
|
|
115
|
+
protocolVersion: PROXY_PROTOCOL_VERSION,
|
|
116
|
+
runId: input.runId,
|
|
117
|
+
proxyBaseUrl,
|
|
118
|
+
endpoints: endpoints.map((e) => ({
|
|
119
|
+
name: e.name,
|
|
120
|
+
baseUrl: e.baseUrl,
|
|
121
|
+
authShape: e.authShape,
|
|
122
|
+
allowMethods: e.allowMethods,
|
|
123
|
+
allowPathPrefixes: e.allowPathPrefixes,
|
|
124
|
+
allowHeaders: e.allowHeaders ?? PROXY_ENDPOINT_DEFAULTS.allowHeaders,
|
|
125
|
+
responseMode: e.responseMode ?? PROXY_ENDPOINT_DEFAULTS.responseMode,
|
|
126
|
+
maxRequestBytes: e.maxRequestBytes ?? PROXY_ENDPOINT_DEFAULTS.maxRequestBytes,
|
|
127
|
+
maxResponseBytes: e.maxResponseBytes ?? PROXY_ENDPOINT_DEFAULTS.maxResponseBytes,
|
|
128
|
+
timeoutMs: e.timeoutMs ?? PROXY_ENDPOINT_DEFAULTS.timeoutMs,
|
|
129
|
+
perCallBudget: e.perCallBudget ?? PROXY_ENDPOINT_DEFAULTS.perCallBudget,
|
|
130
|
+
responseByteBudget: e.responseByteBudget ?? PROXY_ENDPOINT_DEFAULTS.responseByteBudget
|
|
131
|
+
}))
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Header name (lowercase) that an upstream auth shape uses as its
|
|
136
|
+
* carrier. Returns `undefined` for query-based and keyless auth.
|
|
137
|
+
*
|
|
138
|
+
* Used by the submission parser to forbid `allowHeaders` from listing
|
|
139
|
+
* the auth header (avoids leaks via caller-supplied headers), and by
|
|
140
|
+
* the proxy route to strip any caller header that would collide with
|
|
141
|
+
* the auth carrier at request time.
|
|
142
|
+
*/
|
|
143
|
+
export function authShapeHeaderName(shape) {
|
|
144
|
+
switch (shape.type) {
|
|
145
|
+
case "bearer":
|
|
146
|
+
case "basic":
|
|
147
|
+
return "authorization";
|
|
148
|
+
case "header":
|
|
149
|
+
return shape.name.toLowerCase();
|
|
150
|
+
case "query":
|
|
151
|
+
case "none":
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Query-string key that an upstream query-based auth shape uses as its
|
|
157
|
+
* carrier. Returns `undefined` for non-query shapes (including "none").
|
|
158
|
+
*/
|
|
159
|
+
export function authShapeQueryName(shape) {
|
|
160
|
+
return shape.type === "query" ? shape.name : undefined;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Inbound request headers every Aex proxy plane STRIPS before
|
|
164
|
+
* forwarding a runtime/runner request upstream. Three categories:
|
|
165
|
+
*
|
|
166
|
+
* - Credential carriers (`authorization`, `x-api-key`, `cookie`,
|
|
167
|
+
* `proxy-authorization`) — these belong to Aex's own auth gate
|
|
168
|
+
* (the per-run bearer) or to the caller, never the upstream. The
|
|
169
|
+
* legitimate upstream credential is injected server-side from the
|
|
170
|
+
* run's Vault bundle / endpoint auth shape AFTER this strip, so it is
|
|
171
|
+
* never sourced from an inbound header.
|
|
172
|
+
* - Hop-by-hop fields (RFC 7230 §6.1: `connection`, `keep-alive`,
|
|
173
|
+
* `transfer-encoding`, `te`, `trailer`, `upgrade`, `expect`,
|
|
174
|
+
* `proxy-authenticate`, `proxy-connection`) — must not survive a
|
|
175
|
+
* proxy hop.
|
|
176
|
+
* - Routing primitives a compromised runner could spoof to bypass an
|
|
177
|
+
* upstream's IP allowlist / rate-limit (`host`, `content-length`,
|
|
178
|
+
* `x-forwarded-*`, `x-real-ip`, `forwarded`).
|
|
179
|
+
*
|
|
180
|
+
* The api Worker provider-proxy and the dashboard MCP proxy strip exactly
|
|
181
|
+
* this set (both inject upstream auth separately — the provider key, or the
|
|
182
|
+
* Vault MCP-bundle headers, applied AFTER the strip). The dashboard
|
|
183
|
+
* customer HTTP proxy hard-denies this set MINUS `x-api-key`, because a
|
|
184
|
+
* customer endpoint may legitimately declare `x-api-key` as its auth
|
|
185
|
+
* carrier; it derives from this constant so the hop-by-hop + routing
|
|
186
|
+
* entries never drift. Keeping the membership here is the single source of
|
|
187
|
+
* truth that stops those surfaces diverging.
|
|
188
|
+
*/
|
|
189
|
+
export const PROXY_STRIPPED_INBOUND_HEADERS = new Set([
|
|
190
|
+
// credential carriers
|
|
191
|
+
"authorization",
|
|
192
|
+
"x-api-key",
|
|
193
|
+
"cookie",
|
|
194
|
+
"proxy-authorization",
|
|
195
|
+
// hop-by-hop (RFC 7230 §6.1)
|
|
196
|
+
"connection",
|
|
197
|
+
"keep-alive",
|
|
198
|
+
"transfer-encoding",
|
|
199
|
+
"te",
|
|
200
|
+
"trailer",
|
|
201
|
+
"upgrade",
|
|
202
|
+
"expect",
|
|
203
|
+
"proxy-authenticate",
|
|
204
|
+
"proxy-connection",
|
|
205
|
+
// routing primitives a runner could spoof
|
|
206
|
+
"host",
|
|
207
|
+
"content-length",
|
|
208
|
+
"x-forwarded-for",
|
|
209
|
+
"x-forwarded-host",
|
|
210
|
+
"x-forwarded-proto",
|
|
211
|
+
"x-forwarded-port",
|
|
212
|
+
"x-real-ip",
|
|
213
|
+
"forwarded"
|
|
214
|
+
]);
|
|
215
|
+
/**
|
|
216
|
+
* Status code → error code mapping used by the BFF to ensure the audit
|
|
217
|
+
* row's error code and the HTTP response line up. Kept here so callers
|
|
218
|
+
* can do a sanity check in tests.
|
|
219
|
+
*/
|
|
220
|
+
export const PROXY_ERROR_HTTP_STATUS = {
|
|
221
|
+
unsupported_protocol: 426,
|
|
222
|
+
unauthorized: 401,
|
|
223
|
+
endpoint_not_found: 404,
|
|
224
|
+
policy_denied: 403,
|
|
225
|
+
rate_limited: 429,
|
|
226
|
+
budget_exceeded: 429,
|
|
227
|
+
ssrf_denied: 403,
|
|
228
|
+
upstream_timeout: 504,
|
|
229
|
+
upstream_error: 502,
|
|
230
|
+
exceeded_cap: 502,
|
|
231
|
+
bad_request: 400,
|
|
232
|
+
internal_error: 500
|
|
233
|
+
};
|
|
234
|
+
//# sourceMappingURL=proxy-protocol.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { PlatformProxyEndpoint, PlatformProxyEndpointAuth } from "./submission.js";
|
|
2
|
+
/**
|
|
3
|
+
* Cross-validate a `proxyEndpoints` policy list against a
|
|
4
|
+
* `secrets.proxyEndpointAuth` value list. Throws on the first mismatch
|
|
5
|
+
* with an actionable, field-named error message.
|
|
6
|
+
*
|
|
7
|
+
* Mirrors the BFF's authoritative validator so misconfigured submissions
|
|
8
|
+
* fail fast in the SDK/CLI before going over the wire.
|
|
9
|
+
*/
|
|
10
|
+
export declare function validateProxyAuth(endpoints: readonly PlatformProxyEndpoint[], auth: readonly PlatformProxyEndpointAuth[] | undefined): void;
|
|
11
|
+
/**
|
|
12
|
+
* Build an `allowedHosts` list for `environment.network` that includes
|
|
13
|
+
* the aex proxy host (and optionally Anthropic's MCP host) when the
|
|
14
|
+
* caller is hand-rolling networking.
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildPlatformAllowedHosts(input: {
|
|
17
|
+
readonly baseUrl: string;
|
|
18
|
+
readonly extraHosts?: readonly string[];
|
|
19
|
+
}): readonly string[];
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-validate a `proxyEndpoints` policy list against a
|
|
3
|
+
* `secrets.proxyEndpointAuth` value list. Throws on the first mismatch
|
|
4
|
+
* with an actionable, field-named error message.
|
|
5
|
+
*
|
|
6
|
+
* Mirrors the BFF's authoritative validator so misconfigured submissions
|
|
7
|
+
* fail fast in the SDK/CLI before going over the wire.
|
|
8
|
+
*/
|
|
9
|
+
export function validateProxyAuth(endpoints, auth) {
|
|
10
|
+
const authList = auth ?? [];
|
|
11
|
+
const endpointNames = new Set(endpoints.map((e) => e.name));
|
|
12
|
+
const authNames = new Set();
|
|
13
|
+
for (const entry of authList) {
|
|
14
|
+
if (authNames.has(entry.name)) {
|
|
15
|
+
throw new Error(`secrets.proxyEndpointAuth contains duplicate name '${entry.name}'`);
|
|
16
|
+
}
|
|
17
|
+
authNames.add(entry.name);
|
|
18
|
+
if (!endpointNames.has(entry.name)) {
|
|
19
|
+
throw new Error(`secrets.proxyEndpointAuth[].name='${entry.name}' has no matching proxyEndpoints[].name`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
for (const endpoint of endpoints) {
|
|
23
|
+
const match = authList.find((a) => a.name === endpoint.name);
|
|
24
|
+
if (!match) {
|
|
25
|
+
throw new Error(`proxyEndpoints[].name='${endpoint.name}' is missing a matching secrets.proxyEndpointAuth entry`);
|
|
26
|
+
}
|
|
27
|
+
if (match.value.type !== endpoint.authShape.type) {
|
|
28
|
+
throw new Error(`secrets.proxyEndpointAuth[name='${endpoint.name}'].value.type='${match.value.type}' does not match proxyEndpoints[name='${endpoint.name}'].authShape.type='${endpoint.authShape.type}'`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Build an `allowedHosts` list for `environment.network` that includes
|
|
34
|
+
* the aex proxy host (and optionally Anthropic's MCP host) when the
|
|
35
|
+
* caller is hand-rolling networking.
|
|
36
|
+
*/
|
|
37
|
+
export function buildPlatformAllowedHosts(input) {
|
|
38
|
+
const result = [];
|
|
39
|
+
try {
|
|
40
|
+
result.push(new URL(input.baseUrl).host);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
throw new Error("buildPlatformAllowedHosts: baseUrl must be an absolute URL");
|
|
44
|
+
}
|
|
45
|
+
for (const host of input.extraHosts ?? []) {
|
|
46
|
+
if (!result.includes(host))
|
|
47
|
+
result.push(host);
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=proxy-validation.js.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single source of truth for a run's artifact namespaces.
|
|
3
|
+
*
|
|
4
|
+
* Every run stores its artifacts under two sibling prefixes:
|
|
5
|
+
*
|
|
6
|
+
* runs/<runId>/outputs/<rel> — the run's real deliverables.
|
|
7
|
+
* runs/<runId>/logs/<rel> — platform diagnostics (`runtime/`,
|
|
8
|
+
* `host/`, `provider-proxy/`,
|
|
9
|
+
* `control-plane/`).
|
|
10
|
+
*
|
|
11
|
+
* The runner uploads every file with a workspace-relative path and the
|
|
12
|
+
* server decides the namespace from that path's prefix, so the split is
|
|
13
|
+
* owned here — the runner does not need to know about it. Diagnostics
|
|
14
|
+
* reach the upload route as workspace dotdirs (`.runtime-logs/...`,
|
|
15
|
+
* `.host-logs/...`, etc.); the stored path uses canonical log namespaces.
|
|
16
|
+
* Legacy diagnostic prefixes are normalized on read/write compatibility paths.
|
|
17
|
+
*/
|
|
18
|
+
export declare const RUN_OUTPUTS_PREFIX = "outputs";
|
|
19
|
+
export declare const RUN_LOGS_PREFIX = "logs";
|
|
20
|
+
/**
|
|
21
|
+
* Relative-path prefixes that mark a stored artifact as a platform diagnostic
|
|
22
|
+
* rather than a run deliverable. Dotted forms are upload-time paths; legacy
|
|
23
|
+
* forms are accepted so old records normalize to the canonical namespace.
|
|
24
|
+
*/
|
|
25
|
+
export declare const RUN_LOG_REL_PREFIXES: readonly [".runtime-logs/", ".host-logs/", ".provider-proxy/", ".control-plane/", ".anthropic-debug/", ".goose-logs/", ".fly-logs/", "runtime/", "host/", "provider-proxy/", "control-plane/", "anthropic-debug/", "goose-logs/", "fly-logs/"];
|
|
26
|
+
/** True when a workspace-relative artifact path belongs to the `logs` namespace. */
|
|
27
|
+
export declare function isRunLogRelPath(rel: string): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* The artifact's path relative to its namespace prefix as stored. Diagnostics
|
|
30
|
+
* are canonicalized (`.runtime-logs/x` -> `runtime/x`,
|
|
31
|
+
* legacy `.goose-logs/x` -> `runtime/x`, legacy `.fly-logs/x` -> `host/x`).
|
|
32
|
+
*/
|
|
33
|
+
export declare function runArtifactRel(rel: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Storage key for a run artifact uploaded with relative path `rel`, routing
|
|
36
|
+
* diagnostics into `logs/` and everything else into `outputs/`.
|
|
37
|
+
*/
|
|
38
|
+
export declare function runArtifactKey(runId: string, rel: string): string;
|
|
39
|
+
/** The `assets` namespace under a run's prefix. */
|
|
40
|
+
export declare const RUN_ASSETS_PREFIX = "assets";
|
|
41
|
+
/**
|
|
42
|
+
* Storage key for a run's snapshotted asset, addressed by its content hash.
|
|
43
|
+
* At submit, each referenced shared-store asset is copied here so the run owns
|
|
44
|
+
* its bytes. Accepts a `sha256:<hex>` hash or a bare 64-hex digest; the stored
|
|
45
|
+
* suffix is the hex.
|
|
46
|
+
*/
|
|
47
|
+
export declare function runAssetKey(runId: string, hash: string): string;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single source of truth for a run's artifact namespaces.
|
|
3
|
+
*
|
|
4
|
+
* Every run stores its artifacts under two sibling prefixes:
|
|
5
|
+
*
|
|
6
|
+
* runs/<runId>/outputs/<rel> — the run's real deliverables.
|
|
7
|
+
* runs/<runId>/logs/<rel> — platform diagnostics (`runtime/`,
|
|
8
|
+
* `host/`, `provider-proxy/`,
|
|
9
|
+
* `control-plane/`).
|
|
10
|
+
*
|
|
11
|
+
* The runner uploads every file with a workspace-relative path and the
|
|
12
|
+
* server decides the namespace from that path's prefix, so the split is
|
|
13
|
+
* owned here — the runner does not need to know about it. Diagnostics
|
|
14
|
+
* reach the upload route as workspace dotdirs (`.runtime-logs/...`,
|
|
15
|
+
* `.host-logs/...`, etc.); the stored path uses canonical log namespaces.
|
|
16
|
+
* Legacy diagnostic prefixes are normalized on read/write compatibility paths.
|
|
17
|
+
*/
|
|
18
|
+
export const RUN_OUTPUTS_PREFIX = "outputs";
|
|
19
|
+
export const RUN_LOGS_PREFIX = "logs";
|
|
20
|
+
/**
|
|
21
|
+
* Relative-path prefixes that mark a stored artifact as a platform diagnostic
|
|
22
|
+
* rather than a run deliverable. Dotted forms are upload-time paths; legacy
|
|
23
|
+
* forms are accepted so old records normalize to the canonical namespace.
|
|
24
|
+
*/
|
|
25
|
+
export const RUN_LOG_REL_PREFIXES = [
|
|
26
|
+
".runtime-logs/",
|
|
27
|
+
".host-logs/",
|
|
28
|
+
".provider-proxy/",
|
|
29
|
+
".control-plane/",
|
|
30
|
+
".anthropic-debug/",
|
|
31
|
+
".goose-logs/",
|
|
32
|
+
".fly-logs/",
|
|
33
|
+
"runtime/",
|
|
34
|
+
"host/",
|
|
35
|
+
"provider-proxy/",
|
|
36
|
+
"control-plane/",
|
|
37
|
+
"anthropic-debug/",
|
|
38
|
+
"goose-logs/",
|
|
39
|
+
"fly-logs/"
|
|
40
|
+
];
|
|
41
|
+
/** True when a workspace-relative artifact path belongs to the `logs` namespace. */
|
|
42
|
+
export function isRunLogRelPath(rel) {
|
|
43
|
+
return RUN_LOG_REL_PREFIXES.some((prefix) => rel.startsWith(prefix));
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The artifact's path relative to its namespace prefix as stored. Diagnostics
|
|
47
|
+
* are canonicalized (`.runtime-logs/x` -> `runtime/x`,
|
|
48
|
+
* legacy `.goose-logs/x` -> `runtime/x`, legacy `.fly-logs/x` -> `host/x`).
|
|
49
|
+
*/
|
|
50
|
+
export function runArtifactRel(rel) {
|
|
51
|
+
if (rel.startsWith(".runtime-logs/"))
|
|
52
|
+
return `runtime/${rel.slice(".runtime-logs/".length)}`;
|
|
53
|
+
if (rel.startsWith("runtime/"))
|
|
54
|
+
return rel;
|
|
55
|
+
if (rel.startsWith(".host-logs/"))
|
|
56
|
+
return `host/${rel.slice(".host-logs/".length)}`;
|
|
57
|
+
if (rel.startsWith("host/"))
|
|
58
|
+
return rel;
|
|
59
|
+
if (rel.startsWith(".provider-proxy/"))
|
|
60
|
+
return `provider-proxy/${rel.slice(".provider-proxy/".length)}`;
|
|
61
|
+
if (rel.startsWith("provider-proxy/"))
|
|
62
|
+
return rel;
|
|
63
|
+
if (rel.startsWith(".control-plane/"))
|
|
64
|
+
return `control-plane/${rel.slice(".control-plane/".length)}`;
|
|
65
|
+
if (rel.startsWith("control-plane/"))
|
|
66
|
+
return rel;
|
|
67
|
+
if (rel.startsWith(".goose-logs/"))
|
|
68
|
+
return `runtime/${rel.slice(".goose-logs/".length)}`;
|
|
69
|
+
if (rel.startsWith("goose-logs/"))
|
|
70
|
+
return `runtime/${rel.slice("goose-logs/".length)}`;
|
|
71
|
+
if (rel.startsWith(".fly-logs/"))
|
|
72
|
+
return `host/${rel.slice(".fly-logs/".length)}`;
|
|
73
|
+
if (rel.startsWith("fly-logs/"))
|
|
74
|
+
return `host/${rel.slice("fly-logs/".length)}`;
|
|
75
|
+
if (rel.startsWith(".anthropic-debug/"))
|
|
76
|
+
return `provider-proxy/${rel.slice(".anthropic-debug/".length)}`;
|
|
77
|
+
if (rel.startsWith("anthropic-debug/"))
|
|
78
|
+
return `provider-proxy/${rel.slice("anthropic-debug/".length)}`;
|
|
79
|
+
return rel;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Storage key for a run artifact uploaded with relative path `rel`, routing
|
|
83
|
+
* diagnostics into `logs/` and everything else into `outputs/`.
|
|
84
|
+
*/
|
|
85
|
+
export function runArtifactKey(runId, rel) {
|
|
86
|
+
const namespace = isRunLogRelPath(rel) ? RUN_LOGS_PREFIX : RUN_OUTPUTS_PREFIX;
|
|
87
|
+
return `runs/${runId}/${namespace}/${runArtifactRel(rel)}`;
|
|
88
|
+
}
|
|
89
|
+
/** The `assets` namespace under a run's prefix. */
|
|
90
|
+
export const RUN_ASSETS_PREFIX = "assets";
|
|
91
|
+
/**
|
|
92
|
+
* Storage key for a run's snapshotted asset, addressed by its content hash.
|
|
93
|
+
* At submit, each referenced shared-store asset is copied here so the run owns
|
|
94
|
+
* its bytes. Accepts a `sha256:<hex>` hash or a bare 64-hex digest; the stored
|
|
95
|
+
* suffix is the hex.
|
|
96
|
+
*/
|
|
97
|
+
export function runAssetKey(runId, hash) {
|
|
98
|
+
const hex = hash.startsWith("sha256:") ? hash.slice("sha256:".length) : hash;
|
|
99
|
+
return `runs/${runId}/${RUN_ASSETS_PREFIX}/${hex}`;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=run-artifacts.js.map
|