@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.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["Authorization"] = `Bearer ${authToken}`;
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 ?? { time: 0 },
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/parsers/stream-parser.ts
672
- function isLegacyFormat(data) {
673
- return typeof data === "object" && data !== null && "event" in data && !("data" in data) && typeof data.event === "string";
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
- return {
688
- event,
689
- ...parsedData
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
- return buffer;
761
- }
762
- async function streamResponse(options) {
763
- const {
764
- apiUrl,
765
- headers = {},
766
- params,
767
- requestBody,
768
- onChunk,
769
- onError,
770
- onComplete,
771
- signal
772
- } = options;
773
- let buffer = "";
774
- const finalUrl = params && params.toString() ? `${apiUrl}?${params.toString()}` : apiUrl;
775
- try {
776
- const response = await fetch(finalUrl, {
777
- method: "POST",
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 reader = response.body.getReader();
803
- const decoder = new TextDecoder();
804
- const processStream = async () => {
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
- if (typeof error === "object" && error !== null && "detail" in error) {
822
- onError(new Error(String(error.detail)));
823
- } else {
824
- onError(new Error(String(error)));
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 = ["authToken", "Authorization", "token", "password", "apiKey"];
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(chunk, newSessionId, formData.get("message"));
1020
- 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) {
1021
- if (chunk.session_id) {
1022
- newSessionId = chunk.session_id;
1023
- this.configManager.setSessionId(chunk.session_id);
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 || event === import_agno_types2.RunEvent.ReasoningStarted || event === import_agno_types2.RunEvent.TeamReasoningStarted) {
1054
- if (chunk.session_id && (!currentSessionId || currentSessionId !== chunk.session_id)) {
1055
- const sessionData = {
1056
- session_id: chunk.session_id,
1057
- session_name: messageContent,
1058
- created_at: toSafeISOString(chunk.created_at)
1059
- };
1060
- const sessionExists = this.state.sessions.some(
1061
- (s) => s.session_id === chunk.session_id
1062
- );
1063
- if (!sessionExists) {
1064
- this.state.sessions = [sessionData, ...this.state.sessions];
1065
- this.emit("session:created", sessionData);
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(toolCall.tool_call_id, toolCall.ui_component);
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(toolCall.tool_call_id);
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("[AgnoClient] Session refreshed:", `${messages.length} messages`);
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("message:error", `Session refresh failed: ${error instanceof Error ? error.message : String(error)}`);
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:", { entityType, dbId, userId });
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("[AgnoClient] Setting messages to store:", `${messages.length} messages`);
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((t) => !existingIds.has(t.tool_call_id));
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 || !this.state.pausedRunId) {
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 && !hasTeamConfigured) {
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,