@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.
@@ -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 sleep2(ms, signal) {
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 sleep2(waitMs, opts.signal);
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 call2 of toToolCallArguments(raw)) {
1811
- streamedArgs.set(call2.toolCallId, call2.arguments);
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
- serveClientTools,
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
- AgentApiError
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=F147527891A76CE064756E2164756E21
1988
+ //# debugId=D6ABC1088147C99C64756E2164756E21
1982
1989
  //# sourceMappingURL=index.js.map