@antipopp/agno-client 0.9.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/dist/index.d.mts +18 -7
- package/dist/index.d.ts +18 -7
- package/dist/index.js +373 -274
- package/dist/index.mjs +375 -274
- package/package.json +8 -4
package/dist/index.mjs
CHANGED
|
@@ -1,85 +1,9 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { RunEvent as RunEvent2 } from "@antipopp/agno-types";
|
|
3
|
+
|
|
1
4
|
// src/client.ts
|
|
2
|
-
import EventEmitter from "eventemitter3";
|
|
3
5
|
import { RunEvent } from "@antipopp/agno-types";
|
|
4
|
-
|
|
5
|
-
// src/stores/message-store.ts
|
|
6
|
-
var MessageStore = class {
|
|
7
|
-
constructor() {
|
|
8
|
-
this.messages = [];
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Get all messages
|
|
12
|
-
*/
|
|
13
|
-
getMessages() {
|
|
14
|
-
return [...this.messages];
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Set messages (replaces all)
|
|
18
|
-
*/
|
|
19
|
-
setMessages(messages) {
|
|
20
|
-
this.messages = [...messages];
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Add a message
|
|
24
|
-
*/
|
|
25
|
-
addMessage(message) {
|
|
26
|
-
this.messages = [...this.messages, message];
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Update the last message
|
|
30
|
-
*/
|
|
31
|
-
updateLastMessage(updater) {
|
|
32
|
-
if (this.messages.length === 0)
|
|
33
|
-
return void 0;
|
|
34
|
-
const lastMessage = this.messages[this.messages.length - 1];
|
|
35
|
-
const updatedMessage = updater(lastMessage);
|
|
36
|
-
this.messages = [
|
|
37
|
-
...this.messages.slice(0, -1),
|
|
38
|
-
updatedMessage
|
|
39
|
-
];
|
|
40
|
-
return updatedMessage;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Update a specific message by index
|
|
44
|
-
*/
|
|
45
|
-
updateMessage(index, updater) {
|
|
46
|
-
if (index < 0 || index >= this.messages.length)
|
|
47
|
-
return void 0;
|
|
48
|
-
const message = this.messages[index];
|
|
49
|
-
const updatedMessage = updater(message);
|
|
50
|
-
this.messages = [
|
|
51
|
-
...this.messages.slice(0, index),
|
|
52
|
-
updatedMessage,
|
|
53
|
-
...this.messages.slice(index + 1)
|
|
54
|
-
];
|
|
55
|
-
return updatedMessage;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Remove last N messages
|
|
59
|
-
*/
|
|
60
|
-
removeLastMessages(count) {
|
|
61
|
-
this.messages = this.messages.slice(0, -count);
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Clear all messages
|
|
65
|
-
*/
|
|
66
|
-
clear() {
|
|
67
|
-
this.messages = [];
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Get the last message
|
|
71
|
-
*/
|
|
72
|
-
getLastMessage() {
|
|
73
|
-
return this.messages.length > 0 ? this.messages[this.messages.length - 1] : void 0;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Check if last message has streaming error
|
|
77
|
-
*/
|
|
78
|
-
hasLastMessageError() {
|
|
79
|
-
const lastMessage = this.getLastMessage();
|
|
80
|
-
return lastMessage?.streamingError === true;
|
|
81
|
-
}
|
|
82
|
-
};
|
|
6
|
+
import EventEmitter from "eventemitter3";
|
|
83
7
|
|
|
84
8
|
// src/managers/config-manager.ts
|
|
85
9
|
var ConfigManager = class {
|
|
@@ -237,14 +161,14 @@ var ConfigManager = class {
|
|
|
237
161
|
const mode = this.getMode();
|
|
238
162
|
const endpoint = this.getEndpoint();
|
|
239
163
|
const entityId = this.getCurrentEntityId();
|
|
240
|
-
if (!entityId)
|
|
164
|
+
if (!entityId) {
|
|
241
165
|
return null;
|
|
166
|
+
}
|
|
242
167
|
const encodedEntityId = encodeURIComponent(entityId);
|
|
243
168
|
if (mode === "team") {
|
|
244
169
|
return `${endpoint}/teams/${encodedEntityId}/runs`;
|
|
245
|
-
} else {
|
|
246
|
-
return `${endpoint}/agents/${encodedEntityId}/runs`;
|
|
247
170
|
}
|
|
171
|
+
return `${endpoint}/agents/${encodedEntityId}/runs`;
|
|
248
172
|
}
|
|
249
173
|
/**
|
|
250
174
|
* Build request headers by merging global headers, per-request headers, and auth token.
|
|
@@ -267,7 +191,7 @@ var ConfigManager = class {
|
|
|
267
191
|
}
|
|
268
192
|
const authToken = this.getAuthToken();
|
|
269
193
|
if (authToken) {
|
|
270
|
-
headers
|
|
194
|
+
headers.Authorization = `Bearer ${authToken}`;
|
|
271
195
|
}
|
|
272
196
|
return headers;
|
|
273
197
|
}
|
|
@@ -413,7 +337,9 @@ var SessionManager = class {
|
|
|
413
337
|
tool_name: reasoningMsg.tool_name ?? "",
|
|
414
338
|
tool_args: reasoningMsg.tool_args ?? {},
|
|
415
339
|
tool_call_error: reasoningMsg.tool_call_error ?? false,
|
|
416
|
-
metrics: reasoningMsg.metrics ?? {
|
|
340
|
+
metrics: reasoningMsg.metrics ?? {
|
|
341
|
+
time: 0
|
|
342
|
+
},
|
|
417
343
|
created_at: reasoningMsg.created_at ?? timestamp
|
|
418
344
|
});
|
|
419
345
|
}
|
|
@@ -447,6 +373,164 @@ var SessionManager = class {
|
|
|
447
373
|
}
|
|
448
374
|
};
|
|
449
375
|
|
|
376
|
+
// src/parsers/stream-parser.ts
|
|
377
|
+
function isLegacyFormat(data) {
|
|
378
|
+
return typeof data === "object" && data !== null && "event" in data && !("data" in data) && typeof data.event === "string";
|
|
379
|
+
}
|
|
380
|
+
function convertNewFormatToLegacy(newFormatData) {
|
|
381
|
+
const { event, data } = newFormatData;
|
|
382
|
+
let parsedData;
|
|
383
|
+
if (typeof data === "string") {
|
|
384
|
+
try {
|
|
385
|
+
parsedData = JSON.parse(data);
|
|
386
|
+
} catch {
|
|
387
|
+
parsedData = {};
|
|
388
|
+
}
|
|
389
|
+
} else {
|
|
390
|
+
parsedData = data;
|
|
391
|
+
}
|
|
392
|
+
return {
|
|
393
|
+
event,
|
|
394
|
+
...parsedData
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
function processChunk(chunk, onChunk) {
|
|
398
|
+
onChunk(chunk);
|
|
399
|
+
}
|
|
400
|
+
function parseBuffer(buffer, onChunk) {
|
|
401
|
+
let currentIndex = 0;
|
|
402
|
+
let jsonStartIndex = buffer.indexOf("{", currentIndex);
|
|
403
|
+
while (jsonStartIndex !== -1 && jsonStartIndex < buffer.length) {
|
|
404
|
+
let braceCount = 0;
|
|
405
|
+
let inString = false;
|
|
406
|
+
let escapeNext = false;
|
|
407
|
+
let jsonEndIndex = -1;
|
|
408
|
+
let i = jsonStartIndex;
|
|
409
|
+
for (; i < buffer.length; i++) {
|
|
410
|
+
const char = buffer[i];
|
|
411
|
+
if (inString) {
|
|
412
|
+
if (escapeNext) {
|
|
413
|
+
escapeNext = false;
|
|
414
|
+
} else if (char === "\\") {
|
|
415
|
+
escapeNext = true;
|
|
416
|
+
} else if (char === '"') {
|
|
417
|
+
inString = false;
|
|
418
|
+
}
|
|
419
|
+
} else if (char === '"') {
|
|
420
|
+
inString = true;
|
|
421
|
+
} else if (char === "{") {
|
|
422
|
+
braceCount++;
|
|
423
|
+
} else if (char === "}") {
|
|
424
|
+
braceCount--;
|
|
425
|
+
if (braceCount === 0) {
|
|
426
|
+
jsonEndIndex = i;
|
|
427
|
+
break;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
if (jsonEndIndex !== -1) {
|
|
432
|
+
const jsonString = buffer.slice(jsonStartIndex, jsonEndIndex + 1);
|
|
433
|
+
try {
|
|
434
|
+
const parsed = JSON.parse(jsonString);
|
|
435
|
+
if (isLegacyFormat(parsed)) {
|
|
436
|
+
processChunk(parsed, onChunk);
|
|
437
|
+
} else {
|
|
438
|
+
const legacyChunk = convertNewFormatToLegacy(parsed);
|
|
439
|
+
processChunk(legacyChunk, onChunk);
|
|
440
|
+
}
|
|
441
|
+
} catch (error) {
|
|
442
|
+
if (typeof process !== "undefined" && process.env?.NODE_ENV === "development") {
|
|
443
|
+
console.error("Failed to parse JSON chunk:", {
|
|
444
|
+
error,
|
|
445
|
+
chunk: jsonString.substring(0, 100) + (jsonString.length > 100 ? "..." : ""),
|
|
446
|
+
position: jsonStartIndex
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
if (jsonString.length > 1e4) {
|
|
450
|
+
throw new Error(
|
|
451
|
+
`Failed to parse large JSON chunk at position ${jsonStartIndex}`
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
jsonStartIndex = buffer.indexOf("{", jsonStartIndex + 1);
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
currentIndex = jsonEndIndex + 1;
|
|
458
|
+
buffer = buffer.slice(currentIndex).trim();
|
|
459
|
+
currentIndex = 0;
|
|
460
|
+
jsonStartIndex = buffer.indexOf("{", currentIndex);
|
|
461
|
+
} else {
|
|
462
|
+
break;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
return buffer;
|
|
466
|
+
}
|
|
467
|
+
async function streamResponse(options) {
|
|
468
|
+
const {
|
|
469
|
+
apiUrl,
|
|
470
|
+
headers = {},
|
|
471
|
+
params,
|
|
472
|
+
requestBody,
|
|
473
|
+
onChunk,
|
|
474
|
+
onError,
|
|
475
|
+
onComplete,
|
|
476
|
+
signal
|
|
477
|
+
} = options;
|
|
478
|
+
let buffer = "";
|
|
479
|
+
const finalUrl = params?.toString() ? `${apiUrl}?${params.toString()}` : apiUrl;
|
|
480
|
+
try {
|
|
481
|
+
const response = await fetch(finalUrl, {
|
|
482
|
+
method: "POST",
|
|
483
|
+
headers: {
|
|
484
|
+
...!(requestBody instanceof FormData) && {
|
|
485
|
+
"Content-Type": "application/json"
|
|
486
|
+
},
|
|
487
|
+
...headers
|
|
488
|
+
},
|
|
489
|
+
body: requestBody instanceof FormData ? requestBody : JSON.stringify(requestBody),
|
|
490
|
+
signal
|
|
491
|
+
});
|
|
492
|
+
if (!response.ok) {
|
|
493
|
+
let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
|
494
|
+
const contentType = response.headers.get("content-type");
|
|
495
|
+
if (contentType?.includes("application/json")) {
|
|
496
|
+
try {
|
|
497
|
+
const errorData = await response.json();
|
|
498
|
+
errorMessage = errorData.detail || errorData.message || errorMessage;
|
|
499
|
+
} catch {
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
throw new Error(errorMessage);
|
|
503
|
+
}
|
|
504
|
+
if (!response.body) {
|
|
505
|
+
throw new Error("No response body");
|
|
506
|
+
}
|
|
507
|
+
const reader = response.body.getReader();
|
|
508
|
+
const decoder = new TextDecoder();
|
|
509
|
+
const processStream = async () => {
|
|
510
|
+
while (true) {
|
|
511
|
+
const { done, value } = await reader.read();
|
|
512
|
+
if (done) {
|
|
513
|
+
buffer = parseBuffer(buffer, onChunk);
|
|
514
|
+
onComplete();
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
buffer += decoder.decode(value, { stream: true });
|
|
518
|
+
buffer = parseBuffer(buffer, onChunk);
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
await processStream();
|
|
522
|
+
} catch (error) {
|
|
523
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
if (typeof error === "object" && error !== null && "detail" in error) {
|
|
527
|
+
onError(new Error(String(error.detail)));
|
|
528
|
+
} else {
|
|
529
|
+
onError(new Error(String(error)));
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
450
534
|
// src/processors/event-processor.ts
|
|
451
535
|
import { RunEvent as RunEventEnum } from "@antipopp/agno-types";
|
|
452
536
|
|
|
@@ -475,9 +559,8 @@ function processToolCall(toolCall, prevToolCalls = []) {
|
|
|
475
559
|
...toolCall
|
|
476
560
|
};
|
|
477
561
|
return updatedToolCalls;
|
|
478
|
-
} else {
|
|
479
|
-
return [...prevToolCalls, toolCall];
|
|
480
562
|
}
|
|
563
|
+
return [...prevToolCalls, toolCall];
|
|
481
564
|
}
|
|
482
565
|
function processChunkToolCalls(chunk, existingToolCalls = []) {
|
|
483
566
|
let updatedToolCalls = [...existingToolCalls];
|
|
@@ -565,7 +648,7 @@ var EventProcessor = class {
|
|
|
565
648
|
}
|
|
566
649
|
break;
|
|
567
650
|
case RunEventEnum.ReasoningStep:
|
|
568
|
-
case RunEventEnum.TeamReasoningStep:
|
|
651
|
+
case RunEventEnum.TeamReasoningStep: {
|
|
569
652
|
const existingSteps = lastMessage.extra_data?.reasoning_steps ?? [];
|
|
570
653
|
const incomingSteps = chunk.extra_data?.reasoning_steps ?? [];
|
|
571
654
|
updatedMessage.extra_data = {
|
|
@@ -573,6 +656,7 @@ var EventProcessor = class {
|
|
|
573
656
|
reasoning_steps: [...existingSteps, ...incomingSteps]
|
|
574
657
|
};
|
|
575
658
|
break;
|
|
659
|
+
}
|
|
576
660
|
case RunEventEnum.ReasoningCompleted:
|
|
577
661
|
case RunEventEnum.TeamReasoningCompleted:
|
|
578
662
|
if (chunk.extra_data?.reasoning_steps) {
|
|
@@ -583,7 +667,7 @@ var EventProcessor = class {
|
|
|
583
667
|
}
|
|
584
668
|
break;
|
|
585
669
|
case RunEventEnum.RunCompleted:
|
|
586
|
-
case RunEventEnum.TeamRunCompleted:
|
|
670
|
+
case RunEventEnum.TeamRunCompleted: {
|
|
587
671
|
let updatedContent;
|
|
588
672
|
if (typeof chunk.content === "string") {
|
|
589
673
|
updatedContent = chunk.content;
|
|
@@ -608,6 +692,7 @@ var EventProcessor = class {
|
|
|
608
692
|
references: chunk.extra_data?.references ?? lastMessage.extra_data?.references
|
|
609
693
|
};
|
|
610
694
|
break;
|
|
695
|
+
}
|
|
611
696
|
case RunEventEnum.UpdatingMemory:
|
|
612
697
|
case RunEventEnum.TeamMemoryUpdateStarted:
|
|
613
698
|
case RunEventEnum.TeamMemoryUpdateCompleted:
|
|
@@ -630,166 +715,95 @@ var EventProcessor = class {
|
|
|
630
715
|
}
|
|
631
716
|
};
|
|
632
717
|
|
|
633
|
-
// src/
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
function convertNewFormatToLegacy(newFormatData) {
|
|
638
|
-
const { event, data } = newFormatData;
|
|
639
|
-
let parsedData;
|
|
640
|
-
if (typeof data === "string") {
|
|
641
|
-
try {
|
|
642
|
-
parsedData = JSON.parse(data);
|
|
643
|
-
} catch {
|
|
644
|
-
parsedData = {};
|
|
645
|
-
}
|
|
646
|
-
} else {
|
|
647
|
-
parsedData = data;
|
|
718
|
+
// src/stores/message-store.ts
|
|
719
|
+
var MessageStore = class {
|
|
720
|
+
constructor() {
|
|
721
|
+
this.messages = [];
|
|
648
722
|
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
function processChunk(chunk, onChunk) {
|
|
655
|
-
onChunk(chunk);
|
|
656
|
-
}
|
|
657
|
-
function parseBuffer(buffer, onChunk) {
|
|
658
|
-
let currentIndex = 0;
|
|
659
|
-
let jsonStartIndex = buffer.indexOf("{", currentIndex);
|
|
660
|
-
while (jsonStartIndex !== -1 && jsonStartIndex < buffer.length) {
|
|
661
|
-
let braceCount = 0;
|
|
662
|
-
let inString = false;
|
|
663
|
-
let escapeNext = false;
|
|
664
|
-
let jsonEndIndex = -1;
|
|
665
|
-
let i = jsonStartIndex;
|
|
666
|
-
for (; i < buffer.length; i++) {
|
|
667
|
-
const char = buffer[i];
|
|
668
|
-
if (inString) {
|
|
669
|
-
if (escapeNext) {
|
|
670
|
-
escapeNext = false;
|
|
671
|
-
} else if (char === "\\") {
|
|
672
|
-
escapeNext = true;
|
|
673
|
-
} else if (char === '"') {
|
|
674
|
-
inString = false;
|
|
675
|
-
}
|
|
676
|
-
} else {
|
|
677
|
-
if (char === '"') {
|
|
678
|
-
inString = true;
|
|
679
|
-
} else if (char === "{") {
|
|
680
|
-
braceCount++;
|
|
681
|
-
} else if (char === "}") {
|
|
682
|
-
braceCount--;
|
|
683
|
-
if (braceCount === 0) {
|
|
684
|
-
jsonEndIndex = i;
|
|
685
|
-
break;
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
if (jsonEndIndex !== -1) {
|
|
691
|
-
const jsonString = buffer.slice(jsonStartIndex, jsonEndIndex + 1);
|
|
692
|
-
try {
|
|
693
|
-
const parsed = JSON.parse(jsonString);
|
|
694
|
-
if (isLegacyFormat(parsed)) {
|
|
695
|
-
processChunk(parsed, onChunk);
|
|
696
|
-
} else {
|
|
697
|
-
const legacyChunk = convertNewFormatToLegacy(parsed);
|
|
698
|
-
processChunk(legacyChunk, onChunk);
|
|
699
|
-
}
|
|
700
|
-
} catch (error) {
|
|
701
|
-
if (typeof process !== "undefined" && process.env?.NODE_ENV === "development") {
|
|
702
|
-
console.error("Failed to parse JSON chunk:", {
|
|
703
|
-
error,
|
|
704
|
-
chunk: jsonString.substring(0, 100) + (jsonString.length > 100 ? "..." : ""),
|
|
705
|
-
position: jsonStartIndex
|
|
706
|
-
});
|
|
707
|
-
}
|
|
708
|
-
if (jsonString.length > 1e4) {
|
|
709
|
-
throw new Error(`Failed to parse large JSON chunk at position ${jsonStartIndex}`);
|
|
710
|
-
}
|
|
711
|
-
jsonStartIndex = buffer.indexOf("{", jsonStartIndex + 1);
|
|
712
|
-
continue;
|
|
713
|
-
}
|
|
714
|
-
currentIndex = jsonEndIndex + 1;
|
|
715
|
-
buffer = buffer.slice(currentIndex).trim();
|
|
716
|
-
currentIndex = 0;
|
|
717
|
-
jsonStartIndex = buffer.indexOf("{", currentIndex);
|
|
718
|
-
} else {
|
|
719
|
-
break;
|
|
720
|
-
}
|
|
723
|
+
/**
|
|
724
|
+
* Get all messages
|
|
725
|
+
*/
|
|
726
|
+
getMessages() {
|
|
727
|
+
return [...this.messages];
|
|
721
728
|
}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
headers: {
|
|
741
|
-
...!(requestBody instanceof FormData) && {
|
|
742
|
-
"Content-Type": "application/json"
|
|
743
|
-
},
|
|
744
|
-
...headers
|
|
745
|
-
},
|
|
746
|
-
body: requestBody instanceof FormData ? requestBody : JSON.stringify(requestBody),
|
|
747
|
-
signal
|
|
748
|
-
});
|
|
749
|
-
if (!response.ok) {
|
|
750
|
-
let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
|
751
|
-
const contentType = response.headers.get("content-type");
|
|
752
|
-
if (contentType?.includes("application/json")) {
|
|
753
|
-
try {
|
|
754
|
-
const errorData = await response.json();
|
|
755
|
-
errorMessage = errorData.detail || errorData.message || errorMessage;
|
|
756
|
-
} catch {
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
throw new Error(errorMessage);
|
|
760
|
-
}
|
|
761
|
-
if (!response.body) {
|
|
762
|
-
throw new Error("No response body");
|
|
729
|
+
/**
|
|
730
|
+
* Set messages (replaces all)
|
|
731
|
+
*/
|
|
732
|
+
setMessages(messages) {
|
|
733
|
+
this.messages = [...messages];
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Add a message
|
|
737
|
+
*/
|
|
738
|
+
addMessage(message) {
|
|
739
|
+
this.messages = [...this.messages, message];
|
|
740
|
+
}
|
|
741
|
+
/**
|
|
742
|
+
* Update the last message
|
|
743
|
+
*/
|
|
744
|
+
updateLastMessage(updater) {
|
|
745
|
+
if (this.messages.length === 0) {
|
|
746
|
+
return void 0;
|
|
763
747
|
}
|
|
764
|
-
const
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
while (true) {
|
|
768
|
-
const { done, value } = await reader.read();
|
|
769
|
-
if (done) {
|
|
770
|
-
buffer = parseBuffer(buffer, onChunk);
|
|
771
|
-
onComplete();
|
|
772
|
-
return;
|
|
773
|
-
}
|
|
774
|
-
buffer += decoder.decode(value, { stream: true });
|
|
775
|
-
buffer = parseBuffer(buffer, onChunk);
|
|
776
|
-
}
|
|
777
|
-
};
|
|
778
|
-
await processStream();
|
|
779
|
-
} catch (error) {
|
|
780
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
781
|
-
return;
|
|
748
|
+
const lastMessage = this.messages.at(-1);
|
|
749
|
+
if (!lastMessage) {
|
|
750
|
+
return void 0;
|
|
782
751
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
752
|
+
const updatedMessage = updater(lastMessage);
|
|
753
|
+
this.messages = [...this.messages.slice(0, -1), updatedMessage];
|
|
754
|
+
return updatedMessage;
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* Update a specific message by index
|
|
758
|
+
*/
|
|
759
|
+
updateMessage(index, updater) {
|
|
760
|
+
if (index < 0 || index >= this.messages.length) {
|
|
761
|
+
return void 0;
|
|
787
762
|
}
|
|
763
|
+
const message = this.messages[index];
|
|
764
|
+
const updatedMessage = updater(message);
|
|
765
|
+
this.messages = [
|
|
766
|
+
...this.messages.slice(0, index),
|
|
767
|
+
updatedMessage,
|
|
768
|
+
...this.messages.slice(index + 1)
|
|
769
|
+
];
|
|
770
|
+
return updatedMessage;
|
|
788
771
|
}
|
|
789
|
-
|
|
772
|
+
/**
|
|
773
|
+
* Remove last N messages
|
|
774
|
+
*/
|
|
775
|
+
removeLastMessages(count) {
|
|
776
|
+
this.messages = this.messages.slice(0, -count);
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* Clear all messages
|
|
780
|
+
*/
|
|
781
|
+
clear() {
|
|
782
|
+
this.messages = [];
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* Get the last message
|
|
786
|
+
*/
|
|
787
|
+
getLastMessage() {
|
|
788
|
+
return this.messages.length > 0 ? this.messages.at(-1) : void 0;
|
|
789
|
+
}
|
|
790
|
+
/**
|
|
791
|
+
* Check if last message has streaming error
|
|
792
|
+
*/
|
|
793
|
+
hasLastMessageError() {
|
|
794
|
+
const lastMessage = this.getLastMessage();
|
|
795
|
+
return lastMessage?.streamingError === true;
|
|
796
|
+
}
|
|
797
|
+
};
|
|
790
798
|
|
|
791
799
|
// src/utils/logger.ts
|
|
792
|
-
var SENSITIVE_KEYS = [
|
|
800
|
+
var SENSITIVE_KEYS = [
|
|
801
|
+
"authToken",
|
|
802
|
+
"Authorization",
|
|
803
|
+
"token",
|
|
804
|
+
"password",
|
|
805
|
+
"apiKey"
|
|
806
|
+
];
|
|
793
807
|
function sanitizeObject(obj) {
|
|
794
808
|
if (obj === null || obj === void 0) {
|
|
795
809
|
return obj;
|
|
@@ -877,6 +891,7 @@ var AgnoClient = class extends EventEmitter {
|
|
|
877
891
|
this.state = {
|
|
878
892
|
isStreaming: false,
|
|
879
893
|
isRefreshing: false,
|
|
894
|
+
isCancelling: false,
|
|
880
895
|
isEndpointActive: false,
|
|
881
896
|
agents: [],
|
|
882
897
|
teams: [],
|
|
@@ -921,6 +936,49 @@ var AgnoClient = class extends EventEmitter {
|
|
|
921
936
|
this.emit("message:update", this.messageStore.getMessages());
|
|
922
937
|
this.emit("state:change", this.getState());
|
|
923
938
|
}
|
|
939
|
+
/**
|
|
940
|
+
* Cancel an active or paused run
|
|
941
|
+
*/
|
|
942
|
+
async cancelRun() {
|
|
943
|
+
if (!(this.state.isStreaming || this.state.isPaused)) {
|
|
944
|
+
throw new Error("No active or paused run to cancel");
|
|
945
|
+
}
|
|
946
|
+
const runUrl = this.configManager.getRunUrl();
|
|
947
|
+
if (!runUrl) {
|
|
948
|
+
throw new Error("No agent or team selected");
|
|
949
|
+
}
|
|
950
|
+
const runId = this.state.pausedRunId || this.currentRunId;
|
|
951
|
+
if (!runId) {
|
|
952
|
+
throw new Error("No run ID available to cancel");
|
|
953
|
+
}
|
|
954
|
+
const cancelUrl = `${runUrl}/${runId}/cancel`;
|
|
955
|
+
const headers = this.configManager.buildRequestHeaders();
|
|
956
|
+
this.state.isCancelling = true;
|
|
957
|
+
this.emit("state:change", this.getState());
|
|
958
|
+
try {
|
|
959
|
+
const response = await fetch(cancelUrl, {
|
|
960
|
+
method: "POST",
|
|
961
|
+
headers
|
|
962
|
+
});
|
|
963
|
+
if (!response.ok) {
|
|
964
|
+
throw new Error("Failed to cancel run");
|
|
965
|
+
}
|
|
966
|
+
this.state.isStreaming = false;
|
|
967
|
+
this.state.isPaused = false;
|
|
968
|
+
this.state.isCancelling = false;
|
|
969
|
+
this.state.pausedRunId = void 0;
|
|
970
|
+
this.state.toolsAwaitingExecution = void 0;
|
|
971
|
+
this.currentRunId = void 0;
|
|
972
|
+
this.emit("run:cancelled", { runId });
|
|
973
|
+
this.emit("state:change", this.getState());
|
|
974
|
+
} catch (error) {
|
|
975
|
+
this.state.isCancelling = false;
|
|
976
|
+
this.emit("state:change", this.getState());
|
|
977
|
+
throw new Error(
|
|
978
|
+
`Error cancelling run: ${error instanceof Error ? error.message : String(error)}`
|
|
979
|
+
);
|
|
980
|
+
}
|
|
981
|
+
}
|
|
924
982
|
/**
|
|
925
983
|
* Send a message to the agent/team (streaming)
|
|
926
984
|
*/
|
|
@@ -978,12 +1036,14 @@ var AgnoClient = class extends EventEmitter {
|
|
|
978
1036
|
params,
|
|
979
1037
|
requestBody: formData,
|
|
980
1038
|
onChunk: (chunk) => {
|
|
981
|
-
this.handleChunk(
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1039
|
+
this.handleChunk(
|
|
1040
|
+
chunk,
|
|
1041
|
+
newSessionId,
|
|
1042
|
+
formData.get("message")
|
|
1043
|
+
);
|
|
1044
|
+
if ((chunk.event === RunEvent.RunStarted || chunk.event === RunEvent.TeamRunStarted || chunk.event === RunEvent.ReasoningStarted || chunk.event === RunEvent.TeamReasoningStarted) && chunk.session_id) {
|
|
1045
|
+
newSessionId = chunk.session_id;
|
|
1046
|
+
this.configManager.setSessionId(chunk.session_id);
|
|
987
1047
|
}
|
|
988
1048
|
},
|
|
989
1049
|
onError: (error) => {
|
|
@@ -991,6 +1051,7 @@ var AgnoClient = class extends EventEmitter {
|
|
|
991
1051
|
},
|
|
992
1052
|
onComplete: async () => {
|
|
993
1053
|
this.state.isStreaming = false;
|
|
1054
|
+
this.currentRunId = void 0;
|
|
994
1055
|
this.emit("stream:end");
|
|
995
1056
|
this.emit("message:complete", this.messageStore.getMessages());
|
|
996
1057
|
this.emit("state:change", this.getState());
|
|
@@ -1012,20 +1073,21 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1012
1073
|
*/
|
|
1013
1074
|
handleChunk(chunk, currentSessionId, messageContent) {
|
|
1014
1075
|
const event = chunk.event;
|
|
1015
|
-
if (event === RunEvent.RunStarted || event === RunEvent.TeamRunStarted
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1076
|
+
if ((event === RunEvent.RunStarted || event === RunEvent.TeamRunStarted) && chunk.run_id) {
|
|
1077
|
+
this.currentRunId = chunk.run_id;
|
|
1078
|
+
}
|
|
1079
|
+
if ((event === RunEvent.RunStarted || event === RunEvent.TeamRunStarted || event === RunEvent.ReasoningStarted || event === RunEvent.TeamReasoningStarted) && chunk.session_id && (!currentSessionId || currentSessionId !== chunk.session_id)) {
|
|
1080
|
+
const sessionData = {
|
|
1081
|
+
session_id: chunk.session_id,
|
|
1082
|
+
session_name: messageContent,
|
|
1083
|
+
created_at: toSafeISOString(chunk.created_at)
|
|
1084
|
+
};
|
|
1085
|
+
const sessionExists = this.state.sessions.some(
|
|
1086
|
+
(s) => s.session_id === chunk.session_id
|
|
1087
|
+
);
|
|
1088
|
+
if (!sessionExists) {
|
|
1089
|
+
this.state.sessions = [sessionData, ...this.state.sessions];
|
|
1090
|
+
this.emit("session:created", sessionData);
|
|
1029
1091
|
}
|
|
1030
1092
|
}
|
|
1031
1093
|
if (event === RunEvent.RunPaused) {
|
|
@@ -1105,7 +1167,10 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1105
1167
|
if (message.tool_calls) {
|
|
1106
1168
|
for (const toolCall of message.tool_calls) {
|
|
1107
1169
|
if (toolCall.ui_component) {
|
|
1108
|
-
existingUIComponents.set(
|
|
1170
|
+
existingUIComponents.set(
|
|
1171
|
+
toolCall.tool_call_id,
|
|
1172
|
+
toolCall.ui_component
|
|
1173
|
+
);
|
|
1109
1174
|
}
|
|
1110
1175
|
}
|
|
1111
1176
|
}
|
|
@@ -1131,7 +1196,9 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1131
1196
|
if (message.tool_calls) {
|
|
1132
1197
|
for (let i = 0; i < message.tool_calls.length; i++) {
|
|
1133
1198
|
const toolCall = message.tool_calls[i];
|
|
1134
|
-
const uiComponent = existingUIComponents.get(
|
|
1199
|
+
const uiComponent = existingUIComponents.get(
|
|
1200
|
+
toolCall.tool_call_id
|
|
1201
|
+
);
|
|
1135
1202
|
if (uiComponent) {
|
|
1136
1203
|
message.tool_calls[i].ui_component = uiComponent;
|
|
1137
1204
|
}
|
|
@@ -1140,12 +1207,18 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1140
1207
|
}
|
|
1141
1208
|
}
|
|
1142
1209
|
this.messageStore.setMessages(messages);
|
|
1143
|
-
Logger.debug(
|
|
1210
|
+
Logger.debug(
|
|
1211
|
+
"[AgnoClient] Session refreshed:",
|
|
1212
|
+
`${messages.length} messages`
|
|
1213
|
+
);
|
|
1144
1214
|
this.emit("message:refreshed", messages);
|
|
1145
1215
|
this.emit("message:update", messages);
|
|
1146
1216
|
} catch (error) {
|
|
1147
1217
|
Logger.error("[AgnoClient] Failed to refresh session:", error);
|
|
1148
|
-
this.emit(
|
|
1218
|
+
this.emit(
|
|
1219
|
+
"message:error",
|
|
1220
|
+
`Session refresh failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1221
|
+
);
|
|
1149
1222
|
} finally {
|
|
1150
1223
|
this.state.isRefreshing = false;
|
|
1151
1224
|
this.emit("state:change", this.getState());
|
|
@@ -1160,7 +1233,11 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1160
1233
|
const entityType = this.configManager.getMode();
|
|
1161
1234
|
const dbId = this.configManager.getDbId() || "";
|
|
1162
1235
|
const userId = this.configManager.getUserId();
|
|
1163
|
-
Logger.debug("[AgnoClient] Loading session with:", {
|
|
1236
|
+
Logger.debug("[AgnoClient] Loading session with:", {
|
|
1237
|
+
entityType,
|
|
1238
|
+
dbId,
|
|
1239
|
+
userId
|
|
1240
|
+
});
|
|
1164
1241
|
const headers = this.configManager.buildRequestHeaders();
|
|
1165
1242
|
const params = this.configManager.buildQueryString(options?.params);
|
|
1166
1243
|
const response = await this.sessionManager.fetchSession(
|
|
@@ -1173,7 +1250,10 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1173
1250
|
params
|
|
1174
1251
|
);
|
|
1175
1252
|
const messages = this.sessionManager.convertSessionToMessages(response);
|
|
1176
|
-
Logger.debug(
|
|
1253
|
+
Logger.debug(
|
|
1254
|
+
"[AgnoClient] Setting messages to store:",
|
|
1255
|
+
`${messages.length} messages`
|
|
1256
|
+
);
|
|
1177
1257
|
this.messageStore.setMessages(messages);
|
|
1178
1258
|
this.configManager.setSessionId(sessionId);
|
|
1179
1259
|
Logger.debug("[AgnoClient] Emitting events...");
|
|
@@ -1242,7 +1322,9 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1242
1322
|
}
|
|
1243
1323
|
const existingToolCalls = lastMessage.tool_calls || [];
|
|
1244
1324
|
const existingIds = new Set(existingToolCalls.map((t) => t.tool_call_id));
|
|
1245
|
-
const newToolCalls = toolCalls.filter(
|
|
1325
|
+
const newToolCalls = toolCalls.filter(
|
|
1326
|
+
(t) => !existingIds.has(t.tool_call_id)
|
|
1327
|
+
);
|
|
1246
1328
|
if (newToolCalls.length > 0) {
|
|
1247
1329
|
this.messageStore.updateLastMessage((msg) => ({
|
|
1248
1330
|
...msg,
|
|
@@ -1289,8 +1371,9 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1289
1371
|
* Batches all updates to emit only one message:update event
|
|
1290
1372
|
*/
|
|
1291
1373
|
applyPendingUISpecs() {
|
|
1292
|
-
if (this.pendingUISpecs.size === 0)
|
|
1374
|
+
if (this.pendingUISpecs.size === 0) {
|
|
1293
1375
|
return;
|
|
1376
|
+
}
|
|
1294
1377
|
const messages = this.messageStore.getMessages();
|
|
1295
1378
|
const updatedMessages = [];
|
|
1296
1379
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
@@ -1345,7 +1428,7 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1345
1428
|
"HITL (Human-in-the-Loop) frontend tool execution is not supported for teams. Only agents support the continue endpoint."
|
|
1346
1429
|
);
|
|
1347
1430
|
}
|
|
1348
|
-
if (!this.state.isPaused
|
|
1431
|
+
if (!(this.state.isPaused && this.state.pausedRunId)) {
|
|
1349
1432
|
throw new Error("No paused run to continue");
|
|
1350
1433
|
}
|
|
1351
1434
|
const runUrl = this.configManager.getRunUrl();
|
|
@@ -1488,7 +1571,7 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1488
1571
|
const currentConfig = this.configManager.getConfig();
|
|
1489
1572
|
const hasAgentConfigured = currentConfig.agentId;
|
|
1490
1573
|
const hasTeamConfigured = currentConfig.teamId;
|
|
1491
|
-
if (!hasAgentConfigured
|
|
1574
|
+
if (!(hasAgentConfigured || hasTeamConfigured)) {
|
|
1492
1575
|
if (agents.length > 0) {
|
|
1493
1576
|
const firstAgent = agents[0];
|
|
1494
1577
|
this.configManager.updateConfig({
|
|
@@ -1509,10 +1592,28 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1509
1592
|
}
|
|
1510
1593
|
return { agents, teams };
|
|
1511
1594
|
}
|
|
1595
|
+
/**
|
|
1596
|
+
* Dispose of the client and clean up all resources.
|
|
1597
|
+
* Call this method when the client is no longer needed to prevent memory leaks.
|
|
1598
|
+
* After calling dispose(), the client instance should not be reused.
|
|
1599
|
+
*/
|
|
1600
|
+
dispose() {
|
|
1601
|
+
this.removeAllListeners();
|
|
1602
|
+
this.messageStore.clear();
|
|
1603
|
+
this.pendingUISpecs.clear();
|
|
1604
|
+
this.eventProcessor.reset();
|
|
1605
|
+
this.state.isStreaming = false;
|
|
1606
|
+
this.state.isRefreshing = false;
|
|
1607
|
+
this.state.isEndpointActive = false;
|
|
1608
|
+
this.state.agents = [];
|
|
1609
|
+
this.state.teams = [];
|
|
1610
|
+
this.state.sessions = [];
|
|
1611
|
+
this.state.isPaused = false;
|
|
1612
|
+
this.state.pausedRunId = void 0;
|
|
1613
|
+
this.state.toolsAwaitingExecution = void 0;
|
|
1614
|
+
this.state.errorMessage = void 0;
|
|
1615
|
+
}
|
|
1512
1616
|
};
|
|
1513
|
-
|
|
1514
|
-
// src/index.ts
|
|
1515
|
-
import { RunEvent as RunEvent2 } from "@antipopp/agno-types";
|
|
1516
1617
|
export {
|
|
1517
1618
|
AgnoClient,
|
|
1518
1619
|
Logger,
|