@antipopp/agno-client 0.8.0 → 0.10.0

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