@aexhq/sdk 0.34.0 → 0.36.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 +16 -15
- package/dist/_contracts/index.d.ts +3 -4
- package/dist/_contracts/index.js +1 -4
- package/dist/_contracts/operations.d.ts +2 -1
- package/dist/_contracts/operations.js +10 -0
- package/dist/_contracts/run-config.d.ts +1 -3
- package/dist/_contracts/run-config.js +2 -7
- package/dist/_contracts/run-trace.d.ts +0 -86
- package/dist/_contracts/run-trace.js +1 -184
- package/dist/_contracts/run-unit.d.ts +2 -25
- package/dist/_contracts/run-unit.js +1 -2
- package/dist/_contracts/runtime-manifest.d.ts +1 -1
- package/dist/_contracts/runtime-security-profile.d.ts +0 -2
- package/dist/_contracts/runtime-security-profile.js +0 -9
- package/dist/_contracts/runtime-types.d.ts +25 -4
- package/dist/_contracts/stable.d.ts +1 -1
- package/dist/_contracts/stable.js +1 -1
- package/dist/_contracts/submission.d.ts +62 -95
- package/dist/_contracts/submission.js +59 -482
- package/dist/cli.mjs +99 -442
- package/dist/cli.mjs.sha256 +1 -1
- package/dist/client.d.ts +49 -25
- package/dist/client.js +341 -70
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +9 -15
- package/dist/index.js +11 -17
- package/dist/index.js.map +1 -1
- package/dist/retry.d.ts +162 -0
- package/dist/retry.js +320 -0
- package/dist/retry.js.map +1 -0
- package/dist/secret.d.ts +2 -2
- package/dist/secret.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/concepts/composition.md +8 -14
- package/docs/credentials.md +59 -101
- package/docs/defaults.md +0 -8
- package/docs/events.md +8 -9
- package/docs/limits-and-quotas.md +1 -4
- package/docs/limits.md +2 -6
- package/docs/mcp.md +4 -5
- package/docs/networking.md +6 -16
- package/docs/outputs.md +0 -4
- package/docs/public-surface.json +3 -3
- package/docs/quickstart.md +3 -7
- package/docs/retries.md +129 -0
- package/docs/run-config.md +6 -3
- package/docs/secrets.md +1 -1
- package/docs/skills.md +3 -3
- package/docs/vision-skills.md +52 -101
- package/examples/feature-tour.ts +284 -0
- package/package.json +1 -1
- package/dist/_contracts/proxy-protocol.d.ts +0 -305
- package/dist/_contracts/proxy-protocol.js +0 -297
- package/dist/_contracts/proxy-validation.d.ts +0 -19
- package/dist/_contracts/proxy-validation.js +0 -51
- package/dist/data-tools.d.ts +0 -82
- package/dist/data-tools.js +0 -251
- package/dist/data-tools.js.map +0 -1
- package/dist/proxy-endpoint.d.ts +0 -131
- package/dist/proxy-endpoint.js +0 -144
- package/dist/proxy-endpoint.js.map +0 -1
- package/examples/chat-corpus.ts +0 -84
|
@@ -1,297 +0,0 @@
|
|
|
1
|
-
// Wire format between the in-container runtime bridge (mounted at
|
|
2
|
-
// `/mnt/session/uploads/aex/aex`, invoked through `bun`) and
|
|
3
|
-
// the hosted API's named 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 hosted API
|
|
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
|
-
/**
|
|
22
|
-
* Streaming named-proxy protocol. A client that sends `"2"` in
|
|
23
|
-
* {@link PROXY_PROTOCOL_HEADER} opts into the streamed response path: the
|
|
24
|
-
* hosted API pipes the upstream body back unbuffered (no base64, no
|
|
25
|
-
* full-body JSON envelope) and carries the envelope metadata
|
|
26
|
-
* in the `x-aex-proxy-*` response headers below instead of a JSON envelope.
|
|
27
|
-
*
|
|
28
|
-
* Additive: `"1"` stays valid and keeps the buffered
|
|
29
|
-
* {@link ProxyResponseEnvelope}. Old runners keep working; new runners
|
|
30
|
-
* stream. The version is on the request header so the hosted API can serve
|
|
31
|
-
* both shapes without a coordinated CLI/BFF release.
|
|
32
|
-
*/
|
|
33
|
-
export const PROXY_PROTOCOL_VERSION_V2 = "2";
|
|
34
|
-
export const PROXY_PROTOCOL_HEADER = "x-aex-proxy-protocol";
|
|
35
|
-
/**
|
|
36
|
-
* Response headers for the streamed (v2) named-proxy path. The hosted API sets
|
|
37
|
-
* these BEFORE it starts streaming the upstream body, so the client can
|
|
38
|
-
* reconstruct the same fields the v1 {@link ProxyResponseEnvelope} carried
|
|
39
|
-
* without buffering. All values are plain strings; numeric fields are
|
|
40
|
-
* decimal, booleans are `"true"`/`"false"`.
|
|
41
|
-
*/
|
|
42
|
-
export const PROXY_RESP_STATUS_HEADER = "x-aex-proxy-status";
|
|
43
|
-
export const PROXY_RESP_MODE_HEADER = "x-aex-proxy-effective-mode";
|
|
44
|
-
/**
|
|
45
|
-
* `"true"` when the cap forced truncation, `"false"` when the full body
|
|
46
|
-
* fit, `"unknown"` when the upstream omitted `content-length` and the body
|
|
47
|
-
* happened to reach the cap (can't distinguish exact-fit from over-cap
|
|
48
|
-
* without buffering). See the streaming byte-cap note in proxy-routes.ts.
|
|
49
|
-
*/
|
|
50
|
-
export const PROXY_RESP_TRUNCATED_HEADER = "x-aex-proxy-truncated";
|
|
51
|
-
/** JSON object of lowercase upstream header names → values (mode-filtered). */
|
|
52
|
-
export const PROXY_RESP_UPSTREAM_HEADERS_HEADER = "x-aex-proxy-upstream-headers";
|
|
53
|
-
/**
|
|
54
|
-
* Default `User-Agent` the proxy attaches to every outbound request when
|
|
55
|
-
* the caller did not supply one via `allowHeaders`. Some upstreams reject
|
|
56
|
-
* requests that arrive without a meaningful UA — notably the Wikimedia
|
|
57
|
-
* family (Wikidata, Wikipedia, Wikimedia Commons), whose policy requires
|
|
58
|
-
* a contactable identifier and otherwise returns HTTP 403 with a
|
|
59
|
-
* `Please identify your user agent` body.
|
|
60
|
-
*
|
|
61
|
-
* Callers can override per request by listing `user-agent` in their
|
|
62
|
-
* endpoint's `allowHeaders` and setting it on the proxy call; the
|
|
63
|
-
* default only fires when nothing was forwarded.
|
|
64
|
-
*
|
|
65
|
-
* See <https://meta.wikimedia.org/wiki/User-Agent_policy>.
|
|
66
|
-
*/
|
|
67
|
-
export const PROXY_DEFAULT_USER_AGENT = "aex-proxy/1.0 (+https://aex.dev/contact)";
|
|
68
|
-
export const PROXY_METHOD_HEADER = "x-aex-method";
|
|
69
|
-
export const PROXY_PATH_HEADER = "x-aex-path";
|
|
70
|
-
export const PROXY_QUERY_HEADER = "x-aex-query";
|
|
71
|
-
export const PROXY_HEADERS_HEADER = "x-aex-headers";
|
|
72
|
-
export const PROXY_RESPONSE_MODE_HEADER = "x-aex-response-mode";
|
|
73
|
-
export const PROXY_ALLOWED_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"];
|
|
74
|
-
export const PROXY_RESPONSE_MODES = ["status_only", "headers_only", "full"];
|
|
75
|
-
export const PROXY_RETRY_JITTERS = ["full", "none"];
|
|
76
|
-
export const PROXY_RETRY_POLICY_DEFAULTS = {
|
|
77
|
-
maxAttempts: 3,
|
|
78
|
-
initialDelayMs: 250,
|
|
79
|
-
maxDelayMs: 5000,
|
|
80
|
-
jitter: "full",
|
|
81
|
-
retryOnStatuses: [408, 425, 429, 500, 502, 503, 504],
|
|
82
|
-
retryOnMethods: ["GET", "HEAD"],
|
|
83
|
-
respectRetryAfter: true
|
|
84
|
-
};
|
|
85
|
-
export function resolveProxyRetryPolicy(policy) {
|
|
86
|
-
return {
|
|
87
|
-
maxAttempts: policy.maxAttempts ?? PROXY_RETRY_POLICY_DEFAULTS.maxAttempts,
|
|
88
|
-
initialDelayMs: policy.initialDelayMs ?? PROXY_RETRY_POLICY_DEFAULTS.initialDelayMs,
|
|
89
|
-
maxDelayMs: policy.maxDelayMs ?? PROXY_RETRY_POLICY_DEFAULTS.maxDelayMs,
|
|
90
|
-
jitter: policy.jitter ?? PROXY_RETRY_POLICY_DEFAULTS.jitter,
|
|
91
|
-
retryOnStatuses: policy.retryOnStatuses ?? PROXY_RETRY_POLICY_DEFAULTS.retryOnStatuses,
|
|
92
|
-
retryOnMethods: policy.retryOnMethods ?? PROXY_RETRY_POLICY_DEFAULTS.retryOnMethods,
|
|
93
|
-
respectRetryAfter: policy.respectRetryAfter ?? PROXY_RETRY_POLICY_DEFAULTS.respectRetryAfter
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Narrowing order: a request may only narrow below the policy ceiling.
|
|
98
|
-
* `status_only` is narrowest, `full` is widest. The BFF computes
|
|
99
|
-
* `narrowest(policyMode, headerMode)` and ignores escalation attempts,
|
|
100
|
-
* auditing them as `mode_clamped`.
|
|
101
|
-
*/
|
|
102
|
-
const RESPONSE_MODE_WIDTH = {
|
|
103
|
-
status_only: 0,
|
|
104
|
-
headers_only: 1,
|
|
105
|
-
full: 2
|
|
106
|
-
};
|
|
107
|
-
/**
|
|
108
|
-
* Returns the narrower of the two response modes (lower width wins).
|
|
109
|
-
* Pure function so the CLI and BFF can both call it without import cycles.
|
|
110
|
-
*/
|
|
111
|
-
export function narrowResponseMode(policy, requested) {
|
|
112
|
-
return RESPONSE_MODE_WIDTH[requested] < RESPONSE_MODE_WIDTH[policy] ? requested : policy;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Error codes returned by the proxy route. Stable strings — the CLI
|
|
116
|
-
* matches against them in scripts. Adding a new code is non-breaking;
|
|
117
|
-
* removing or renaming an existing code requires a protocol bump.
|
|
118
|
-
*/
|
|
119
|
-
export const PROXY_ERROR_CODES = [
|
|
120
|
-
"unsupported_protocol",
|
|
121
|
-
"unauthorized",
|
|
122
|
-
"endpoint_not_found",
|
|
123
|
-
"policy_denied",
|
|
124
|
-
"rate_limited",
|
|
125
|
-
"ssrf_denied",
|
|
126
|
-
"upstream_timeout",
|
|
127
|
-
"upstream_error",
|
|
128
|
-
"exceeded_cap",
|
|
129
|
-
"bad_request",
|
|
130
|
-
"internal_error"
|
|
131
|
-
];
|
|
132
|
-
/**
|
|
133
|
-
* Default caps for a proxy endpoint when the submission doesn't specify one.
|
|
134
|
-
* Lives in the protocol module (next to the index-file shape) so
|
|
135
|
-
* {@link buildProxyIndexFile} can fill every optional cap with a concrete
|
|
136
|
-
* value; the submission parser re-exports it.
|
|
137
|
-
*
|
|
138
|
-
* `maxResponseBytes: 0` means UNLIMITED — the v2 path streams the upstream body
|
|
139
|
-
* unbuffered (O(1) memory regardless of size), so there is no cap to apply by
|
|
140
|
-
* default. A customer can opt into a per-response truncation cap by setting a
|
|
141
|
-
* positive value. There is no cumulative per-run call/byte budget: it needed a
|
|
142
|
-
* per-call counter on the hot path and only existed to bound memory, which
|
|
143
|
-
* streaming already does. The platform records named-proxy request bytes,
|
|
144
|
-
* response bytes, attempts, and retries as run-log usage telemetry only; no
|
|
145
|
-
* pricing/charging model is derived here.
|
|
146
|
-
*/
|
|
147
|
-
export const PROXY_ENDPOINT_DEFAULTS = {
|
|
148
|
-
allowHeaders: [],
|
|
149
|
-
responseMode: "headers_only",
|
|
150
|
-
// 10 MiB. The body is buffered in the hosted API to enforce this cap, while the
|
|
151
|
-
// launch default fits practical multimodal/tool POSTs without every endpoint
|
|
152
|
-
// needing an override.
|
|
153
|
-
maxRequestBytes: 10 * 1024 * 1024,
|
|
154
|
-
// Unlimited (0). The request body is buffered to enforce its cap, so that
|
|
155
|
-
// stays finite; the response is streamed, so it does not need one.
|
|
156
|
-
maxResponseBytes: 0,
|
|
157
|
-
// 5 minutes. Long-running upstream tool/model calls should not fail under a
|
|
158
|
-
// development-oriented 10s ceiling; endpoints can still set a smaller value.
|
|
159
|
-
timeoutMs: 5 * 60 * 1000
|
|
160
|
-
};
|
|
161
|
-
/**
|
|
162
|
-
* Build the per-run {@link ProxyIndexFile} mounted into the container at
|
|
163
|
-
* `/mnt/session/uploads/aex/index.json`. Pure: applies
|
|
164
|
-
* {@link PROXY_ENDPOINT_DEFAULTS} so every optional cap is concrete, and
|
|
165
|
-
* carries ONLY the non-secret endpoint policy — auth values never appear.
|
|
166
|
-
*
|
|
167
|
-
* ALWAYS emits a file (the always-on surface). With zero endpoints OR no
|
|
168
|
-
* `proxyPublicBaseUrl`, `proxyBaseUrl` is `null` and `endpoints` is `[]`.
|
|
169
|
-
* Otherwise `proxyBaseUrl` is `<trimmed base>/api/runs/<runId>/proxy`, the
|
|
170
|
-
* prefix the in-container runtime bridge appends `/<endpointName>` to (proxy.ts).
|
|
171
|
-
*/
|
|
172
|
-
export function buildProxyIndexFile(input) {
|
|
173
|
-
const endpoints = input.endpoints ?? [];
|
|
174
|
-
const base = input.proxyPublicBaseUrl?.trim() ?? "";
|
|
175
|
-
const haveBase = base.length > 0;
|
|
176
|
-
const proxyBaseUrl = endpoints.length > 0 && haveBase
|
|
177
|
-
? `${base.replace(/\/+$/, "")}/api/runs/${input.runId}/proxy`
|
|
178
|
-
: null;
|
|
179
|
-
return {
|
|
180
|
-
protocolVersion: PROXY_PROTOCOL_VERSION,
|
|
181
|
-
runId: input.runId,
|
|
182
|
-
proxyBaseUrl,
|
|
183
|
-
endpoints: endpoints.map((e) => ({
|
|
184
|
-
name: e.name,
|
|
185
|
-
baseUrl: e.baseUrl,
|
|
186
|
-
authShape: e.authShape,
|
|
187
|
-
allowMethods: e.allowMethods,
|
|
188
|
-
allowPathPrefixes: e.allowPathPrefixes,
|
|
189
|
-
allowHeaders: e.allowHeaders ?? PROXY_ENDPOINT_DEFAULTS.allowHeaders,
|
|
190
|
-
responseMode: e.responseMode ?? PROXY_ENDPOINT_DEFAULTS.responseMode,
|
|
191
|
-
maxRequestBytes: e.maxRequestBytes ?? PROXY_ENDPOINT_DEFAULTS.maxRequestBytes,
|
|
192
|
-
maxResponseBytes: e.maxResponseBytes ?? PROXY_ENDPOINT_DEFAULTS.maxResponseBytes,
|
|
193
|
-
timeoutMs: e.timeoutMs ?? PROXY_ENDPOINT_DEFAULTS.timeoutMs,
|
|
194
|
-
...(e.retry !== undefined ? { retry: resolveProxyRetryPolicy(e.retry) } : {})
|
|
195
|
-
}))
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Header name (lowercase) that an upstream auth shape uses as its
|
|
200
|
-
* carrier. Returns `undefined` for query-based and keyless auth.
|
|
201
|
-
*
|
|
202
|
-
* Used by the submission parser to forbid `allowHeaders` from listing
|
|
203
|
-
* the auth header (avoids leaks via caller-supplied headers), and by
|
|
204
|
-
* the proxy route to strip any caller header that would collide with
|
|
205
|
-
* the auth carrier at request time.
|
|
206
|
-
*/
|
|
207
|
-
export function authShapeHeaderName(shape) {
|
|
208
|
-
switch (shape.type) {
|
|
209
|
-
case "bearer":
|
|
210
|
-
case "basic":
|
|
211
|
-
return "authorization";
|
|
212
|
-
case "header":
|
|
213
|
-
return shape.name.toLowerCase();
|
|
214
|
-
case "query":
|
|
215
|
-
case "none":
|
|
216
|
-
return undefined;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* Query-string key that an upstream query-based auth shape uses as its
|
|
221
|
-
* carrier. Returns `undefined` for non-query shapes (including "none").
|
|
222
|
-
*/
|
|
223
|
-
export function authShapeQueryName(shape) {
|
|
224
|
-
return shape.type === "query" ? shape.name : undefined;
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Inbound request headers every Aex proxy plane STRIPS before
|
|
228
|
-
* forwarding a runtime/runner request upstream. Three categories:
|
|
229
|
-
*
|
|
230
|
-
* - Credential carriers (`authorization`, `x-api-key`, `cookie`,
|
|
231
|
-
* `proxy-authorization`) — these belong to Aex's own auth gate
|
|
232
|
-
* (the per-run bearer) or to the caller, never the upstream. The
|
|
233
|
-
* legitimate upstream credential is injected server-side from the
|
|
234
|
-
* run's Vault bundle / endpoint auth shape AFTER this strip, so it is
|
|
235
|
-
* never sourced from an inbound header.
|
|
236
|
-
* - Hop-by-hop fields (RFC 7230 §6.1: `connection`, `keep-alive`,
|
|
237
|
-
* `transfer-encoding`, `te`, `trailer`, `upgrade`, `expect`,
|
|
238
|
-
* `proxy-authenticate`, `proxy-connection`) — must not survive a
|
|
239
|
-
* proxy hop.
|
|
240
|
-
* - Routing primitives a compromised runner could spoof to bypass an
|
|
241
|
-
* upstream's IP allowlist / rate-limit (`host`, `content-length`,
|
|
242
|
-
* `x-forwarded-*`, `x-real-ip`, `forwarded`).
|
|
243
|
-
*
|
|
244
|
-
* The platform API provider-proxy and the dashboard MCP proxy strip exactly
|
|
245
|
-
* this set (both inject upstream auth separately — the provider key, or the
|
|
246
|
-
* Vault MCP-bundle headers, applied AFTER the strip). The dashboard
|
|
247
|
-
* customer HTTP proxy hard-denies this set MINUS `x-api-key`, because a
|
|
248
|
-
* customer endpoint may legitimately declare `x-api-key` as its auth
|
|
249
|
-
* carrier; it derives from this constant so the hop-by-hop + routing
|
|
250
|
-
* entries never drift. Keeping the membership here is the single source of
|
|
251
|
-
* truth that stops those surfaces diverging.
|
|
252
|
-
*/
|
|
253
|
-
export const PROXY_STRIPPED_INBOUND_HEADERS = new Set([
|
|
254
|
-
// credential carriers
|
|
255
|
-
"authorization",
|
|
256
|
-
"x-api-key",
|
|
257
|
-
"cookie",
|
|
258
|
-
"proxy-authorization",
|
|
259
|
-
// hop-by-hop (RFC 7230 §6.1)
|
|
260
|
-
"connection",
|
|
261
|
-
"keep-alive",
|
|
262
|
-
"transfer-encoding",
|
|
263
|
-
"te",
|
|
264
|
-
"trailer",
|
|
265
|
-
"upgrade",
|
|
266
|
-
"expect",
|
|
267
|
-
"proxy-authenticate",
|
|
268
|
-
"proxy-connection",
|
|
269
|
-
// routing primitives a runner could spoof
|
|
270
|
-
"host",
|
|
271
|
-
"content-length",
|
|
272
|
-
"x-forwarded-for",
|
|
273
|
-
"x-forwarded-host",
|
|
274
|
-
"x-forwarded-proto",
|
|
275
|
-
"x-forwarded-port",
|
|
276
|
-
"x-real-ip",
|
|
277
|
-
"forwarded"
|
|
278
|
-
]);
|
|
279
|
-
/**
|
|
280
|
-
* Status code → error code mapping used by the BFF to ensure the audit
|
|
281
|
-
* row's error code and the HTTP response line up. Kept here so callers
|
|
282
|
-
* can do a sanity check in tests.
|
|
283
|
-
*/
|
|
284
|
-
export const PROXY_ERROR_HTTP_STATUS = {
|
|
285
|
-
unsupported_protocol: 426,
|
|
286
|
-
unauthorized: 401,
|
|
287
|
-
endpoint_not_found: 404,
|
|
288
|
-
policy_denied: 403,
|
|
289
|
-
rate_limited: 429,
|
|
290
|
-
ssrf_denied: 403,
|
|
291
|
-
upstream_timeout: 504,
|
|
292
|
-
upstream_error: 502,
|
|
293
|
-
exceeded_cap: 502,
|
|
294
|
-
bad_request: 400,
|
|
295
|
-
internal_error: 500
|
|
296
|
-
};
|
|
297
|
-
//# sourceMappingURL=proxy-protocol.js.map
|
|
@@ -1,19 +0,0 @@
|
|
|
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[];
|
|
@@ -1,51 +0,0 @@
|
|
|
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
|
package/dist/data-tools.d.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Data-source chat tools — turn the SDK's sessions read surface into LLM tool
|
|
3
|
-
* definitions.
|
|
4
|
-
*
|
|
5
|
-
* `createDataTools(client)` returns a small, PROVIDER-AGNOSTIC tool set (plain
|
|
6
|
-
* JSON-Schema `input_schema`, the Anthropic/OpenAI tool shape) plus an
|
|
7
|
-
* `execute(name, input)` dispatcher. A chat backend wires `tools` into its
|
|
8
|
-
* Messages loop and calls `execute` on each `tool_use`. There is no LLM-vendor
|
|
9
|
-
* dependency here: the executor only ever calls public `AgentExecutor` session
|
|
10
|
-
* methods, so a chat built on these tools can reach a workspace's sessions and
|
|
11
|
-
* outputs and NOTHING else — internal/operator data is unreachable by construction.
|
|
12
|
-
*
|
|
13
|
-
* The tools follow search-then-fetch: `list_sessions` / `list_outputs` return
|
|
14
|
-
* lean references and metadata; only `read_output` returns file content, and it
|
|
15
|
-
* is byte-capped so a large deliverable never floods the context window.
|
|
16
|
-
*/
|
|
17
|
-
import type { AgentExecutor } from "./client.js";
|
|
18
|
-
import type { SessionListQuery } from "./_contracts/index.js";
|
|
19
|
-
/** JSON Schema for a tool's input — the subset every major LLM tool API accepts. */
|
|
20
|
-
export interface DataChatToolSchema {
|
|
21
|
-
readonly type: "object";
|
|
22
|
-
readonly properties: Record<string, unknown>;
|
|
23
|
-
readonly required?: readonly string[];
|
|
24
|
-
readonly additionalProperties?: boolean;
|
|
25
|
-
}
|
|
26
|
-
/** One tool definition in the vendor-neutral `{ name, description, input_schema }` shape. */
|
|
27
|
-
export interface DataChatTool {
|
|
28
|
-
readonly name: string;
|
|
29
|
-
readonly description: string;
|
|
30
|
-
readonly input_schema: DataChatToolSchema;
|
|
31
|
-
}
|
|
32
|
-
/** The tool set plus its dispatcher, returned by {@link createDataTools}. */
|
|
33
|
-
export interface DataTools {
|
|
34
|
-
/** Tool definitions to pass to the model. */
|
|
35
|
-
readonly tools: readonly DataChatTool[];
|
|
36
|
-
/** A system-prompt fragment that teaches the model to search-then-fetch. */
|
|
37
|
-
readonly instructions: string;
|
|
38
|
-
/**
|
|
39
|
-
* Run one tool by name with the model's arguments. Returns a JSON-serializable
|
|
40
|
-
* result (never raw bytes). Throws `DataToolError` for an unknown tool or
|
|
41
|
-
* invalid arguments — surface that text back to the model as the tool result.
|
|
42
|
-
*/
|
|
43
|
-
execute(name: string, input: Record<string, unknown>): Promise<unknown>;
|
|
44
|
-
}
|
|
45
|
-
export interface CreateDataToolsOptions {
|
|
46
|
-
/** Default `max_bytes` for `read_output` when the model omits it. Default 50_000. */
|
|
47
|
-
readonly defaultReadBytes?: number;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Scopes a chat to a fixed set of sessions. Either pin explicit `sessionIds`
|
|
51
|
-
* (the primary path — needs only `sessions.get` / `sessions.outputs(id).read`,
|
|
52
|
-
* no `sessions.list`), or supply a `filter`
|
|
53
|
-
* (status/since/limit) resolved to a concrete allow-list via `sessions.list`
|
|
54
|
-
* (owner-gated). Every corpus read tool refuses a session outside the resolved
|
|
55
|
-
* set.
|
|
56
|
-
*/
|
|
57
|
-
export interface ChatCorpus {
|
|
58
|
-
/** Explicit session-id allow-list. */
|
|
59
|
-
readonly sessionIds?: readonly string[];
|
|
60
|
-
/** Resolve the corpus from a `sessions.list` query (status / since / limit). */
|
|
61
|
-
readonly filter?: SessionListQuery;
|
|
62
|
-
}
|
|
63
|
-
/** Thrown by `DataTools.execute` for an unknown tool or malformed arguments. */
|
|
64
|
-
export declare class DataToolError extends Error {
|
|
65
|
-
constructor(message: string);
|
|
66
|
-
}
|
|
67
|
-
export declare const DATA_TOOLS_INSTRUCTIONS: string;
|
|
68
|
-
/**
|
|
69
|
-
* Build the data-source chat tool set bound to one {@link AgentExecutor}.
|
|
70
|
-
* Everything the tools can reach is scoped to the client's workspace token.
|
|
71
|
-
*/
|
|
72
|
-
export declare function createDataTools(client: AgentExecutor, options?: CreateDataToolsOptions): DataTools;
|
|
73
|
-
/**
|
|
74
|
-
* Build a corpus-scoped variant of {@link createDataTools}: identical tools, but
|
|
75
|
-
* every read tool is fenced to the sessions in `corpus`. A `get_session`/
|
|
76
|
-
* `list_outputs`/`read_output` for a session outside the corpus throws a
|
|
77
|
-
* {@link DataToolError} ("session <id> is not in this chat's corpus");
|
|
78
|
-
* `list_sessions` returns only corpus sessions; `search_outputs` is auto-scoped
|
|
79
|
-
* to the corpus. This is a client-side guard on top of the server-side
|
|
80
|
-
* workspace-token data scope.
|
|
81
|
-
*/
|
|
82
|
-
export declare function createCorpusTools(client: AgentExecutor, corpus: ChatCorpus, options?: CreateDataToolsOptions): DataTools;
|