@cubos/agent-sdk 0.0.1148891 → 0.0.1149194
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/dist/admin/agents.d.ts +10 -0
- package/dist/generated/schema.d.ts +168 -1
- package/dist/index.js +202 -195
- package/dist/index.js.map +5 -5
- package/dist/sse.js +4 -4
- package/dist/sse.js.map +2 -2
- package/package.json +2 -2
package/dist/admin/agents.d.ts
CHANGED
|
@@ -192,6 +192,16 @@ export declare function agentsApi(t: Transport, tenantSlug: string): {
|
|
|
192
192
|
addTaskTemplate: (agentSlug: string, templateSlug: string) => Promise<void>;
|
|
193
193
|
removeTaskTemplate: (agentSlug: string, templateSlug: string) => Promise<void>;
|
|
194
194
|
replaceTaskTemplateRoles: (agentSlug: string, templateSlug: string, roleSlugs: string[]) => Promise<void>;
|
|
195
|
+
listKnowledgeBases: (agentSlug: string, signal?: AbortSignal) => Promise<{
|
|
196
|
+
created_at: string;
|
|
197
|
+
display_name: string;
|
|
198
|
+
id: string;
|
|
199
|
+
pending_count: number;
|
|
200
|
+
slug: string;
|
|
201
|
+
updated_at: string;
|
|
202
|
+
}[]>;
|
|
203
|
+
attachKnowledgeBase: (agentSlug: string, kbSlug: string) => Promise<void>;
|
|
204
|
+
detachKnowledgeBase: (agentSlug: string, kbSlug: string) => Promise<void>;
|
|
195
205
|
listAutoCallTools: (agentSlug: string, signal?: AbortSignal) => Promise<{
|
|
196
206
|
available: import("../generated/schema.js").components["schemas"]["AutoCallableTool"][];
|
|
197
207
|
enabled_mcp_count: number;
|
|
@@ -1354,6 +1354,173 @@ export interface paths {
|
|
|
1354
1354
|
patch?: never;
|
|
1355
1355
|
trace?: never;
|
|
1356
1356
|
};
|
|
1357
|
+
"/api/v1/tenants/{tenantSlug}/agents/{agentSlug}/knowledge-bases": {
|
|
1358
|
+
parameters: {
|
|
1359
|
+
query?: never;
|
|
1360
|
+
header?: never;
|
|
1361
|
+
path?: never;
|
|
1362
|
+
cookie?: never;
|
|
1363
|
+
};
|
|
1364
|
+
/**
|
|
1365
|
+
* List an agent's knowledge bases
|
|
1366
|
+
* @description Lists the knowledge bases attached to the agent. These reach every conversation the agent runs, read-only: conversation material is never filed into a base reached only through its agent.
|
|
1367
|
+
*/
|
|
1368
|
+
get: {
|
|
1369
|
+
parameters: {
|
|
1370
|
+
query?: never;
|
|
1371
|
+
header?: never;
|
|
1372
|
+
path: {
|
|
1373
|
+
/** @description Agent slug. */
|
|
1374
|
+
agentSlug: string;
|
|
1375
|
+
/** @description Tenant slug. */
|
|
1376
|
+
tenantSlug: string;
|
|
1377
|
+
};
|
|
1378
|
+
cookie?: never;
|
|
1379
|
+
};
|
|
1380
|
+
requestBody?: never;
|
|
1381
|
+
responses: {
|
|
1382
|
+
200: {
|
|
1383
|
+
headers: {
|
|
1384
|
+
[name: string]: unknown;
|
|
1385
|
+
};
|
|
1386
|
+
content: {
|
|
1387
|
+
"application/json": components["schemas"]["KnowledgeBaseListItem"][];
|
|
1388
|
+
};
|
|
1389
|
+
};
|
|
1390
|
+
401: {
|
|
1391
|
+
headers: {
|
|
1392
|
+
[name: string]: unknown;
|
|
1393
|
+
};
|
|
1394
|
+
content?: never;
|
|
1395
|
+
};
|
|
1396
|
+
403: {
|
|
1397
|
+
headers: {
|
|
1398
|
+
[name: string]: unknown;
|
|
1399
|
+
};
|
|
1400
|
+
content?: never;
|
|
1401
|
+
};
|
|
1402
|
+
404: {
|
|
1403
|
+
headers: {
|
|
1404
|
+
[name: string]: unknown;
|
|
1405
|
+
};
|
|
1406
|
+
content?: never;
|
|
1407
|
+
};
|
|
1408
|
+
};
|
|
1409
|
+
};
|
|
1410
|
+
put?: never;
|
|
1411
|
+
post?: never;
|
|
1412
|
+
delete?: never;
|
|
1413
|
+
options?: never;
|
|
1414
|
+
head?: never;
|
|
1415
|
+
patch?: never;
|
|
1416
|
+
trace?: never;
|
|
1417
|
+
};
|
|
1418
|
+
"/api/v1/tenants/{tenantSlug}/agents/{agentSlug}/knowledge-bases/{kbSlug}": {
|
|
1419
|
+
parameters: {
|
|
1420
|
+
query?: never;
|
|
1421
|
+
header?: never;
|
|
1422
|
+
path?: never;
|
|
1423
|
+
cookie?: never;
|
|
1424
|
+
};
|
|
1425
|
+
get?: never;
|
|
1426
|
+
/**
|
|
1427
|
+
* Attach a knowledge base to an agent
|
|
1428
|
+
* @description Attaches a knowledge base to the agent so every conversation it runs searches it. Read-only from those conversations: `memory_write` files into a base only when it is also attached to the conversation or its user. Idempotent; takes effect on each conversation's next turn.
|
|
1429
|
+
*/
|
|
1430
|
+
put: {
|
|
1431
|
+
parameters: {
|
|
1432
|
+
query?: never;
|
|
1433
|
+
header?: never;
|
|
1434
|
+
path: {
|
|
1435
|
+
/** @description Agent slug. */
|
|
1436
|
+
agentSlug: string;
|
|
1437
|
+
/** @description Knowledge base slug. */
|
|
1438
|
+
kbSlug: string;
|
|
1439
|
+
/** @description Tenant slug. */
|
|
1440
|
+
tenantSlug: string;
|
|
1441
|
+
};
|
|
1442
|
+
cookie?: never;
|
|
1443
|
+
};
|
|
1444
|
+
requestBody?: never;
|
|
1445
|
+
responses: {
|
|
1446
|
+
204: {
|
|
1447
|
+
headers: {
|
|
1448
|
+
[name: string]: unknown;
|
|
1449
|
+
};
|
|
1450
|
+
content?: never;
|
|
1451
|
+
};
|
|
1452
|
+
401: {
|
|
1453
|
+
headers: {
|
|
1454
|
+
[name: string]: unknown;
|
|
1455
|
+
};
|
|
1456
|
+
content?: never;
|
|
1457
|
+
};
|
|
1458
|
+
403: {
|
|
1459
|
+
headers: {
|
|
1460
|
+
[name: string]: unknown;
|
|
1461
|
+
};
|
|
1462
|
+
content?: never;
|
|
1463
|
+
};
|
|
1464
|
+
404: {
|
|
1465
|
+
headers: {
|
|
1466
|
+
[name: string]: unknown;
|
|
1467
|
+
};
|
|
1468
|
+
content?: never;
|
|
1469
|
+
};
|
|
1470
|
+
};
|
|
1471
|
+
};
|
|
1472
|
+
post?: never;
|
|
1473
|
+
/**
|
|
1474
|
+
* Detach a knowledge base from an agent
|
|
1475
|
+
* @description Stops the agent's conversations from searching the knowledge base through the agent. Links to a conversation or a user are untouched.
|
|
1476
|
+
*/
|
|
1477
|
+
delete: {
|
|
1478
|
+
parameters: {
|
|
1479
|
+
query?: never;
|
|
1480
|
+
header?: never;
|
|
1481
|
+
path: {
|
|
1482
|
+
/** @description Agent slug. */
|
|
1483
|
+
agentSlug: string;
|
|
1484
|
+
/** @description Knowledge base slug. */
|
|
1485
|
+
kbSlug: string;
|
|
1486
|
+
/** @description Tenant slug. */
|
|
1487
|
+
tenantSlug: string;
|
|
1488
|
+
};
|
|
1489
|
+
cookie?: never;
|
|
1490
|
+
};
|
|
1491
|
+
requestBody?: never;
|
|
1492
|
+
responses: {
|
|
1493
|
+
204: {
|
|
1494
|
+
headers: {
|
|
1495
|
+
[name: string]: unknown;
|
|
1496
|
+
};
|
|
1497
|
+
content?: never;
|
|
1498
|
+
};
|
|
1499
|
+
401: {
|
|
1500
|
+
headers: {
|
|
1501
|
+
[name: string]: unknown;
|
|
1502
|
+
};
|
|
1503
|
+
content?: never;
|
|
1504
|
+
};
|
|
1505
|
+
403: {
|
|
1506
|
+
headers: {
|
|
1507
|
+
[name: string]: unknown;
|
|
1508
|
+
};
|
|
1509
|
+
content?: never;
|
|
1510
|
+
};
|
|
1511
|
+
404: {
|
|
1512
|
+
headers: {
|
|
1513
|
+
[name: string]: unknown;
|
|
1514
|
+
};
|
|
1515
|
+
content?: never;
|
|
1516
|
+
};
|
|
1517
|
+
};
|
|
1518
|
+
};
|
|
1519
|
+
options?: never;
|
|
1520
|
+
head?: never;
|
|
1521
|
+
patch?: never;
|
|
1522
|
+
trace?: never;
|
|
1523
|
+
};
|
|
1357
1524
|
"/api/v1/tenants/{tenantSlug}/agents/{agentSlug}/mcps": {
|
|
1358
1525
|
parameters: {
|
|
1359
1526
|
query?: never;
|
|
@@ -5632,7 +5799,7 @@ export interface paths {
|
|
|
5632
5799
|
};
|
|
5633
5800
|
/**
|
|
5634
5801
|
* List a conversation's knowledge bases
|
|
5635
|
-
* @description Lists the knowledge bases this conversation searches — those attached to the conversation directly plus those attached to its user. Deduplicated.
|
|
5802
|
+
* @description Lists the knowledge bases this conversation searches — those attached to the conversation directly plus those attached to its user or to its agent. Deduplicated.
|
|
5636
5803
|
*/
|
|
5637
5804
|
get: {
|
|
5638
5805
|
parameters: {
|
package/dist/index.js
CHANGED
|
@@ -88,186 +88,11 @@ function parseRetryAfter(header) {
|
|
|
88
88
|
return Math.max(0, date - Date.now());
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
// src/sse.ts
|
|
92
|
-
var MAX_BACKOFF_MS = 30000;
|
|
93
|
-
var DEFAULT_IDLE_TIMEOUT_MS = 30000;
|
|
94
|
-
|
|
95
|
-
class Fatal extends Error {
|
|
96
|
-
cause;
|
|
97
|
-
constructor(cause) {
|
|
98
|
-
super("fatal stream error");
|
|
99
|
-
this.cause = cause;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
class SseIdleTimeout extends Error {
|
|
104
|
-
constructor(url, ms) {
|
|
105
|
-
super(`Stream ${url} sent nothing for ${ms}ms — reconnecting.`);
|
|
106
|
-
this.name = "SseIdleTimeout";
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
async function readSse(opts) {
|
|
110
|
-
const doFetch = opts.fetchImpl ?? globalThis.fetch;
|
|
111
|
-
const idleMs = opts.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
112
|
-
const cursor = opts.cursor ?? { lastEventId: opts.lastEventId };
|
|
113
|
-
let attempt = 0;
|
|
114
|
-
let refreshing = false;
|
|
115
|
-
while (!opts.signal.aborted) {
|
|
116
|
-
let madeProgress = false;
|
|
117
|
-
let retryAfterMs = null;
|
|
118
|
-
const connection = new AbortController;
|
|
119
|
-
const unlink = forward(opts.signal, connection);
|
|
120
|
-
let idleTimer;
|
|
121
|
-
let wentIdle = false;
|
|
122
|
-
const armIdle = () => {
|
|
123
|
-
if (idleMs <= 0)
|
|
124
|
-
return;
|
|
125
|
-
clearTimeout(idleTimer);
|
|
126
|
-
idleTimer = setTimeout(() => {
|
|
127
|
-
wentIdle = true;
|
|
128
|
-
connection.abort();
|
|
129
|
-
}, idleMs);
|
|
130
|
-
};
|
|
131
|
-
try {
|
|
132
|
-
const headers = {
|
|
133
|
-
...await opts.headers?.({ forceRefresh: refreshing }),
|
|
134
|
-
Accept: "text/event-stream"
|
|
135
|
-
};
|
|
136
|
-
if (cursor.lastEventId !== undefined)
|
|
137
|
-
headers["Last-Event-ID"] = cursor.lastEventId;
|
|
138
|
-
armIdle();
|
|
139
|
-
const res = await doFetch(opts.url, { headers, signal: connection.signal });
|
|
140
|
-
if (opts.signal.aborted)
|
|
141
|
-
return;
|
|
142
|
-
if (res.ok && res.body) {
|
|
143
|
-
refreshing = false;
|
|
144
|
-
opts.onOpen?.();
|
|
145
|
-
}
|
|
146
|
-
if (!res.ok || !res.body) {
|
|
147
|
-
if (res.status === 401 && opts.headers && !refreshing) {
|
|
148
|
-
refreshing = true;
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
if (res.status === 429) {
|
|
152
|
-
retryAfterMs = Math.min(MAX_BACKOFF_MS, parseRetryAfter(res.headers.get("retry-after")) ?? MAX_BACKOFF_MS);
|
|
153
|
-
await raiseForStatus(res, `Could not open ${opts.url}.`);
|
|
154
|
-
}
|
|
155
|
-
if (res.status >= 400 && res.status < 500) {
|
|
156
|
-
await raiseForStatus(res, `Could not open ${opts.url}.`).catch((err) => {
|
|
157
|
-
throw new Fatal(err);
|
|
158
|
-
});
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
throw new Error(`stream open failed with HTTP ${res.status}`);
|
|
162
|
-
}
|
|
163
|
-
for await (const frame of frames(res.body, connection.signal, armIdle)) {
|
|
164
|
-
const parsed = parseFrame(frame, opts.event);
|
|
165
|
-
if (parsed === null)
|
|
166
|
-
continue;
|
|
167
|
-
if (parsed.id !== null)
|
|
168
|
-
cursor.lastEventId = parsed.id;
|
|
169
|
-
opts.onEvent(parsed.data, parsed.event);
|
|
170
|
-
madeProgress = true;
|
|
171
|
-
}
|
|
172
|
-
if (wentIdle)
|
|
173
|
-
throw new SseIdleTimeout(opts.url, idleMs);
|
|
174
|
-
} catch (err) {
|
|
175
|
-
if (opts.signal.aborted)
|
|
176
|
-
return;
|
|
177
|
-
if (err instanceof Fatal)
|
|
178
|
-
throw err.cause;
|
|
179
|
-
opts.onError?.(wentIdle ? new SseIdleTimeout(opts.url, idleMs) : err);
|
|
180
|
-
} finally {
|
|
181
|
-
clearTimeout(idleTimer);
|
|
182
|
-
unlink();
|
|
183
|
-
connection.abort();
|
|
184
|
-
opts.onClose?.();
|
|
185
|
-
}
|
|
186
|
-
if (opts.signal.aborted)
|
|
187
|
-
return;
|
|
188
|
-
if (madeProgress)
|
|
189
|
-
attempt = 0;
|
|
190
|
-
const delayMs = retryAfterMs ?? Math.min(MAX_BACKOFF_MS, 1000 * 2 ** attempt);
|
|
191
|
-
attempt += 1;
|
|
192
|
-
await sleep(delayMs, opts.signal);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
async function* frames(body, signal, onRead) {
|
|
196
|
-
const reader = body.getReader();
|
|
197
|
-
const decoder = new TextDecoder;
|
|
198
|
-
let buffer = "";
|
|
199
|
-
try {
|
|
200
|
-
while (!signal.aborted) {
|
|
201
|
-
const { value, done } = await reader.read();
|
|
202
|
-
if (done)
|
|
203
|
-
return;
|
|
204
|
-
onRead();
|
|
205
|
-
buffer += decoder.decode(value, { stream: true });
|
|
206
|
-
for (;; ) {
|
|
207
|
-
const sep = buffer.indexOf(`
|
|
208
|
-
|
|
209
|
-
`);
|
|
210
|
-
if (sep === -1)
|
|
211
|
-
break;
|
|
212
|
-
yield buffer.slice(0, sep);
|
|
213
|
-
buffer = buffer.slice(sep + 2);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
} finally {
|
|
217
|
-
reader.cancel().catch(() => {});
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
function parseFrame(frame, expectedEvent) {
|
|
221
|
-
let dataLine = null;
|
|
222
|
-
let id = null;
|
|
223
|
-
let eventName = "message";
|
|
224
|
-
for (const line of frame.split(`
|
|
225
|
-
`)) {
|
|
226
|
-
if (line.startsWith(":"))
|
|
227
|
-
continue;
|
|
228
|
-
if (line.startsWith("data:"))
|
|
229
|
-
dataLine = line.slice(5).trimStart();
|
|
230
|
-
else if (line.startsWith("event:"))
|
|
231
|
-
eventName = line.slice(6).trim();
|
|
232
|
-
else if (line.startsWith("id:"))
|
|
233
|
-
id = line.slice(3).trim();
|
|
234
|
-
}
|
|
235
|
-
const wanted = typeof expectedEvent === "string" ? eventName === expectedEvent : expectedEvent.includes(eventName);
|
|
236
|
-
if (!wanted || dataLine === null)
|
|
237
|
-
return null;
|
|
238
|
-
try {
|
|
239
|
-
return { data: JSON.parse(dataLine), id, event: eventName };
|
|
240
|
-
} catch {
|
|
241
|
-
return null;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
function sleep(ms, signal) {
|
|
245
|
-
return new Promise((resolve) => {
|
|
246
|
-
const onAbort = () => {
|
|
247
|
-
clearTimeout(timer);
|
|
248
|
-
resolve();
|
|
249
|
-
};
|
|
250
|
-
const timer = setTimeout(() => {
|
|
251
|
-
signal.removeEventListener("abort", onAbort);
|
|
252
|
-
resolve();
|
|
253
|
-
}, ms);
|
|
254
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
function forward(outer, child) {
|
|
258
|
-
const onAbort = () => child.abort();
|
|
259
|
-
if (outer.aborted)
|
|
260
|
-
child.abort();
|
|
261
|
-
else
|
|
262
|
-
outer.addEventListener("abort", onAbort, { once: true });
|
|
263
|
-
return () => outer.removeEventListener("abort", onAbort);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
91
|
// src/http.ts
|
|
267
92
|
var DEFAULT_TIMEOUT_MS = 30000;
|
|
268
93
|
var DEFAULT_MAX_RETRIES = 2;
|
|
269
94
|
var MAX_RETRY_WAIT_MS = 20000;
|
|
270
|
-
function
|
|
95
|
+
function sleep(ms, signal) {
|
|
271
96
|
return new Promise((resolve, reject) => {
|
|
272
97
|
if (signal?.aborted) {
|
|
273
98
|
reject(signal.reason ?? new Error("Aborted"));
|
|
@@ -371,7 +196,7 @@ function createTransport(baseUrl, auth, fetchImpl = globalThis.fetch, timeoutMs
|
|
|
371
196
|
if (waitMs === null || waitMs > MAX_RETRY_WAIT_MS)
|
|
372
197
|
return res;
|
|
373
198
|
attempt += 1;
|
|
374
|
-
await
|
|
199
|
+
await sleep(waitMs, opts.signal);
|
|
375
200
|
}
|
|
376
201
|
}
|
|
377
202
|
return {
|
|
@@ -451,6 +276,13 @@ function agentsApi(t, tenantSlug) {
|
|
|
451
276
|
body: { role_slugs: roleSlugs },
|
|
452
277
|
raw: true
|
|
453
278
|
}),
|
|
279
|
+
listKnowledgeBases: (agentSlug, signal) => t.request("GET", `${agent(agentSlug)}/knowledge-bases`, {
|
|
280
|
+
signal
|
|
281
|
+
}),
|
|
282
|
+
attachKnowledgeBase: (agentSlug, kbSlug) => t.request("PUT", `${agent(agentSlug)}/knowledge-bases/${enc(kbSlug)}`, { raw: true }),
|
|
283
|
+
detachKnowledgeBase: (agentSlug, kbSlug) => t.request("DELETE", `${agent(agentSlug)}/knowledge-bases/${enc(kbSlug)}`, {
|
|
284
|
+
raw: true
|
|
285
|
+
}),
|
|
454
286
|
listAutoCallTools: (agentSlug, signal) => t.request("GET", `${agent(agentSlug)}/auto-call-tools`, {
|
|
455
287
|
signal
|
|
456
288
|
}),
|
|
@@ -506,6 +338,181 @@ function channelsApi(t, tenantSlug) {
|
|
|
506
338
|
};
|
|
507
339
|
}
|
|
508
340
|
|
|
341
|
+
// src/sse.ts
|
|
342
|
+
var MAX_BACKOFF_MS = 30000;
|
|
343
|
+
var DEFAULT_IDLE_TIMEOUT_MS = 30000;
|
|
344
|
+
|
|
345
|
+
class Fatal extends Error {
|
|
346
|
+
cause;
|
|
347
|
+
constructor(cause) {
|
|
348
|
+
super("fatal stream error");
|
|
349
|
+
this.cause = cause;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
class SseIdleTimeout extends Error {
|
|
354
|
+
constructor(url, ms) {
|
|
355
|
+
super(`Stream ${url} sent nothing for ${ms}ms — reconnecting.`);
|
|
356
|
+
this.name = "SseIdleTimeout";
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
async function readSse(opts) {
|
|
360
|
+
const doFetch = opts.fetchImpl ?? globalThis.fetch;
|
|
361
|
+
const idleMs = opts.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
362
|
+
const cursor = opts.cursor ?? { lastEventId: opts.lastEventId };
|
|
363
|
+
let attempt = 0;
|
|
364
|
+
let refreshing = false;
|
|
365
|
+
while (!opts.signal.aborted) {
|
|
366
|
+
let madeProgress = false;
|
|
367
|
+
let retryAfterMs = null;
|
|
368
|
+
const connection = new AbortController;
|
|
369
|
+
const unlink = forward(opts.signal, connection);
|
|
370
|
+
let idleTimer;
|
|
371
|
+
let wentIdle = false;
|
|
372
|
+
const armIdle = () => {
|
|
373
|
+
if (idleMs <= 0)
|
|
374
|
+
return;
|
|
375
|
+
clearTimeout(idleTimer);
|
|
376
|
+
idleTimer = setTimeout(() => {
|
|
377
|
+
wentIdle = true;
|
|
378
|
+
connection.abort();
|
|
379
|
+
}, idleMs);
|
|
380
|
+
};
|
|
381
|
+
try {
|
|
382
|
+
const headers = {
|
|
383
|
+
...await opts.headers?.({ forceRefresh: refreshing }),
|
|
384
|
+
Accept: "text/event-stream"
|
|
385
|
+
};
|
|
386
|
+
if (cursor.lastEventId !== undefined)
|
|
387
|
+
headers["Last-Event-ID"] = cursor.lastEventId;
|
|
388
|
+
armIdle();
|
|
389
|
+
const res = await doFetch(opts.url, { headers, signal: connection.signal });
|
|
390
|
+
if (opts.signal.aborted)
|
|
391
|
+
return;
|
|
392
|
+
if (res.ok && res.body) {
|
|
393
|
+
refreshing = false;
|
|
394
|
+
opts.onOpen?.();
|
|
395
|
+
}
|
|
396
|
+
if (!res.ok || !res.body) {
|
|
397
|
+
if (res.status === 401 && opts.headers && !refreshing) {
|
|
398
|
+
refreshing = true;
|
|
399
|
+
continue;
|
|
400
|
+
}
|
|
401
|
+
if (res.status === 429) {
|
|
402
|
+
retryAfterMs = Math.min(MAX_BACKOFF_MS, parseRetryAfter(res.headers.get("retry-after")) ?? MAX_BACKOFF_MS);
|
|
403
|
+
await raiseForStatus(res, `Could not open ${opts.url}.`);
|
|
404
|
+
}
|
|
405
|
+
if (res.status >= 400 && res.status < 500) {
|
|
406
|
+
await raiseForStatus(res, `Could not open ${opts.url}.`).catch((err) => {
|
|
407
|
+
throw new Fatal(err);
|
|
408
|
+
});
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
throw new Error(`stream open failed with HTTP ${res.status}`);
|
|
412
|
+
}
|
|
413
|
+
for await (const frame of frames(res.body, connection.signal, armIdle)) {
|
|
414
|
+
const parsed = parseFrame(frame, opts.event);
|
|
415
|
+
if (parsed === null)
|
|
416
|
+
continue;
|
|
417
|
+
if (parsed.id !== null)
|
|
418
|
+
cursor.lastEventId = parsed.id;
|
|
419
|
+
opts.onEvent(parsed.data, parsed.event);
|
|
420
|
+
madeProgress = true;
|
|
421
|
+
}
|
|
422
|
+
if (wentIdle)
|
|
423
|
+
throw new SseIdleTimeout(opts.url, idleMs);
|
|
424
|
+
} catch (err) {
|
|
425
|
+
if (opts.signal.aborted)
|
|
426
|
+
return;
|
|
427
|
+
if (err instanceof Fatal)
|
|
428
|
+
throw err.cause;
|
|
429
|
+
opts.onError?.(wentIdle ? new SseIdleTimeout(opts.url, idleMs) : err);
|
|
430
|
+
} finally {
|
|
431
|
+
clearTimeout(idleTimer);
|
|
432
|
+
unlink();
|
|
433
|
+
connection.abort();
|
|
434
|
+
opts.onClose?.();
|
|
435
|
+
}
|
|
436
|
+
if (opts.signal.aborted)
|
|
437
|
+
return;
|
|
438
|
+
if (madeProgress)
|
|
439
|
+
attempt = 0;
|
|
440
|
+
const delayMs = retryAfterMs ?? Math.min(MAX_BACKOFF_MS, 1000 * 2 ** attempt);
|
|
441
|
+
attempt += 1;
|
|
442
|
+
await sleep2(delayMs, opts.signal);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
async function* frames(body, signal, onRead) {
|
|
446
|
+
const reader = body.getReader();
|
|
447
|
+
const decoder = new TextDecoder;
|
|
448
|
+
let buffer = "";
|
|
449
|
+
try {
|
|
450
|
+
while (!signal.aborted) {
|
|
451
|
+
const { value, done } = await reader.read();
|
|
452
|
+
if (done)
|
|
453
|
+
return;
|
|
454
|
+
onRead();
|
|
455
|
+
buffer += decoder.decode(value, { stream: true });
|
|
456
|
+
for (;; ) {
|
|
457
|
+
const sep = buffer.indexOf(`
|
|
458
|
+
|
|
459
|
+
`);
|
|
460
|
+
if (sep === -1)
|
|
461
|
+
break;
|
|
462
|
+
yield buffer.slice(0, sep);
|
|
463
|
+
buffer = buffer.slice(sep + 2);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
} finally {
|
|
467
|
+
reader.cancel().catch(() => {});
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
function parseFrame(frame, expectedEvent) {
|
|
471
|
+
let dataLine = null;
|
|
472
|
+
let id = null;
|
|
473
|
+
let eventName = "message";
|
|
474
|
+
for (const line of frame.split(`
|
|
475
|
+
`)) {
|
|
476
|
+
if (line.startsWith(":"))
|
|
477
|
+
continue;
|
|
478
|
+
if (line.startsWith("data:"))
|
|
479
|
+
dataLine = line.slice(5).trimStart();
|
|
480
|
+
else if (line.startsWith("event:"))
|
|
481
|
+
eventName = line.slice(6).trim();
|
|
482
|
+
else if (line.startsWith("id:"))
|
|
483
|
+
id = line.slice(3).trim();
|
|
484
|
+
}
|
|
485
|
+
const wanted = typeof expectedEvent === "string" ? eventName === expectedEvent : expectedEvent.includes(eventName);
|
|
486
|
+
if (!wanted || dataLine === null)
|
|
487
|
+
return null;
|
|
488
|
+
try {
|
|
489
|
+
return { data: JSON.parse(dataLine), id, event: eventName };
|
|
490
|
+
} catch {
|
|
491
|
+
return null;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
function sleep2(ms, signal) {
|
|
495
|
+
return new Promise((resolve) => {
|
|
496
|
+
const onAbort = () => {
|
|
497
|
+
clearTimeout(timer);
|
|
498
|
+
resolve();
|
|
499
|
+
};
|
|
500
|
+
const timer = setTimeout(() => {
|
|
501
|
+
signal.removeEventListener("abort", onAbort);
|
|
502
|
+
resolve();
|
|
503
|
+
}, ms);
|
|
504
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
function forward(outer, child) {
|
|
508
|
+
const onAbort = () => child.abort();
|
|
509
|
+
if (outer.aborted)
|
|
510
|
+
child.abort();
|
|
511
|
+
else
|
|
512
|
+
outer.addEventListener("abort", onAbort, { once: true });
|
|
513
|
+
return () => outer.removeEventListener("abort", onAbort);
|
|
514
|
+
}
|
|
515
|
+
|
|
509
516
|
// src/client-tools.ts
|
|
510
517
|
var DEFAULT_CLAIM_TTL_SECONDS = 70;
|
|
511
518
|
var SUBMIT_ATTEMPTS = 5;
|
|
@@ -1807,8 +1814,8 @@ class AgentClient {
|
|
|
1807
1814
|
const call = toClientToolCall(raw);
|
|
1808
1815
|
if (call)
|
|
1809
1816
|
handlers.onClientToolCall?.(call);
|
|
1810
|
-
for (const
|
|
1811
|
-
streamedArgs.set(
|
|
1817
|
+
for (const call of toToolCallArguments(raw)) {
|
|
1818
|
+
streamedArgs.set(call.toolCallId, call.arguments);
|
|
1812
1819
|
}
|
|
1813
1820
|
const activity = toToolActivity(raw);
|
|
1814
1821
|
if (activity)
|
|
@@ -1960,23 +1967,23 @@ function createUserClient(options) {
|
|
|
1960
1967
|
return new AgentClient(options);
|
|
1961
1968
|
}
|
|
1962
1969
|
export {
|
|
1963
|
-
|
|
1964
|
-
readSse,
|
|
1965
|
-
mergeVoiceMessages,
|
|
1966
|
-
mergeToolActivities,
|
|
1967
|
-
createUserClient,
|
|
1968
|
-
createAdminClient,
|
|
1969
|
-
SseIdleTimeout,
|
|
1970
|
-
MemoryConversationCache,
|
|
1971
|
-
DEFAULT_TIMEOUT_MS,
|
|
1972
|
-
DEFAULT_MAX_RETRIES,
|
|
1973
|
-
DEFAULT_IDLE_TIMEOUT_MS,
|
|
1974
|
-
AgentNetworkError,
|
|
1975
|
-
AgentError,
|
|
1976
|
-
AgentConfigError,
|
|
1970
|
+
AgentApiError,
|
|
1977
1971
|
AgentClient,
|
|
1978
|
-
|
|
1972
|
+
AgentConfigError,
|
|
1973
|
+
AgentError,
|
|
1974
|
+
AgentNetworkError,
|
|
1975
|
+
DEFAULT_IDLE_TIMEOUT_MS,
|
|
1976
|
+
DEFAULT_MAX_RETRIES,
|
|
1977
|
+
DEFAULT_TIMEOUT_MS,
|
|
1978
|
+
MemoryConversationCache,
|
|
1979
|
+
SseIdleTimeout,
|
|
1980
|
+
createAdminClient,
|
|
1981
|
+
createUserClient,
|
|
1982
|
+
mergeToolActivities,
|
|
1983
|
+
mergeVoiceMessages,
|
|
1984
|
+
readSse,
|
|
1985
|
+
serveClientTools
|
|
1979
1986
|
};
|
|
1980
1987
|
|
|
1981
|
-
//# debugId=
|
|
1988
|
+
//# debugId=D6ABC1088147C99C64756E2164756E21
|
|
1982
1989
|
//# sourceMappingURL=index.js.map
|