@blazingagents/sdk 0.1.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/LICENSE +21 -0
- package/README.md +366 -0
- package/dist/chat-transport.d.ts +17 -0
- package/dist/chat-transport.js +58 -0
- package/dist/client.d.ts +38 -0
- package/dist/client.js +86 -0
- package/dist/contracts/api.d.ts +256 -0
- package/dist/contracts/api.js +189 -0
- package/dist/contracts/entities/agent-tools.d.ts +26 -0
- package/dist/contracts/entities/agent-tools.js +52 -0
- package/dist/contracts/entities/agents.d.ts +183 -0
- package/dist/contracts/entities/agents.js +153 -0
- package/dist/contracts/entities/artifacts.d.ts +71 -0
- package/dist/contracts/entities/artifacts.js +71 -0
- package/dist/contracts/entities/attribution.d.ts +27 -0
- package/dist/contracts/entities/attribution.js +27 -0
- package/dist/contracts/entities/chat.d.ts +269 -0
- package/dist/contracts/entities/chat.js +198 -0
- package/dist/contracts/entities/mcp-connections.d.ts +421 -0
- package/dist/contracts/entities/mcp-connections.js +473 -0
- package/dist/contracts/entities/memories.d.ts +56 -0
- package/dist/contracts/entities/memories.js +62 -0
- package/dist/contracts/entities/prompts.d.ts +61 -0
- package/dist/contracts/entities/prompts.js +96 -0
- package/dist/contracts/entities/providers.d.ts +123 -0
- package/dist/contracts/entities/providers.js +111 -0
- package/dist/contracts/entities/sessions.d.ts +156 -0
- package/dist/contracts/entities/sessions.js +120 -0
- package/dist/contracts/entities/skills.d.ts +167 -0
- package/dist/contracts/entities/skills.js +153 -0
- package/dist/contracts/entities/tasks.d.ts +457 -0
- package/dist/contracts/entities/tasks.js +252 -0
- package/dist/contracts/entities/tenants.d.ts +69 -0
- package/dist/contracts/entities/tenants.js +54 -0
- package/dist/contracts/entities/usage.d.ts +95 -0
- package/dist/contracts/entities/usage.js +117 -0
- package/dist/contracts/entities/workspaces.d.ts +89 -0
- package/dist/contracts/entities/workspaces.js +71 -0
- package/dist/contracts/ids.d.ts +57 -0
- package/dist/contracts/ids.js +79 -0
- package/dist/contracts/index.d.ts +15 -0
- package/dist/contracts/index.js +16 -0
- package/dist/contracts/limitations.d.ts +138 -0
- package/dist/contracts/limitations.js +140 -0
- package/dist/contracts/utils.d.ts +3 -0
- package/dist/contracts/utils.js +7 -0
- package/dist/errors.d.ts +33 -0
- package/dist/errors.js +48 -0
- package/dist/generation.d.ts +5 -0
- package/dist/generation.js +422 -0
- package/dist/http.d.ts +21 -0
- package/dist/http.js +307 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +13 -0
- package/dist/relay.d.ts +20 -0
- package/dist/relay.js +113 -0
- package/dist/resources/agents.d.ts +8 -0
- package/dist/resources/agents.js +82 -0
- package/dist/resources/artifacts.d.ts +5 -0
- package/dist/resources/artifacts.js +29 -0
- package/dist/resources/mcp-connections.d.ts +2 -0
- package/dist/resources/mcp-connections.js +40 -0
- package/dist/resources/memories.d.ts +7 -0
- package/dist/resources/memories.js +33 -0
- package/dist/resources/prompts.d.ts +6 -0
- package/dist/resources/prompts.js +36 -0
- package/dist/resources/providers.d.ts +5 -0
- package/dist/resources/providers.js +38 -0
- package/dist/resources/sessions.d.ts +8 -0
- package/dist/resources/sessions.js +49 -0
- package/dist/resources/skills.d.ts +2 -0
- package/dist/resources/skills.js +49 -0
- package/dist/resources/tasks.d.ts +7 -0
- package/dist/resources/tasks.js +63 -0
- package/dist/resources/tenant.d.ts +6 -0
- package/dist/resources/tenant.js +19 -0
- package/dist/resources/usage.d.ts +7 -0
- package/dist/resources/usage.js +19 -0
- package/dist/resources/workspaces.d.ts +2 -0
- package/dist/resources/workspaces.js +31 -0
- package/dist/types.d.ts +381 -0
- package/dist/types.js +1 -0
- package/package.json +65 -0
package/dist/http.js
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import { receivedApiErrorResponseSchema } from "./contracts/api.js";
|
|
2
|
+
import { BlazingAgentsError } from "./errors.js";
|
|
3
|
+
const DIAGNOSTIC_BODY_LIMIT_BYTES = 64 * 1024;
|
|
4
|
+
const INVALID_RESPONSE_MESSAGE = "The server returned an invalid response.";
|
|
5
|
+
const NETWORK_ERROR_MESSAGE = "Network request failed (fetch threw before any HTTP exchange).";
|
|
6
|
+
const REQUEST_ABORTED_MESSAGE = "The request was aborted before any HTTP response.";
|
|
7
|
+
/**
|
|
8
|
+
* The fetch client — a thin wrapper in the stripe/openai-node shape.
|
|
9
|
+
* `apiKey` rides the `Authorization: Bearer ${apiKey}` header; `baseUrl`
|
|
10
|
+
* defaults to the local api dev port. No OpenAI wire compatibility.
|
|
11
|
+
*/
|
|
12
|
+
function buildUrl(baseUrl, path, query) {
|
|
13
|
+
const url = `${baseUrl}${path}`;
|
|
14
|
+
if (!query) {
|
|
15
|
+
return url;
|
|
16
|
+
}
|
|
17
|
+
const params = new URLSearchParams();
|
|
18
|
+
for (const [key, value] of Object.entries(query)) {
|
|
19
|
+
if (value === undefined || value === null) {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
params.append(key, String(value));
|
|
23
|
+
}
|
|
24
|
+
const qs = params.toString();
|
|
25
|
+
return qs.length > 0 ? `${url}?${qs}` : url;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Performs a request and returns the parsed JSON body for success (status
|
|
29
|
+
* 2xx). API errors preserve the tolerant wire envelope; malformed responses
|
|
30
|
+
* become `invalid_response`.
|
|
31
|
+
*/
|
|
32
|
+
export async function requestJson(config, path, options = {}, schema) {
|
|
33
|
+
const response = await rawRequest(config, path, options);
|
|
34
|
+
if (response.status < 200 || response.status >= 300) {
|
|
35
|
+
throw await errorFromResponse(response, options.signal);
|
|
36
|
+
}
|
|
37
|
+
const headers = new Headers(response.headers);
|
|
38
|
+
if (response.status === 204) {
|
|
39
|
+
try {
|
|
40
|
+
return schema === undefined ? undefined : schema.parse(undefined);
|
|
41
|
+
}
|
|
42
|
+
catch (cause) {
|
|
43
|
+
throw invalidResponseError(headers, response.status, "", false, cause);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const read = await readResponseBody(response, false);
|
|
47
|
+
if (read.readFailed) {
|
|
48
|
+
if (isRequestAborted(read.cause, options.signal)) {
|
|
49
|
+
throw requestAbortedError(read.cause);
|
|
50
|
+
}
|
|
51
|
+
throw invalidResponseError(headers, response.status, read.diagnosticBody, true, read.cause);
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
const json = JSON.parse(read.bodyText);
|
|
55
|
+
return schema === undefined ? json : schema.parse(json);
|
|
56
|
+
}
|
|
57
|
+
catch (cause) {
|
|
58
|
+
throw invalidResponseError(headers, response.status, read.diagnosticBody, read.diagnosticBodyTruncated, cause);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Performs a request and returns the raw `Response` for streaming paths.
|
|
63
|
+
* Non-2xx bodies are decoded before a caller can observe a streaming body.
|
|
64
|
+
*/
|
|
65
|
+
export async function requestStream(config, path, options = {}) {
|
|
66
|
+
const response = await rawRequest(config, path, options);
|
|
67
|
+
if (response.status >= 200 && response.status < 300) {
|
|
68
|
+
return response;
|
|
69
|
+
}
|
|
70
|
+
throw await errorFromResponse(response, options.signal);
|
|
71
|
+
}
|
|
72
|
+
async function rawRequest(config, path, options) {
|
|
73
|
+
const fetchImpl = config.fetch ?? globalThis.fetch;
|
|
74
|
+
const url = buildUrl(config.baseUrl, path, options.query);
|
|
75
|
+
const method = options.method ?? "GET";
|
|
76
|
+
const startedAt = performance.now();
|
|
77
|
+
const clientRequestId = options.clientRequestId ?? config.clientRequestId;
|
|
78
|
+
const headers = {
|
|
79
|
+
authorization: `Bearer ${config.apiKey}`,
|
|
80
|
+
...(options.headers ?? {}),
|
|
81
|
+
...(clientRequestId === undefined
|
|
82
|
+
? {}
|
|
83
|
+
: { "x-client-request-id": clientRequestId }),
|
|
84
|
+
};
|
|
85
|
+
let body = options.body ?? null;
|
|
86
|
+
if (options.json !== undefined) {
|
|
87
|
+
headers["content-type"] = "application/json";
|
|
88
|
+
body = JSON.stringify(options.json);
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const response = await fetchImpl(url, {
|
|
92
|
+
method,
|
|
93
|
+
headers,
|
|
94
|
+
body,
|
|
95
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
96
|
+
});
|
|
97
|
+
try {
|
|
98
|
+
config.onResponse?.({
|
|
99
|
+
method,
|
|
100
|
+
path,
|
|
101
|
+
status: response.status,
|
|
102
|
+
durationMs: performance.now() - startedAt,
|
|
103
|
+
requestId: response.headers.get("x-request-id") ?? undefined,
|
|
104
|
+
...(clientRequestId === undefined ? {} : { clientRequestId }),
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
/** Observation must not affect transport or response ownership. */
|
|
109
|
+
}
|
|
110
|
+
return response;
|
|
111
|
+
}
|
|
112
|
+
catch (cause) {
|
|
113
|
+
const requestAborted = isRequestAborted(cause, options.signal);
|
|
114
|
+
if (requestAborted) {
|
|
115
|
+
throw requestAbortedError(cause);
|
|
116
|
+
}
|
|
117
|
+
let message = NETWORK_ERROR_MESSAGE;
|
|
118
|
+
if (cause instanceof Error) {
|
|
119
|
+
message = cause.message;
|
|
120
|
+
}
|
|
121
|
+
throw new BlazingAgentsError({
|
|
122
|
+
code: "network_error",
|
|
123
|
+
message,
|
|
124
|
+
}, { cause });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async function errorFromResponse(response, signal) {
|
|
128
|
+
const read = await readResponseBody(response, true);
|
|
129
|
+
if (read.readFailed && isRequestAborted(read.cause, signal)) {
|
|
130
|
+
return requestAbortedError(read.cause);
|
|
131
|
+
}
|
|
132
|
+
const headers = new Headers(response.headers);
|
|
133
|
+
if (read.readFailed || read.diagnosticBodyTruncated) {
|
|
134
|
+
return invalidResponseError(headers, response.status, read.diagnosticBody, read.diagnosticBodyTruncated, read.cause);
|
|
135
|
+
}
|
|
136
|
+
return parseErrorEnvelope(read.diagnosticBody, response.status, headers);
|
|
137
|
+
}
|
|
138
|
+
function isRequestAborted(cause, signal) {
|
|
139
|
+
return (signal?.aborted === true ||
|
|
140
|
+
(cause !== null &&
|
|
141
|
+
typeof cause === "object" &&
|
|
142
|
+
"name" in cause &&
|
|
143
|
+
cause.name === "AbortError"));
|
|
144
|
+
}
|
|
145
|
+
function requestAbortedError(cause) {
|
|
146
|
+
return new BlazingAgentsError({
|
|
147
|
+
code: "request_aborted",
|
|
148
|
+
message: cause instanceof Error ? cause.message : REQUEST_ABORTED_MESSAGE,
|
|
149
|
+
}, { cause });
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Reads a response while retaining at most 64 KiB of UTF-8 diagnostics.
|
|
153
|
+
* Error responses stop as soon as the body is known to exceed the limit.
|
|
154
|
+
* Successful JSON responses continue so legitimate large payloads can parse.
|
|
155
|
+
*/
|
|
156
|
+
async function readResponseBody(response, stopAtDiagnosticLimit) {
|
|
157
|
+
if (response.body === null) {
|
|
158
|
+
return {
|
|
159
|
+
bodyText: "",
|
|
160
|
+
diagnosticBody: "",
|
|
161
|
+
diagnosticBodyTruncated: false,
|
|
162
|
+
readFailed: false,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
let reader;
|
|
166
|
+
try {
|
|
167
|
+
reader = response.body.getReader();
|
|
168
|
+
}
|
|
169
|
+
catch (cause) {
|
|
170
|
+
return {
|
|
171
|
+
bodyText: "",
|
|
172
|
+
cause,
|
|
173
|
+
diagnosticBody: "",
|
|
174
|
+
diagnosticBodyTruncated: true,
|
|
175
|
+
readFailed: true,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
const chunks = [];
|
|
179
|
+
let byteLength = 0;
|
|
180
|
+
while (true) {
|
|
181
|
+
let read;
|
|
182
|
+
try {
|
|
183
|
+
read = await reader.read();
|
|
184
|
+
}
|
|
185
|
+
catch (cause) {
|
|
186
|
+
const diagnostic = decodeDiagnosticChunks(chunks, Math.min(byteLength, DIAGNOSTIC_BODY_LIMIT_BYTES), true);
|
|
187
|
+
return {
|
|
188
|
+
bodyText: "",
|
|
189
|
+
cause,
|
|
190
|
+
diagnosticBody: diagnostic.body,
|
|
191
|
+
diagnosticBodyTruncated: true,
|
|
192
|
+
readFailed: true,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
if (read.done) {
|
|
196
|
+
const diagnostic = decodeDiagnosticChunks(chunks, Math.min(byteLength, DIAGNOSTIC_BODY_LIMIT_BYTES), byteLength > DIAGNOSTIC_BODY_LIMIT_BYTES);
|
|
197
|
+
return {
|
|
198
|
+
bodyText: stopAtDiagnosticLimit
|
|
199
|
+
? diagnostic.body
|
|
200
|
+
: decodeChunks(chunks, byteLength, false),
|
|
201
|
+
diagnosticBody: diagnostic.body,
|
|
202
|
+
diagnosticBodyTruncated: diagnostic.truncated,
|
|
203
|
+
readFailed: false,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
const chunk = read.value;
|
|
207
|
+
if (stopAtDiagnosticLimit &&
|
|
208
|
+
byteLength + chunk.byteLength > DIAGNOSTIC_BODY_LIMIT_BYTES) {
|
|
209
|
+
const remaining = DIAGNOSTIC_BODY_LIMIT_BYTES - byteLength;
|
|
210
|
+
if (remaining > 0) {
|
|
211
|
+
chunks.push(chunk.slice(0, remaining));
|
|
212
|
+
byteLength += remaining;
|
|
213
|
+
}
|
|
214
|
+
return cancelTruncatedBody(reader, chunks, byteLength);
|
|
215
|
+
}
|
|
216
|
+
chunks.push(chunk);
|
|
217
|
+
byteLength += chunk.byteLength;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
async function cancelTruncatedBody(reader, chunks, byteLength) {
|
|
221
|
+
const diagnosticBody = decodeDiagnosticChunks(chunks, byteLength, true).body;
|
|
222
|
+
try {
|
|
223
|
+
await reader.cancel();
|
|
224
|
+
return {
|
|
225
|
+
bodyText: diagnosticBody,
|
|
226
|
+
diagnosticBody,
|
|
227
|
+
diagnosticBodyTruncated: true,
|
|
228
|
+
readFailed: false,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
catch (cause) {
|
|
232
|
+
return {
|
|
233
|
+
bodyText: diagnosticBody,
|
|
234
|
+
cause,
|
|
235
|
+
diagnosticBody,
|
|
236
|
+
diagnosticBodyTruncated: true,
|
|
237
|
+
readFailed: true,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function decodeDiagnosticChunks(chunks, byteLength, sourceTruncated) {
|
|
242
|
+
const body = decodeChunks(chunks, byteLength, sourceTruncated);
|
|
243
|
+
const encoded = new TextEncoder().encode(body);
|
|
244
|
+
if (encoded.byteLength <= DIAGNOSTIC_BODY_LIMIT_BYTES) {
|
|
245
|
+
return { body, truncated: sourceTruncated };
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
body: decodeChunks([encoded.slice(0, DIAGNOSTIC_BODY_LIMIT_BYTES)], DIAGNOSTIC_BODY_LIMIT_BYTES, true),
|
|
249
|
+
truncated: true,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
function decodeChunks(chunks, byteLength, truncated) {
|
|
253
|
+
const bytes = new Uint8Array(byteLength);
|
|
254
|
+
let offset = 0;
|
|
255
|
+
for (const chunk of chunks) {
|
|
256
|
+
if (offset === byteLength) {
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
const retained = chunk.subarray(0, byteLength - offset);
|
|
260
|
+
bytes.set(retained, offset);
|
|
261
|
+
offset += retained.byteLength;
|
|
262
|
+
}
|
|
263
|
+
return new TextDecoder().decode(bytes, truncated ? { stream: true } : {});
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Decodes a response body with the tolerant consumer schema. Unknown future
|
|
267
|
+
* codes and fields remain valid; malformed responses never infer a domain
|
|
268
|
+
* code from HTTP status.
|
|
269
|
+
*/
|
|
270
|
+
export function parseErrorEnvelope(bodyText, status, headers = new Headers()) {
|
|
271
|
+
let parsed;
|
|
272
|
+
if (bodyText.length === 0) {
|
|
273
|
+
parsed = null;
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
try {
|
|
277
|
+
parsed = JSON.parse(bodyText);
|
|
278
|
+
}
|
|
279
|
+
catch (cause) {
|
|
280
|
+
return invalidResponseError(headers, status, bodyText, false, cause);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
const result = receivedApiErrorResponseSchema.safeParse(parsed);
|
|
284
|
+
if (result.success) {
|
|
285
|
+
return new BlazingAgentsError({
|
|
286
|
+
code: result.data.error.code,
|
|
287
|
+
details: result.data.error.details,
|
|
288
|
+
headers,
|
|
289
|
+
message: result.data.error.message,
|
|
290
|
+
param: result.data.error.param,
|
|
291
|
+
requestId: headers.get("x-request-id") ?? undefined,
|
|
292
|
+
status,
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
return invalidResponseError(headers, status, bodyText, false);
|
|
296
|
+
}
|
|
297
|
+
function invalidResponseError(headers, status, responseBody, responseBodyTruncated, cause) {
|
|
298
|
+
return new BlazingAgentsError({
|
|
299
|
+
code: "invalid_response",
|
|
300
|
+
headers,
|
|
301
|
+
message: INVALID_RESPONSE_MESSAGE,
|
|
302
|
+
requestId: headers.get("x-request-id") ?? undefined,
|
|
303
|
+
responseBody,
|
|
304
|
+
responseBodyTruncated: responseBodyTruncated ? true : undefined,
|
|
305
|
+
status,
|
|
306
|
+
}, cause === undefined ? undefined : { cause });
|
|
307
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@blazingagents/sdk` — the resource-style client SDK for the
|
|
3
|
+
* Blazing Agents `/v1` API. `ai` is a peer dependency (`^7`);
|
|
4
|
+
* `UIMessage` is re-exported from `ai`, never redeclared.
|
|
5
|
+
*
|
|
6
|
+
* This is the package's entry point — a barrel file that re-exports the
|
|
7
|
+
* public surface from the internal modules.
|
|
8
|
+
*/
|
|
9
|
+
export type { UIMessage } from "ai";
|
|
10
|
+
export { BlazingAgentsChatTransport, type BlazingAgentsChatTransportOptions, } from "./chat-transport.ts";
|
|
11
|
+
export { BlazingAgents } from "./client.ts";
|
|
12
|
+
export type { Agent, AgentResponse, AgentsResponse, AgentVersion, AgentVersionsListQuery, AgentVersionsResponse, CreateAgentBody, UpdateAgentBody, } from "./contracts/entities/agents.ts";
|
|
13
|
+
export type { ArtifactDownloadUrlResponse, ArtifactListItem, ArtifactsListResponse, } from "./contracts/entities/artifacts.ts";
|
|
14
|
+
export type { CreateMcpConnectionBody, McpAttachmentResponse, McpAttachmentsResponse, McpConnectionAuthType, McpConnectionOauthConnectResponse, McpConnectionReconnectResult, McpConnectionResponse, McpConnectionStatus, McpConnectionTestResponse, ReconnectMcpConnectionBody, UpdateMcpAttachmentBody, UpdateMcpConnectionBody, } from "./contracts/entities/mcp-connections.ts";
|
|
15
|
+
export type { CreateProviderBody, ProviderModel, ProviderModelsResponse, ProviderResponse, ProvidersResponse, ProviderType, UpdateProviderBody, } from "./contracts/entities/providers.ts";
|
|
16
|
+
export type { CreateSkillBody, Skill, SkillArchiveType, SkillCopyResult, SkillCopyResults, SkillDetail, SkillFile, SkillsListResponse, } from "./contracts/entities/skills.ts";
|
|
17
|
+
export type { CreateWorkspaceBody, UpdateWorkspaceBody, Workspace, WorkspaceNetworkPolicy, WorkspacesListResponse, } from "./contracts/entities/workspaces.ts";
|
|
18
|
+
export { BlazingAgentsError } from "./errors.ts";
|
|
19
|
+
export { createChatRelay, createCompletionRelay, type RelayContext, type SessionOwnershipStore, } from "./relay.ts";
|
|
20
|
+
export type { AgentClient, AgentSkillsResource, AgentsListOptions, AgentsResource, AgentVersionsListOptions, ArtifactsResource, AttributionInput, BlazingAgentsErrorCode, BlazingAgentsOptions, BlazingAgentsRequestOptions, BlazingAgentsUIMessage, BlazingAgentsUIMessageChunk, ChatInput, ChatMessageInput, ChatPromptInput, ChatResult, ChatTrigger, CompletionInput, CompletionPromptIdInput, CompletionPromptInput, CompletionResult, KnownBlazingAgentsErrorCode, McpConnectionsResource, MemoriesListOptions, MemoriesResource, ObjectInput, ObjectPromptIdInput, ObjectPromptInput, ObjectResult, PromptsResource, ProvidersResource, ResponseObservation, SessionsResource, SkillsListOptions, TasksResource, TenantResource, TerminalStreamResult, UsageResource, WorkspacesListOptions, WorkspacesResource, } from "./types.ts";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@blazingagents/sdk` — the resource-style client SDK for the
|
|
3
|
+
* Blazing Agents `/v1` API. `ai` is a peer dependency (`^7`);
|
|
4
|
+
* `UIMessage` is re-exported from `ai`, never redeclared.
|
|
5
|
+
*
|
|
6
|
+
* This is the package's entry point — a barrel file that re-exports the
|
|
7
|
+
* public surface from the internal modules.
|
|
8
|
+
*/
|
|
9
|
+
// biome-ignore lint/performance/noBarrelFile: package entry point
|
|
10
|
+
export { BlazingAgentsChatTransport, } from "./chat-transport.js";
|
|
11
|
+
export { BlazingAgents } from "./client.js";
|
|
12
|
+
export { BlazingAgentsError } from "./errors.js";
|
|
13
|
+
export { createChatRelay, createCompletionRelay, } from "./relay.js";
|
package/dist/relay.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { BlazingAgents } from "./client.ts";
|
|
2
|
+
export interface RelayContext {
|
|
3
|
+
agentId: string;
|
|
4
|
+
metadata?: Record<string, unknown>;
|
|
5
|
+
userId: string;
|
|
6
|
+
version?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface SessionOwnershipStore {
|
|
9
|
+
ownerOf(sessionId: string): Promise<string | undefined>;
|
|
10
|
+
recordOwner(sessionId: string, userId: string): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
interface RelayOptions {
|
|
13
|
+
client: Pick<BlazingAgents, "chat" | "completion">;
|
|
14
|
+
resolveContext(request: Request): Promise<RelayContext | null>;
|
|
15
|
+
}
|
|
16
|
+
export declare function createChatRelay(options: RelayOptions & {
|
|
17
|
+
sessions: SessionOwnershipStore;
|
|
18
|
+
}): (request: Request) => Promise<Response>;
|
|
19
|
+
export declare function createCompletionRelay(options: RelayOptions): (request: Request) => Promise<Response>;
|
|
20
|
+
export {};
|
package/dist/relay.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { safeValidateUIMessages } from "ai";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { sessionIdSchema } from "./contracts/ids.js";
|
|
4
|
+
import { BlazingAgentsError } from "./errors.js";
|
|
5
|
+
const chatBodySchema = z.object({
|
|
6
|
+
message: z.unknown(),
|
|
7
|
+
messageId: z.string().min(1).optional(),
|
|
8
|
+
sessionId: sessionIdSchema.optional(),
|
|
9
|
+
trigger: z
|
|
10
|
+
.enum(["submit-message", "regenerate-message"])
|
|
11
|
+
.default("submit-message"),
|
|
12
|
+
});
|
|
13
|
+
const completionBodySchema = z.object({ prompt: z.string().trim().min(1) });
|
|
14
|
+
export function createChatRelay(options) {
|
|
15
|
+
return async (request) => {
|
|
16
|
+
try {
|
|
17
|
+
const context = await options.resolveContext(request);
|
|
18
|
+
if (!context) {
|
|
19
|
+
return errorResponse(401, "unauthorized", "Authentication required.");
|
|
20
|
+
}
|
|
21
|
+
const body = chatBodySchema.parse(await request.json());
|
|
22
|
+
const validated = await safeValidateUIMessages({
|
|
23
|
+
messages: [body.message],
|
|
24
|
+
});
|
|
25
|
+
if (!validated.success) {
|
|
26
|
+
return errorResponse(400, "invalid_request", "Invalid chat message.");
|
|
27
|
+
}
|
|
28
|
+
if (body.sessionId !== undefined &&
|
|
29
|
+
(await options.sessions.ownerOf(body.sessionId)) !== context.userId) {
|
|
30
|
+
return errorResponse(403, "forbidden", "Session is not available.");
|
|
31
|
+
}
|
|
32
|
+
const chatInput = {
|
|
33
|
+
agentId: context.agentId,
|
|
34
|
+
message: validated.data[0],
|
|
35
|
+
messageId: body.messageId,
|
|
36
|
+
metadata: context.metadata,
|
|
37
|
+
signal: request.signal,
|
|
38
|
+
userId: context.userId,
|
|
39
|
+
};
|
|
40
|
+
const result = await options.client.chat(body.sessionId === undefined
|
|
41
|
+
? {
|
|
42
|
+
...chatInput,
|
|
43
|
+
trigger: "submit-message",
|
|
44
|
+
version: context.version,
|
|
45
|
+
}
|
|
46
|
+
: {
|
|
47
|
+
...chatInput,
|
|
48
|
+
sessionId: body.sessionId,
|
|
49
|
+
trigger: body.trigger,
|
|
50
|
+
});
|
|
51
|
+
const sessionId = await result.sessionId;
|
|
52
|
+
if (body.sessionId === undefined) {
|
|
53
|
+
try {
|
|
54
|
+
await options.sessions.recordOwner(sessionId, context.userId);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
await result
|
|
58
|
+
.toResponse()
|
|
59
|
+
.body?.cancel(error)
|
|
60
|
+
.catch(() => undefined);
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return result.toResponse();
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
return safeErrorResponse(error);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export function createCompletionRelay(options) {
|
|
72
|
+
return async (request) => {
|
|
73
|
+
try {
|
|
74
|
+
const context = await options.resolveContext(request);
|
|
75
|
+
if (!context) {
|
|
76
|
+
return errorResponse(401, "unauthorized", "Authentication required.");
|
|
77
|
+
}
|
|
78
|
+
const body = completionBodySchema.parse(await request.json());
|
|
79
|
+
const result = await options.client.completion({
|
|
80
|
+
agentId: context.agentId,
|
|
81
|
+
metadata: context.metadata,
|
|
82
|
+
prompt: body.prompt,
|
|
83
|
+
signal: request.signal,
|
|
84
|
+
userId: context.userId,
|
|
85
|
+
version: context.version,
|
|
86
|
+
});
|
|
87
|
+
return result.toResponse();
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
return safeErrorResponse(error);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function safeErrorResponse(error) {
|
|
95
|
+
if (error instanceof z.ZodError || error instanceof SyntaxError) {
|
|
96
|
+
return errorResponse(400, "invalid_request", "Invalid request body.");
|
|
97
|
+
}
|
|
98
|
+
if (BlazingAgentsError.isInstance(error)) {
|
|
99
|
+
const status = error.status ?? (error.code === "request_aborted" ? 499 : 502);
|
|
100
|
+
const headers = new Headers();
|
|
101
|
+
const requestId = error.requestId ?? error.headers?.get("x-request-id");
|
|
102
|
+
if (requestId) {
|
|
103
|
+
headers.set("x-request-id", requestId);
|
|
104
|
+
}
|
|
105
|
+
return errorResponse(status, error.code, error.message, headers);
|
|
106
|
+
}
|
|
107
|
+
return errorResponse(500, "internal_error", "Request failed.");
|
|
108
|
+
}
|
|
109
|
+
function errorResponse(status, code, message, headers) {
|
|
110
|
+
const responseHeaders = new Headers(headers);
|
|
111
|
+
responseHeaders.set("content-type", "application/json");
|
|
112
|
+
return Response.json({ error: { code, message } }, { status, headers: responseHeaders });
|
|
113
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AgentsResource, HttpConfig } from "../types.ts";
|
|
2
|
+
/**
|
|
3
|
+
* `client.agents` — full CRUD over `/v1/agents`. The list endpoint is
|
|
4
|
+
* unpaginated (bounded by the 100/tenant cap); create/update bodies are
|
|
5
|
+
* the core zod contracts' input shapes. Responses are parsed against the
|
|
6
|
+
* core wire schemas (parse-on-read).
|
|
7
|
+
*/
|
|
8
|
+
export declare function createAgentsResource(config: HttpConfig): AgentsResource;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { agentResponseSchema, agentsResponseSchema, agentVersionSchema, agentVersionsResponseSchema, } from "../contracts/entities/agents.js";
|
|
2
|
+
import { mcpAttachmentResponseSchema, mcpAttachmentsResponseSchema, } from "../contracts/entities/mcp-connections.js";
|
|
3
|
+
import { requestJson } from "../http.js";
|
|
4
|
+
/**
|
|
5
|
+
* `client.agents` — full CRUD over `/v1/agents`. The list endpoint is
|
|
6
|
+
* unpaginated (bounded by the 100/tenant cap); create/update bodies are
|
|
7
|
+
* the core zod contracts' input shapes. Responses are parsed against the
|
|
8
|
+
* core wire schemas (parse-on-read).
|
|
9
|
+
*/
|
|
10
|
+
export function createAgentsResource(config) {
|
|
11
|
+
const getVersion = async (agentId, version) => requestJson(config, `/v1/agents/${agentId}/versions/${version}`, {}, agentVersionSchema);
|
|
12
|
+
const update = async (agentId, body) => requestJson(config, `/v1/agents/${agentId}`, {
|
|
13
|
+
json: body,
|
|
14
|
+
method: "PUT",
|
|
15
|
+
}, agentResponseSchema);
|
|
16
|
+
return {
|
|
17
|
+
async create(body) {
|
|
18
|
+
return await requestJson(config, "/v1/agents", {
|
|
19
|
+
json: body,
|
|
20
|
+
method: "POST",
|
|
21
|
+
}, agentResponseSchema);
|
|
22
|
+
},
|
|
23
|
+
async list(options = {}) {
|
|
24
|
+
return await requestJson(config, "/v1/agents", {
|
|
25
|
+
query: {
|
|
26
|
+
userId: options.userId,
|
|
27
|
+
workspaceId: options.workspaceId,
|
|
28
|
+
},
|
|
29
|
+
}, agentsResponseSchema);
|
|
30
|
+
},
|
|
31
|
+
async get(agentId) {
|
|
32
|
+
return await requestJson(config, `/v1/agents/${agentId}`, {}, agentResponseSchema);
|
|
33
|
+
},
|
|
34
|
+
async disable(agentId) {
|
|
35
|
+
return await requestJson(config, `/v1/agents/${agentId}/disable`, { method: "POST" }, agentResponseSchema);
|
|
36
|
+
},
|
|
37
|
+
async enable(agentId) {
|
|
38
|
+
return await requestJson(config, `/v1/agents/${agentId}/enable`, { method: "POST" }, agentResponseSchema);
|
|
39
|
+
},
|
|
40
|
+
getVersion,
|
|
41
|
+
async listVersions(agentId, options = {}) {
|
|
42
|
+
return await requestJson(config, `/v1/agents/${agentId}/versions`, { query: { cursor: options.cursor, limit: options.limit } }, agentVersionsResponseSchema);
|
|
43
|
+
},
|
|
44
|
+
async listMcpAttachments(agentId) {
|
|
45
|
+
return await requestJson(config, `/v1/agents/${agentId}/mcp-attachments`, {}, mcpAttachmentsResponseSchema);
|
|
46
|
+
},
|
|
47
|
+
async restoreVersion(agentId, versionNumber) {
|
|
48
|
+
const version = await getVersion(agentId, versionNumber);
|
|
49
|
+
return update(agentId, {
|
|
50
|
+
name: version.name,
|
|
51
|
+
model: version.model,
|
|
52
|
+
providerId: version.providerId,
|
|
53
|
+
memoryInjectionEnabled: version.memoryInjectionEnabled,
|
|
54
|
+
tools: version.tools,
|
|
55
|
+
instructions: version.instructions,
|
|
56
|
+
metadata: version.metadata,
|
|
57
|
+
mcpConnectionIds: version.mcpConnectionIds,
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
update,
|
|
61
|
+
async updateMcpAttachment(agentId, mcpConnectionId, body) {
|
|
62
|
+
return await requestJson(config, `/v1/agents/${agentId}/mcp-attachments/${mcpConnectionId}`, { json: body, method: "PATCH" }, mcpAttachmentResponseSchema);
|
|
63
|
+
},
|
|
64
|
+
async delete(agentId, includeArtifacts) {
|
|
65
|
+
await requestJson(config, `/v1/agents/${agentId}`, {
|
|
66
|
+
method: "DELETE",
|
|
67
|
+
query: { includeArtifacts },
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
async uploadAvatar(agentId, file) {
|
|
71
|
+
const form = new FormData();
|
|
72
|
+
form.append("file", file);
|
|
73
|
+
return await requestJson(config, `/v1/agents/${agentId}/avatar`, {
|
|
74
|
+
body: form,
|
|
75
|
+
method: "POST",
|
|
76
|
+
}, agentResponseSchema);
|
|
77
|
+
},
|
|
78
|
+
async removeAvatar(agentId) {
|
|
79
|
+
return await requestJson(config, `/v1/agents/${agentId}/avatar`, { method: "DELETE" }, agentResponseSchema);
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { artifactDownloadUrlResponseSchema, artifactListItemSchema, artifactsListResponseSchema, } from "../contracts/entities/artifacts.js";
|
|
2
|
+
import { requestJson } from "../http.js";
|
|
3
|
+
/**
|
|
4
|
+
* `client.artifacts` — Tenant-level metadata and direct download URLs.
|
|
5
|
+
*/
|
|
6
|
+
export function createArtifactsResource(config) {
|
|
7
|
+
return {
|
|
8
|
+
async createDownloadUrl(artifactId) {
|
|
9
|
+
return await requestJson(config, `/v1/artifacts/${artifactId}/download-url`, { method: "POST" }, artifactDownloadUrlResponseSchema);
|
|
10
|
+
},
|
|
11
|
+
async get(artifactId) {
|
|
12
|
+
return await requestJson(config, `/v1/artifacts/${artifactId}`, {}, artifactListItemSchema);
|
|
13
|
+
},
|
|
14
|
+
async list(options = {}) {
|
|
15
|
+
return await requestJson(config, "/v1/artifacts", {
|
|
16
|
+
query: {
|
|
17
|
+
agentId: options.agentId,
|
|
18
|
+
sessionId: options.sessionId,
|
|
19
|
+
cursor: options.cursor,
|
|
20
|
+
},
|
|
21
|
+
}, artifactsListResponseSchema);
|
|
22
|
+
},
|
|
23
|
+
async delete(artifactId) {
|
|
24
|
+
await requestJson(config, `/v1/artifacts/${artifactId}`, {
|
|
25
|
+
method: "DELETE",
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { mcpConnectionOauthConnectResponseSchema, mcpConnectionReconnectResultSchema, mcpConnectionResponseSchema, mcpConnectionsResponseSchema, mcpConnectionTestResponseSchema, reconnectMcpConnectionBodySchema, updateMcpConnectionBodySchema, } from "../contracts/entities/mcp-connections.js";
|
|
2
|
+
import { requestJson } from "../http.js";
|
|
3
|
+
export function createMcpConnectionsResource(config) {
|
|
4
|
+
const create = (async (body) => requestJson(config, "/v1/mcp-connections", {
|
|
5
|
+
json: body,
|
|
6
|
+
method: "POST",
|
|
7
|
+
}, mcpConnectionResponseSchema));
|
|
8
|
+
return {
|
|
9
|
+
async connect(id) {
|
|
10
|
+
return await requestJson(config, `/v1/mcp-connections/${id}/connect`, { method: "POST" }, mcpConnectionOauthConnectResponseSchema);
|
|
11
|
+
},
|
|
12
|
+
create,
|
|
13
|
+
async list() {
|
|
14
|
+
return await requestJson(config, "/v1/mcp-connections", {}, mcpConnectionsResponseSchema);
|
|
15
|
+
},
|
|
16
|
+
async get(id) {
|
|
17
|
+
return await requestJson(config, `/v1/mcp-connections/${id}`, {}, mcpConnectionResponseSchema);
|
|
18
|
+
},
|
|
19
|
+
async update(id, body) {
|
|
20
|
+
return await requestJson(config, `/v1/mcp-connections/${id}`, {
|
|
21
|
+
json: updateMcpConnectionBodySchema.parse(body),
|
|
22
|
+
method: "PATCH",
|
|
23
|
+
}, mcpConnectionResponseSchema);
|
|
24
|
+
},
|
|
25
|
+
async delete(id) {
|
|
26
|
+
await requestJson(config, `/v1/mcp-connections/${id}`, {
|
|
27
|
+
method: "DELETE",
|
|
28
|
+
});
|
|
29
|
+
},
|
|
30
|
+
async test(id) {
|
|
31
|
+
return await requestJson(config, `/v1/mcp-connections/${id}/test`, { method: "POST" }, mcpConnectionTestResponseSchema);
|
|
32
|
+
},
|
|
33
|
+
async reconnect(id, body) {
|
|
34
|
+
return await requestJson(config, `/v1/mcp-connections/${id}/reconnect`, {
|
|
35
|
+
json: reconnectMcpConnectionBodySchema.parse(body),
|
|
36
|
+
method: "POST",
|
|
37
|
+
}, mcpConnectionReconnectResultSchema);
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { HttpConfig, MemoriesResource } from "../types.ts";
|
|
2
|
+
/**
|
|
3
|
+
* `client.memories` — CRUD and query over `/v1/agents/:agentId/memories`.
|
|
4
|
+
* Memories are Agent-nested; `userId` is stamped at creation and immutable,
|
|
5
|
+
* while list can filter it (including explicit `''`) or full-text search.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createMemoriesResource(config: HttpConfig): MemoriesResource;
|