@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,114 @@
|
|
|
1
|
+
import { rejectStdioMcpShape } from "./_contracts/index.js";
|
|
2
|
+
const WORKSPACE_MCP_ID_PATTERN = /^mcp_[A-Za-z0-9_-]{8,128}$/;
|
|
3
|
+
/**
|
|
4
|
+
* Inline MCP server reference OR a workspace-persistent ref via
|
|
5
|
+
* `McpServer.fromId("mcp_...")`.
|
|
6
|
+
*
|
|
7
|
+
* For inline refs, headers (typically `Authorization`) are vaulted
|
|
8
|
+
* server-side under `secrets.mcpServers` and excluded from the
|
|
9
|
+
* idempotency hash; the non-secret `{name, url}` part is hashed.
|
|
10
|
+
*
|
|
11
|
+
* The SDK splits the header bag from the public ref BEFORE the wire
|
|
12
|
+
* payload is built, so a single inline `McpServer` instance becomes:
|
|
13
|
+
*
|
|
14
|
+
* - a `submission.mcpServers` entry of `{ name, url }`, and
|
|
15
|
+
* - (when `headers` is present) a `secrets.mcpServers` entry of
|
|
16
|
+
* `{ name, headers }`.
|
|
17
|
+
*
|
|
18
|
+
* For workspace refs (`McpServer.fromId(id)`), the submission entry
|
|
19
|
+
* is `{kind:"workspace", id}`; the BFF resolves it to inline at
|
|
20
|
+
* submit time. The user still supplies auth separately via
|
|
21
|
+
* `secrets.mcpServers[<workspace-name>]` keyed by the workspace
|
|
22
|
+
* MCP's persisted `name`.
|
|
23
|
+
*/
|
|
24
|
+
export class McpServer {
|
|
25
|
+
kind;
|
|
26
|
+
name;
|
|
27
|
+
url;
|
|
28
|
+
transport;
|
|
29
|
+
id;
|
|
30
|
+
headers;
|
|
31
|
+
/** Internal constructor. Use `McpServer.remote(...)` or `McpServer.fromId(...)`. */
|
|
32
|
+
constructor(args) {
|
|
33
|
+
if (!args || typeof args !== "object") {
|
|
34
|
+
throw new Error("McpServer: args is required");
|
|
35
|
+
}
|
|
36
|
+
// Defence in depth: any stdio-shaped input that slips past the
|
|
37
|
+
// builder type (callers will reach in with `as never` to feed stdio
|
|
38
|
+
// shapes) is rejected with the canonical error.
|
|
39
|
+
rejectStdioMcpShape(args);
|
|
40
|
+
if (args.kind === "workspace") {
|
|
41
|
+
if (typeof args.id !== "string" || !WORKSPACE_MCP_ID_PATTERN.test(args.id)) {
|
|
42
|
+
throw new Error(`McpServer.fromId: id must match ${WORKSPACE_MCP_ID_PATTERN.source}`);
|
|
43
|
+
}
|
|
44
|
+
this.kind = "workspace";
|
|
45
|
+
this.id = args.id;
|
|
46
|
+
// `name` and `url` are resolved server-side; populate placeholders so
|
|
47
|
+
// type-level access never returns undefined, but mark the workspace
|
|
48
|
+
// ref so callers can branch.
|
|
49
|
+
this.name = "";
|
|
50
|
+
this.url = "";
|
|
51
|
+
this.transport = undefined;
|
|
52
|
+
this.headers = undefined;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (typeof args.name !== "string" || !args.name) {
|
|
56
|
+
throw new Error("McpServer: name is required");
|
|
57
|
+
}
|
|
58
|
+
if (typeof args.url !== "string" || !args.url) {
|
|
59
|
+
throw new Error("McpServer: url is required");
|
|
60
|
+
}
|
|
61
|
+
this.kind = "inline";
|
|
62
|
+
this.id = undefined;
|
|
63
|
+
this.name = args.name;
|
|
64
|
+
this.url = args.url;
|
|
65
|
+
this.transport = args.transport;
|
|
66
|
+
this.headers = args.headers && Object.keys(args.headers).length > 0 ? { ...args.headers } : undefined;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Inline remote MCP server reachable over HTTP(S) by URL. `transport`
|
|
70
|
+
* defaults to the runtime's choice when omitted; pass it explicitly
|
|
71
|
+
* to pin `"http"` (streamable) or `"sse"` (event-stream). Stdio is
|
|
72
|
+
* not supported — see {@link rejectStdioMcpShape}.
|
|
73
|
+
*/
|
|
74
|
+
static remote(args) {
|
|
75
|
+
return new McpServer({ kind: "inline", ...args });
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Reference a workspace-persistent MCP server by id. The BFF
|
|
79
|
+
* resolves the ref to inline `{name, url}` at submit time using the
|
|
80
|
+
* row from `workspace_mcp_servers`. Auth still arrives inline at
|
|
81
|
+
* the call site — pass it in `secrets.mcpServers[<workspace-name>]`.
|
|
82
|
+
*/
|
|
83
|
+
static fromId(id) {
|
|
84
|
+
return new McpServer({ kind: "workspace", id });
|
|
85
|
+
}
|
|
86
|
+
/** Wire shape for the non-secret `submission.mcpServers` entry. */
|
|
87
|
+
toSubmissionEntry() {
|
|
88
|
+
if (this.kind === "workspace") {
|
|
89
|
+
return { kind: "workspace", id: this.id };
|
|
90
|
+
}
|
|
91
|
+
return this.transport
|
|
92
|
+
? { name: this.name, transport: this.transport, url: this.url }
|
|
93
|
+
: { name: this.name, url: this.url };
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Wire shape for the `secrets.mcpServers` entry, or `undefined`
|
|
97
|
+
* when no headers were provided. Returned headers are a defensive
|
|
98
|
+
* copy.
|
|
99
|
+
*
|
|
100
|
+
* Workspace refs never emit a secret entry from the SDK — the
|
|
101
|
+
* caller knows the resolved `name` (from the dashboard or from a
|
|
102
|
+
* prior list call) and supplies the headers under that name
|
|
103
|
+
* directly on the `secrets.mcpServers[]` array. Mixing SDK-side
|
|
104
|
+
* auth into a workspace ref's `name` would create a name/auth
|
|
105
|
+
* mismatch the BFF can't validate.
|
|
106
|
+
*/
|
|
107
|
+
toSecretEntry() {
|
|
108
|
+
if (this.kind === "workspace" || !this.headers) {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
return { name: this.name, url: this.url, headers: { ...this.headers } };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=mcp-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SkillFiles } from "./bundle.js";
|
|
2
|
+
/**
|
|
3
|
+
* Walk a local directory and load every regular file into an in-memory
|
|
4
|
+
* `SkillFiles` map. Symlinks and non-regular files are skipped (a
|
|
5
|
+
* symlink that points outside the root would still be skipped because
|
|
6
|
+
* we use `lstat` semantics). Paths are normalised to forward-slash
|
|
7
|
+
* relative form so they can flow into `bundleSkillFiles` directly.
|
|
8
|
+
*
|
|
9
|
+
* Node-only. Browser callers should use `bundleSkillFiles` with a
|
|
10
|
+
* pre-built files map instead.
|
|
11
|
+
*/
|
|
12
|
+
export declare function readDirectoryAsFiles(rootDir: string): Promise<SkillFiles>;
|
package/dist/node-fs.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { readFile, readdir, stat } from "node:fs/promises";
|
|
2
|
+
import { join, posix, relative, sep } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Walk a local directory and load every regular file into an in-memory
|
|
5
|
+
* `SkillFiles` map. Symlinks and non-regular files are skipped (a
|
|
6
|
+
* symlink that points outside the root would still be skipped because
|
|
7
|
+
* we use `lstat` semantics). Paths are normalised to forward-slash
|
|
8
|
+
* relative form so they can flow into `bundleSkillFiles` directly.
|
|
9
|
+
*
|
|
10
|
+
* Node-only. Browser callers should use `bundleSkillFiles` with a
|
|
11
|
+
* pre-built files map instead.
|
|
12
|
+
*/
|
|
13
|
+
export async function readDirectoryAsFiles(rootDir) {
|
|
14
|
+
if (typeof rootDir !== "string" || !rootDir) {
|
|
15
|
+
throw new Error("readDirectoryAsFiles: rootDir is required");
|
|
16
|
+
}
|
|
17
|
+
const rootStat = await stat(rootDir);
|
|
18
|
+
if (!rootStat.isDirectory()) {
|
|
19
|
+
throw new Error(`readDirectoryAsFiles: ${rootDir} is not a directory`);
|
|
20
|
+
}
|
|
21
|
+
const files = {};
|
|
22
|
+
await walk(rootDir, rootDir, files);
|
|
23
|
+
return files;
|
|
24
|
+
}
|
|
25
|
+
async function walk(rootDir, currentDir, out) {
|
|
26
|
+
const entries = await readdir(currentDir, { withFileTypes: true });
|
|
27
|
+
for (const dirent of entries) {
|
|
28
|
+
const full = join(currentDir, dirent.name);
|
|
29
|
+
if (dirent.isSymbolicLink()) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (dirent.isDirectory()) {
|
|
33
|
+
await walk(rootDir, full, out);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (!dirent.isFile()) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const rel = relative(rootDir, full);
|
|
40
|
+
const posixPath = sep === "/" ? rel : rel.split(sep).join(posix.sep);
|
|
41
|
+
out[posixPath] = await readFile(full);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=node-fs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-fs.js","sourceRoot":"","sources":["../src/node-fs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAGvD;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAAe;IACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,OAAO,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,yBAAyB,OAAO,qBAAqB,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,KAAK,GAA+B,EAAE,CAAC;IAC7C,MAAM,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;IACpC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,KAAK,UAAU,IAAI,CAAC,OAAe,EAAE,UAAkB,EAAE,GAA+B;IACtF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACnE,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,MAAM,CAAC,cAAc,EAAE,EAAE,CAAC;YAC5B,SAAS;QACX,CAAC;QACD,IAAI,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;YACzB,MAAM,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;YAC/B,SAAS;QACX,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YACrB,SAAS;QACX,CAAC;QACD,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACpC,MAAM,SAAS,GAAG,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrE,GAAG,CAAC,SAAS,CAAC,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { type PlatformProxyAuthValue, type PlatformProxyEndpoint, type PlatformProxyEndpointAuth, type ProxyMethod, type ProxyResponseMode } from "./_contracts/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Constructor-only surface for declaring a per-run HTTP proxy endpoint.
|
|
4
|
+
*
|
|
5
|
+
* Why a class rather than a raw object literal: the raw
|
|
6
|
+
* `PlatformProxyEndpoint` + `PlatformProxyEndpointAuth` shape lets the
|
|
7
|
+
* caller assemble two halves of one logical thing (the auth shape and
|
|
8
|
+
* the auth value), and they often drift — agents writing freeform
|
|
9
|
+
* objects regularly hit runtime rejections with `responseMode: "json"`
|
|
10
|
+
* (real values are `status_only | headers_only | full`) or
|
|
11
|
+
* `authShape: { type: "header", header: "X-Api-Key" }` (real field is
|
|
12
|
+
* `name`). The constructor signatures here put the auth secret on the
|
|
13
|
+
* same call as the shape, so any drift becomes a TypeScript error at
|
|
14
|
+
* the call site, not an HTTP 400 a round-trip later.
|
|
15
|
+
*
|
|
16
|
+
* Wire-format unchanged: the SDK splits each `ProxyEndpoint` instance
|
|
17
|
+
* into a `PlatformProxyEndpoint` (the non-secret declaration) plus a
|
|
18
|
+
* `PlatformProxyEndpointAuth` entry (the per-request secret) at
|
|
19
|
+
* `submitRun` time, exactly the way `McpServer` already splits
|
|
20
|
+
* `headers` into `secrets.mcpServers`.
|
|
21
|
+
*
|
|
22
|
+
* Five named constructors:
|
|
23
|
+
*
|
|
24
|
+
* - `ProxyEndpoint.none ({ name, baseUrl, ... })` — keyless upstream
|
|
25
|
+
* - `ProxyEndpoint.bearer({ name, baseUrl, token, ... })`
|
|
26
|
+
* - `ProxyEndpoint.header({ name, baseUrl, header, value, ... })`
|
|
27
|
+
* - `ProxyEndpoint.basic ({ name, baseUrl, username, password, ... })`
|
|
28
|
+
* - `ProxyEndpoint.query ({ name, baseUrl, query, value, ... })`
|
|
29
|
+
*
|
|
30
|
+
* All five share the same allow-list / response-mode / cap parameters.
|
|
31
|
+
* The four authenticated variants split into `secrets.proxyEndpointAuth[].value`
|
|
32
|
+
* at submit time; `none` produces only a declaration (no secret).
|
|
33
|
+
*/
|
|
34
|
+
export interface ProxyEndpointCommonOptions {
|
|
35
|
+
/**
|
|
36
|
+
* Endpoint name. Lowercase letters, digits, `_`, `-`, up to 63
|
|
37
|
+
* chars. Matches the BFF's `PROXY_ENDPOINT_NAME_PATTERN`. Used as
|
|
38
|
+
* the path segment in `/api/runs/:runId/proxy/:name` and as the
|
|
39
|
+
* cross-reference key in `secrets.proxyEndpointAuth`.
|
|
40
|
+
*/
|
|
41
|
+
readonly name: string;
|
|
42
|
+
/** Upstream base URL. Must be an absolute `https://` URL. */
|
|
43
|
+
readonly baseUrl: string;
|
|
44
|
+
/** HTTP methods the in-container caller is allowed to use. */
|
|
45
|
+
readonly allowMethods: readonly ProxyMethod[];
|
|
46
|
+
/** Path prefixes the in-container caller is allowed to hit. */
|
|
47
|
+
readonly allowPathPrefixes: readonly string[];
|
|
48
|
+
/**
|
|
49
|
+
* Caller-supplied headers permitted to pass through the proxy. The
|
|
50
|
+
* auth header (Bearer/Basic/custom-name) is enforced by the proxy
|
|
51
|
+
* itself and MUST NOT appear here.
|
|
52
|
+
*/
|
|
53
|
+
readonly allowHeaders?: readonly string[];
|
|
54
|
+
/** Default narrowest response disclosure mode. */
|
|
55
|
+
readonly responseMode?: ProxyResponseMode;
|
|
56
|
+
readonly maxRequestBytes?: number;
|
|
57
|
+
readonly maxResponseBytes?: number;
|
|
58
|
+
readonly timeoutMs?: number;
|
|
59
|
+
readonly perCallBudget?: number;
|
|
60
|
+
readonly responseByteBudget?: number;
|
|
61
|
+
}
|
|
62
|
+
export interface BearerProxyEndpointOptions extends ProxyEndpointCommonOptions {
|
|
63
|
+
/** Bearer token sent as `Authorization: Bearer <token>`. */
|
|
64
|
+
readonly token: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Options for `ProxyEndpoint.none` — keyless upstream. Same shape as
|
|
68
|
+
* `ProxyEndpointCommonOptions`; declared as an empty extension so the
|
|
69
|
+
* call site reads symmetrically with the other constructors and stays
|
|
70
|
+
* a stable extension point if a future field becomes auth-shape-only.
|
|
71
|
+
*/
|
|
72
|
+
export interface NoneProxyEndpointOptions extends ProxyEndpointCommonOptions {
|
|
73
|
+
}
|
|
74
|
+
export interface BasicProxyEndpointOptions extends ProxyEndpointCommonOptions {
|
|
75
|
+
readonly username: string;
|
|
76
|
+
readonly password: string;
|
|
77
|
+
}
|
|
78
|
+
export interface HeaderProxyEndpointOptions extends ProxyEndpointCommonOptions {
|
|
79
|
+
/** Header name the upstream expects the auth value in. */
|
|
80
|
+
readonly header: string;
|
|
81
|
+
/** Header value (the actual secret). */
|
|
82
|
+
readonly value: string;
|
|
83
|
+
}
|
|
84
|
+
export interface QueryProxyEndpointOptions extends ProxyEndpointCommonOptions {
|
|
85
|
+
/** Query parameter name the upstream expects the auth value in. */
|
|
86
|
+
readonly query: string;
|
|
87
|
+
/** Query parameter value (the actual secret). */
|
|
88
|
+
readonly value: string;
|
|
89
|
+
}
|
|
90
|
+
export declare class ProxyEndpoint {
|
|
91
|
+
/** Non-secret half of the wire shape — declaration only. */
|
|
92
|
+
readonly declaration: PlatformProxyEndpoint;
|
|
93
|
+
/**
|
|
94
|
+
* Per-request secret half — auth value keyed by the same `name`.
|
|
95
|
+
* `null` for keyless (`ProxyEndpoint.none`) endpoints; `splitProxyEndpoints`
|
|
96
|
+
* filters those out so they never land in `secrets.proxyEndpointAuth`.
|
|
97
|
+
*/
|
|
98
|
+
readonly auth: PlatformProxyEndpointAuth | null;
|
|
99
|
+
private constructor();
|
|
100
|
+
/**
|
|
101
|
+
* Keyless endpoint. Routes through the aex managed proxy for
|
|
102
|
+
* unified egress, audit, and budget enforcement, but the BFF injects
|
|
103
|
+
* no auth header or query parameter. Use for public APIs (Wikimedia
|
|
104
|
+
* Commons, NASA Images, Library of Congress, NARA, GDELT, etc.).
|
|
105
|
+
*/
|
|
106
|
+
static none(options: NoneProxyEndpointOptions): ProxyEndpoint;
|
|
107
|
+
/** Bearer-token endpoint. */
|
|
108
|
+
static bearer(options: BearerProxyEndpointOptions): ProxyEndpoint;
|
|
109
|
+
/** Basic-auth endpoint. */
|
|
110
|
+
static basic(options: BasicProxyEndpointOptions): ProxyEndpoint;
|
|
111
|
+
/** Custom-header endpoint. */
|
|
112
|
+
static header(options: HeaderProxyEndpointOptions): ProxyEndpoint;
|
|
113
|
+
/** Query-string-auth endpoint. */
|
|
114
|
+
static query(options: QueryProxyEndpointOptions): ProxyEndpoint;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Split a list of `ProxyEndpoint` instances into the public declarations
|
|
118
|
+
* (`proxyEndpoints[]`) and the per-request auth bundle
|
|
119
|
+
* (`secrets.proxyEndpointAuth[]`). Mirrors the way `submitRun` already
|
|
120
|
+
* splits `McpServer.headers` into `secrets.mcpServers[]`.
|
|
121
|
+
*
|
|
122
|
+
* Throws on duplicate endpoint names — names are the cross-reference
|
|
123
|
+
* key between the two halves and the BFF rejects collisions; failing
|
|
124
|
+
* here gives the caller a precise message at the call site instead of
|
|
125
|
+
* an opaque HTTP error.
|
|
126
|
+
*/
|
|
127
|
+
export declare function splitProxyEndpoints(inputs: readonly ProxyEndpoint[]): {
|
|
128
|
+
endpoints: readonly PlatformProxyEndpoint[];
|
|
129
|
+
auth: readonly PlatformProxyEndpointAuth[];
|
|
130
|
+
};
|
|
131
|
+
export type { PlatformProxyAuthValue as ProxyAuthValue };
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { authShapeHeaderName, PROXY_RESPONSE_MODES } from "./_contracts/index.js";
|
|
2
|
+
export class ProxyEndpoint {
|
|
3
|
+
/** Non-secret half of the wire shape — declaration only. */
|
|
4
|
+
declaration;
|
|
5
|
+
/**
|
|
6
|
+
* Per-request secret half — auth value keyed by the same `name`.
|
|
7
|
+
* `null` for keyless (`ProxyEndpoint.none`) endpoints; `splitProxyEndpoints`
|
|
8
|
+
* filters those out so they never land in `secrets.proxyEndpointAuth`.
|
|
9
|
+
*/
|
|
10
|
+
auth;
|
|
11
|
+
constructor(declaration, auth) {
|
|
12
|
+
this.declaration = declaration;
|
|
13
|
+
this.auth = auth;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Keyless endpoint. Routes through the aex managed proxy for
|
|
17
|
+
* unified egress, audit, and budget enforcement, but the BFF injects
|
|
18
|
+
* no auth header or query parameter. Use for public APIs (Wikimedia
|
|
19
|
+
* Commons, NASA Images, Library of Congress, NARA, GDELT, etc.).
|
|
20
|
+
*/
|
|
21
|
+
static none(options) {
|
|
22
|
+
const common = buildCommonDeclaration(options, { type: "none" });
|
|
23
|
+
return new ProxyEndpoint(common, null);
|
|
24
|
+
}
|
|
25
|
+
/** Bearer-token endpoint. */
|
|
26
|
+
static bearer(options) {
|
|
27
|
+
const common = buildCommonDeclaration(options, { type: "bearer" });
|
|
28
|
+
requireNonEmpty(options.token, "ProxyEndpoint.bearer: token is required");
|
|
29
|
+
return new ProxyEndpoint(common, {
|
|
30
|
+
name: common.name,
|
|
31
|
+
value: { type: "bearer", token: options.token }
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/** Basic-auth endpoint. */
|
|
35
|
+
static basic(options) {
|
|
36
|
+
const common = buildCommonDeclaration(options, { type: "basic" });
|
|
37
|
+
requireNonEmpty(options.username, "ProxyEndpoint.basic: username is required");
|
|
38
|
+
requireNonEmpty(options.password, "ProxyEndpoint.basic: password is required");
|
|
39
|
+
return new ProxyEndpoint(common, {
|
|
40
|
+
name: common.name,
|
|
41
|
+
value: { type: "basic", username: options.username, password: options.password }
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/** Custom-header endpoint. */
|
|
45
|
+
static header(options) {
|
|
46
|
+
requireNonEmpty(options.header, "ProxyEndpoint.header: header is required");
|
|
47
|
+
const common = buildCommonDeclaration(options, { type: "header", name: options.header });
|
|
48
|
+
requireNonEmpty(options.value, "ProxyEndpoint.header: value is required");
|
|
49
|
+
return new ProxyEndpoint(common, {
|
|
50
|
+
name: common.name,
|
|
51
|
+
value: { type: "header", value: options.value }
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/** Query-string-auth endpoint. */
|
|
55
|
+
static query(options) {
|
|
56
|
+
requireNonEmpty(options.query, "ProxyEndpoint.query: query is required");
|
|
57
|
+
const common = buildCommonDeclaration(options, { type: "query", name: options.query });
|
|
58
|
+
requireNonEmpty(options.value, "ProxyEndpoint.query: value is required");
|
|
59
|
+
return new ProxyEndpoint(common, {
|
|
60
|
+
name: common.name,
|
|
61
|
+
value: { type: "query", value: options.value }
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Split a list of `ProxyEndpoint` instances into the public declarations
|
|
67
|
+
* (`proxyEndpoints[]`) and the per-request auth bundle
|
|
68
|
+
* (`secrets.proxyEndpointAuth[]`). Mirrors the way `submitRun` already
|
|
69
|
+
* splits `McpServer.headers` into `secrets.mcpServers[]`.
|
|
70
|
+
*
|
|
71
|
+
* Throws on duplicate endpoint names — names are the cross-reference
|
|
72
|
+
* key between the two halves and the BFF rejects collisions; failing
|
|
73
|
+
* here gives the caller a precise message at the call site instead of
|
|
74
|
+
* an opaque HTTP error.
|
|
75
|
+
*/
|
|
76
|
+
export function splitProxyEndpoints(inputs) {
|
|
77
|
+
if (inputs.length === 0) {
|
|
78
|
+
return { endpoints: [], auth: [] };
|
|
79
|
+
}
|
|
80
|
+
const endpoints = [];
|
|
81
|
+
const auth = [];
|
|
82
|
+
const seen = new Set();
|
|
83
|
+
for (let i = 0; i < inputs.length; i++) {
|
|
84
|
+
const entry = inputs[i];
|
|
85
|
+
if (!(entry instanceof ProxyEndpoint)) {
|
|
86
|
+
throw new TypeError(`proxyEndpoints[${i}] must be a ProxyEndpoint built via ProxyEndpoint.none / bearer / header / basic / query`);
|
|
87
|
+
}
|
|
88
|
+
if (seen.has(entry.declaration.name)) {
|
|
89
|
+
throw new Error(`proxyEndpoints duplicate name: ${entry.declaration.name}`);
|
|
90
|
+
}
|
|
91
|
+
seen.add(entry.declaration.name);
|
|
92
|
+
endpoints.push(entry.declaration);
|
|
93
|
+
if (entry.auth !== null) {
|
|
94
|
+
auth.push(entry.auth);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return { endpoints, auth };
|
|
98
|
+
}
|
|
99
|
+
function buildCommonDeclaration(options, authShape) {
|
|
100
|
+
requireNonEmpty(options.name, "ProxyEndpoint: name is required");
|
|
101
|
+
requireNonEmpty(options.baseUrl, "ProxyEndpoint: baseUrl is required");
|
|
102
|
+
if (!Array.isArray(options.allowMethods) || options.allowMethods.length === 0) {
|
|
103
|
+
throw new Error("ProxyEndpoint: allowMethods must be a non-empty array");
|
|
104
|
+
}
|
|
105
|
+
if (!Array.isArray(options.allowPathPrefixes) || options.allowPathPrefixes.length === 0) {
|
|
106
|
+
throw new Error("ProxyEndpoint: allowPathPrefixes must be a non-empty array");
|
|
107
|
+
}
|
|
108
|
+
if (options.responseMode !== undefined && !PROXY_RESPONSE_MODES.includes(options.responseMode)) {
|
|
109
|
+
throw new Error(`ProxyEndpoint: responseMode must be one of ${PROXY_RESPONSE_MODES.join(" | ")}`);
|
|
110
|
+
}
|
|
111
|
+
// Defence in depth: don't let the caller list the auth carrier
|
|
112
|
+
// header in `allowHeaders`. The BFF rejects this too, but a precise
|
|
113
|
+
// SDK-side error message is clearer.
|
|
114
|
+
if (options.allowHeaders) {
|
|
115
|
+
const carrier = authShapeHeaderName(authShape);
|
|
116
|
+
if (carrier) {
|
|
117
|
+
for (const h of options.allowHeaders) {
|
|
118
|
+
if (h.toLowerCase() === carrier) {
|
|
119
|
+
throw new Error(`ProxyEndpoint: allowHeaders MUST NOT include the auth header "${h}" — ` +
|
|
120
|
+
`it's set by the proxy on every request`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
name: options.name,
|
|
127
|
+
baseUrl: options.baseUrl,
|
|
128
|
+
authShape,
|
|
129
|
+
allowMethods: options.allowMethods,
|
|
130
|
+
allowPathPrefixes: options.allowPathPrefixes,
|
|
131
|
+
...(options.allowHeaders ? { allowHeaders: options.allowHeaders } : {}),
|
|
132
|
+
...(options.responseMode ? { responseMode: options.responseMode } : {}),
|
|
133
|
+
...(options.maxRequestBytes !== undefined ? { maxRequestBytes: options.maxRequestBytes } : {}),
|
|
134
|
+
...(options.maxResponseBytes !== undefined ? { maxResponseBytes: options.maxResponseBytes } : {}),
|
|
135
|
+
...(options.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}),
|
|
136
|
+
...(options.perCallBudget !== undefined ? { perCallBudget: options.perCallBudget } : {}),
|
|
137
|
+
...(options.responseByteBudget !== undefined
|
|
138
|
+
? { responseByteBudget: options.responseByteBudget }
|
|
139
|
+
: {})
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function requireNonEmpty(value, message) {
|
|
143
|
+
if (typeof value !== "string" || !value) {
|
|
144
|
+
throw new Error(message);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=proxy-endpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy-endpoint.js","sourceRoot":"","sources":["../src/proxy-endpoint.ts"],"names":[],"mappings":"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"}
|
package/dist/skill.d.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { type AssetRef, type FetchLike, type SkillRef } from "./_contracts/index.js";
|
|
2
|
+
import { type SkillFiles } from "./bundle.js";
|
|
3
|
+
/**
|
|
4
|
+
* One `Skill` class for skill bytes. `client.submitRun` materializes the bytes
|
|
5
|
+
* as an uploaded asset before the run lands; the wire ref becomes
|
|
6
|
+
* `kind:"asset"`.
|
|
7
|
+
*
|
|
8
|
+
* Build from an inline files map (`Skill.fromFiles`), a local directory
|
|
9
|
+
* (`Skill.fromPath`), or a remote zip archive over a signed URL
|
|
10
|
+
* (`Skill.fromUrl`). All three converge on the same canonical bundle, so
|
|
11
|
+
* identical content dedups across sources.
|
|
12
|
+
*
|
|
13
|
+
* Asset deduplication makes the same bytes a no-op upload on subsequent runs.
|
|
14
|
+
* There is no `Skill.fromId(...)` and no `.upload(client)` — a URL is an
|
|
15
|
+
* ingestion source, not a persistent reference.
|
|
16
|
+
*/
|
|
17
|
+
export declare class Skill {
|
|
18
|
+
#private;
|
|
19
|
+
/**
|
|
20
|
+
* Internal constructor. Use `Skill.fromFiles` or `Skill.fromPath` to create
|
|
21
|
+
* instances.
|
|
22
|
+
*/
|
|
23
|
+
private constructor();
|
|
24
|
+
/**
|
|
25
|
+
* The wire-level reference. Returns the SDK-private draft shape for
|
|
26
|
+
* un-materialized skills (kind:"draft", with name + contentHash).
|
|
27
|
+
* `client.submitRun` walks these and uploads them before the run
|
|
28
|
+
* lands.
|
|
29
|
+
*/
|
|
30
|
+
get ref(): AssetRef | DraftSkillRef;
|
|
31
|
+
/** True for local-bytes Skills that haven't been uploaded yet. */
|
|
32
|
+
get isDraft(): boolean;
|
|
33
|
+
get isConsumed(): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Build a draft Skill from an inline files map. The SDK validates
|
|
36
|
+
* basic safety (no path traversal, size caps, has `SKILL.md`),
|
|
37
|
+
* deterministically zips the bundle, and computes the
|
|
38
|
+
* `sha256:<hex>` content hash. `client.submitRun` materializes
|
|
39
|
+
* these before the run lands.
|
|
40
|
+
*/
|
|
41
|
+
static fromFiles(args: {
|
|
42
|
+
readonly name: string;
|
|
43
|
+
readonly files: SkillFiles;
|
|
44
|
+
}): Promise<Skill>;
|
|
45
|
+
/**
|
|
46
|
+
* Read a local directory and build a draft Skill. Symlinks and
|
|
47
|
+
* non-regular files are skipped. Node-only.
|
|
48
|
+
*/
|
|
49
|
+
static fromPath(rootDir: string, args: {
|
|
50
|
+
readonly name: string;
|
|
51
|
+
}): Promise<Skill>;
|
|
52
|
+
/**
|
|
53
|
+
* Fetch a zip-archived skill from a URL and build a draft Skill. The archive
|
|
54
|
+
* is downloaded in the SDK process, so the URL is caller-controlled — host
|
|
55
|
+
* the skill yourself and pass a temporary signed URL (e.g. an S3 presigned
|
|
56
|
+
* URL). Its bytes are optionally integrity-checked against `sha256`, unzipped,
|
|
57
|
+
* and reduced to the same files map as `Skill.fromFiles` — so a URL-sourced
|
|
58
|
+
* skill and the identical local skill produce the same canonical asset and
|
|
59
|
+
* dedup against each other.
|
|
60
|
+
*
|
|
61
|
+
* The archive must contain `SKILL.md` at its root, or inside a single
|
|
62
|
+
* top-level folder (which is stripped). The signed URL only needs to be valid
|
|
63
|
+
* for this call; `client.submitRun` snapshots the bytes into the run.
|
|
64
|
+
*
|
|
65
|
+
* Universal (Node 18+ / browser): requires a global `fetch`, or pass one.
|
|
66
|
+
*/
|
|
67
|
+
static fromUrl(url: string, args: {
|
|
68
|
+
readonly name: string;
|
|
69
|
+
readonly sha256?: string;
|
|
70
|
+
readonly timeoutMs?: number;
|
|
71
|
+
readonly fetch?: FetchLike;
|
|
72
|
+
}): Promise<Skill>;
|
|
73
|
+
/**
|
|
74
|
+
* Reference a skill already uploaded to the workspace catalog
|
|
75
|
+
* (`aex skills upload` / `operations.createSkillBundle`) in a run.
|
|
76
|
+
*
|
|
77
|
+
* A catalog skill's bytes are a content-addressed asset, so referencing it
|
|
78
|
+
* is just an `{ kind:"asset" }` ref — once a run snapshots the bytes, it is
|
|
79
|
+
* the identical normalized flow as an inline or file-sourced skill. Pass the
|
|
80
|
+
* `Skill` record returned by `client.skills.list()` / `.get()`:
|
|
81
|
+
*
|
|
82
|
+
* const [s] = await client.skills.list();
|
|
83
|
+
* await client.submitRun({ ..., skills: [Skill.fromCatalog(s)] });
|
|
84
|
+
*
|
|
85
|
+
* The record must be `ready` (it has a content hash). Unlike the draft
|
|
86
|
+
* builders this performs no upload — the bytes already live in the catalog.
|
|
87
|
+
*/
|
|
88
|
+
static fromCatalog(record: {
|
|
89
|
+
readonly name: string;
|
|
90
|
+
readonly hash?: string | null;
|
|
91
|
+
}): Skill;
|
|
92
|
+
/**
|
|
93
|
+
* Internal: yield the draft's bytes + metadata so `client.submitRun`
|
|
94
|
+
* can upload the asset. After this returns, the Skill is marked consumed
|
|
95
|
+
* so a second submitRun call against the same instance throws
|
|
96
|
+
* (avoid silently re-uploading; explicit re-construction is the
|
|
97
|
+
* supported retry pattern).
|
|
98
|
+
*
|
|
99
|
+
* Returns undefined for already-materialized Skills.
|
|
100
|
+
*/
|
|
101
|
+
_takeDraftBundle(): {
|
|
102
|
+
name: string;
|
|
103
|
+
contentHash: string;
|
|
104
|
+
bytes: Uint8Array;
|
|
105
|
+
} | undefined;
|
|
106
|
+
toJSON(): SkillRef;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* SDK-internal draft skill marker. Never reaches the wire; the
|
|
110
|
+
* materialize step inside `client.submitRun` converts these to
|
|
111
|
+
* `kind:"asset"` refs.
|
|
112
|
+
*/
|
|
113
|
+
export interface DraftSkillRef {
|
|
114
|
+
readonly kind: "draft";
|
|
115
|
+
readonly name: string;
|
|
116
|
+
readonly contentHash: string;
|
|
117
|
+
}
|