@antipopp/agno-client 0.8.0 → 0.10.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 +101 -0
- package/dist/index.d.mts +42 -15
- package/dist/index.d.ts +42 -15
- package/dist/index.js +474 -293
- package/dist/index.mjs +476 -293
- package/package.json +8 -4
package/dist/index.js
CHANGED
|
@@ -35,89 +35,11 @@ __export(src_exports, {
|
|
|
35
35
|
RunEvent: () => import_agno_types3.RunEvent
|
|
36
36
|
});
|
|
37
37
|
module.exports = __toCommonJS(src_exports);
|
|
38
|
+
var import_agno_types3 = require("@antipopp/agno-types");
|
|
38
39
|
|
|
39
40
|
// src/client.ts
|
|
40
|
-
var import_eventemitter3 = __toESM(require("eventemitter3"));
|
|
41
41
|
var import_agno_types2 = require("@antipopp/agno-types");
|
|
42
|
-
|
|
43
|
-
// src/stores/message-store.ts
|
|
44
|
-
var MessageStore = class {
|
|
45
|
-
constructor() {
|
|
46
|
-
this.messages = [];
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Get all messages
|
|
50
|
-
*/
|
|
51
|
-
getMessages() {
|
|
52
|
-
return [...this.messages];
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Set messages (replaces all)
|
|
56
|
-
*/
|
|
57
|
-
setMessages(messages) {
|
|
58
|
-
this.messages = [...messages];
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Add a message
|
|
62
|
-
*/
|
|
63
|
-
addMessage(message) {
|
|
64
|
-
this.messages = [...this.messages, message];
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Update the last message
|
|
68
|
-
*/
|
|
69
|
-
updateLastMessage(updater) {
|
|
70
|
-
if (this.messages.length === 0)
|
|
71
|
-
return void 0;
|
|
72
|
-
const lastMessage = this.messages[this.messages.length - 1];
|
|
73
|
-
const updatedMessage = updater(lastMessage);
|
|
74
|
-
this.messages = [
|
|
75
|
-
...this.messages.slice(0, -1),
|
|
76
|
-
updatedMessage
|
|
77
|
-
];
|
|
78
|
-
return updatedMessage;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Update a specific message by index
|
|
82
|
-
*/
|
|
83
|
-
updateMessage(index, updater) {
|
|
84
|
-
if (index < 0 || index >= this.messages.length)
|
|
85
|
-
return void 0;
|
|
86
|
-
const message = this.messages[index];
|
|
87
|
-
const updatedMessage = updater(message);
|
|
88
|
-
this.messages = [
|
|
89
|
-
...this.messages.slice(0, index),
|
|
90
|
-
updatedMessage,
|
|
91
|
-
...this.messages.slice(index + 1)
|
|
92
|
-
];
|
|
93
|
-
return updatedMessage;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Remove last N messages
|
|
97
|
-
*/
|
|
98
|
-
removeLastMessages(count) {
|
|
99
|
-
this.messages = this.messages.slice(0, -count);
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Clear all messages
|
|
103
|
-
*/
|
|
104
|
-
clear() {
|
|
105
|
-
this.messages = [];
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Get the last message
|
|
109
|
-
*/
|
|
110
|
-
getLastMessage() {
|
|
111
|
-
return this.messages.length > 0 ? this.messages[this.messages.length - 1] : void 0;
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Check if last message has streaming error
|
|
115
|
-
*/
|
|
116
|
-
hasLastMessageError() {
|
|
117
|
-
const lastMessage = this.getLastMessage();
|
|
118
|
-
return lastMessage?.streamingError === true;
|
|
119
|
-
}
|
|
120
|
-
};
|
|
42
|
+
var import_eventemitter3 = __toESM(require("eventemitter3"));
|
|
121
43
|
|
|
122
44
|
// src/managers/config-manager.ts
|
|
123
45
|
var ConfigManager = class {
|
|
@@ -250,6 +172,18 @@ var ConfigManager = class {
|
|
|
250
172
|
setHeaders(headers) {
|
|
251
173
|
this.updateField("headers", headers);
|
|
252
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Get global query parameters
|
|
177
|
+
*/
|
|
178
|
+
getParams() {
|
|
179
|
+
return this.config.params;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Set global query parameters
|
|
183
|
+
*/
|
|
184
|
+
setParams(params) {
|
|
185
|
+
this.updateField("params", params);
|
|
186
|
+
}
|
|
253
187
|
/**
|
|
254
188
|
* Get current entity ID (agent or team based on mode)
|
|
255
189
|
*/
|
|
@@ -263,14 +197,14 @@ var ConfigManager = class {
|
|
|
263
197
|
const mode = this.getMode();
|
|
264
198
|
const endpoint = this.getEndpoint();
|
|
265
199
|
const entityId = this.getCurrentEntityId();
|
|
266
|
-
if (!entityId)
|
|
200
|
+
if (!entityId) {
|
|
267
201
|
return null;
|
|
202
|
+
}
|
|
268
203
|
const encodedEntityId = encodeURIComponent(entityId);
|
|
269
204
|
if (mode === "team") {
|
|
270
205
|
return `${endpoint}/teams/${encodedEntityId}/runs`;
|
|
271
|
-
} else {
|
|
272
|
-
return `${endpoint}/agents/${encodedEntityId}/runs`;
|
|
273
206
|
}
|
|
207
|
+
return `${endpoint}/agents/${encodedEntityId}/runs`;
|
|
274
208
|
}
|
|
275
209
|
/**
|
|
276
210
|
* Build request headers by merging global headers, per-request headers, and auth token.
|
|
@@ -293,10 +227,30 @@ var ConfigManager = class {
|
|
|
293
227
|
}
|
|
294
228
|
const authToken = this.getAuthToken();
|
|
295
229
|
if (authToken) {
|
|
296
|
-
headers
|
|
230
|
+
headers.Authorization = `Bearer ${authToken}`;
|
|
297
231
|
}
|
|
298
232
|
return headers;
|
|
299
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* Build query string by merging global params and per-request params.
|
|
236
|
+
* Merge order (lowest to highest precedence):
|
|
237
|
+
* 1. Global params from config
|
|
238
|
+
* 2. Per-request params (overrides global)
|
|
239
|
+
*
|
|
240
|
+
* @param perRequestParams - Optional query parameters for this specific request
|
|
241
|
+
* @returns URLSearchParams object ready to append to URLs
|
|
242
|
+
*/
|
|
243
|
+
buildQueryString(perRequestParams) {
|
|
244
|
+
const params = {};
|
|
245
|
+
const globalParams = this.getParams();
|
|
246
|
+
if (globalParams) {
|
|
247
|
+
Object.assign(params, globalParams);
|
|
248
|
+
}
|
|
249
|
+
if (perRequestParams) {
|
|
250
|
+
Object.assign(params, perRequestParams);
|
|
251
|
+
}
|
|
252
|
+
return new URLSearchParams(params);
|
|
253
|
+
}
|
|
300
254
|
};
|
|
301
255
|
|
|
302
256
|
// src/managers/session-manager.ts
|
|
@@ -304,11 +258,16 @@ var SessionManager = class {
|
|
|
304
258
|
/**
|
|
305
259
|
* Fetch all sessions for an entity
|
|
306
260
|
*/
|
|
307
|
-
async fetchSessions(endpoint, entityType, entityId, dbId, headers) {
|
|
261
|
+
async fetchSessions(endpoint, entityType, entityId, dbId, headers, params) {
|
|
308
262
|
const url = new URL(`${endpoint}/sessions`);
|
|
309
263
|
url.searchParams.set("type", entityType);
|
|
310
264
|
url.searchParams.set("component_id", entityId);
|
|
311
265
|
url.searchParams.set("db_id", dbId);
|
|
266
|
+
if (params) {
|
|
267
|
+
params.forEach((value, key) => {
|
|
268
|
+
url.searchParams.set(key, value);
|
|
269
|
+
});
|
|
270
|
+
}
|
|
312
271
|
const response = await fetch(url.toString(), { headers });
|
|
313
272
|
if (!response.ok) {
|
|
314
273
|
if (response.status === 404) {
|
|
@@ -323,7 +282,7 @@ var SessionManager = class {
|
|
|
323
282
|
* Fetch a specific session's runs
|
|
324
283
|
* Returns an array of RunSchema directly (not wrapped in { data, meta })
|
|
325
284
|
*/
|
|
326
|
-
async fetchSession(endpoint, entityType, sessionId, dbId, headers, userId) {
|
|
285
|
+
async fetchSession(endpoint, entityType, sessionId, dbId, headers, userId, params) {
|
|
327
286
|
const url = new URL(`${endpoint}/sessions/${sessionId}/runs`);
|
|
328
287
|
url.searchParams.set("type", entityType);
|
|
329
288
|
if (dbId) {
|
|
@@ -332,6 +291,11 @@ var SessionManager = class {
|
|
|
332
291
|
if (userId) {
|
|
333
292
|
url.searchParams.set("user_id", userId);
|
|
334
293
|
}
|
|
294
|
+
if (params) {
|
|
295
|
+
params.forEach((value, key) => {
|
|
296
|
+
url.searchParams.set(key, value);
|
|
297
|
+
});
|
|
298
|
+
}
|
|
335
299
|
const response = await fetch(url.toString(), { headers });
|
|
336
300
|
if (!response.ok) {
|
|
337
301
|
throw new Error(`Failed to fetch session: ${response.statusText}`);
|
|
@@ -341,11 +305,16 @@ var SessionManager = class {
|
|
|
341
305
|
/**
|
|
342
306
|
* Delete a session
|
|
343
307
|
*/
|
|
344
|
-
async deleteSession(endpoint, sessionId, dbId, headers) {
|
|
308
|
+
async deleteSession(endpoint, sessionId, dbId, headers, params) {
|
|
345
309
|
const url = new URL(`${endpoint}/sessions/${sessionId}`);
|
|
346
310
|
if (dbId) {
|
|
347
311
|
url.searchParams.set("db_id", dbId);
|
|
348
312
|
}
|
|
313
|
+
if (params) {
|
|
314
|
+
params.forEach((value, key) => {
|
|
315
|
+
url.searchParams.set(key, value);
|
|
316
|
+
});
|
|
317
|
+
}
|
|
349
318
|
const response = await fetch(url.toString(), {
|
|
350
319
|
method: "DELETE",
|
|
351
320
|
headers
|
|
@@ -404,7 +373,9 @@ var SessionManager = class {
|
|
|
404
373
|
tool_name: reasoningMsg.tool_name ?? "",
|
|
405
374
|
tool_args: reasoningMsg.tool_args ?? {},
|
|
406
375
|
tool_call_error: reasoningMsg.tool_call_error ?? false,
|
|
407
|
-
metrics: reasoningMsg.metrics ?? {
|
|
376
|
+
metrics: reasoningMsg.metrics ?? {
|
|
377
|
+
time: 0
|
|
378
|
+
},
|
|
408
379
|
created_at: reasoningMsg.created_at ?? timestamp
|
|
409
380
|
});
|
|
410
381
|
}
|
|
@@ -438,6 +409,164 @@ var SessionManager = class {
|
|
|
438
409
|
}
|
|
439
410
|
};
|
|
440
411
|
|
|
412
|
+
// src/parsers/stream-parser.ts
|
|
413
|
+
function isLegacyFormat(data) {
|
|
414
|
+
return typeof data === "object" && data !== null && "event" in data && !("data" in data) && typeof data.event === "string";
|
|
415
|
+
}
|
|
416
|
+
function convertNewFormatToLegacy(newFormatData) {
|
|
417
|
+
const { event, data } = newFormatData;
|
|
418
|
+
let parsedData;
|
|
419
|
+
if (typeof data === "string") {
|
|
420
|
+
try {
|
|
421
|
+
parsedData = JSON.parse(data);
|
|
422
|
+
} catch {
|
|
423
|
+
parsedData = {};
|
|
424
|
+
}
|
|
425
|
+
} else {
|
|
426
|
+
parsedData = data;
|
|
427
|
+
}
|
|
428
|
+
return {
|
|
429
|
+
event,
|
|
430
|
+
...parsedData
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
function processChunk(chunk, onChunk) {
|
|
434
|
+
onChunk(chunk);
|
|
435
|
+
}
|
|
436
|
+
function parseBuffer(buffer, onChunk) {
|
|
437
|
+
let currentIndex = 0;
|
|
438
|
+
let jsonStartIndex = buffer.indexOf("{", currentIndex);
|
|
439
|
+
while (jsonStartIndex !== -1 && jsonStartIndex < buffer.length) {
|
|
440
|
+
let braceCount = 0;
|
|
441
|
+
let inString = false;
|
|
442
|
+
let escapeNext = false;
|
|
443
|
+
let jsonEndIndex = -1;
|
|
444
|
+
let i = jsonStartIndex;
|
|
445
|
+
for (; i < buffer.length; i++) {
|
|
446
|
+
const char = buffer[i];
|
|
447
|
+
if (inString) {
|
|
448
|
+
if (escapeNext) {
|
|
449
|
+
escapeNext = false;
|
|
450
|
+
} else if (char === "\\") {
|
|
451
|
+
escapeNext = true;
|
|
452
|
+
} else if (char === '"') {
|
|
453
|
+
inString = false;
|
|
454
|
+
}
|
|
455
|
+
} else if (char === '"') {
|
|
456
|
+
inString = true;
|
|
457
|
+
} else if (char === "{") {
|
|
458
|
+
braceCount++;
|
|
459
|
+
} else if (char === "}") {
|
|
460
|
+
braceCount--;
|
|
461
|
+
if (braceCount === 0) {
|
|
462
|
+
jsonEndIndex = i;
|
|
463
|
+
break;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
if (jsonEndIndex !== -1) {
|
|
468
|
+
const jsonString = buffer.slice(jsonStartIndex, jsonEndIndex + 1);
|
|
469
|
+
try {
|
|
470
|
+
const parsed = JSON.parse(jsonString);
|
|
471
|
+
if (isLegacyFormat(parsed)) {
|
|
472
|
+
processChunk(parsed, onChunk);
|
|
473
|
+
} else {
|
|
474
|
+
const legacyChunk = convertNewFormatToLegacy(parsed);
|
|
475
|
+
processChunk(legacyChunk, onChunk);
|
|
476
|
+
}
|
|
477
|
+
} catch (error) {
|
|
478
|
+
if (typeof process !== "undefined" && process.env?.NODE_ENV === "development") {
|
|
479
|
+
console.error("Failed to parse JSON chunk:", {
|
|
480
|
+
error,
|
|
481
|
+
chunk: jsonString.substring(0, 100) + (jsonString.length > 100 ? "..." : ""),
|
|
482
|
+
position: jsonStartIndex
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
if (jsonString.length > 1e4) {
|
|
486
|
+
throw new Error(
|
|
487
|
+
`Failed to parse large JSON chunk at position ${jsonStartIndex}`
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
jsonStartIndex = buffer.indexOf("{", jsonStartIndex + 1);
|
|
491
|
+
continue;
|
|
492
|
+
}
|
|
493
|
+
currentIndex = jsonEndIndex + 1;
|
|
494
|
+
buffer = buffer.slice(currentIndex).trim();
|
|
495
|
+
currentIndex = 0;
|
|
496
|
+
jsonStartIndex = buffer.indexOf("{", currentIndex);
|
|
497
|
+
} else {
|
|
498
|
+
break;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
return buffer;
|
|
502
|
+
}
|
|
503
|
+
async function streamResponse(options) {
|
|
504
|
+
const {
|
|
505
|
+
apiUrl,
|
|
506
|
+
headers = {},
|
|
507
|
+
params,
|
|
508
|
+
requestBody,
|
|
509
|
+
onChunk,
|
|
510
|
+
onError,
|
|
511
|
+
onComplete,
|
|
512
|
+
signal
|
|
513
|
+
} = options;
|
|
514
|
+
let buffer = "";
|
|
515
|
+
const finalUrl = params?.toString() ? `${apiUrl}?${params.toString()}` : apiUrl;
|
|
516
|
+
try {
|
|
517
|
+
const response = await fetch(finalUrl, {
|
|
518
|
+
method: "POST",
|
|
519
|
+
headers: {
|
|
520
|
+
...!(requestBody instanceof FormData) && {
|
|
521
|
+
"Content-Type": "application/json"
|
|
522
|
+
},
|
|
523
|
+
...headers
|
|
524
|
+
},
|
|
525
|
+
body: requestBody instanceof FormData ? requestBody : JSON.stringify(requestBody),
|
|
526
|
+
signal
|
|
527
|
+
});
|
|
528
|
+
if (!response.ok) {
|
|
529
|
+
let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
|
530
|
+
const contentType = response.headers.get("content-type");
|
|
531
|
+
if (contentType?.includes("application/json")) {
|
|
532
|
+
try {
|
|
533
|
+
const errorData = await response.json();
|
|
534
|
+
errorMessage = errorData.detail || errorData.message || errorMessage;
|
|
535
|
+
} catch {
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
throw new Error(errorMessage);
|
|
539
|
+
}
|
|
540
|
+
if (!response.body) {
|
|
541
|
+
throw new Error("No response body");
|
|
542
|
+
}
|
|
543
|
+
const reader = response.body.getReader();
|
|
544
|
+
const decoder = new TextDecoder();
|
|
545
|
+
const processStream = async () => {
|
|
546
|
+
while (true) {
|
|
547
|
+
const { done, value } = await reader.read();
|
|
548
|
+
if (done) {
|
|
549
|
+
buffer = parseBuffer(buffer, onChunk);
|
|
550
|
+
onComplete();
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
buffer += decoder.decode(value, { stream: true });
|
|
554
|
+
buffer = parseBuffer(buffer, onChunk);
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
await processStream();
|
|
558
|
+
} catch (error) {
|
|
559
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
if (typeof error === "object" && error !== null && "detail" in error) {
|
|
563
|
+
onError(new Error(String(error.detail)));
|
|
564
|
+
} else {
|
|
565
|
+
onError(new Error(String(error)));
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
441
570
|
// src/processors/event-processor.ts
|
|
442
571
|
var import_agno_types = require("@antipopp/agno-types");
|
|
443
572
|
|
|
@@ -466,9 +595,8 @@ function processToolCall(toolCall, prevToolCalls = []) {
|
|
|
466
595
|
...toolCall
|
|
467
596
|
};
|
|
468
597
|
return updatedToolCalls;
|
|
469
|
-
} else {
|
|
470
|
-
return [...prevToolCalls, toolCall];
|
|
471
598
|
}
|
|
599
|
+
return [...prevToolCalls, toolCall];
|
|
472
600
|
}
|
|
473
601
|
function processChunkToolCalls(chunk, existingToolCalls = []) {
|
|
474
602
|
let updatedToolCalls = [...existingToolCalls];
|
|
@@ -556,7 +684,7 @@ var EventProcessor = class {
|
|
|
556
684
|
}
|
|
557
685
|
break;
|
|
558
686
|
case import_agno_types.RunEvent.ReasoningStep:
|
|
559
|
-
case import_agno_types.RunEvent.TeamReasoningStep:
|
|
687
|
+
case import_agno_types.RunEvent.TeamReasoningStep: {
|
|
560
688
|
const existingSteps = lastMessage.extra_data?.reasoning_steps ?? [];
|
|
561
689
|
const incomingSteps = chunk.extra_data?.reasoning_steps ?? [];
|
|
562
690
|
updatedMessage.extra_data = {
|
|
@@ -564,6 +692,7 @@ var EventProcessor = class {
|
|
|
564
692
|
reasoning_steps: [...existingSteps, ...incomingSteps]
|
|
565
693
|
};
|
|
566
694
|
break;
|
|
695
|
+
}
|
|
567
696
|
case import_agno_types.RunEvent.ReasoningCompleted:
|
|
568
697
|
case import_agno_types.RunEvent.TeamReasoningCompleted:
|
|
569
698
|
if (chunk.extra_data?.reasoning_steps) {
|
|
@@ -574,7 +703,7 @@ var EventProcessor = class {
|
|
|
574
703
|
}
|
|
575
704
|
break;
|
|
576
705
|
case import_agno_types.RunEvent.RunCompleted:
|
|
577
|
-
case import_agno_types.RunEvent.TeamRunCompleted:
|
|
706
|
+
case import_agno_types.RunEvent.TeamRunCompleted: {
|
|
578
707
|
let updatedContent;
|
|
579
708
|
if (typeof chunk.content === "string") {
|
|
580
709
|
updatedContent = chunk.content;
|
|
@@ -599,6 +728,7 @@ var EventProcessor = class {
|
|
|
599
728
|
references: chunk.extra_data?.references ?? lastMessage.extra_data?.references
|
|
600
729
|
};
|
|
601
730
|
break;
|
|
731
|
+
}
|
|
602
732
|
case import_agno_types.RunEvent.UpdatingMemory:
|
|
603
733
|
case import_agno_types.RunEvent.TeamMemoryUpdateStarted:
|
|
604
734
|
case import_agno_types.RunEvent.TeamMemoryUpdateCompleted:
|
|
@@ -621,164 +751,95 @@ var EventProcessor = class {
|
|
|
621
751
|
}
|
|
622
752
|
};
|
|
623
753
|
|
|
624
|
-
// src/
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
function convertNewFormatToLegacy(newFormatData) {
|
|
629
|
-
const { event, data } = newFormatData;
|
|
630
|
-
let parsedData;
|
|
631
|
-
if (typeof data === "string") {
|
|
632
|
-
try {
|
|
633
|
-
parsedData = JSON.parse(data);
|
|
634
|
-
} catch {
|
|
635
|
-
parsedData = {};
|
|
636
|
-
}
|
|
637
|
-
} else {
|
|
638
|
-
parsedData = data;
|
|
754
|
+
// src/stores/message-store.ts
|
|
755
|
+
var MessageStore = class {
|
|
756
|
+
constructor() {
|
|
757
|
+
this.messages = [];
|
|
639
758
|
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
function processChunk(chunk, onChunk) {
|
|
646
|
-
onChunk(chunk);
|
|
647
|
-
}
|
|
648
|
-
function parseBuffer(buffer, onChunk) {
|
|
649
|
-
let currentIndex = 0;
|
|
650
|
-
let jsonStartIndex = buffer.indexOf("{", currentIndex);
|
|
651
|
-
while (jsonStartIndex !== -1 && jsonStartIndex < buffer.length) {
|
|
652
|
-
let braceCount = 0;
|
|
653
|
-
let inString = false;
|
|
654
|
-
let escapeNext = false;
|
|
655
|
-
let jsonEndIndex = -1;
|
|
656
|
-
let i = jsonStartIndex;
|
|
657
|
-
for (; i < buffer.length; i++) {
|
|
658
|
-
const char = buffer[i];
|
|
659
|
-
if (inString) {
|
|
660
|
-
if (escapeNext) {
|
|
661
|
-
escapeNext = false;
|
|
662
|
-
} else if (char === "\\") {
|
|
663
|
-
escapeNext = true;
|
|
664
|
-
} else if (char === '"') {
|
|
665
|
-
inString = false;
|
|
666
|
-
}
|
|
667
|
-
} else {
|
|
668
|
-
if (char === '"') {
|
|
669
|
-
inString = true;
|
|
670
|
-
} else if (char === "{") {
|
|
671
|
-
braceCount++;
|
|
672
|
-
} else if (char === "}") {
|
|
673
|
-
braceCount--;
|
|
674
|
-
if (braceCount === 0) {
|
|
675
|
-
jsonEndIndex = i;
|
|
676
|
-
break;
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
if (jsonEndIndex !== -1) {
|
|
682
|
-
const jsonString = buffer.slice(jsonStartIndex, jsonEndIndex + 1);
|
|
683
|
-
try {
|
|
684
|
-
const parsed = JSON.parse(jsonString);
|
|
685
|
-
if (isLegacyFormat(parsed)) {
|
|
686
|
-
processChunk(parsed, onChunk);
|
|
687
|
-
} else {
|
|
688
|
-
const legacyChunk = convertNewFormatToLegacy(parsed);
|
|
689
|
-
processChunk(legacyChunk, onChunk);
|
|
690
|
-
}
|
|
691
|
-
} catch (error) {
|
|
692
|
-
if (typeof process !== "undefined" && process.env?.NODE_ENV === "development") {
|
|
693
|
-
console.error("Failed to parse JSON chunk:", {
|
|
694
|
-
error,
|
|
695
|
-
chunk: jsonString.substring(0, 100) + (jsonString.length > 100 ? "..." : ""),
|
|
696
|
-
position: jsonStartIndex
|
|
697
|
-
});
|
|
698
|
-
}
|
|
699
|
-
if (jsonString.length > 1e4) {
|
|
700
|
-
throw new Error(`Failed to parse large JSON chunk at position ${jsonStartIndex}`);
|
|
701
|
-
}
|
|
702
|
-
jsonStartIndex = buffer.indexOf("{", jsonStartIndex + 1);
|
|
703
|
-
continue;
|
|
704
|
-
}
|
|
705
|
-
currentIndex = jsonEndIndex + 1;
|
|
706
|
-
buffer = buffer.slice(currentIndex).trim();
|
|
707
|
-
currentIndex = 0;
|
|
708
|
-
jsonStartIndex = buffer.indexOf("{", currentIndex);
|
|
709
|
-
} else {
|
|
710
|
-
break;
|
|
711
|
-
}
|
|
759
|
+
/**
|
|
760
|
+
* Get all messages
|
|
761
|
+
*/
|
|
762
|
+
getMessages() {
|
|
763
|
+
return [...this.messages];
|
|
712
764
|
}
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
"Content-Type": "application/json"
|
|
732
|
-
},
|
|
733
|
-
...headers
|
|
734
|
-
},
|
|
735
|
-
body: requestBody instanceof FormData ? requestBody : JSON.stringify(requestBody),
|
|
736
|
-
signal
|
|
737
|
-
});
|
|
738
|
-
if (!response.ok) {
|
|
739
|
-
let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
|
740
|
-
const contentType = response.headers.get("content-type");
|
|
741
|
-
if (contentType?.includes("application/json")) {
|
|
742
|
-
try {
|
|
743
|
-
const errorData = await response.json();
|
|
744
|
-
errorMessage = errorData.detail || errorData.message || errorMessage;
|
|
745
|
-
} catch {
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
throw new Error(errorMessage);
|
|
749
|
-
}
|
|
750
|
-
if (!response.body) {
|
|
751
|
-
throw new Error("No response body");
|
|
765
|
+
/**
|
|
766
|
+
* Set messages (replaces all)
|
|
767
|
+
*/
|
|
768
|
+
setMessages(messages) {
|
|
769
|
+
this.messages = [...messages];
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Add a message
|
|
773
|
+
*/
|
|
774
|
+
addMessage(message) {
|
|
775
|
+
this.messages = [...this.messages, message];
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* Update the last message
|
|
779
|
+
*/
|
|
780
|
+
updateLastMessage(updater) {
|
|
781
|
+
if (this.messages.length === 0) {
|
|
782
|
+
return void 0;
|
|
752
783
|
}
|
|
753
|
-
const
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
while (true) {
|
|
757
|
-
const { done, value } = await reader.read();
|
|
758
|
-
if (done) {
|
|
759
|
-
buffer = parseBuffer(buffer, onChunk);
|
|
760
|
-
onComplete();
|
|
761
|
-
return;
|
|
762
|
-
}
|
|
763
|
-
buffer += decoder.decode(value, { stream: true });
|
|
764
|
-
buffer = parseBuffer(buffer, onChunk);
|
|
765
|
-
}
|
|
766
|
-
};
|
|
767
|
-
await processStream();
|
|
768
|
-
} catch (error) {
|
|
769
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
770
|
-
return;
|
|
784
|
+
const lastMessage = this.messages.at(-1);
|
|
785
|
+
if (!lastMessage) {
|
|
786
|
+
return void 0;
|
|
771
787
|
}
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
788
|
+
const updatedMessage = updater(lastMessage);
|
|
789
|
+
this.messages = [...this.messages.slice(0, -1), updatedMessage];
|
|
790
|
+
return updatedMessage;
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Update a specific message by index
|
|
794
|
+
*/
|
|
795
|
+
updateMessage(index, updater) {
|
|
796
|
+
if (index < 0 || index >= this.messages.length) {
|
|
797
|
+
return void 0;
|
|
776
798
|
}
|
|
799
|
+
const message = this.messages[index];
|
|
800
|
+
const updatedMessage = updater(message);
|
|
801
|
+
this.messages = [
|
|
802
|
+
...this.messages.slice(0, index),
|
|
803
|
+
updatedMessage,
|
|
804
|
+
...this.messages.slice(index + 1)
|
|
805
|
+
];
|
|
806
|
+
return updatedMessage;
|
|
777
807
|
}
|
|
778
|
-
|
|
808
|
+
/**
|
|
809
|
+
* Remove last N messages
|
|
810
|
+
*/
|
|
811
|
+
removeLastMessages(count) {
|
|
812
|
+
this.messages = this.messages.slice(0, -count);
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Clear all messages
|
|
816
|
+
*/
|
|
817
|
+
clear() {
|
|
818
|
+
this.messages = [];
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* Get the last message
|
|
822
|
+
*/
|
|
823
|
+
getLastMessage() {
|
|
824
|
+
return this.messages.length > 0 ? this.messages.at(-1) : void 0;
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
* Check if last message has streaming error
|
|
828
|
+
*/
|
|
829
|
+
hasLastMessageError() {
|
|
830
|
+
const lastMessage = this.getLastMessage();
|
|
831
|
+
return lastMessage?.streamingError === true;
|
|
832
|
+
}
|
|
833
|
+
};
|
|
779
834
|
|
|
780
835
|
// src/utils/logger.ts
|
|
781
|
-
var SENSITIVE_KEYS = [
|
|
836
|
+
var SENSITIVE_KEYS = [
|
|
837
|
+
"authToken",
|
|
838
|
+
"Authorization",
|
|
839
|
+
"token",
|
|
840
|
+
"password",
|
|
841
|
+
"apiKey"
|
|
842
|
+
];
|
|
782
843
|
function sanitizeObject(obj) {
|
|
783
844
|
if (obj === null || obj === void 0) {
|
|
784
845
|
return obj;
|
|
@@ -866,6 +927,7 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
866
927
|
this.state = {
|
|
867
928
|
isStreaming: false,
|
|
868
929
|
isRefreshing: false,
|
|
930
|
+
isCancelling: false,
|
|
869
931
|
isEndpointActive: false,
|
|
870
932
|
agents: [],
|
|
871
933
|
teams: [],
|
|
@@ -910,6 +972,49 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
910
972
|
this.emit("message:update", this.messageStore.getMessages());
|
|
911
973
|
this.emit("state:change", this.getState());
|
|
912
974
|
}
|
|
975
|
+
/**
|
|
976
|
+
* Cancel an active or paused run
|
|
977
|
+
*/
|
|
978
|
+
async cancelRun() {
|
|
979
|
+
if (!(this.state.isStreaming || this.state.isPaused)) {
|
|
980
|
+
throw new Error("No active or paused run to cancel");
|
|
981
|
+
}
|
|
982
|
+
const runUrl = this.configManager.getRunUrl();
|
|
983
|
+
if (!runUrl) {
|
|
984
|
+
throw new Error("No agent or team selected");
|
|
985
|
+
}
|
|
986
|
+
const runId = this.state.pausedRunId || this.currentRunId;
|
|
987
|
+
if (!runId) {
|
|
988
|
+
throw new Error("No run ID available to cancel");
|
|
989
|
+
}
|
|
990
|
+
const cancelUrl = `${runUrl}/${runId}/cancel`;
|
|
991
|
+
const headers = this.configManager.buildRequestHeaders();
|
|
992
|
+
this.state.isCancelling = true;
|
|
993
|
+
this.emit("state:change", this.getState());
|
|
994
|
+
try {
|
|
995
|
+
const response = await fetch(cancelUrl, {
|
|
996
|
+
method: "POST",
|
|
997
|
+
headers
|
|
998
|
+
});
|
|
999
|
+
if (!response.ok) {
|
|
1000
|
+
throw new Error("Failed to cancel run");
|
|
1001
|
+
}
|
|
1002
|
+
this.state.isStreaming = false;
|
|
1003
|
+
this.state.isPaused = false;
|
|
1004
|
+
this.state.isCancelling = false;
|
|
1005
|
+
this.state.pausedRunId = void 0;
|
|
1006
|
+
this.state.toolsAwaitingExecution = void 0;
|
|
1007
|
+
this.currentRunId = void 0;
|
|
1008
|
+
this.emit("run:cancelled", { runId });
|
|
1009
|
+
this.emit("state:change", this.getState());
|
|
1010
|
+
} catch (error) {
|
|
1011
|
+
this.state.isCancelling = false;
|
|
1012
|
+
this.emit("state:change", this.getState());
|
|
1013
|
+
throw new Error(
|
|
1014
|
+
`Error cancelling run: ${error instanceof Error ? error.message : String(error)}`
|
|
1015
|
+
);
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
913
1018
|
/**
|
|
914
1019
|
* Send a message to the agent/team (streaming)
|
|
915
1020
|
*/
|
|
@@ -960,17 +1065,21 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
960
1065
|
formData.append("user_id", userId);
|
|
961
1066
|
}
|
|
962
1067
|
const headers = this.configManager.buildRequestHeaders(options?.headers);
|
|
1068
|
+
const params = this.configManager.buildQueryString(options?.params);
|
|
963
1069
|
await streamResponse({
|
|
964
1070
|
apiUrl: runUrl,
|
|
965
1071
|
headers,
|
|
1072
|
+
params,
|
|
966
1073
|
requestBody: formData,
|
|
967
1074
|
onChunk: (chunk) => {
|
|
968
|
-
this.handleChunk(
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
1075
|
+
this.handleChunk(
|
|
1076
|
+
chunk,
|
|
1077
|
+
newSessionId,
|
|
1078
|
+
formData.get("message")
|
|
1079
|
+
);
|
|
1080
|
+
if ((chunk.event === import_agno_types2.RunEvent.RunStarted || chunk.event === import_agno_types2.RunEvent.TeamRunStarted || chunk.event === import_agno_types2.RunEvent.ReasoningStarted || chunk.event === import_agno_types2.RunEvent.TeamReasoningStarted) && chunk.session_id) {
|
|
1081
|
+
newSessionId = chunk.session_id;
|
|
1082
|
+
this.configManager.setSessionId(chunk.session_id);
|
|
974
1083
|
}
|
|
975
1084
|
},
|
|
976
1085
|
onError: (error) => {
|
|
@@ -978,6 +1087,7 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
978
1087
|
},
|
|
979
1088
|
onComplete: async () => {
|
|
980
1089
|
this.state.isStreaming = false;
|
|
1090
|
+
this.currentRunId = void 0;
|
|
981
1091
|
this.emit("stream:end");
|
|
982
1092
|
this.emit("message:complete", this.messageStore.getMessages());
|
|
983
1093
|
this.emit("state:change", this.getState());
|
|
@@ -999,20 +1109,21 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
999
1109
|
*/
|
|
1000
1110
|
handleChunk(chunk, currentSessionId, messageContent) {
|
|
1001
1111
|
const event = chunk.event;
|
|
1002
|
-
if (event === import_agno_types2.RunEvent.RunStarted || event === import_agno_types2.RunEvent.TeamRunStarted
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1112
|
+
if ((event === import_agno_types2.RunEvent.RunStarted || event === import_agno_types2.RunEvent.TeamRunStarted) && chunk.run_id) {
|
|
1113
|
+
this.currentRunId = chunk.run_id;
|
|
1114
|
+
}
|
|
1115
|
+
if ((event === import_agno_types2.RunEvent.RunStarted || event === import_agno_types2.RunEvent.TeamRunStarted || event === import_agno_types2.RunEvent.ReasoningStarted || event === import_agno_types2.RunEvent.TeamReasoningStarted) && chunk.session_id && (!currentSessionId || currentSessionId !== chunk.session_id)) {
|
|
1116
|
+
const sessionData = {
|
|
1117
|
+
session_id: chunk.session_id,
|
|
1118
|
+
session_name: messageContent,
|
|
1119
|
+
created_at: toSafeISOString(chunk.created_at)
|
|
1120
|
+
};
|
|
1121
|
+
const sessionExists = this.state.sessions.some(
|
|
1122
|
+
(s) => s.session_id === chunk.session_id
|
|
1123
|
+
);
|
|
1124
|
+
if (!sessionExists) {
|
|
1125
|
+
this.state.sessions = [sessionData, ...this.state.sessions];
|
|
1126
|
+
this.emit("session:created", sessionData);
|
|
1016
1127
|
}
|
|
1017
1128
|
}
|
|
1018
1129
|
if (event === import_agno_types2.RunEvent.RunPaused) {
|
|
@@ -1092,7 +1203,10 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1092
1203
|
if (message.tool_calls) {
|
|
1093
1204
|
for (const toolCall of message.tool_calls) {
|
|
1094
1205
|
if (toolCall.ui_component) {
|
|
1095
|
-
existingUIComponents.set(
|
|
1206
|
+
existingUIComponents.set(
|
|
1207
|
+
toolCall.tool_call_id,
|
|
1208
|
+
toolCall.ui_component
|
|
1209
|
+
);
|
|
1096
1210
|
}
|
|
1097
1211
|
}
|
|
1098
1212
|
}
|
|
@@ -1102,13 +1216,15 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1102
1216
|
const dbId = this.configManager.getDbId() || "";
|
|
1103
1217
|
const userId = this.configManager.getUserId();
|
|
1104
1218
|
const headers = this.configManager.buildRequestHeaders();
|
|
1219
|
+
const params = this.configManager.buildQueryString();
|
|
1105
1220
|
const response = await this.sessionManager.fetchSession(
|
|
1106
1221
|
config.endpoint,
|
|
1107
1222
|
entityType,
|
|
1108
1223
|
sessionId,
|
|
1109
1224
|
dbId,
|
|
1110
1225
|
headers,
|
|
1111
|
-
userId
|
|
1226
|
+
userId,
|
|
1227
|
+
params
|
|
1112
1228
|
);
|
|
1113
1229
|
const messages = this.sessionManager.convertSessionToMessages(response);
|
|
1114
1230
|
if (existingUIComponents.size > 0) {
|
|
@@ -1116,7 +1232,9 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1116
1232
|
if (message.tool_calls) {
|
|
1117
1233
|
for (let i = 0; i < message.tool_calls.length; i++) {
|
|
1118
1234
|
const toolCall = message.tool_calls[i];
|
|
1119
|
-
const uiComponent = existingUIComponents.get(
|
|
1235
|
+
const uiComponent = existingUIComponents.get(
|
|
1236
|
+
toolCall.tool_call_id
|
|
1237
|
+
);
|
|
1120
1238
|
if (uiComponent) {
|
|
1121
1239
|
message.tool_calls[i].ui_component = uiComponent;
|
|
1122
1240
|
}
|
|
@@ -1125,12 +1243,18 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1125
1243
|
}
|
|
1126
1244
|
}
|
|
1127
1245
|
this.messageStore.setMessages(messages);
|
|
1128
|
-
Logger.debug(
|
|
1246
|
+
Logger.debug(
|
|
1247
|
+
"[AgnoClient] Session refreshed:",
|
|
1248
|
+
`${messages.length} messages`
|
|
1249
|
+
);
|
|
1129
1250
|
this.emit("message:refreshed", messages);
|
|
1130
1251
|
this.emit("message:update", messages);
|
|
1131
1252
|
} catch (error) {
|
|
1132
1253
|
Logger.error("[AgnoClient] Failed to refresh session:", error);
|
|
1133
|
-
this.emit(
|
|
1254
|
+
this.emit(
|
|
1255
|
+
"message:error",
|
|
1256
|
+
`Session refresh failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1257
|
+
);
|
|
1134
1258
|
} finally {
|
|
1135
1259
|
this.state.isRefreshing = false;
|
|
1136
1260
|
this.emit("state:change", this.getState());
|
|
@@ -1139,24 +1263,33 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1139
1263
|
/**
|
|
1140
1264
|
* Load a session
|
|
1141
1265
|
*/
|
|
1142
|
-
async loadSession(sessionId) {
|
|
1266
|
+
async loadSession(sessionId, options) {
|
|
1143
1267
|
Logger.debug("[AgnoClient] loadSession called with sessionId:", sessionId);
|
|
1144
1268
|
const config = this.configManager.getConfig();
|
|
1145
1269
|
const entityType = this.configManager.getMode();
|
|
1146
1270
|
const dbId = this.configManager.getDbId() || "";
|
|
1147
1271
|
const userId = this.configManager.getUserId();
|
|
1148
|
-
Logger.debug("[AgnoClient] Loading session with:", {
|
|
1272
|
+
Logger.debug("[AgnoClient] Loading session with:", {
|
|
1273
|
+
entityType,
|
|
1274
|
+
dbId,
|
|
1275
|
+
userId
|
|
1276
|
+
});
|
|
1149
1277
|
const headers = this.configManager.buildRequestHeaders();
|
|
1278
|
+
const params = this.configManager.buildQueryString(options?.params);
|
|
1150
1279
|
const response = await this.sessionManager.fetchSession(
|
|
1151
1280
|
config.endpoint,
|
|
1152
1281
|
entityType,
|
|
1153
1282
|
sessionId,
|
|
1154
1283
|
dbId,
|
|
1155
1284
|
headers,
|
|
1156
|
-
userId
|
|
1285
|
+
userId,
|
|
1286
|
+
params
|
|
1157
1287
|
);
|
|
1158
1288
|
const messages = this.sessionManager.convertSessionToMessages(response);
|
|
1159
|
-
Logger.debug(
|
|
1289
|
+
Logger.debug(
|
|
1290
|
+
"[AgnoClient] Setting messages to store:",
|
|
1291
|
+
`${messages.length} messages`
|
|
1292
|
+
);
|
|
1160
1293
|
this.messageStore.setMessages(messages);
|
|
1161
1294
|
this.configManager.setSessionId(sessionId);
|
|
1162
1295
|
Logger.debug("[AgnoClient] Emitting events...");
|
|
@@ -1169,7 +1302,7 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1169
1302
|
/**
|
|
1170
1303
|
* Fetch all sessions
|
|
1171
1304
|
*/
|
|
1172
|
-
async fetchSessions() {
|
|
1305
|
+
async fetchSessions(options) {
|
|
1173
1306
|
const config = this.configManager.getConfig();
|
|
1174
1307
|
const entityType = this.configManager.getMode();
|
|
1175
1308
|
const entityId = this.configManager.getCurrentEntityId();
|
|
@@ -1178,12 +1311,14 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1178
1311
|
throw new Error("Entity ID must be configured");
|
|
1179
1312
|
}
|
|
1180
1313
|
const headers = this.configManager.buildRequestHeaders();
|
|
1314
|
+
const params = this.configManager.buildQueryString(options?.params);
|
|
1181
1315
|
const sessions = await this.sessionManager.fetchSessions(
|
|
1182
1316
|
config.endpoint,
|
|
1183
1317
|
entityType,
|
|
1184
1318
|
entityId,
|
|
1185
1319
|
dbId,
|
|
1186
|
-
headers
|
|
1320
|
+
headers,
|
|
1321
|
+
params
|
|
1187
1322
|
);
|
|
1188
1323
|
this.state.sessions = sessions;
|
|
1189
1324
|
this.emit("state:change", this.getState());
|
|
@@ -1192,15 +1327,17 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1192
1327
|
/**
|
|
1193
1328
|
* Delete a session
|
|
1194
1329
|
*/
|
|
1195
|
-
async deleteSession(sessionId) {
|
|
1330
|
+
async deleteSession(sessionId, options) {
|
|
1196
1331
|
const config = this.configManager.getConfig();
|
|
1197
1332
|
const dbId = this.configManager.getDbId() || "";
|
|
1198
1333
|
const headers = this.configManager.buildRequestHeaders();
|
|
1334
|
+
const params = this.configManager.buildQueryString(options?.params);
|
|
1199
1335
|
await this.sessionManager.deleteSession(
|
|
1200
1336
|
config.endpoint,
|
|
1201
1337
|
sessionId,
|
|
1202
1338
|
dbId,
|
|
1203
|
-
headers
|
|
1339
|
+
headers,
|
|
1340
|
+
params
|
|
1204
1341
|
);
|
|
1205
1342
|
this.state.sessions = this.state.sessions.filter(
|
|
1206
1343
|
(s) => s.session_id !== sessionId
|
|
@@ -1221,7 +1358,9 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1221
1358
|
}
|
|
1222
1359
|
const existingToolCalls = lastMessage.tool_calls || [];
|
|
1223
1360
|
const existingIds = new Set(existingToolCalls.map((t) => t.tool_call_id));
|
|
1224
|
-
const newToolCalls = toolCalls.filter(
|
|
1361
|
+
const newToolCalls = toolCalls.filter(
|
|
1362
|
+
(t) => !existingIds.has(t.tool_call_id)
|
|
1363
|
+
);
|
|
1225
1364
|
if (newToolCalls.length > 0) {
|
|
1226
1365
|
this.messageStore.updateLastMessage((msg) => ({
|
|
1227
1366
|
...msg,
|
|
@@ -1268,8 +1407,9 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1268
1407
|
* Batches all updates to emit only one message:update event
|
|
1269
1408
|
*/
|
|
1270
1409
|
applyPendingUISpecs() {
|
|
1271
|
-
if (this.pendingUISpecs.size === 0)
|
|
1410
|
+
if (this.pendingUISpecs.size === 0) {
|
|
1272
1411
|
return;
|
|
1412
|
+
}
|
|
1273
1413
|
const messages = this.messageStore.getMessages();
|
|
1274
1414
|
const updatedMessages = [];
|
|
1275
1415
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
@@ -1314,7 +1454,7 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1314
1454
|
* Teams do not support the continue endpoint.
|
|
1315
1455
|
*
|
|
1316
1456
|
* @param tools - Array of tool calls with execution results
|
|
1317
|
-
* @param options - Optional request headers
|
|
1457
|
+
* @param options - Optional request headers and query parameters
|
|
1318
1458
|
* @throws Error if no paused run exists
|
|
1319
1459
|
* @throws Error if called with team mode (teams don't support HITL)
|
|
1320
1460
|
*/
|
|
@@ -1324,7 +1464,7 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1324
1464
|
"HITL (Human-in-the-Loop) frontend tool execution is not supported for teams. Only agents support the continue endpoint."
|
|
1325
1465
|
);
|
|
1326
1466
|
}
|
|
1327
|
-
if (!this.state.isPaused
|
|
1467
|
+
if (!(this.state.isPaused && this.state.pausedRunId)) {
|
|
1328
1468
|
throw new Error("No paused run to continue");
|
|
1329
1469
|
}
|
|
1330
1470
|
const runUrl = this.configManager.getRunUrl();
|
|
@@ -1352,10 +1492,12 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1352
1492
|
formData.append("user_id", userId);
|
|
1353
1493
|
}
|
|
1354
1494
|
const headers = this.configManager.buildRequestHeaders(options?.headers);
|
|
1495
|
+
const params = this.configManager.buildQueryString(options?.params);
|
|
1355
1496
|
try {
|
|
1356
1497
|
await streamResponse({
|
|
1357
1498
|
apiUrl: continueUrl,
|
|
1358
1499
|
headers,
|
|
1500
|
+
params,
|
|
1359
1501
|
requestBody: formData,
|
|
1360
1502
|
onChunk: (chunk) => {
|
|
1361
1503
|
this.handleChunk(chunk, currentSessionId, "");
|
|
@@ -1386,10 +1528,17 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1386
1528
|
/**
|
|
1387
1529
|
* Check endpoint status
|
|
1388
1530
|
*/
|
|
1389
|
-
async checkStatus() {
|
|
1531
|
+
async checkStatus(options) {
|
|
1390
1532
|
try {
|
|
1391
1533
|
const headers = this.configManager.buildRequestHeaders();
|
|
1392
|
-
const
|
|
1534
|
+
const params = this.configManager.buildQueryString(options?.params);
|
|
1535
|
+
const url = new URL(`${this.configManager.getEndpoint()}/health`);
|
|
1536
|
+
if (params.toString()) {
|
|
1537
|
+
params.forEach((value, key) => {
|
|
1538
|
+
url.searchParams.set(key, value);
|
|
1539
|
+
});
|
|
1540
|
+
}
|
|
1541
|
+
const response = await fetch(url.toString(), { headers });
|
|
1393
1542
|
const isActive = response.ok;
|
|
1394
1543
|
this.state.isEndpointActive = isActive;
|
|
1395
1544
|
this.emit("state:change", this.getState());
|
|
@@ -1403,9 +1552,16 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1403
1552
|
/**
|
|
1404
1553
|
* Fetch agents from endpoint
|
|
1405
1554
|
*/
|
|
1406
|
-
async fetchAgents() {
|
|
1555
|
+
async fetchAgents(options) {
|
|
1407
1556
|
const headers = this.configManager.buildRequestHeaders();
|
|
1408
|
-
const
|
|
1557
|
+
const params = this.configManager.buildQueryString(options?.params);
|
|
1558
|
+
const url = new URL(`${this.configManager.getEndpoint()}/agents`);
|
|
1559
|
+
if (params.toString()) {
|
|
1560
|
+
params.forEach((value, key) => {
|
|
1561
|
+
url.searchParams.set(key, value);
|
|
1562
|
+
});
|
|
1563
|
+
}
|
|
1564
|
+
const response = await fetch(url.toString(), { headers });
|
|
1409
1565
|
if (!response.ok) {
|
|
1410
1566
|
throw new Error("Failed to fetch agents");
|
|
1411
1567
|
}
|
|
@@ -1417,9 +1573,16 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1417
1573
|
/**
|
|
1418
1574
|
* Fetch teams from endpoint
|
|
1419
1575
|
*/
|
|
1420
|
-
async fetchTeams() {
|
|
1576
|
+
async fetchTeams(options) {
|
|
1421
1577
|
const headers = this.configManager.buildRequestHeaders();
|
|
1422
|
-
const
|
|
1578
|
+
const params = this.configManager.buildQueryString(options?.params);
|
|
1579
|
+
const url = new URL(`${this.configManager.getEndpoint()}/teams`);
|
|
1580
|
+
if (params.toString()) {
|
|
1581
|
+
params.forEach((value, key) => {
|
|
1582
|
+
url.searchParams.set(key, value);
|
|
1583
|
+
});
|
|
1584
|
+
}
|
|
1585
|
+
const response = await fetch(url.toString(), { headers });
|
|
1423
1586
|
if (!response.ok) {
|
|
1424
1587
|
throw new Error("Failed to fetch teams");
|
|
1425
1588
|
}
|
|
@@ -1432,19 +1595,19 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1432
1595
|
* Initialize client (check status and fetch agents/teams)
|
|
1433
1596
|
* Automatically selects the first available agent or team if none is configured
|
|
1434
1597
|
*/
|
|
1435
|
-
async initialize() {
|
|
1436
|
-
const isActive = await this.checkStatus();
|
|
1598
|
+
async initialize(options) {
|
|
1599
|
+
const isActive = await this.checkStatus(options);
|
|
1437
1600
|
if (!isActive) {
|
|
1438
1601
|
return { agents: [], teams: [] };
|
|
1439
1602
|
}
|
|
1440
1603
|
const [agents, teams] = await Promise.all([
|
|
1441
|
-
this.fetchAgents(),
|
|
1442
|
-
this.fetchTeams()
|
|
1604
|
+
this.fetchAgents(options),
|
|
1605
|
+
this.fetchTeams(options)
|
|
1443
1606
|
]);
|
|
1444
1607
|
const currentConfig = this.configManager.getConfig();
|
|
1445
1608
|
const hasAgentConfigured = currentConfig.agentId;
|
|
1446
1609
|
const hasTeamConfigured = currentConfig.teamId;
|
|
1447
|
-
if (!hasAgentConfigured
|
|
1610
|
+
if (!(hasAgentConfigured || hasTeamConfigured)) {
|
|
1448
1611
|
if (agents.length > 0) {
|
|
1449
1612
|
const firstAgent = agents[0];
|
|
1450
1613
|
this.configManager.updateConfig({
|
|
@@ -1465,10 +1628,28 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1465
1628
|
}
|
|
1466
1629
|
return { agents, teams };
|
|
1467
1630
|
}
|
|
1631
|
+
/**
|
|
1632
|
+
* Dispose of the client and clean up all resources.
|
|
1633
|
+
* Call this method when the client is no longer needed to prevent memory leaks.
|
|
1634
|
+
* After calling dispose(), the client instance should not be reused.
|
|
1635
|
+
*/
|
|
1636
|
+
dispose() {
|
|
1637
|
+
this.removeAllListeners();
|
|
1638
|
+
this.messageStore.clear();
|
|
1639
|
+
this.pendingUISpecs.clear();
|
|
1640
|
+
this.eventProcessor.reset();
|
|
1641
|
+
this.state.isStreaming = false;
|
|
1642
|
+
this.state.isRefreshing = false;
|
|
1643
|
+
this.state.isEndpointActive = false;
|
|
1644
|
+
this.state.agents = [];
|
|
1645
|
+
this.state.teams = [];
|
|
1646
|
+
this.state.sessions = [];
|
|
1647
|
+
this.state.isPaused = false;
|
|
1648
|
+
this.state.pausedRunId = void 0;
|
|
1649
|
+
this.state.toolsAwaitingExecution = void 0;
|
|
1650
|
+
this.state.errorMessage = void 0;
|
|
1651
|
+
}
|
|
1468
1652
|
};
|
|
1469
|
-
|
|
1470
|
-
// src/index.ts
|
|
1471
|
-
var import_agno_types3 = require("@antipopp/agno-types");
|
|
1472
1653
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1473
1654
|
0 && (module.exports = {
|
|
1474
1655
|
AgnoClient,
|