@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.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 {
|
|
@@ -275,14 +197,14 @@ var ConfigManager = class {
|
|
|
275
197
|
const mode = this.getMode();
|
|
276
198
|
const endpoint = this.getEndpoint();
|
|
277
199
|
const entityId = this.getCurrentEntityId();
|
|
278
|
-
if (!entityId)
|
|
200
|
+
if (!entityId) {
|
|
279
201
|
return null;
|
|
202
|
+
}
|
|
280
203
|
const encodedEntityId = encodeURIComponent(entityId);
|
|
281
204
|
if (mode === "team") {
|
|
282
205
|
return `${endpoint}/teams/${encodedEntityId}/runs`;
|
|
283
|
-
} else {
|
|
284
|
-
return `${endpoint}/agents/${encodedEntityId}/runs`;
|
|
285
206
|
}
|
|
207
|
+
return `${endpoint}/agents/${encodedEntityId}/runs`;
|
|
286
208
|
}
|
|
287
209
|
/**
|
|
288
210
|
* Build request headers by merging global headers, per-request headers, and auth token.
|
|
@@ -305,7 +227,7 @@ var ConfigManager = class {
|
|
|
305
227
|
}
|
|
306
228
|
const authToken = this.getAuthToken();
|
|
307
229
|
if (authToken) {
|
|
308
|
-
headers
|
|
230
|
+
headers.Authorization = `Bearer ${authToken}`;
|
|
309
231
|
}
|
|
310
232
|
return headers;
|
|
311
233
|
}
|
|
@@ -451,7 +373,9 @@ var SessionManager = class {
|
|
|
451
373
|
tool_name: reasoningMsg.tool_name ?? "",
|
|
452
374
|
tool_args: reasoningMsg.tool_args ?? {},
|
|
453
375
|
tool_call_error: reasoningMsg.tool_call_error ?? false,
|
|
454
|
-
metrics: reasoningMsg.metrics ?? {
|
|
376
|
+
metrics: reasoningMsg.metrics ?? {
|
|
377
|
+
time: 0
|
|
378
|
+
},
|
|
455
379
|
created_at: reasoningMsg.created_at ?? timestamp
|
|
456
380
|
});
|
|
457
381
|
}
|
|
@@ -485,6 +409,164 @@ var SessionManager = class {
|
|
|
485
409
|
}
|
|
486
410
|
};
|
|
487
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
|
+
|
|
488
570
|
// src/processors/event-processor.ts
|
|
489
571
|
var import_agno_types = require("@antipopp/agno-types");
|
|
490
572
|
|
|
@@ -513,9 +595,8 @@ function processToolCall(toolCall, prevToolCalls = []) {
|
|
|
513
595
|
...toolCall
|
|
514
596
|
};
|
|
515
597
|
return updatedToolCalls;
|
|
516
|
-
} else {
|
|
517
|
-
return [...prevToolCalls, toolCall];
|
|
518
598
|
}
|
|
599
|
+
return [...prevToolCalls, toolCall];
|
|
519
600
|
}
|
|
520
601
|
function processChunkToolCalls(chunk, existingToolCalls = []) {
|
|
521
602
|
let updatedToolCalls = [...existingToolCalls];
|
|
@@ -603,7 +684,7 @@ var EventProcessor = class {
|
|
|
603
684
|
}
|
|
604
685
|
break;
|
|
605
686
|
case import_agno_types.RunEvent.ReasoningStep:
|
|
606
|
-
case import_agno_types.RunEvent.TeamReasoningStep:
|
|
687
|
+
case import_agno_types.RunEvent.TeamReasoningStep: {
|
|
607
688
|
const existingSteps = lastMessage.extra_data?.reasoning_steps ?? [];
|
|
608
689
|
const incomingSteps = chunk.extra_data?.reasoning_steps ?? [];
|
|
609
690
|
updatedMessage.extra_data = {
|
|
@@ -611,6 +692,7 @@ var EventProcessor = class {
|
|
|
611
692
|
reasoning_steps: [...existingSteps, ...incomingSteps]
|
|
612
693
|
};
|
|
613
694
|
break;
|
|
695
|
+
}
|
|
614
696
|
case import_agno_types.RunEvent.ReasoningCompleted:
|
|
615
697
|
case import_agno_types.RunEvent.TeamReasoningCompleted:
|
|
616
698
|
if (chunk.extra_data?.reasoning_steps) {
|
|
@@ -621,7 +703,7 @@ var EventProcessor = class {
|
|
|
621
703
|
}
|
|
622
704
|
break;
|
|
623
705
|
case import_agno_types.RunEvent.RunCompleted:
|
|
624
|
-
case import_agno_types.RunEvent.TeamRunCompleted:
|
|
706
|
+
case import_agno_types.RunEvent.TeamRunCompleted: {
|
|
625
707
|
let updatedContent;
|
|
626
708
|
if (typeof chunk.content === "string") {
|
|
627
709
|
updatedContent = chunk.content;
|
|
@@ -646,6 +728,7 @@ var EventProcessor = class {
|
|
|
646
728
|
references: chunk.extra_data?.references ?? lastMessage.extra_data?.references
|
|
647
729
|
};
|
|
648
730
|
break;
|
|
731
|
+
}
|
|
649
732
|
case import_agno_types.RunEvent.UpdatingMemory:
|
|
650
733
|
case import_agno_types.RunEvent.TeamMemoryUpdateStarted:
|
|
651
734
|
case import_agno_types.RunEvent.TeamMemoryUpdateCompleted:
|
|
@@ -668,166 +751,95 @@ var EventProcessor = class {
|
|
|
668
751
|
}
|
|
669
752
|
};
|
|
670
753
|
|
|
671
|
-
// src/
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
function convertNewFormatToLegacy(newFormatData) {
|
|
676
|
-
const { event, data } = newFormatData;
|
|
677
|
-
let parsedData;
|
|
678
|
-
if (typeof data === "string") {
|
|
679
|
-
try {
|
|
680
|
-
parsedData = JSON.parse(data);
|
|
681
|
-
} catch {
|
|
682
|
-
parsedData = {};
|
|
683
|
-
}
|
|
684
|
-
} else {
|
|
685
|
-
parsedData = data;
|
|
754
|
+
// src/stores/message-store.ts
|
|
755
|
+
var MessageStore = class {
|
|
756
|
+
constructor() {
|
|
757
|
+
this.messages = [];
|
|
686
758
|
}
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
function processChunk(chunk, onChunk) {
|
|
693
|
-
onChunk(chunk);
|
|
694
|
-
}
|
|
695
|
-
function parseBuffer(buffer, onChunk) {
|
|
696
|
-
let currentIndex = 0;
|
|
697
|
-
let jsonStartIndex = buffer.indexOf("{", currentIndex);
|
|
698
|
-
while (jsonStartIndex !== -1 && jsonStartIndex < buffer.length) {
|
|
699
|
-
let braceCount = 0;
|
|
700
|
-
let inString = false;
|
|
701
|
-
let escapeNext = false;
|
|
702
|
-
let jsonEndIndex = -1;
|
|
703
|
-
let i = jsonStartIndex;
|
|
704
|
-
for (; i < buffer.length; i++) {
|
|
705
|
-
const char = buffer[i];
|
|
706
|
-
if (inString) {
|
|
707
|
-
if (escapeNext) {
|
|
708
|
-
escapeNext = false;
|
|
709
|
-
} else if (char === "\\") {
|
|
710
|
-
escapeNext = true;
|
|
711
|
-
} else if (char === '"') {
|
|
712
|
-
inString = false;
|
|
713
|
-
}
|
|
714
|
-
} else {
|
|
715
|
-
if (char === '"') {
|
|
716
|
-
inString = true;
|
|
717
|
-
} else if (char === "{") {
|
|
718
|
-
braceCount++;
|
|
719
|
-
} else if (char === "}") {
|
|
720
|
-
braceCount--;
|
|
721
|
-
if (braceCount === 0) {
|
|
722
|
-
jsonEndIndex = i;
|
|
723
|
-
break;
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
if (jsonEndIndex !== -1) {
|
|
729
|
-
const jsonString = buffer.slice(jsonStartIndex, jsonEndIndex + 1);
|
|
730
|
-
try {
|
|
731
|
-
const parsed = JSON.parse(jsonString);
|
|
732
|
-
if (isLegacyFormat(parsed)) {
|
|
733
|
-
processChunk(parsed, onChunk);
|
|
734
|
-
} else {
|
|
735
|
-
const legacyChunk = convertNewFormatToLegacy(parsed);
|
|
736
|
-
processChunk(legacyChunk, onChunk);
|
|
737
|
-
}
|
|
738
|
-
} catch (error) {
|
|
739
|
-
if (typeof process !== "undefined" && process.env?.NODE_ENV === "development") {
|
|
740
|
-
console.error("Failed to parse JSON chunk:", {
|
|
741
|
-
error,
|
|
742
|
-
chunk: jsonString.substring(0, 100) + (jsonString.length > 100 ? "..." : ""),
|
|
743
|
-
position: jsonStartIndex
|
|
744
|
-
});
|
|
745
|
-
}
|
|
746
|
-
if (jsonString.length > 1e4) {
|
|
747
|
-
throw new Error(`Failed to parse large JSON chunk at position ${jsonStartIndex}`);
|
|
748
|
-
}
|
|
749
|
-
jsonStartIndex = buffer.indexOf("{", jsonStartIndex + 1);
|
|
750
|
-
continue;
|
|
751
|
-
}
|
|
752
|
-
currentIndex = jsonEndIndex + 1;
|
|
753
|
-
buffer = buffer.slice(currentIndex).trim();
|
|
754
|
-
currentIndex = 0;
|
|
755
|
-
jsonStartIndex = buffer.indexOf("{", currentIndex);
|
|
756
|
-
} else {
|
|
757
|
-
break;
|
|
758
|
-
}
|
|
759
|
+
/**
|
|
760
|
+
* Get all messages
|
|
761
|
+
*/
|
|
762
|
+
getMessages() {
|
|
763
|
+
return [...this.messages];
|
|
759
764
|
}
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
headers: {
|
|
779
|
-
...!(requestBody instanceof FormData) && {
|
|
780
|
-
"Content-Type": "application/json"
|
|
781
|
-
},
|
|
782
|
-
...headers
|
|
783
|
-
},
|
|
784
|
-
body: requestBody instanceof FormData ? requestBody : JSON.stringify(requestBody),
|
|
785
|
-
signal
|
|
786
|
-
});
|
|
787
|
-
if (!response.ok) {
|
|
788
|
-
let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
|
789
|
-
const contentType = response.headers.get("content-type");
|
|
790
|
-
if (contentType?.includes("application/json")) {
|
|
791
|
-
try {
|
|
792
|
-
const errorData = await response.json();
|
|
793
|
-
errorMessage = errorData.detail || errorData.message || errorMessage;
|
|
794
|
-
} catch {
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
throw new Error(errorMessage);
|
|
798
|
-
}
|
|
799
|
-
if (!response.body) {
|
|
800
|
-
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;
|
|
801
783
|
}
|
|
802
|
-
const
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
while (true) {
|
|
806
|
-
const { done, value } = await reader.read();
|
|
807
|
-
if (done) {
|
|
808
|
-
buffer = parseBuffer(buffer, onChunk);
|
|
809
|
-
onComplete();
|
|
810
|
-
return;
|
|
811
|
-
}
|
|
812
|
-
buffer += decoder.decode(value, { stream: true });
|
|
813
|
-
buffer = parseBuffer(buffer, onChunk);
|
|
814
|
-
}
|
|
815
|
-
};
|
|
816
|
-
await processStream();
|
|
817
|
-
} catch (error) {
|
|
818
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
819
|
-
return;
|
|
784
|
+
const lastMessage = this.messages.at(-1);
|
|
785
|
+
if (!lastMessage) {
|
|
786
|
+
return void 0;
|
|
820
787
|
}
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
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;
|
|
825
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;
|
|
826
807
|
}
|
|
827
|
-
|
|
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
|
+
};
|
|
828
834
|
|
|
829
835
|
// src/utils/logger.ts
|
|
830
|
-
var SENSITIVE_KEYS = [
|
|
836
|
+
var SENSITIVE_KEYS = [
|
|
837
|
+
"authToken",
|
|
838
|
+
"Authorization",
|
|
839
|
+
"token",
|
|
840
|
+
"password",
|
|
841
|
+
"apiKey"
|
|
842
|
+
];
|
|
831
843
|
function sanitizeObject(obj) {
|
|
832
844
|
if (obj === null || obj === void 0) {
|
|
833
845
|
return obj;
|
|
@@ -915,6 +927,7 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
915
927
|
this.state = {
|
|
916
928
|
isStreaming: false,
|
|
917
929
|
isRefreshing: false,
|
|
930
|
+
isCancelling: false,
|
|
918
931
|
isEndpointActive: false,
|
|
919
932
|
agents: [],
|
|
920
933
|
teams: [],
|
|
@@ -959,6 +972,49 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
959
972
|
this.emit("message:update", this.messageStore.getMessages());
|
|
960
973
|
this.emit("state:change", this.getState());
|
|
961
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
|
+
}
|
|
962
1018
|
/**
|
|
963
1019
|
* Send a message to the agent/team (streaming)
|
|
964
1020
|
*/
|
|
@@ -1016,12 +1072,14 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1016
1072
|
params,
|
|
1017
1073
|
requestBody: formData,
|
|
1018
1074
|
onChunk: (chunk) => {
|
|
1019
|
-
this.handleChunk(
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
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);
|
|
1025
1083
|
}
|
|
1026
1084
|
},
|
|
1027
1085
|
onError: (error) => {
|
|
@@ -1029,6 +1087,7 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1029
1087
|
},
|
|
1030
1088
|
onComplete: async () => {
|
|
1031
1089
|
this.state.isStreaming = false;
|
|
1090
|
+
this.currentRunId = void 0;
|
|
1032
1091
|
this.emit("stream:end");
|
|
1033
1092
|
this.emit("message:complete", this.messageStore.getMessages());
|
|
1034
1093
|
this.emit("state:change", this.getState());
|
|
@@ -1050,20 +1109,21 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1050
1109
|
*/
|
|
1051
1110
|
handleChunk(chunk, currentSessionId, messageContent) {
|
|
1052
1111
|
const event = chunk.event;
|
|
1053
|
-
if (event === import_agno_types2.RunEvent.RunStarted || event === import_agno_types2.RunEvent.TeamRunStarted
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
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);
|
|
1067
1127
|
}
|
|
1068
1128
|
}
|
|
1069
1129
|
if (event === import_agno_types2.RunEvent.RunPaused) {
|
|
@@ -1143,7 +1203,10 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1143
1203
|
if (message.tool_calls) {
|
|
1144
1204
|
for (const toolCall of message.tool_calls) {
|
|
1145
1205
|
if (toolCall.ui_component) {
|
|
1146
|
-
existingUIComponents.set(
|
|
1206
|
+
existingUIComponents.set(
|
|
1207
|
+
toolCall.tool_call_id,
|
|
1208
|
+
toolCall.ui_component
|
|
1209
|
+
);
|
|
1147
1210
|
}
|
|
1148
1211
|
}
|
|
1149
1212
|
}
|
|
@@ -1169,7 +1232,9 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1169
1232
|
if (message.tool_calls) {
|
|
1170
1233
|
for (let i = 0; i < message.tool_calls.length; i++) {
|
|
1171
1234
|
const toolCall = message.tool_calls[i];
|
|
1172
|
-
const uiComponent = existingUIComponents.get(
|
|
1235
|
+
const uiComponent = existingUIComponents.get(
|
|
1236
|
+
toolCall.tool_call_id
|
|
1237
|
+
);
|
|
1173
1238
|
if (uiComponent) {
|
|
1174
1239
|
message.tool_calls[i].ui_component = uiComponent;
|
|
1175
1240
|
}
|
|
@@ -1178,12 +1243,18 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1178
1243
|
}
|
|
1179
1244
|
}
|
|
1180
1245
|
this.messageStore.setMessages(messages);
|
|
1181
|
-
Logger.debug(
|
|
1246
|
+
Logger.debug(
|
|
1247
|
+
"[AgnoClient] Session refreshed:",
|
|
1248
|
+
`${messages.length} messages`
|
|
1249
|
+
);
|
|
1182
1250
|
this.emit("message:refreshed", messages);
|
|
1183
1251
|
this.emit("message:update", messages);
|
|
1184
1252
|
} catch (error) {
|
|
1185
1253
|
Logger.error("[AgnoClient] Failed to refresh session:", error);
|
|
1186
|
-
this.emit(
|
|
1254
|
+
this.emit(
|
|
1255
|
+
"message:error",
|
|
1256
|
+
`Session refresh failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1257
|
+
);
|
|
1187
1258
|
} finally {
|
|
1188
1259
|
this.state.isRefreshing = false;
|
|
1189
1260
|
this.emit("state:change", this.getState());
|
|
@@ -1198,7 +1269,11 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1198
1269
|
const entityType = this.configManager.getMode();
|
|
1199
1270
|
const dbId = this.configManager.getDbId() || "";
|
|
1200
1271
|
const userId = this.configManager.getUserId();
|
|
1201
|
-
Logger.debug("[AgnoClient] Loading session with:", {
|
|
1272
|
+
Logger.debug("[AgnoClient] Loading session with:", {
|
|
1273
|
+
entityType,
|
|
1274
|
+
dbId,
|
|
1275
|
+
userId
|
|
1276
|
+
});
|
|
1202
1277
|
const headers = this.configManager.buildRequestHeaders();
|
|
1203
1278
|
const params = this.configManager.buildQueryString(options?.params);
|
|
1204
1279
|
const response = await this.sessionManager.fetchSession(
|
|
@@ -1211,7 +1286,10 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1211
1286
|
params
|
|
1212
1287
|
);
|
|
1213
1288
|
const messages = this.sessionManager.convertSessionToMessages(response);
|
|
1214
|
-
Logger.debug(
|
|
1289
|
+
Logger.debug(
|
|
1290
|
+
"[AgnoClient] Setting messages to store:",
|
|
1291
|
+
`${messages.length} messages`
|
|
1292
|
+
);
|
|
1215
1293
|
this.messageStore.setMessages(messages);
|
|
1216
1294
|
this.configManager.setSessionId(sessionId);
|
|
1217
1295
|
Logger.debug("[AgnoClient] Emitting events...");
|
|
@@ -1280,7 +1358,9 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1280
1358
|
}
|
|
1281
1359
|
const existingToolCalls = lastMessage.tool_calls || [];
|
|
1282
1360
|
const existingIds = new Set(existingToolCalls.map((t) => t.tool_call_id));
|
|
1283
|
-
const newToolCalls = toolCalls.filter(
|
|
1361
|
+
const newToolCalls = toolCalls.filter(
|
|
1362
|
+
(t) => !existingIds.has(t.tool_call_id)
|
|
1363
|
+
);
|
|
1284
1364
|
if (newToolCalls.length > 0) {
|
|
1285
1365
|
this.messageStore.updateLastMessage((msg) => ({
|
|
1286
1366
|
...msg,
|
|
@@ -1327,8 +1407,9 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1327
1407
|
* Batches all updates to emit only one message:update event
|
|
1328
1408
|
*/
|
|
1329
1409
|
applyPendingUISpecs() {
|
|
1330
|
-
if (this.pendingUISpecs.size === 0)
|
|
1410
|
+
if (this.pendingUISpecs.size === 0) {
|
|
1331
1411
|
return;
|
|
1412
|
+
}
|
|
1332
1413
|
const messages = this.messageStore.getMessages();
|
|
1333
1414
|
const updatedMessages = [];
|
|
1334
1415
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
@@ -1383,7 +1464,7 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1383
1464
|
"HITL (Human-in-the-Loop) frontend tool execution is not supported for teams. Only agents support the continue endpoint."
|
|
1384
1465
|
);
|
|
1385
1466
|
}
|
|
1386
|
-
if (!this.state.isPaused
|
|
1467
|
+
if (!(this.state.isPaused && this.state.pausedRunId)) {
|
|
1387
1468
|
throw new Error("No paused run to continue");
|
|
1388
1469
|
}
|
|
1389
1470
|
const runUrl = this.configManager.getRunUrl();
|
|
@@ -1526,7 +1607,7 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1526
1607
|
const currentConfig = this.configManager.getConfig();
|
|
1527
1608
|
const hasAgentConfigured = currentConfig.agentId;
|
|
1528
1609
|
const hasTeamConfigured = currentConfig.teamId;
|
|
1529
|
-
if (!hasAgentConfigured
|
|
1610
|
+
if (!(hasAgentConfigured || hasTeamConfigured)) {
|
|
1530
1611
|
if (agents.length > 0) {
|
|
1531
1612
|
const firstAgent = agents[0];
|
|
1532
1613
|
this.configManager.updateConfig({
|
|
@@ -1547,10 +1628,28 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1547
1628
|
}
|
|
1548
1629
|
return { agents, teams };
|
|
1549
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
|
+
}
|
|
1550
1652
|
};
|
|
1551
|
-
|
|
1552
|
-
// src/index.ts
|
|
1553
|
-
var import_agno_types3 = require("@antipopp/agno-types");
|
|
1554
1653
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1555
1654
|
0 && (module.exports = {
|
|
1556
1655
|
AgnoClient,
|