@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
package/dist/data-tools.js
DELETED
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
/** Thrown by `DataTools.execute` for an unknown tool or malformed arguments. */
|
|
2
|
-
export class DataToolError extends Error {
|
|
3
|
-
constructor(message) {
|
|
4
|
-
super(message);
|
|
5
|
-
this.name = "DataToolError";
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
const DEFAULT_READ_BYTES = 50_000;
|
|
9
|
-
export const DATA_TOOLS_INSTRUCTIONS = "You can read this workspace's agent sessions and their output files. " +
|
|
10
|
-
"Call `list_sessions` to discover sessions (most recent first; page with `cursor`). " +
|
|
11
|
-
"Call `list_outputs` for a session to see its files. Only call `read_output` for a " +
|
|
12
|
-
"specific file when you actually need its contents — it is byte-capped, so if a " +
|
|
13
|
-
"read comes back `truncated`, narrow it with `grep` or a more specific `path` " +
|
|
14
|
-
"rather than re-reading. Never assume a session or file exists without listing first.";
|
|
15
|
-
/** The vendor-neutral tool definitions, shared by createDataTools/createCorpusTools. */
|
|
16
|
-
function buildToolDefs(defaultReadBytes) {
|
|
17
|
-
return [
|
|
18
|
-
{
|
|
19
|
-
name: "list_sessions",
|
|
20
|
-
description: "List agent sessions in the workspace, most recent first. Returns id/status/timestamps " +
|
|
21
|
-
"(and cost when settled) plus a `nextCursor` for the next page. Does NOT return prompts or outputs.",
|
|
22
|
-
input_schema: {
|
|
23
|
-
type: "object",
|
|
24
|
-
additionalProperties: false,
|
|
25
|
-
properties: {
|
|
26
|
-
status: { type: "string", description: "Filter by session status, e.g. 'idle'." },
|
|
27
|
-
since: { type: "string", description: "ISO-8601 lower bound on createdAt." },
|
|
28
|
-
limit: { type: "integer", description: "Page size, 1-100 (default 25)." },
|
|
29
|
-
cursor: { type: "string", description: "Opaque cursor from a prior page's nextCursor." }
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
name: "get_session",
|
|
35
|
-
description: "Get one session's status, timing, and cost summary by id. Does NOT return the submission or outputs.",
|
|
36
|
-
input_schema: {
|
|
37
|
-
type: "object",
|
|
38
|
-
additionalProperties: false,
|
|
39
|
-
required: ["session_id"],
|
|
40
|
-
properties: { session_id: { type: "string", description: "The session id." } }
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
name: "list_outputs",
|
|
45
|
-
description: "List a session's captured output files (id, filename, size, content type). Metadata only, no content.",
|
|
46
|
-
input_schema: {
|
|
47
|
-
type: "object",
|
|
48
|
-
additionalProperties: false,
|
|
49
|
-
required: ["session_id"],
|
|
50
|
-
properties: { session_id: { type: "string", description: "The session id." } }
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
name: "read_output",
|
|
55
|
-
description: "Read one output file of a session as text. Byte-capped: if the file is larger than `max_bytes` the result " +
|
|
56
|
-
"is a prefix with `truncated: true`. Select the file by `path` (e.g. 'report.md') or by `id` from list_outputs.",
|
|
57
|
-
input_schema: {
|
|
58
|
-
type: "object",
|
|
59
|
-
additionalProperties: false,
|
|
60
|
-
required: ["session_id"],
|
|
61
|
-
properties: {
|
|
62
|
-
session_id: { type: "string", description: "The session id." },
|
|
63
|
-
path: { type: "string", description: "Output file path/name (suffix match). Provide this or `id`." },
|
|
64
|
-
id: { type: "string", description: "Output file id from list_outputs. Provide this or `path`." },
|
|
65
|
-
max_bytes: { type: "integer", description: `Cap on bytes read (default ${defaultReadBytes}, max 10000000).` },
|
|
66
|
-
grep: { type: "string", description: "Optional: return only lines matching this substring (case-insensitive)." }
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
name: "search_outputs",
|
|
72
|
-
description: "Find output files across sessions by filename/extension/content type. Returns references " +
|
|
73
|
-
"(session_id, outputId, filename, size) — call read_output to fetch content.",
|
|
74
|
-
input_schema: {
|
|
75
|
-
type: "object",
|
|
76
|
-
additionalProperties: false,
|
|
77
|
-
properties: {
|
|
78
|
-
filename: { type: "string", description: "Case-insensitive substring match on the filename." },
|
|
79
|
-
extension: { type: "string", description: "File extension, e.g. 'md', 'json' (no dot)." },
|
|
80
|
-
content_type: { type: "string", description: "Exact content type or a prefix wildcard like 'image/*'." },
|
|
81
|
-
limit: { type: "integer", description: "Max hits (default 100)." }
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
];
|
|
86
|
-
}
|
|
87
|
-
/** Shared executor over the read surface; `corpus` (when present) enforces the allow-list. */
|
|
88
|
-
function makeExecute(client, defaultReadBytes, corpus) {
|
|
89
|
-
return async function execute(name, input) {
|
|
90
|
-
const args = input ?? {};
|
|
91
|
-
switch (name) {
|
|
92
|
-
case "list_sessions": {
|
|
93
|
-
if (corpus)
|
|
94
|
-
return { sessions: await corpus.listSessionSummaries() };
|
|
95
|
-
const page = await client.sessions.list({
|
|
96
|
-
...(typeof args.status === "string" ? { status: args.status } : {}),
|
|
97
|
-
...(typeof args.since === "string" ? { since: args.since } : {}),
|
|
98
|
-
...(typeof args.limit === "number" ? { limit: args.limit } : {}),
|
|
99
|
-
...(typeof args.cursor === "string" ? { cursor: args.cursor } : {})
|
|
100
|
-
});
|
|
101
|
-
return {
|
|
102
|
-
sessions: page.sessions.map(summarizeSession),
|
|
103
|
-
...(page.nextCursor !== undefined ? { nextCursor: page.nextCursor } : {})
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
case "get_session": {
|
|
107
|
-
const sessionId = requireString(args.session_id, "session_id");
|
|
108
|
-
if (corpus)
|
|
109
|
-
await corpus.ensure(sessionId);
|
|
110
|
-
return summarizeSession(await client.sessions.get(sessionId));
|
|
111
|
-
}
|
|
112
|
-
case "list_outputs": {
|
|
113
|
-
const sessionId = requireString(args.session_id, "session_id");
|
|
114
|
-
if (corpus)
|
|
115
|
-
await corpus.ensure(sessionId);
|
|
116
|
-
const outputs = await client.sessions.outputs(sessionId).list();
|
|
117
|
-
return outputs.map((o) => ({
|
|
118
|
-
id: o.id,
|
|
119
|
-
filename: o.filename,
|
|
120
|
-
sizeBytes: o.sizeBytes,
|
|
121
|
-
contentType: o.contentType
|
|
122
|
-
}));
|
|
123
|
-
}
|
|
124
|
-
case "read_output": {
|
|
125
|
-
const sessionId = requireString(args.session_id, "session_id");
|
|
126
|
-
if (corpus)
|
|
127
|
-
await corpus.ensure(sessionId);
|
|
128
|
-
const selector = readSelector(args);
|
|
129
|
-
const result = await client.sessions.outputs(sessionId).read(selector, {
|
|
130
|
-
maxBytes: typeof args.max_bytes === "number" ? args.max_bytes : defaultReadBytes,
|
|
131
|
-
...(typeof args.grep === "string" && args.grep.length > 0 ? { grep: args.grep } : {})
|
|
132
|
-
});
|
|
133
|
-
return {
|
|
134
|
-
path: result.output.filename ?? result.output.id,
|
|
135
|
-
text: result.text,
|
|
136
|
-
truncated: result.truncated,
|
|
137
|
-
totalBytes: result.totalBytes
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
case "search_outputs": {
|
|
141
|
-
const sessionIds = corpus ? await corpus.ids() : undefined;
|
|
142
|
-
const page = await client.sessions.searchOutputs({
|
|
143
|
-
...(sessionIds ? { runIds: sessionIds } : {}),
|
|
144
|
-
...(typeof args.filename === "string" ? { filename: args.filename } : {}),
|
|
145
|
-
...(typeof args.extension === "string" ? { extension: args.extension } : {}),
|
|
146
|
-
...(typeof args.content_type === "string" ? { contentType: args.content_type } : {}),
|
|
147
|
-
...(typeof args.limit === "number" ? { limit: args.limit } : {})
|
|
148
|
-
});
|
|
149
|
-
// The wire hit carries `runId`; expose it to the model as `session_id`.
|
|
150
|
-
return {
|
|
151
|
-
hits: page.hits.map((hit) => ({
|
|
152
|
-
session_id: hit.runId,
|
|
153
|
-
outputId: hit.outputId,
|
|
154
|
-
...(hit.filename !== undefined ? { filename: hit.filename } : {}),
|
|
155
|
-
...(hit.sizeBytes !== undefined ? { sizeBytes: hit.sizeBytes } : {}),
|
|
156
|
-
...(hit.contentType !== undefined ? { contentType: hit.contentType } : {})
|
|
157
|
-
}))
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
default:
|
|
161
|
-
throw new DataToolError(`unknown tool: ${name}`);
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Build the data-source chat tool set bound to one {@link AgentExecutor}.
|
|
167
|
-
* Everything the tools can reach is scoped to the client's workspace token.
|
|
168
|
-
*/
|
|
169
|
-
export function createDataTools(client, options) {
|
|
170
|
-
const defaultReadBytes = options?.defaultReadBytes ?? DEFAULT_READ_BYTES;
|
|
171
|
-
return {
|
|
172
|
-
tools: buildToolDefs(defaultReadBytes),
|
|
173
|
-
instructions: DATA_TOOLS_INSTRUCTIONS,
|
|
174
|
-
execute: makeExecute(client, defaultReadBytes)
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Build a corpus-scoped variant of {@link createDataTools}: identical tools, but
|
|
179
|
-
* every read tool is fenced to the sessions in `corpus`. A `get_session`/
|
|
180
|
-
* `list_outputs`/`read_output` for a session outside the corpus throws a
|
|
181
|
-
* {@link DataToolError} ("session <id> is not in this chat's corpus");
|
|
182
|
-
* `list_sessions` returns only corpus sessions; `search_outputs` is auto-scoped
|
|
183
|
-
* to the corpus. This is a client-side guard on top of the server-side
|
|
184
|
-
* workspace-token data scope.
|
|
185
|
-
*/
|
|
186
|
-
export function createCorpusTools(client, corpus, options) {
|
|
187
|
-
const defaultReadBytes = options?.defaultReadBytes ?? DEFAULT_READ_BYTES;
|
|
188
|
-
let resolved = corpus.sessionIds ? new Set(corpus.sessionIds) : null;
|
|
189
|
-
async function resolve() {
|
|
190
|
-
if (resolved)
|
|
191
|
-
return resolved;
|
|
192
|
-
// No explicit sessionIds → page sessions.list with the filter to a concrete set.
|
|
193
|
-
const ids = [];
|
|
194
|
-
const base = corpus.filter ?? {};
|
|
195
|
-
let cursor = base.cursor;
|
|
196
|
-
do {
|
|
197
|
-
const page = await client.sessions.list({ ...base, ...(cursor ? { cursor } : {}) });
|
|
198
|
-
for (const s of page.sessions)
|
|
199
|
-
ids.push(s.id);
|
|
200
|
-
cursor = page.nextCursor;
|
|
201
|
-
} while (cursor);
|
|
202
|
-
resolved = new Set(ids);
|
|
203
|
-
return resolved;
|
|
204
|
-
}
|
|
205
|
-
const guard = {
|
|
206
|
-
ensure: async (sessionId) => {
|
|
207
|
-
const set = await resolve();
|
|
208
|
-
if (!set.has(sessionId))
|
|
209
|
-
throw new DataToolError(`session ${sessionId} is not in this chat's corpus`);
|
|
210
|
-
},
|
|
211
|
-
ids: async () => [...(await resolve())],
|
|
212
|
-
// Build list_sessions rows from sessions.get so the sessionIds corpus never
|
|
213
|
-
// needs the owner-gated sessions.list; bounded by the corpus size.
|
|
214
|
-
listSessionSummaries: async () => {
|
|
215
|
-
const set = await resolve();
|
|
216
|
-
return Promise.all([...set].map(async (id) => summarizeSession(await client.sessions.get(id))));
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
return {
|
|
220
|
-
tools: buildToolDefs(defaultReadBytes),
|
|
221
|
-
instructions: DATA_TOOLS_INSTRUCTIONS,
|
|
222
|
-
execute: makeExecute(client, defaultReadBytes, guard)
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
function requireString(value, field) {
|
|
226
|
-
if (typeof value !== "string" || value.length === 0) {
|
|
227
|
-
throw new DataToolError(`missing required string argument: ${field}`);
|
|
228
|
-
}
|
|
229
|
-
return value;
|
|
230
|
-
}
|
|
231
|
-
function readSelector(args) {
|
|
232
|
-
if (typeof args.path === "string" && args.path.length > 0) {
|
|
233
|
-
return { path: args.path, match: "suffix" };
|
|
234
|
-
}
|
|
235
|
-
if (typeof args.id === "string" && args.id.length > 0) {
|
|
236
|
-
return { id: args.id };
|
|
237
|
-
}
|
|
238
|
-
throw new DataToolError("read_output requires either `path` or `id`");
|
|
239
|
-
}
|
|
240
|
-
/** Pick the small, useful, non-sensitive subset of a session record for the model. */
|
|
241
|
-
function summarizeSession(session) {
|
|
242
|
-
return {
|
|
243
|
-
id: session.id,
|
|
244
|
-
status: session.status,
|
|
245
|
-
createdAt: session.createdAt,
|
|
246
|
-
updatedAt: session.updatedAt,
|
|
247
|
-
costUsd: session.costUsd,
|
|
248
|
-
errorMessage: session.errorMessage ?? undefined
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
//# sourceMappingURL=data-tools.js.map
|
package/dist/data-tools.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"data-tools.js","sourceRoot":"","sources":["../src/data-tools.ts"],"names":[],"mappings":"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"}
|
package/dist/proxy-endpoint.d.ts
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { type PlatformProxyAuthValue, type PlatformProxyEndpoint, type PlatformProxyEndpointAuth, type ProxyMethod, type ProxyRetryPolicy, 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) when the
|
|
19
|
-
* session is created, 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
|
-
* when the session is created; `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
|
-
/** Opt-in retry policy for in-container calls to this endpoint. */
|
|
60
|
-
readonly retry?: ProxyRetryPolicy;
|
|
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 and audit, 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 the SDK 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 };
|
package/dist/proxy-endpoint.js
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
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 and audit, 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 the SDK 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.retry !== undefined ? { retry: options.retry } : {})
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
function requireNonEmpty(value, message) {
|
|
140
|
-
if (typeof value !== "string" || !value) {
|
|
141
|
-
throw new Error(message);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
//# sourceMappingURL=proxy-endpoint.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"proxy-endpoint.js","sourceRoot":"","sources":["../src/proxy-endpoint.ts"],"names":[],"mappings":"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"}
|
package/examples/chat-corpus.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reference: a read-only, multi-run chat over a CORPUS of aex runs.
|
|
3
|
-
*
|
|
4
|
-
* Combines the public `@aexhq/sdk` corpus read-tools (`createCorpusTools`) with a
|
|
5
|
-
* direct Claude chat loop (`@anthropic-ai/sdk`). The importable `@aexhq/sdk` stays
|
|
6
|
-
* LLM-vendor-free; the vendor dependency lives only here in the example.
|
|
7
|
-
*
|
|
8
|
-
* Run (Bun): ANTHROPIC_API_KEY=… AEX_API_TOKEN=… bun examples/chat-corpus.ts <sessionId> [sessionId…]
|
|
9
|
-
*
|
|
10
|
-
* The model answers ONLY from the named runs' outputs (read via the corpus
|
|
11
|
-
* tools); a run outside the corpus is refused by the tool layer.
|
|
12
|
-
*/
|
|
13
|
-
import Anthropic from "@anthropic-ai/sdk";
|
|
14
|
-
import { AgentExecutor, createCorpusTools, DataToolError } from "@aexhq/sdk";
|
|
15
|
-
|
|
16
|
-
const sessionIds = process.argv.slice(2);
|
|
17
|
-
if (sessionIds.length === 0) {
|
|
18
|
-
console.error("usage: bun examples/chat-corpus.ts <sessionId> [sessionId…]");
|
|
19
|
-
process.exit(2);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const aex = new AgentExecutor({
|
|
23
|
-
apiToken: process.env.AEX_API_TOKEN!,
|
|
24
|
-
...(process.env.AEX_API_URL ? { baseUrl: process.env.AEX_API_URL } : {})
|
|
25
|
-
});
|
|
26
|
-
const tools = createCorpusTools(aex, { sessionIds });
|
|
27
|
-
const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY! });
|
|
28
|
-
|
|
29
|
-
const SYSTEM =
|
|
30
|
-
"You answer questions about a fixed set of aex agent runs using the provided tools. " +
|
|
31
|
-
tools.instructions;
|
|
32
|
-
|
|
33
|
-
// Anthropic wire-shape tool defs: { name, description, input_schema }. The corpus
|
|
34
|
-
// tool defs are already in that exact shape. Put one cache_control breakpoint on
|
|
35
|
-
// the LAST tool so the (deterministic) tool list + system prefix cache together.
|
|
36
|
-
const wireTools = tools.tools.map((t, i) => ({
|
|
37
|
-
name: t.name,
|
|
38
|
-
description: t.description,
|
|
39
|
-
input_schema: t.input_schema,
|
|
40
|
-
...(i === tools.tools.length - 1 ? { cache_control: { type: "ephemeral" as const } } : {})
|
|
41
|
-
}));
|
|
42
|
-
|
|
43
|
-
const messages: Anthropic.MessageParam[] = [
|
|
44
|
-
{
|
|
45
|
-
role: "user",
|
|
46
|
-
content: "Across these runs, what did they produce and what are the headline findings?"
|
|
47
|
-
}
|
|
48
|
-
];
|
|
49
|
-
|
|
50
|
-
for (let turn = 0; turn < 12; turn++) {
|
|
51
|
-
const stream = anthropic.messages.stream({
|
|
52
|
-
model: process.env.AEX_CHAT_MODEL ?? "claude-opus-4-8",
|
|
53
|
-
max_tokens: 8192,
|
|
54
|
-
thinking: { type: "adaptive" },
|
|
55
|
-
system: [{ type: "text", text: SYSTEM }],
|
|
56
|
-
tools: wireTools,
|
|
57
|
-
messages
|
|
58
|
-
});
|
|
59
|
-
stream.on("text", (delta) => process.stdout.write(delta));
|
|
60
|
-
const response = await stream.finalMessage();
|
|
61
|
-
messages.push({ role: "assistant", content: response.content });
|
|
62
|
-
|
|
63
|
-
if (response.stop_reason === "refusal") {
|
|
64
|
-
console.error("\n[refused]", response.stop_details?.category ?? "");
|
|
65
|
-
break;
|
|
66
|
-
}
|
|
67
|
-
if (response.stop_reason === "end_turn" || response.stop_reason === "max_tokens") break;
|
|
68
|
-
if (response.stop_reason === "pause_turn") continue;
|
|
69
|
-
if (response.stop_reason !== "tool_use") break;
|
|
70
|
-
|
|
71
|
-
const toolResults: Anthropic.ToolResultBlockParam[] = [];
|
|
72
|
-
for (const block of response.content) {
|
|
73
|
-
if (block.type !== "tool_use") continue;
|
|
74
|
-
try {
|
|
75
|
-
const result = await tools.execute(block.name, block.input as Record<string, unknown>);
|
|
76
|
-
toolResults.push({ type: "tool_result", tool_use_id: block.id, content: JSON.stringify(result) });
|
|
77
|
-
} catch (err) {
|
|
78
|
-
const message = err instanceof DataToolError ? err.message : String(err);
|
|
79
|
-
toolResults.push({ type: "tool_result", tool_use_id: block.id, content: message, is_error: true });
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
messages.push({ role: "user", content: toolResults });
|
|
83
|
-
}
|
|
84
|
-
console.log();
|