@antipopp/agno-client 0.2.0 → 0.3.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 CHANGED
@@ -12,6 +12,7 @@ declare class AgnoClient extends EventEmitter {
12
12
  private sessionManager;
13
13
  private eventProcessor;
14
14
  private state;
15
+ private pendingUISpecs;
15
16
  constructor(config: AgnoClientConfig);
16
17
  /**
17
18
  * Get current messages
@@ -63,6 +64,22 @@ declare class AgnoClient extends EventEmitter {
63
64
  * Delete a team session
64
65
  */
65
66
  deleteTeamSession(teamId: string, sessionId: string): Promise<void>;
67
+ /**
68
+ * Add tool calls to the last message
69
+ * Used by frontend execution to add tool calls that were executed locally
70
+ */
71
+ addToolCallsToLastMessage(toolCalls: ToolCall[]): void;
72
+ /**
73
+ * Hydrate a specific tool call with its UI component
74
+ * If tool call doesn't exist yet, stores UI spec as pending
75
+ */
76
+ hydrateToolCallUI(toolCallId: string, uiSpec: any): void;
77
+ /**
78
+ * Apply any pending UI specs to tool calls that have just been added
79
+ * Called after message updates to attach UI to newly arrived tool calls
80
+ * Batches all updates to emit only one message:update event
81
+ */
82
+ private applyPendingUISpecs;
66
83
  /**
67
84
  * Continue a paused run after executing external tools
68
85
  */
package/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@ declare class AgnoClient extends EventEmitter {
12
12
  private sessionManager;
13
13
  private eventProcessor;
14
14
  private state;
15
+ private pendingUISpecs;
15
16
  constructor(config: AgnoClientConfig);
16
17
  /**
17
18
  * Get current messages
@@ -63,6 +64,22 @@ declare class AgnoClient extends EventEmitter {
63
64
  * Delete a team session
64
65
  */
65
66
  deleteTeamSession(teamId: string, sessionId: string): Promise<void>;
67
+ /**
68
+ * Add tool calls to the last message
69
+ * Used by frontend execution to add tool calls that were executed locally
70
+ */
71
+ addToolCallsToLastMessage(toolCalls: ToolCall[]): void;
72
+ /**
73
+ * Hydrate a specific tool call with its UI component
74
+ * If tool call doesn't exist yet, stores UI spec as pending
75
+ */
76
+ hydrateToolCallUI(toolCallId: string, uiSpec: any): void;
77
+ /**
78
+ * Apply any pending UI specs to tool calls that have just been added
79
+ * Called after message updates to attach UI to newly arrived tool calls
80
+ * Batches all updates to emit only one message:update event
81
+ */
82
+ private applyPendingUISpecs;
66
83
  /**
67
84
  * Continue a paused run after executing external tools
68
85
  */
package/dist/index.js CHANGED
@@ -77,6 +77,21 @@ var MessageStore = class {
77
77
  ];
78
78
  return updatedMessage;
79
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
+ }
80
95
  /**
81
96
  * Remove last N messages
82
97
  */
@@ -321,9 +336,7 @@ var SessionManager = class {
321
336
  * Convert session runs array to chat messages
322
337
  */
323
338
  convertSessionToMessages(runs) {
324
- console.log("[SessionManager] convertSessionToMessages received:", runs.length, "runs");
325
339
  const messages = this.convertRunsToMessages(runs);
326
- console.log("[SessionManager] Converted to messages:", messages.length, "messages");
327
340
  return messages;
328
341
  }
329
342
  /**
@@ -345,7 +358,7 @@ var SessionManager = class {
345
358
  if (run.tools && Array.isArray(run.tools)) {
346
359
  for (const tool of run.tools) {
347
360
  const toolObj = tool;
348
- toolCalls.push({
361
+ const toolCall = {
349
362
  role: "tool",
350
363
  content: toolObj.content ?? "",
351
364
  tool_call_id: toolObj.tool_call_id ?? "",
@@ -354,7 +367,8 @@ var SessionManager = class {
354
367
  tool_call_error: toolObj.tool_call_error ?? false,
355
368
  metrics: toolObj.metrics ?? { time: 0 },
356
369
  created_at: timestamp
357
- });
370
+ };
371
+ toolCalls.push(toolCall);
358
372
  }
359
373
  }
360
374
  if (run.reasoning_messages && Array.isArray(run.reasoning_messages)) {
@@ -501,6 +515,28 @@ var EventProcessor = class {
501
515
  references: chunk.extra_data.references
502
516
  };
503
517
  }
518
+ if (chunk.extra_data?.generated_ui) {
519
+ const existingUI = updatedMessage.extra_data?.generated_ui ?? [];
520
+ const incomingUI = chunk.extra_data.generated_ui;
521
+ const mergedUI = [...existingUI];
522
+ for (const uiData of incomingUI) {
523
+ const existingIndex = mergedUI.findIndex(
524
+ (ui) => ui.tool_call_id === uiData.tool_call_id
525
+ );
526
+ if (existingIndex >= 0) {
527
+ mergedUI[existingIndex] = {
528
+ ...mergedUI[existingIndex],
529
+ ...uiData
530
+ };
531
+ } else {
532
+ mergedUI.push(uiData);
533
+ }
534
+ }
535
+ updatedMessage.extra_data = {
536
+ ...updatedMessage.extra_data,
537
+ generated_ui: mergedUI
538
+ };
539
+ }
504
540
  updatedMessage.created_at = chunk.created_at ?? lastMessage.created_at;
505
541
  if (chunk.images) {
506
542
  updatedMessage.images = chunk.images;
@@ -560,7 +596,8 @@ var EventProcessor = class {
560
596
  updatedMessage.created_at = chunk.created_at ?? lastMessage.created_at;
561
597
  updatedMessage.extra_data = {
562
598
  reasoning_steps: chunk.extra_data?.reasoning_steps ?? lastMessage.extra_data?.reasoning_steps,
563
- references: chunk.extra_data?.references ?? lastMessage.extra_data?.references
599
+ references: chunk.extra_data?.references ?? lastMessage.extra_data?.references,
600
+ generated_ui: chunk.extra_data?.generated_ui ?? lastMessage.extra_data?.generated_ui
564
601
  };
565
602
  break;
566
603
  case import_agno_types.RunEvent.UpdatingMemory:
@@ -818,12 +855,14 @@ function toSafeISOString(timestamp) {
818
855
  return new Date(ts).toISOString();
819
856
  }
820
857
  var AgnoClient = class extends import_eventemitter3.default {
858
+ // toolCallId -> UIComponentSpec
821
859
  constructor(config) {
822
860
  super();
823
861
  this.messageStore = new MessageStore();
824
862
  this.configManager = new ConfigManager(config);
825
863
  this.sessionManager = new SessionManager();
826
864
  this.eventProcessor = new EventProcessor();
865
+ this.pendingUISpecs = /* @__PURE__ */ new Map();
827
866
  this.state = {
828
867
  isStreaming: false,
829
868
  isEndpointActive: false,
@@ -866,6 +905,7 @@ var AgnoClient = class extends import_eventemitter3.default {
866
905
  clearMessages() {
867
906
  this.messageStore.clear();
868
907
  this.configManager.setSessionId(void 0);
908
+ this.pendingUISpecs.clear();
869
909
  this.emit("message:update", this.messageStore.getMessages());
870
910
  this.emit("state:change", this.getState());
871
911
  }
@@ -970,18 +1010,10 @@ var AgnoClient = class extends import_eventemitter3.default {
970
1010
  }
971
1011
  }
972
1012
  if (event === import_agno_types2.RunEvent.RunPaused) {
973
- console.log("[AgnoClient] RunPaused event detected");
974
- console.log("[AgnoClient] Chunk:", chunk);
975
- console.log("[AgnoClient] tools_awaiting_external_execution:", chunk.tools_awaiting_external_execution);
976
- console.log("[AgnoClient] tools_requiring_confirmation:", chunk.tools_requiring_confirmation);
977
- console.log("[AgnoClient] tools_requiring_user_input:", chunk.tools_requiring_user_input);
978
- console.log("[AgnoClient] tools:", chunk.tools);
979
1013
  this.state.isStreaming = false;
980
1014
  this.state.isPaused = true;
981
1015
  this.state.pausedRunId = chunk.run_id;
982
1016
  this.state.toolsAwaitingExecution = chunk.tools_awaiting_external_execution || chunk.tools_requiring_confirmation || chunk.tools_requiring_user_input || chunk.tools || [];
983
- console.log("[AgnoClient] toolsAwaitingExecution:", this.state.toolsAwaitingExecution);
984
- console.log("[AgnoClient] Emitting run:paused event");
985
1017
  this.emit("run:paused", {
986
1018
  runId: chunk.run_id,
987
1019
  sessionId: chunk.session_id,
@@ -1009,6 +1041,7 @@ var AgnoClient = class extends import_eventemitter3.default {
1009
1041
  const updated = this.eventProcessor.processChunk(chunk, lastMessage);
1010
1042
  return updated || lastMessage;
1011
1043
  });
1044
+ this.applyPendingUISpecs();
1012
1045
  this.emit("message:update", this.messageStore.getMessages());
1013
1046
  }
1014
1047
  /**
@@ -1118,6 +1151,103 @@ var AgnoClient = class extends import_eventemitter3.default {
1118
1151
  }
1119
1152
  this.emit("state:change", this.getState());
1120
1153
  }
1154
+ /**
1155
+ * Add tool calls to the last message
1156
+ * Used by frontend execution to add tool calls that were executed locally
1157
+ */
1158
+ addToolCallsToLastMessage(toolCalls) {
1159
+ const lastMessage = this.messageStore.getLastMessage();
1160
+ if (!lastMessage || lastMessage.role !== "agent") {
1161
+ return;
1162
+ }
1163
+ const existingToolCalls = lastMessage.tool_calls || [];
1164
+ const existingIds = new Set(existingToolCalls.map((t) => t.tool_call_id));
1165
+ const newToolCalls = toolCalls.filter((t) => !existingIds.has(t.tool_call_id));
1166
+ if (newToolCalls.length > 0) {
1167
+ this.messageStore.updateLastMessage((msg) => ({
1168
+ ...msg,
1169
+ tool_calls: [...existingToolCalls, ...newToolCalls]
1170
+ }));
1171
+ this.emit("message:update", this.messageStore.getMessages());
1172
+ }
1173
+ }
1174
+ /**
1175
+ * Hydrate a specific tool call with its UI component
1176
+ * If tool call doesn't exist yet, stores UI spec as pending
1177
+ */
1178
+ hydrateToolCallUI(toolCallId, uiSpec) {
1179
+ const messages = this.messageStore.getMessages();
1180
+ for (let i = messages.length - 1; i >= 0; i--) {
1181
+ const message = messages[i];
1182
+ if (message.tool_calls) {
1183
+ const toolIndex = message.tool_calls.findIndex(
1184
+ (t) => t.tool_call_id === toolCallId
1185
+ );
1186
+ if (toolIndex !== -1) {
1187
+ this.messageStore.updateMessage(i, (msg) => {
1188
+ const updatedToolCalls = [...msg.tool_calls || []];
1189
+ updatedToolCalls[toolIndex] = {
1190
+ ...updatedToolCalls[toolIndex],
1191
+ ui_component: uiSpec
1192
+ };
1193
+ return {
1194
+ ...msg,
1195
+ tool_calls: updatedToolCalls
1196
+ };
1197
+ });
1198
+ this.pendingUISpecs.delete(toolCallId);
1199
+ this.emit("message:update", this.messageStore.getMessages());
1200
+ return;
1201
+ }
1202
+ }
1203
+ }
1204
+ this.pendingUISpecs.set(toolCallId, uiSpec);
1205
+ }
1206
+ /**
1207
+ * Apply any pending UI specs to tool calls that have just been added
1208
+ * Called after message updates to attach UI to newly arrived tool calls
1209
+ * Batches all updates to emit only one message:update event
1210
+ */
1211
+ applyPendingUISpecs() {
1212
+ if (this.pendingUISpecs.size === 0)
1213
+ return;
1214
+ const messages = this.messageStore.getMessages();
1215
+ const updatedMessages = [];
1216
+ for (let i = messages.length - 1; i >= 0; i--) {
1217
+ const message = messages[i];
1218
+ if (message.tool_calls) {
1219
+ let messageUpdated = false;
1220
+ const updatedToolCalls = [...message.tool_calls];
1221
+ for (let j = 0; j < updatedToolCalls.length; j++) {
1222
+ const toolCall = updatedToolCalls[j];
1223
+ const pendingUI = this.pendingUISpecs.get(toolCall.tool_call_id);
1224
+ if (pendingUI && !toolCall.ui_component) {
1225
+ updatedToolCalls[j] = {
1226
+ ...updatedToolCalls[j],
1227
+ ui_component: pendingUI
1228
+ };
1229
+ this.pendingUISpecs.delete(toolCall.tool_call_id);
1230
+ messageUpdated = true;
1231
+ }
1232
+ }
1233
+ if (messageUpdated) {
1234
+ updatedMessages.push({
1235
+ index: i,
1236
+ message: {
1237
+ ...message,
1238
+ tool_calls: updatedToolCalls
1239
+ }
1240
+ });
1241
+ }
1242
+ }
1243
+ }
1244
+ if (updatedMessages.length > 0) {
1245
+ updatedMessages.forEach(({ index, message }) => {
1246
+ this.messageStore.updateMessage(index, () => message);
1247
+ });
1248
+ this.emit("message:update", this.messageStore.getMessages());
1249
+ }
1250
+ }
1121
1251
  /**
1122
1252
  * Continue a paused run after executing external tools
1123
1253
  */
@@ -1134,8 +1264,12 @@ var AgnoClient = class extends import_eventemitter3.default {
1134
1264
  this.state.isStreaming = true;
1135
1265
  this.emit("run:continued", { runId: this.state.pausedRunId });
1136
1266
  this.emit("state:change", this.getState());
1267
+ const cleanedTools = tools.map((tool) => {
1268
+ const { ui_component, ...backendTool } = tool;
1269
+ return backendTool;
1270
+ });
1137
1271
  const formData = new FormData();
1138
- formData.append("tools", JSON.stringify(tools));
1272
+ formData.append("tools", JSON.stringify(cleanedTools));
1139
1273
  formData.append("stream", "true");
1140
1274
  const currentSessionId = this.configManager.getSessionId();
1141
1275
  if (currentSessionId) {
package/dist/index.mjs CHANGED
@@ -39,6 +39,21 @@ var MessageStore = class {
39
39
  ];
40
40
  return updatedMessage;
41
41
  }
42
+ /**
43
+ * Update a specific message by index
44
+ */
45
+ updateMessage(index, updater) {
46
+ if (index < 0 || index >= this.messages.length)
47
+ return void 0;
48
+ const message = this.messages[index];
49
+ const updatedMessage = updater(message);
50
+ this.messages = [
51
+ ...this.messages.slice(0, index),
52
+ updatedMessage,
53
+ ...this.messages.slice(index + 1)
54
+ ];
55
+ return updatedMessage;
56
+ }
42
57
  /**
43
58
  * Remove last N messages
44
59
  */
@@ -283,9 +298,7 @@ var SessionManager = class {
283
298
  * Convert session runs array to chat messages
284
299
  */
285
300
  convertSessionToMessages(runs) {
286
- console.log("[SessionManager] convertSessionToMessages received:", runs.length, "runs");
287
301
  const messages = this.convertRunsToMessages(runs);
288
- console.log("[SessionManager] Converted to messages:", messages.length, "messages");
289
302
  return messages;
290
303
  }
291
304
  /**
@@ -307,7 +320,7 @@ var SessionManager = class {
307
320
  if (run.tools && Array.isArray(run.tools)) {
308
321
  for (const tool of run.tools) {
309
322
  const toolObj = tool;
310
- toolCalls.push({
323
+ const toolCall = {
311
324
  role: "tool",
312
325
  content: toolObj.content ?? "",
313
326
  tool_call_id: toolObj.tool_call_id ?? "",
@@ -316,7 +329,8 @@ var SessionManager = class {
316
329
  tool_call_error: toolObj.tool_call_error ?? false,
317
330
  metrics: toolObj.metrics ?? { time: 0 },
318
331
  created_at: timestamp
319
- });
332
+ };
333
+ toolCalls.push(toolCall);
320
334
  }
321
335
  }
322
336
  if (run.reasoning_messages && Array.isArray(run.reasoning_messages)) {
@@ -463,6 +477,28 @@ var EventProcessor = class {
463
477
  references: chunk.extra_data.references
464
478
  };
465
479
  }
480
+ if (chunk.extra_data?.generated_ui) {
481
+ const existingUI = updatedMessage.extra_data?.generated_ui ?? [];
482
+ const incomingUI = chunk.extra_data.generated_ui;
483
+ const mergedUI = [...existingUI];
484
+ for (const uiData of incomingUI) {
485
+ const existingIndex = mergedUI.findIndex(
486
+ (ui) => ui.tool_call_id === uiData.tool_call_id
487
+ );
488
+ if (existingIndex >= 0) {
489
+ mergedUI[existingIndex] = {
490
+ ...mergedUI[existingIndex],
491
+ ...uiData
492
+ };
493
+ } else {
494
+ mergedUI.push(uiData);
495
+ }
496
+ }
497
+ updatedMessage.extra_data = {
498
+ ...updatedMessage.extra_data,
499
+ generated_ui: mergedUI
500
+ };
501
+ }
466
502
  updatedMessage.created_at = chunk.created_at ?? lastMessage.created_at;
467
503
  if (chunk.images) {
468
504
  updatedMessage.images = chunk.images;
@@ -522,7 +558,8 @@ var EventProcessor = class {
522
558
  updatedMessage.created_at = chunk.created_at ?? lastMessage.created_at;
523
559
  updatedMessage.extra_data = {
524
560
  reasoning_steps: chunk.extra_data?.reasoning_steps ?? lastMessage.extra_data?.reasoning_steps,
525
- references: chunk.extra_data?.references ?? lastMessage.extra_data?.references
561
+ references: chunk.extra_data?.references ?? lastMessage.extra_data?.references,
562
+ generated_ui: chunk.extra_data?.generated_ui ?? lastMessage.extra_data?.generated_ui
526
563
  };
527
564
  break;
528
565
  case RunEventEnum.UpdatingMemory:
@@ -780,12 +817,14 @@ function toSafeISOString(timestamp) {
780
817
  return new Date(ts).toISOString();
781
818
  }
782
819
  var AgnoClient = class extends EventEmitter {
820
+ // toolCallId -> UIComponentSpec
783
821
  constructor(config) {
784
822
  super();
785
823
  this.messageStore = new MessageStore();
786
824
  this.configManager = new ConfigManager(config);
787
825
  this.sessionManager = new SessionManager();
788
826
  this.eventProcessor = new EventProcessor();
827
+ this.pendingUISpecs = /* @__PURE__ */ new Map();
789
828
  this.state = {
790
829
  isStreaming: false,
791
830
  isEndpointActive: false,
@@ -828,6 +867,7 @@ var AgnoClient = class extends EventEmitter {
828
867
  clearMessages() {
829
868
  this.messageStore.clear();
830
869
  this.configManager.setSessionId(void 0);
870
+ this.pendingUISpecs.clear();
831
871
  this.emit("message:update", this.messageStore.getMessages());
832
872
  this.emit("state:change", this.getState());
833
873
  }
@@ -932,18 +972,10 @@ var AgnoClient = class extends EventEmitter {
932
972
  }
933
973
  }
934
974
  if (event === RunEvent.RunPaused) {
935
- console.log("[AgnoClient] RunPaused event detected");
936
- console.log("[AgnoClient] Chunk:", chunk);
937
- console.log("[AgnoClient] tools_awaiting_external_execution:", chunk.tools_awaiting_external_execution);
938
- console.log("[AgnoClient] tools_requiring_confirmation:", chunk.tools_requiring_confirmation);
939
- console.log("[AgnoClient] tools_requiring_user_input:", chunk.tools_requiring_user_input);
940
- console.log("[AgnoClient] tools:", chunk.tools);
941
975
  this.state.isStreaming = false;
942
976
  this.state.isPaused = true;
943
977
  this.state.pausedRunId = chunk.run_id;
944
978
  this.state.toolsAwaitingExecution = chunk.tools_awaiting_external_execution || chunk.tools_requiring_confirmation || chunk.tools_requiring_user_input || chunk.tools || [];
945
- console.log("[AgnoClient] toolsAwaitingExecution:", this.state.toolsAwaitingExecution);
946
- console.log("[AgnoClient] Emitting run:paused event");
947
979
  this.emit("run:paused", {
948
980
  runId: chunk.run_id,
949
981
  sessionId: chunk.session_id,
@@ -971,6 +1003,7 @@ var AgnoClient = class extends EventEmitter {
971
1003
  const updated = this.eventProcessor.processChunk(chunk, lastMessage);
972
1004
  return updated || lastMessage;
973
1005
  });
1006
+ this.applyPendingUISpecs();
974
1007
  this.emit("message:update", this.messageStore.getMessages());
975
1008
  }
976
1009
  /**
@@ -1080,6 +1113,103 @@ var AgnoClient = class extends EventEmitter {
1080
1113
  }
1081
1114
  this.emit("state:change", this.getState());
1082
1115
  }
1116
+ /**
1117
+ * Add tool calls to the last message
1118
+ * Used by frontend execution to add tool calls that were executed locally
1119
+ */
1120
+ addToolCallsToLastMessage(toolCalls) {
1121
+ const lastMessage = this.messageStore.getLastMessage();
1122
+ if (!lastMessage || lastMessage.role !== "agent") {
1123
+ return;
1124
+ }
1125
+ const existingToolCalls = lastMessage.tool_calls || [];
1126
+ const existingIds = new Set(existingToolCalls.map((t) => t.tool_call_id));
1127
+ const newToolCalls = toolCalls.filter((t) => !existingIds.has(t.tool_call_id));
1128
+ if (newToolCalls.length > 0) {
1129
+ this.messageStore.updateLastMessage((msg) => ({
1130
+ ...msg,
1131
+ tool_calls: [...existingToolCalls, ...newToolCalls]
1132
+ }));
1133
+ this.emit("message:update", this.messageStore.getMessages());
1134
+ }
1135
+ }
1136
+ /**
1137
+ * Hydrate a specific tool call with its UI component
1138
+ * If tool call doesn't exist yet, stores UI spec as pending
1139
+ */
1140
+ hydrateToolCallUI(toolCallId, uiSpec) {
1141
+ const messages = this.messageStore.getMessages();
1142
+ for (let i = messages.length - 1; i >= 0; i--) {
1143
+ const message = messages[i];
1144
+ if (message.tool_calls) {
1145
+ const toolIndex = message.tool_calls.findIndex(
1146
+ (t) => t.tool_call_id === toolCallId
1147
+ );
1148
+ if (toolIndex !== -1) {
1149
+ this.messageStore.updateMessage(i, (msg) => {
1150
+ const updatedToolCalls = [...msg.tool_calls || []];
1151
+ updatedToolCalls[toolIndex] = {
1152
+ ...updatedToolCalls[toolIndex],
1153
+ ui_component: uiSpec
1154
+ };
1155
+ return {
1156
+ ...msg,
1157
+ tool_calls: updatedToolCalls
1158
+ };
1159
+ });
1160
+ this.pendingUISpecs.delete(toolCallId);
1161
+ this.emit("message:update", this.messageStore.getMessages());
1162
+ return;
1163
+ }
1164
+ }
1165
+ }
1166
+ this.pendingUISpecs.set(toolCallId, uiSpec);
1167
+ }
1168
+ /**
1169
+ * Apply any pending UI specs to tool calls that have just been added
1170
+ * Called after message updates to attach UI to newly arrived tool calls
1171
+ * Batches all updates to emit only one message:update event
1172
+ */
1173
+ applyPendingUISpecs() {
1174
+ if (this.pendingUISpecs.size === 0)
1175
+ return;
1176
+ const messages = this.messageStore.getMessages();
1177
+ const updatedMessages = [];
1178
+ for (let i = messages.length - 1; i >= 0; i--) {
1179
+ const message = messages[i];
1180
+ if (message.tool_calls) {
1181
+ let messageUpdated = false;
1182
+ const updatedToolCalls = [...message.tool_calls];
1183
+ for (let j = 0; j < updatedToolCalls.length; j++) {
1184
+ const toolCall = updatedToolCalls[j];
1185
+ const pendingUI = this.pendingUISpecs.get(toolCall.tool_call_id);
1186
+ if (pendingUI && !toolCall.ui_component) {
1187
+ updatedToolCalls[j] = {
1188
+ ...updatedToolCalls[j],
1189
+ ui_component: pendingUI
1190
+ };
1191
+ this.pendingUISpecs.delete(toolCall.tool_call_id);
1192
+ messageUpdated = true;
1193
+ }
1194
+ }
1195
+ if (messageUpdated) {
1196
+ updatedMessages.push({
1197
+ index: i,
1198
+ message: {
1199
+ ...message,
1200
+ tool_calls: updatedToolCalls
1201
+ }
1202
+ });
1203
+ }
1204
+ }
1205
+ }
1206
+ if (updatedMessages.length > 0) {
1207
+ updatedMessages.forEach(({ index, message }) => {
1208
+ this.messageStore.updateMessage(index, () => message);
1209
+ });
1210
+ this.emit("message:update", this.messageStore.getMessages());
1211
+ }
1212
+ }
1083
1213
  /**
1084
1214
  * Continue a paused run after executing external tools
1085
1215
  */
@@ -1096,8 +1226,12 @@ var AgnoClient = class extends EventEmitter {
1096
1226
  this.state.isStreaming = true;
1097
1227
  this.emit("run:continued", { runId: this.state.pausedRunId });
1098
1228
  this.emit("state:change", this.getState());
1229
+ const cleanedTools = tools.map((tool) => {
1230
+ const { ui_component, ...backendTool } = tool;
1231
+ return backendTool;
1232
+ });
1099
1233
  const formData = new FormData();
1100
- formData.append("tools", JSON.stringify(tools));
1234
+ formData.append("tools", JSON.stringify(cleanedTools));
1101
1235
  formData.append("stream", "true");
1102
1236
  const currentSessionId = this.configManager.getSessionId();
1103
1237
  if (currentSessionId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antipopp/agno-client",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Core client library for Agno agents with streaming support and HITL frontend tool execution",
5
5
  "author": "antipopp",
6
6
  "license": "MIT",
@@ -34,7 +34,7 @@
34
34
  ],
35
35
  "dependencies": {
36
36
  "eventemitter3": "^5.0.1",
37
- "@antipopp/agno-types": "0.2.0"
37
+ "@antipopp/agno-types": "0.3.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "tsup": "^8.0.1",