@antipopp/agno-client 0.1.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 +17 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +148 -6
- package/dist/index.mjs +148 -6
- package/package.json +2 -2
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
|
-
|
|
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
|
}
|
|
@@ -1001,6 +1041,7 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1001
1041
|
const updated = this.eventProcessor.processChunk(chunk, lastMessage);
|
|
1002
1042
|
return updated || lastMessage;
|
|
1003
1043
|
});
|
|
1044
|
+
this.applyPendingUISpecs();
|
|
1004
1045
|
this.emit("message:update", this.messageStore.getMessages());
|
|
1005
1046
|
}
|
|
1006
1047
|
/**
|
|
@@ -1110,6 +1151,103 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1110
1151
|
}
|
|
1111
1152
|
this.emit("state:change", this.getState());
|
|
1112
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
|
+
}
|
|
1113
1251
|
/**
|
|
1114
1252
|
* Continue a paused run after executing external tools
|
|
1115
1253
|
*/
|
|
@@ -1126,8 +1264,12 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1126
1264
|
this.state.isStreaming = true;
|
|
1127
1265
|
this.emit("run:continued", { runId: this.state.pausedRunId });
|
|
1128
1266
|
this.emit("state:change", this.getState());
|
|
1267
|
+
const cleanedTools = tools.map((tool) => {
|
|
1268
|
+
const { ui_component, ...backendTool } = tool;
|
|
1269
|
+
return backendTool;
|
|
1270
|
+
});
|
|
1129
1271
|
const formData = new FormData();
|
|
1130
|
-
formData.append("tools", JSON.stringify(
|
|
1272
|
+
formData.append("tools", JSON.stringify(cleanedTools));
|
|
1131
1273
|
formData.append("stream", "true");
|
|
1132
1274
|
const currentSessionId = this.configManager.getSessionId();
|
|
1133
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
|
-
|
|
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
|
}
|
|
@@ -963,6 +1003,7 @@ var AgnoClient = class extends EventEmitter {
|
|
|
963
1003
|
const updated = this.eventProcessor.processChunk(chunk, lastMessage);
|
|
964
1004
|
return updated || lastMessage;
|
|
965
1005
|
});
|
|
1006
|
+
this.applyPendingUISpecs();
|
|
966
1007
|
this.emit("message:update", this.messageStore.getMessages());
|
|
967
1008
|
}
|
|
968
1009
|
/**
|
|
@@ -1072,6 +1113,103 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1072
1113
|
}
|
|
1073
1114
|
this.emit("state:change", this.getState());
|
|
1074
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
|
+
}
|
|
1075
1213
|
/**
|
|
1076
1214
|
* Continue a paused run after executing external tools
|
|
1077
1215
|
*/
|
|
@@ -1088,8 +1226,12 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1088
1226
|
this.state.isStreaming = true;
|
|
1089
1227
|
this.emit("run:continued", { runId: this.state.pausedRunId });
|
|
1090
1228
|
this.emit("state:change", this.getState());
|
|
1229
|
+
const cleanedTools = tools.map((tool) => {
|
|
1230
|
+
const { ui_component, ...backendTool } = tool;
|
|
1231
|
+
return backendTool;
|
|
1232
|
+
});
|
|
1091
1233
|
const formData = new FormData();
|
|
1092
|
-
formData.append("tools", JSON.stringify(
|
|
1234
|
+
formData.append("tools", JSON.stringify(cleanedTools));
|
|
1093
1235
|
formData.append("stream", "true");
|
|
1094
1236
|
const currentSessionId = this.configManager.getSessionId();
|
|
1095
1237
|
if (currentSessionId) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antipopp/agno-client",
|
|
3
|
-
"version": "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.
|
|
37
|
+
"@antipopp/agno-types": "0.3.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"tsup": "^8.0.1",
|