@antipopp/agno-client 0.7.0 → 0.8.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
@@ -13,6 +13,7 @@ declare class AgnoClient extends EventEmitter {
13
13
  private eventProcessor;
14
14
  private state;
15
15
  private pendingUISpecs;
16
+ private runCompletedSuccessfully;
16
17
  constructor(config: AgnoClientConfig);
17
18
  /**
18
19
  * Get current messages
@@ -48,6 +49,13 @@ declare class AgnoClient extends EventEmitter {
48
49
  * Handle error
49
50
  */
50
51
  private handleError;
52
+ /**
53
+ * Refresh messages from the session API after run completion.
54
+ * Replaces streamed messages with authoritative session data.
55
+ * Preserves client-side properties like ui_component that aren't stored on the server.
56
+ * @private
57
+ */
58
+ private refreshSessionMessages;
51
59
  /**
52
60
  * Load a session
53
61
  */
package/dist/index.d.ts CHANGED
@@ -13,6 +13,7 @@ declare class AgnoClient extends EventEmitter {
13
13
  private eventProcessor;
14
14
  private state;
15
15
  private pendingUISpecs;
16
+ private runCompletedSuccessfully;
16
17
  constructor(config: AgnoClientConfig);
17
18
  /**
18
19
  * Get current messages
@@ -48,6 +49,13 @@ declare class AgnoClient extends EventEmitter {
48
49
  * Handle error
49
50
  */
50
51
  private handleError;
52
+ /**
53
+ * Refresh messages from the session API after run completion.
54
+ * Replaces streamed messages with authoritative session data.
55
+ * Preserves client-side properties like ui_component that aren't stored on the server.
56
+ * @private
57
+ */
58
+ private refreshSessionMessages;
51
59
  /**
52
60
  * Load a session
53
61
  */
package/dist/index.js CHANGED
@@ -323,12 +323,15 @@ var SessionManager = class {
323
323
  * Fetch a specific session's runs
324
324
  * Returns an array of RunSchema directly (not wrapped in { data, meta })
325
325
  */
326
- async fetchSession(endpoint, entityType, sessionId, dbId, headers) {
326
+ async fetchSession(endpoint, entityType, sessionId, dbId, headers, userId) {
327
327
  const url = new URL(`${endpoint}/sessions/${sessionId}/runs`);
328
328
  url.searchParams.set("type", entityType);
329
329
  if (dbId) {
330
330
  url.searchParams.set("db_id", dbId);
331
331
  }
332
+ if (userId) {
333
+ url.searchParams.set("user_id", userId);
334
+ }
332
335
  const response = await fetch(url.toString(), { headers });
333
336
  if (!response.ok) {
334
337
  throw new Error(`Failed to fetch session: ${response.statusText}`);
@@ -851,9 +854,10 @@ function toSafeISOString(timestamp) {
851
854
  return new Date(ts).toISOString();
852
855
  }
853
856
  var AgnoClient = class extends import_eventemitter3.default {
854
- // toolCallId -> UIComponentSpec
855
857
  constructor(config) {
856
858
  super();
859
+ // toolCallId -> UIComponentSpec
860
+ this.runCompletedSuccessfully = false;
857
861
  this.messageStore = new MessageStore();
858
862
  this.configManager = new ConfigManager(config);
859
863
  this.sessionManager = new SessionManager();
@@ -861,6 +865,7 @@ var AgnoClient = class extends import_eventemitter3.default {
861
865
  this.pendingUISpecs = /* @__PURE__ */ new Map();
862
866
  this.state = {
863
867
  isStreaming: false,
868
+ isRefreshing: false,
864
869
  isEndpointActive: false,
865
870
  agents: [],
866
871
  teams: [],
@@ -912,6 +917,7 @@ var AgnoClient = class extends import_eventemitter3.default {
912
917
  if (this.state.isStreaming) {
913
918
  throw new Error("Already streaming a message");
914
919
  }
920
+ this.runCompletedSuccessfully = false;
915
921
  const runUrl = this.configManager.getRunUrl();
916
922
  if (!runUrl) {
917
923
  throw new Error("No agent or team selected");
@@ -970,11 +976,15 @@ var AgnoClient = class extends import_eventemitter3.default {
970
976
  onError: (error) => {
971
977
  this.handleError(error, newSessionId);
972
978
  },
973
- onComplete: () => {
979
+ onComplete: async () => {
974
980
  this.state.isStreaming = false;
975
981
  this.emit("stream:end");
976
982
  this.emit("message:complete", this.messageStore.getMessages());
977
983
  this.emit("state:change", this.getState());
984
+ if (this.runCompletedSuccessfully) {
985
+ this.runCompletedSuccessfully = false;
986
+ await this.refreshSessionMessages();
987
+ }
978
988
  }
979
989
  });
980
990
  } catch (error) {
@@ -1038,6 +1048,9 @@ var AgnoClient = class extends import_eventemitter3.default {
1038
1048
  return updated || lastMessage;
1039
1049
  });
1040
1050
  this.applyPendingUISpecs();
1051
+ if (event === import_agno_types2.RunEvent.RunCompleted || event === import_agno_types2.RunEvent.TeamRunCompleted) {
1052
+ this.runCompletedSuccessfully = true;
1053
+ }
1041
1054
  this.emit("message:update", this.messageStore.getMessages());
1042
1055
  }
1043
1056
  /**
@@ -1059,6 +1072,70 @@ var AgnoClient = class extends import_eventemitter3.default {
1059
1072
  this.emit("stream:end");
1060
1073
  this.emit("state:change", this.getState());
1061
1074
  }
1075
+ /**
1076
+ * Refresh messages from the session API after run completion.
1077
+ * Replaces streamed messages with authoritative session data.
1078
+ * Preserves client-side properties like ui_component that aren't stored on the server.
1079
+ * @private
1080
+ */
1081
+ async refreshSessionMessages() {
1082
+ const sessionId = this.configManager.getSessionId();
1083
+ if (!sessionId) {
1084
+ Logger.debug("[AgnoClient] Cannot refresh: no session ID");
1085
+ return;
1086
+ }
1087
+ this.state.isRefreshing = true;
1088
+ this.emit("state:change", this.getState());
1089
+ try {
1090
+ const existingUIComponents = /* @__PURE__ */ new Map();
1091
+ for (const message of this.messageStore.getMessages()) {
1092
+ if (message.tool_calls) {
1093
+ for (const toolCall of message.tool_calls) {
1094
+ if (toolCall.ui_component) {
1095
+ existingUIComponents.set(toolCall.tool_call_id, toolCall.ui_component);
1096
+ }
1097
+ }
1098
+ }
1099
+ }
1100
+ const config = this.configManager.getConfig();
1101
+ const entityType = this.configManager.getMode();
1102
+ const dbId = this.configManager.getDbId() || "";
1103
+ const userId = this.configManager.getUserId();
1104
+ const headers = this.configManager.buildRequestHeaders();
1105
+ const response = await this.sessionManager.fetchSession(
1106
+ config.endpoint,
1107
+ entityType,
1108
+ sessionId,
1109
+ dbId,
1110
+ headers,
1111
+ userId
1112
+ );
1113
+ const messages = this.sessionManager.convertSessionToMessages(response);
1114
+ if (existingUIComponents.size > 0) {
1115
+ for (const message of messages) {
1116
+ if (message.tool_calls) {
1117
+ for (let i = 0; i < message.tool_calls.length; i++) {
1118
+ const toolCall = message.tool_calls[i];
1119
+ const uiComponent = existingUIComponents.get(toolCall.tool_call_id);
1120
+ if (uiComponent) {
1121
+ message.tool_calls[i].ui_component = uiComponent;
1122
+ }
1123
+ }
1124
+ }
1125
+ }
1126
+ }
1127
+ this.messageStore.setMessages(messages);
1128
+ Logger.debug("[AgnoClient] Session refreshed:", `${messages.length} messages`);
1129
+ this.emit("message:refreshed", messages);
1130
+ this.emit("message:update", messages);
1131
+ } catch (error) {
1132
+ Logger.error("[AgnoClient] Failed to refresh session:", error);
1133
+ this.emit("message:error", `Session refresh failed: ${error instanceof Error ? error.message : String(error)}`);
1134
+ } finally {
1135
+ this.state.isRefreshing = false;
1136
+ this.emit("state:change", this.getState());
1137
+ }
1138
+ }
1062
1139
  /**
1063
1140
  * Load a session
1064
1141
  */
@@ -1067,14 +1144,16 @@ var AgnoClient = class extends import_eventemitter3.default {
1067
1144
  const config = this.configManager.getConfig();
1068
1145
  const entityType = this.configManager.getMode();
1069
1146
  const dbId = this.configManager.getDbId() || "";
1070
- Logger.debug("[AgnoClient] Loading session with:", { entityType, dbId });
1147
+ const userId = this.configManager.getUserId();
1148
+ Logger.debug("[AgnoClient] Loading session with:", { entityType, dbId, userId });
1071
1149
  const headers = this.configManager.buildRequestHeaders();
1072
1150
  const response = await this.sessionManager.fetchSession(
1073
1151
  config.endpoint,
1074
1152
  entityType,
1075
1153
  sessionId,
1076
1154
  dbId,
1077
- headers
1155
+ headers,
1156
+ userId
1078
1157
  );
1079
1158
  const messages = this.sessionManager.convertSessionToMessages(response);
1080
1159
  Logger.debug("[AgnoClient] Setting messages to store:", `${messages.length} messages`);
@@ -1284,13 +1363,17 @@ var AgnoClient = class extends import_eventemitter3.default {
1284
1363
  onError: (error) => {
1285
1364
  this.handleError(error, currentSessionId);
1286
1365
  },
1287
- onComplete: () => {
1366
+ onComplete: async () => {
1288
1367
  this.state.isStreaming = false;
1289
1368
  this.state.pausedRunId = void 0;
1290
1369
  this.state.toolsAwaitingExecution = void 0;
1291
1370
  this.emit("stream:end");
1292
1371
  this.emit("message:complete", this.messageStore.getMessages());
1293
1372
  this.emit("state:change", this.getState());
1373
+ if (this.runCompletedSuccessfully) {
1374
+ this.runCompletedSuccessfully = false;
1375
+ await this.refreshSessionMessages();
1376
+ }
1294
1377
  }
1295
1378
  });
1296
1379
  } catch (error) {
package/dist/index.mjs CHANGED
@@ -285,12 +285,15 @@ var SessionManager = class {
285
285
  * Fetch a specific session's runs
286
286
  * Returns an array of RunSchema directly (not wrapped in { data, meta })
287
287
  */
288
- async fetchSession(endpoint, entityType, sessionId, dbId, headers) {
288
+ async fetchSession(endpoint, entityType, sessionId, dbId, headers, userId) {
289
289
  const url = new URL(`${endpoint}/sessions/${sessionId}/runs`);
290
290
  url.searchParams.set("type", entityType);
291
291
  if (dbId) {
292
292
  url.searchParams.set("db_id", dbId);
293
293
  }
294
+ if (userId) {
295
+ url.searchParams.set("user_id", userId);
296
+ }
294
297
  const response = await fetch(url.toString(), { headers });
295
298
  if (!response.ok) {
296
299
  throw new Error(`Failed to fetch session: ${response.statusText}`);
@@ -813,9 +816,10 @@ function toSafeISOString(timestamp) {
813
816
  return new Date(ts).toISOString();
814
817
  }
815
818
  var AgnoClient = class extends EventEmitter {
816
- // toolCallId -> UIComponentSpec
817
819
  constructor(config) {
818
820
  super();
821
+ // toolCallId -> UIComponentSpec
822
+ this.runCompletedSuccessfully = false;
819
823
  this.messageStore = new MessageStore();
820
824
  this.configManager = new ConfigManager(config);
821
825
  this.sessionManager = new SessionManager();
@@ -823,6 +827,7 @@ var AgnoClient = class extends EventEmitter {
823
827
  this.pendingUISpecs = /* @__PURE__ */ new Map();
824
828
  this.state = {
825
829
  isStreaming: false,
830
+ isRefreshing: false,
826
831
  isEndpointActive: false,
827
832
  agents: [],
828
833
  teams: [],
@@ -874,6 +879,7 @@ var AgnoClient = class extends EventEmitter {
874
879
  if (this.state.isStreaming) {
875
880
  throw new Error("Already streaming a message");
876
881
  }
882
+ this.runCompletedSuccessfully = false;
877
883
  const runUrl = this.configManager.getRunUrl();
878
884
  if (!runUrl) {
879
885
  throw new Error("No agent or team selected");
@@ -932,11 +938,15 @@ var AgnoClient = class extends EventEmitter {
932
938
  onError: (error) => {
933
939
  this.handleError(error, newSessionId);
934
940
  },
935
- onComplete: () => {
941
+ onComplete: async () => {
936
942
  this.state.isStreaming = false;
937
943
  this.emit("stream:end");
938
944
  this.emit("message:complete", this.messageStore.getMessages());
939
945
  this.emit("state:change", this.getState());
946
+ if (this.runCompletedSuccessfully) {
947
+ this.runCompletedSuccessfully = false;
948
+ await this.refreshSessionMessages();
949
+ }
940
950
  }
941
951
  });
942
952
  } catch (error) {
@@ -1000,6 +1010,9 @@ var AgnoClient = class extends EventEmitter {
1000
1010
  return updated || lastMessage;
1001
1011
  });
1002
1012
  this.applyPendingUISpecs();
1013
+ if (event === RunEvent.RunCompleted || event === RunEvent.TeamRunCompleted) {
1014
+ this.runCompletedSuccessfully = true;
1015
+ }
1003
1016
  this.emit("message:update", this.messageStore.getMessages());
1004
1017
  }
1005
1018
  /**
@@ -1021,6 +1034,70 @@ var AgnoClient = class extends EventEmitter {
1021
1034
  this.emit("stream:end");
1022
1035
  this.emit("state:change", this.getState());
1023
1036
  }
1037
+ /**
1038
+ * Refresh messages from the session API after run completion.
1039
+ * Replaces streamed messages with authoritative session data.
1040
+ * Preserves client-side properties like ui_component that aren't stored on the server.
1041
+ * @private
1042
+ */
1043
+ async refreshSessionMessages() {
1044
+ const sessionId = this.configManager.getSessionId();
1045
+ if (!sessionId) {
1046
+ Logger.debug("[AgnoClient] Cannot refresh: no session ID");
1047
+ return;
1048
+ }
1049
+ this.state.isRefreshing = true;
1050
+ this.emit("state:change", this.getState());
1051
+ try {
1052
+ const existingUIComponents = /* @__PURE__ */ new Map();
1053
+ for (const message of this.messageStore.getMessages()) {
1054
+ if (message.tool_calls) {
1055
+ for (const toolCall of message.tool_calls) {
1056
+ if (toolCall.ui_component) {
1057
+ existingUIComponents.set(toolCall.tool_call_id, toolCall.ui_component);
1058
+ }
1059
+ }
1060
+ }
1061
+ }
1062
+ const config = this.configManager.getConfig();
1063
+ const entityType = this.configManager.getMode();
1064
+ const dbId = this.configManager.getDbId() || "";
1065
+ const userId = this.configManager.getUserId();
1066
+ const headers = this.configManager.buildRequestHeaders();
1067
+ const response = await this.sessionManager.fetchSession(
1068
+ config.endpoint,
1069
+ entityType,
1070
+ sessionId,
1071
+ dbId,
1072
+ headers,
1073
+ userId
1074
+ );
1075
+ const messages = this.sessionManager.convertSessionToMessages(response);
1076
+ if (existingUIComponents.size > 0) {
1077
+ for (const message of messages) {
1078
+ if (message.tool_calls) {
1079
+ for (let i = 0; i < message.tool_calls.length; i++) {
1080
+ const toolCall = message.tool_calls[i];
1081
+ const uiComponent = existingUIComponents.get(toolCall.tool_call_id);
1082
+ if (uiComponent) {
1083
+ message.tool_calls[i].ui_component = uiComponent;
1084
+ }
1085
+ }
1086
+ }
1087
+ }
1088
+ }
1089
+ this.messageStore.setMessages(messages);
1090
+ Logger.debug("[AgnoClient] Session refreshed:", `${messages.length} messages`);
1091
+ this.emit("message:refreshed", messages);
1092
+ this.emit("message:update", messages);
1093
+ } catch (error) {
1094
+ Logger.error("[AgnoClient] Failed to refresh session:", error);
1095
+ this.emit("message:error", `Session refresh failed: ${error instanceof Error ? error.message : String(error)}`);
1096
+ } finally {
1097
+ this.state.isRefreshing = false;
1098
+ this.emit("state:change", this.getState());
1099
+ }
1100
+ }
1024
1101
  /**
1025
1102
  * Load a session
1026
1103
  */
@@ -1029,14 +1106,16 @@ var AgnoClient = class extends EventEmitter {
1029
1106
  const config = this.configManager.getConfig();
1030
1107
  const entityType = this.configManager.getMode();
1031
1108
  const dbId = this.configManager.getDbId() || "";
1032
- Logger.debug("[AgnoClient] Loading session with:", { entityType, dbId });
1109
+ const userId = this.configManager.getUserId();
1110
+ Logger.debug("[AgnoClient] Loading session with:", { entityType, dbId, userId });
1033
1111
  const headers = this.configManager.buildRequestHeaders();
1034
1112
  const response = await this.sessionManager.fetchSession(
1035
1113
  config.endpoint,
1036
1114
  entityType,
1037
1115
  sessionId,
1038
1116
  dbId,
1039
- headers
1117
+ headers,
1118
+ userId
1040
1119
  );
1041
1120
  const messages = this.sessionManager.convertSessionToMessages(response);
1042
1121
  Logger.debug("[AgnoClient] Setting messages to store:", `${messages.length} messages`);
@@ -1246,13 +1325,17 @@ var AgnoClient = class extends EventEmitter {
1246
1325
  onError: (error) => {
1247
1326
  this.handleError(error, currentSessionId);
1248
1327
  },
1249
- onComplete: () => {
1328
+ onComplete: async () => {
1250
1329
  this.state.isStreaming = false;
1251
1330
  this.state.pausedRunId = void 0;
1252
1331
  this.state.toolsAwaitingExecution = void 0;
1253
1332
  this.emit("stream:end");
1254
1333
  this.emit("message:complete", this.messageStore.getMessages());
1255
1334
  this.emit("state:change", this.getState());
1335
+ if (this.runCompletedSuccessfully) {
1336
+ this.runCompletedSuccessfully = false;
1337
+ await this.refreshSessionMessages();
1338
+ }
1256
1339
  }
1257
1340
  });
1258
1341
  } catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antipopp/agno-client",
3
- "version": "0.7.0",
3
+ "version": "0.8.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.7.0"
37
+ "@antipopp/agno-types": "0.8.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "tsup": "^8.0.1",