@rodrigocoliveira/agno-client 1.0.1 → 1.0.2
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 +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +194 -5
- package/dist/index.mjs +194 -5
- package/package.json +4 -4
package/dist/index.d.mts
CHANGED
|
@@ -67,6 +67,25 @@ declare class AgnoClient extends EventEmitter {
|
|
|
67
67
|
headers?: Record<string, string>;
|
|
68
68
|
params?: Record<string, string>;
|
|
69
69
|
}): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Determine if a RunEvent is a team-level event (prefixed with "Team")
|
|
72
|
+
*/
|
|
73
|
+
private isTeamEvent;
|
|
74
|
+
/**
|
|
75
|
+
* Determine if an event should update the user-facing message based on mode.
|
|
76
|
+
*
|
|
77
|
+
* In team mode: only Team* events should update the user-facing message.
|
|
78
|
+
* In agent mode: only Run* (non-Team) events should update the user-facing message.
|
|
79
|
+
*
|
|
80
|
+
* Certain events are always processed regardless of mode:
|
|
81
|
+
* - CustomEvent, RunPaused, RunContinued (control flow events)
|
|
82
|
+
*/
|
|
83
|
+
private shouldProcessForUserMessage;
|
|
84
|
+
/**
|
|
85
|
+
* Emit member-specific events for internal team member activity.
|
|
86
|
+
* Only emits when emitMemberEvents config option is true.
|
|
87
|
+
*/
|
|
88
|
+
private emitMemberEvent;
|
|
70
89
|
/**
|
|
71
90
|
* Handle streaming chunk
|
|
72
91
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -67,6 +67,25 @@ declare class AgnoClient extends EventEmitter {
|
|
|
67
67
|
headers?: Record<string, string>;
|
|
68
68
|
params?: Record<string, string>;
|
|
69
69
|
}): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Determine if a RunEvent is a team-level event (prefixed with "Team")
|
|
72
|
+
*/
|
|
73
|
+
private isTeamEvent;
|
|
74
|
+
/**
|
|
75
|
+
* Determine if an event should update the user-facing message based on mode.
|
|
76
|
+
*
|
|
77
|
+
* In team mode: only Team* events should update the user-facing message.
|
|
78
|
+
* In agent mode: only Run* (non-Team) events should update the user-facing message.
|
|
79
|
+
*
|
|
80
|
+
* Certain events are always processed regardless of mode:
|
|
81
|
+
* - CustomEvent, RunPaused, RunContinued (control flow events)
|
|
82
|
+
*/
|
|
83
|
+
private shouldProcessForUserMessage;
|
|
84
|
+
/**
|
|
85
|
+
* Emit member-specific events for internal team member activity.
|
|
86
|
+
* Only emits when emitMemberEvents config option is true.
|
|
87
|
+
*/
|
|
88
|
+
private emitMemberEvent;
|
|
70
89
|
/**
|
|
71
90
|
* Handle streaming chunk
|
|
72
91
|
*/
|
package/dist/index.js
CHANGED
|
@@ -272,6 +272,30 @@ var ConfigManager = class {
|
|
|
272
272
|
setOnTokenExpired(callback) {
|
|
273
273
|
this.config.onTokenExpired = callback;
|
|
274
274
|
}
|
|
275
|
+
/**
|
|
276
|
+
* Get whether to emit member:* events for internal team activity
|
|
277
|
+
*/
|
|
278
|
+
getEmitMemberEvents() {
|
|
279
|
+
return this.config.emitMemberEvents ?? false;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Set whether to emit member:* events
|
|
283
|
+
*/
|
|
284
|
+
setEmitMemberEvents(emit) {
|
|
285
|
+
this.updateField("emitMemberEvents", emit);
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Get whether to request member events from backend
|
|
289
|
+
*/
|
|
290
|
+
getStreamMemberEvents() {
|
|
291
|
+
return this.config.streamMemberEvents ?? false;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Set whether to request member events from backend
|
|
295
|
+
*/
|
|
296
|
+
setStreamMemberEvents(stream) {
|
|
297
|
+
this.updateField("streamMemberEvents", stream);
|
|
298
|
+
}
|
|
275
299
|
/**
|
|
276
300
|
* Get current entity ID (agent or team based on mode)
|
|
277
301
|
*/
|
|
@@ -590,10 +614,13 @@ var SessionManager = class {
|
|
|
590
614
|
}
|
|
591
615
|
}
|
|
592
616
|
/**
|
|
593
|
-
* Convert session runs array to chat messages
|
|
617
|
+
* Convert session runs array to chat messages.
|
|
618
|
+
* Filters out child runs (those with parent_run_id) to prevent
|
|
619
|
+
* internal team member communications from appearing as user messages.
|
|
594
620
|
*/
|
|
595
621
|
convertSessionToMessages(runs) {
|
|
596
|
-
const
|
|
622
|
+
const rootRuns = runs.filter((run) => !run.parent_run_id);
|
|
623
|
+
const messages = this.convertRunsToMessages(rootRuns);
|
|
597
624
|
return messages;
|
|
598
625
|
}
|
|
599
626
|
/**
|
|
@@ -605,10 +632,67 @@ var SessionManager = class {
|
|
|
605
632
|
for (const run of runs) {
|
|
606
633
|
const timestamp = run.created_at ? new Date(run.created_at).getTime() / 1e3 : Math.floor(Date.now() / 1e3);
|
|
607
634
|
if (run.run_input) {
|
|
635
|
+
const userImages = [];
|
|
636
|
+
const userAudio = [];
|
|
637
|
+
const userFiles = [];
|
|
638
|
+
if (run.input_media && typeof run.input_media === "object") {
|
|
639
|
+
const media = run.input_media;
|
|
640
|
+
if (Array.isArray(media.images)) {
|
|
641
|
+
for (const img of media.images) {
|
|
642
|
+
const imgObj = img;
|
|
643
|
+
let url = imgObj.url;
|
|
644
|
+
if (!url && imgObj.content) {
|
|
645
|
+
const mimeType = imgObj.mime_type || `image/${imgObj.format || "png"}`;
|
|
646
|
+
url = `data:${mimeType};base64,${imgObj.content}`;
|
|
647
|
+
}
|
|
648
|
+
if (url) {
|
|
649
|
+
userImages.push({
|
|
650
|
+
url,
|
|
651
|
+
revised_prompt: imgObj.original_name || "Uploaded image"
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
if (Array.isArray(media.audio)) {
|
|
657
|
+
for (const aud of media.audio) {
|
|
658
|
+
const audObj = aud;
|
|
659
|
+
let url = audObj.url;
|
|
660
|
+
if (!url && audObj.content) {
|
|
661
|
+
const mimeType = audObj.mime_type || `audio/${audObj.format || "wav"}`;
|
|
662
|
+
url = `data:${mimeType};base64,${audObj.content}`;
|
|
663
|
+
}
|
|
664
|
+
if (url) {
|
|
665
|
+
userAudio.push({
|
|
666
|
+
url,
|
|
667
|
+
mime_type: audObj.mime_type || void 0
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
if (Array.isArray(media.files)) {
|
|
673
|
+
for (const file of media.files) {
|
|
674
|
+
const fileObj = file;
|
|
675
|
+
let url = fileObj.url;
|
|
676
|
+
if (!url && fileObj.content) {
|
|
677
|
+
const mimeType = fileObj.mime_type || fileObj.content_type || "application/octet-stream";
|
|
678
|
+
url = `data:${mimeType};base64,${fileObj.content}`;
|
|
679
|
+
}
|
|
680
|
+
userFiles.push({
|
|
681
|
+
name: fileObj.original_name || fileObj.name || "file",
|
|
682
|
+
type: fileObj.content_type || fileObj.mime_type || "",
|
|
683
|
+
url,
|
|
684
|
+
size: fileObj.size || void 0
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
}
|
|
608
689
|
messages.push({
|
|
609
690
|
role: "user",
|
|
610
691
|
content: run.run_input,
|
|
611
|
-
created_at: timestamp
|
|
692
|
+
created_at: timestamp,
|
|
693
|
+
...userImages.length > 0 ? { images: userImages } : {},
|
|
694
|
+
...userAudio.length > 0 ? { audio: userAudio } : {},
|
|
695
|
+
...userFiles.length > 0 ? { files: userFiles } : {}
|
|
612
696
|
});
|
|
613
697
|
}
|
|
614
698
|
const toolCalls = [];
|
|
@@ -1879,10 +1963,38 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1879
1963
|
this.messageStore.removeLastMessages(2);
|
|
1880
1964
|
}
|
|
1881
1965
|
}
|
|
1966
|
+
const userImages = [];
|
|
1967
|
+
const userAudio = [];
|
|
1968
|
+
const userFiles = [];
|
|
1969
|
+
if (message instanceof FormData) {
|
|
1970
|
+
const entries = message.getAll("files");
|
|
1971
|
+
for (const entry of entries) {
|
|
1972
|
+
if (typeof entry !== "string") {
|
|
1973
|
+
const file = entry;
|
|
1974
|
+
const url = URL.createObjectURL(file);
|
|
1975
|
+
const mimeType = file.type || "";
|
|
1976
|
+
if (mimeType.startsWith("image/")) {
|
|
1977
|
+
userImages.push({ url, revised_prompt: file.name || "Uploaded image" });
|
|
1978
|
+
} else if (mimeType.startsWith("audio/")) {
|
|
1979
|
+
userAudio.push({ url, mime_type: mimeType });
|
|
1980
|
+
} else {
|
|
1981
|
+
userFiles.push({
|
|
1982
|
+
name: file.name || "file",
|
|
1983
|
+
type: mimeType,
|
|
1984
|
+
url,
|
|
1985
|
+
size: file.size
|
|
1986
|
+
});
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1882
1991
|
this.messageStore.addMessage({
|
|
1883
1992
|
role: "user",
|
|
1884
1993
|
content: formData.get("message"),
|
|
1885
|
-
created_at: Math.floor(Date.now() / 1e3)
|
|
1994
|
+
created_at: Math.floor(Date.now() / 1e3),
|
|
1995
|
+
...userImages.length > 0 ? { images: userImages } : {},
|
|
1996
|
+
...userAudio.length > 0 ? { audio: userAudio } : {},
|
|
1997
|
+
...userFiles.length > 0 ? { files: userFiles } : {}
|
|
1886
1998
|
});
|
|
1887
1999
|
this.messageStore.addMessage({
|
|
1888
2000
|
role: "agent",
|
|
@@ -1900,6 +2012,10 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1900
2012
|
if (userId) {
|
|
1901
2013
|
formData.append("user_id", userId);
|
|
1902
2014
|
}
|
|
2015
|
+
if (this.configManager.getMode() === "team") {
|
|
2016
|
+
const streamMembers = this.configManager.getStreamMemberEvents();
|
|
2017
|
+
formData.append("stream_member_events", String(streamMembers));
|
|
2018
|
+
}
|
|
1903
2019
|
await this.executeStream({
|
|
1904
2020
|
apiUrl: runUrl,
|
|
1905
2021
|
requestBody: formData,
|
|
@@ -1933,13 +2049,56 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1933
2049
|
}
|
|
1934
2050
|
});
|
|
1935
2051
|
}
|
|
2052
|
+
/**
|
|
2053
|
+
* Determine if a RunEvent is a team-level event (prefixed with "Team")
|
|
2054
|
+
*/
|
|
2055
|
+
isTeamEvent(event) {
|
|
2056
|
+
return event.toString().startsWith("Team");
|
|
2057
|
+
}
|
|
2058
|
+
/**
|
|
2059
|
+
* Determine if an event should update the user-facing message based on mode.
|
|
2060
|
+
*
|
|
2061
|
+
* In team mode: only Team* events should update the user-facing message.
|
|
2062
|
+
* In agent mode: only Run* (non-Team) events should update the user-facing message.
|
|
2063
|
+
*
|
|
2064
|
+
* Certain events are always processed regardless of mode:
|
|
2065
|
+
* - CustomEvent, RunPaused, RunContinued (control flow events)
|
|
2066
|
+
*/
|
|
2067
|
+
shouldProcessForUserMessage(event) {
|
|
2068
|
+
if (event === import_agno_types2.RunEvent.CustomEvent || event === import_agno_types2.RunEvent.RunPaused || event === import_agno_types2.RunEvent.RunContinued) {
|
|
2069
|
+
return true;
|
|
2070
|
+
}
|
|
2071
|
+
const mode = this.configManager.getMode();
|
|
2072
|
+
const isTeam = this.isTeamEvent(event);
|
|
2073
|
+
if (mode === "team") {
|
|
2074
|
+
return isTeam;
|
|
2075
|
+
}
|
|
2076
|
+
return !isTeam;
|
|
2077
|
+
}
|
|
2078
|
+
/**
|
|
2079
|
+
* Emit member-specific events for internal team member activity.
|
|
2080
|
+
* Only emits when emitMemberEvents config option is true.
|
|
2081
|
+
*/
|
|
2082
|
+
emitMemberEvent(event, chunk) {
|
|
2083
|
+
if (!this.configManager.getEmitMemberEvents()) return;
|
|
2084
|
+
this.emit("member:event", chunk);
|
|
2085
|
+
if (event === import_agno_types2.RunEvent.RunStarted) {
|
|
2086
|
+
this.emit("member:started", chunk);
|
|
2087
|
+
} else if (event === import_agno_types2.RunEvent.RunContent) {
|
|
2088
|
+
this.emit("member:content", chunk);
|
|
2089
|
+
} else if (event === import_agno_types2.RunEvent.RunCompleted) {
|
|
2090
|
+
this.emit("member:completed", chunk);
|
|
2091
|
+
} else if (event === import_agno_types2.RunEvent.RunError) {
|
|
2092
|
+
this.emit("member:error", chunk);
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
1936
2095
|
/**
|
|
1937
2096
|
* Handle streaming chunk
|
|
1938
2097
|
*/
|
|
1939
2098
|
handleChunk(chunk, currentSessionId, messageContent) {
|
|
1940
2099
|
const event = chunk.event;
|
|
1941
2100
|
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) {
|
|
1942
|
-
if (chunk.run_id) {
|
|
2101
|
+
if (this.shouldProcessForUserMessage(event) && chunk.run_id) {
|
|
1943
2102
|
this.currentRunId = chunk.run_id;
|
|
1944
2103
|
this.state.currentRunId = chunk.run_id;
|
|
1945
2104
|
this.emit("state:change", this.getState());
|
|
@@ -1976,6 +2135,10 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
1976
2135
|
this.emit("state:change", this.getState());
|
|
1977
2136
|
return;
|
|
1978
2137
|
}
|
|
2138
|
+
if (!this.shouldProcessForUserMessage(event)) {
|
|
2139
|
+
this.emitMemberEvent(event, chunk);
|
|
2140
|
+
return;
|
|
2141
|
+
}
|
|
1979
2142
|
if (event === import_agno_types2.RunEvent.RunError || event === import_agno_types2.RunEvent.TeamRunError) {
|
|
1980
2143
|
const errorContent = chunk.content || "Error during run";
|
|
1981
2144
|
this.state.errorMessage = errorContent;
|
|
@@ -2274,6 +2437,7 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
2274
2437
|
this.emit("state:change", this.getState());
|
|
2275
2438
|
try {
|
|
2276
2439
|
const existingUIComponents = /* @__PURE__ */ new Map();
|
|
2440
|
+
const existingUserAttachments = [];
|
|
2277
2441
|
for (const message of this.messageStore.getMessages()) {
|
|
2278
2442
|
if (message.tool_calls) {
|
|
2279
2443
|
for (const toolCall of message.tool_calls) {
|
|
@@ -2282,6 +2446,13 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
2282
2446
|
}
|
|
2283
2447
|
}
|
|
2284
2448
|
}
|
|
2449
|
+
if (message.role === "user") {
|
|
2450
|
+
existingUserAttachments.push({
|
|
2451
|
+
images: message.images,
|
|
2452
|
+
audio: message.audio,
|
|
2453
|
+
files: message.files
|
|
2454
|
+
});
|
|
2455
|
+
}
|
|
2285
2456
|
}
|
|
2286
2457
|
const config = this.configManager.getConfig();
|
|
2287
2458
|
const entityType = this.configManager.getMode();
|
|
@@ -2314,6 +2485,24 @@ var AgnoClient = class extends import_eventemitter3.default {
|
|
|
2314
2485
|
}
|
|
2315
2486
|
}
|
|
2316
2487
|
}
|
|
2488
|
+
if (existingUserAttachments.length > 0) {
|
|
2489
|
+
let userIdx = 0;
|
|
2490
|
+
for (const message of messages) {
|
|
2491
|
+
if (message.role === "user" && userIdx < existingUserAttachments.length) {
|
|
2492
|
+
const saved = existingUserAttachments[userIdx];
|
|
2493
|
+
if (!message.images?.length && saved.images?.length) {
|
|
2494
|
+
message.images = saved.images;
|
|
2495
|
+
}
|
|
2496
|
+
if (!message.audio?.length && saved.audio?.length) {
|
|
2497
|
+
message.audio = saved.audio;
|
|
2498
|
+
}
|
|
2499
|
+
if (!message.files?.length && saved.files?.length) {
|
|
2500
|
+
message.files = saved.files;
|
|
2501
|
+
}
|
|
2502
|
+
userIdx++;
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2317
2506
|
this.messageStore.setMessages(messages);
|
|
2318
2507
|
Logger.debug("[AgnoClient] Session refreshed:", `${messages.length} messages`);
|
|
2319
2508
|
this.emit("message:refreshed", messages);
|
package/dist/index.mjs
CHANGED
|
@@ -234,6 +234,30 @@ var ConfigManager = class {
|
|
|
234
234
|
setOnTokenExpired(callback) {
|
|
235
235
|
this.config.onTokenExpired = callback;
|
|
236
236
|
}
|
|
237
|
+
/**
|
|
238
|
+
* Get whether to emit member:* events for internal team activity
|
|
239
|
+
*/
|
|
240
|
+
getEmitMemberEvents() {
|
|
241
|
+
return this.config.emitMemberEvents ?? false;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Set whether to emit member:* events
|
|
245
|
+
*/
|
|
246
|
+
setEmitMemberEvents(emit) {
|
|
247
|
+
this.updateField("emitMemberEvents", emit);
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Get whether to request member events from backend
|
|
251
|
+
*/
|
|
252
|
+
getStreamMemberEvents() {
|
|
253
|
+
return this.config.streamMemberEvents ?? false;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Set whether to request member events from backend
|
|
257
|
+
*/
|
|
258
|
+
setStreamMemberEvents(stream) {
|
|
259
|
+
this.updateField("streamMemberEvents", stream);
|
|
260
|
+
}
|
|
237
261
|
/**
|
|
238
262
|
* Get current entity ID (agent or team based on mode)
|
|
239
263
|
*/
|
|
@@ -552,10 +576,13 @@ var SessionManager = class {
|
|
|
552
576
|
}
|
|
553
577
|
}
|
|
554
578
|
/**
|
|
555
|
-
* Convert session runs array to chat messages
|
|
579
|
+
* Convert session runs array to chat messages.
|
|
580
|
+
* Filters out child runs (those with parent_run_id) to prevent
|
|
581
|
+
* internal team member communications from appearing as user messages.
|
|
556
582
|
*/
|
|
557
583
|
convertSessionToMessages(runs) {
|
|
558
|
-
const
|
|
584
|
+
const rootRuns = runs.filter((run) => !run.parent_run_id);
|
|
585
|
+
const messages = this.convertRunsToMessages(rootRuns);
|
|
559
586
|
return messages;
|
|
560
587
|
}
|
|
561
588
|
/**
|
|
@@ -567,10 +594,67 @@ var SessionManager = class {
|
|
|
567
594
|
for (const run of runs) {
|
|
568
595
|
const timestamp = run.created_at ? new Date(run.created_at).getTime() / 1e3 : Math.floor(Date.now() / 1e3);
|
|
569
596
|
if (run.run_input) {
|
|
597
|
+
const userImages = [];
|
|
598
|
+
const userAudio = [];
|
|
599
|
+
const userFiles = [];
|
|
600
|
+
if (run.input_media && typeof run.input_media === "object") {
|
|
601
|
+
const media = run.input_media;
|
|
602
|
+
if (Array.isArray(media.images)) {
|
|
603
|
+
for (const img of media.images) {
|
|
604
|
+
const imgObj = img;
|
|
605
|
+
let url = imgObj.url;
|
|
606
|
+
if (!url && imgObj.content) {
|
|
607
|
+
const mimeType = imgObj.mime_type || `image/${imgObj.format || "png"}`;
|
|
608
|
+
url = `data:${mimeType};base64,${imgObj.content}`;
|
|
609
|
+
}
|
|
610
|
+
if (url) {
|
|
611
|
+
userImages.push({
|
|
612
|
+
url,
|
|
613
|
+
revised_prompt: imgObj.original_name || "Uploaded image"
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
if (Array.isArray(media.audio)) {
|
|
619
|
+
for (const aud of media.audio) {
|
|
620
|
+
const audObj = aud;
|
|
621
|
+
let url = audObj.url;
|
|
622
|
+
if (!url && audObj.content) {
|
|
623
|
+
const mimeType = audObj.mime_type || `audio/${audObj.format || "wav"}`;
|
|
624
|
+
url = `data:${mimeType};base64,${audObj.content}`;
|
|
625
|
+
}
|
|
626
|
+
if (url) {
|
|
627
|
+
userAudio.push({
|
|
628
|
+
url,
|
|
629
|
+
mime_type: audObj.mime_type || void 0
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
if (Array.isArray(media.files)) {
|
|
635
|
+
for (const file of media.files) {
|
|
636
|
+
const fileObj = file;
|
|
637
|
+
let url = fileObj.url;
|
|
638
|
+
if (!url && fileObj.content) {
|
|
639
|
+
const mimeType = fileObj.mime_type || fileObj.content_type || "application/octet-stream";
|
|
640
|
+
url = `data:${mimeType};base64,${fileObj.content}`;
|
|
641
|
+
}
|
|
642
|
+
userFiles.push({
|
|
643
|
+
name: fileObj.original_name || fileObj.name || "file",
|
|
644
|
+
type: fileObj.content_type || fileObj.mime_type || "",
|
|
645
|
+
url,
|
|
646
|
+
size: fileObj.size || void 0
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
}
|
|
570
651
|
messages.push({
|
|
571
652
|
role: "user",
|
|
572
653
|
content: run.run_input,
|
|
573
|
-
created_at: timestamp
|
|
654
|
+
created_at: timestamp,
|
|
655
|
+
...userImages.length > 0 ? { images: userImages } : {},
|
|
656
|
+
...userAudio.length > 0 ? { audio: userAudio } : {},
|
|
657
|
+
...userFiles.length > 0 ? { files: userFiles } : {}
|
|
574
658
|
});
|
|
575
659
|
}
|
|
576
660
|
const toolCalls = [];
|
|
@@ -1841,10 +1925,38 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1841
1925
|
this.messageStore.removeLastMessages(2);
|
|
1842
1926
|
}
|
|
1843
1927
|
}
|
|
1928
|
+
const userImages = [];
|
|
1929
|
+
const userAudio = [];
|
|
1930
|
+
const userFiles = [];
|
|
1931
|
+
if (message instanceof FormData) {
|
|
1932
|
+
const entries = message.getAll("files");
|
|
1933
|
+
for (const entry of entries) {
|
|
1934
|
+
if (typeof entry !== "string") {
|
|
1935
|
+
const file = entry;
|
|
1936
|
+
const url = URL.createObjectURL(file);
|
|
1937
|
+
const mimeType = file.type || "";
|
|
1938
|
+
if (mimeType.startsWith("image/")) {
|
|
1939
|
+
userImages.push({ url, revised_prompt: file.name || "Uploaded image" });
|
|
1940
|
+
} else if (mimeType.startsWith("audio/")) {
|
|
1941
|
+
userAudio.push({ url, mime_type: mimeType });
|
|
1942
|
+
} else {
|
|
1943
|
+
userFiles.push({
|
|
1944
|
+
name: file.name || "file",
|
|
1945
|
+
type: mimeType,
|
|
1946
|
+
url,
|
|
1947
|
+
size: file.size
|
|
1948
|
+
});
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1844
1953
|
this.messageStore.addMessage({
|
|
1845
1954
|
role: "user",
|
|
1846
1955
|
content: formData.get("message"),
|
|
1847
|
-
created_at: Math.floor(Date.now() / 1e3)
|
|
1956
|
+
created_at: Math.floor(Date.now() / 1e3),
|
|
1957
|
+
...userImages.length > 0 ? { images: userImages } : {},
|
|
1958
|
+
...userAudio.length > 0 ? { audio: userAudio } : {},
|
|
1959
|
+
...userFiles.length > 0 ? { files: userFiles } : {}
|
|
1848
1960
|
});
|
|
1849
1961
|
this.messageStore.addMessage({
|
|
1850
1962
|
role: "agent",
|
|
@@ -1862,6 +1974,10 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1862
1974
|
if (userId) {
|
|
1863
1975
|
formData.append("user_id", userId);
|
|
1864
1976
|
}
|
|
1977
|
+
if (this.configManager.getMode() === "team") {
|
|
1978
|
+
const streamMembers = this.configManager.getStreamMemberEvents();
|
|
1979
|
+
formData.append("stream_member_events", String(streamMembers));
|
|
1980
|
+
}
|
|
1865
1981
|
await this.executeStream({
|
|
1866
1982
|
apiUrl: runUrl,
|
|
1867
1983
|
requestBody: formData,
|
|
@@ -1895,13 +2011,56 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1895
2011
|
}
|
|
1896
2012
|
});
|
|
1897
2013
|
}
|
|
2014
|
+
/**
|
|
2015
|
+
* Determine if a RunEvent is a team-level event (prefixed with "Team")
|
|
2016
|
+
*/
|
|
2017
|
+
isTeamEvent(event) {
|
|
2018
|
+
return event.toString().startsWith("Team");
|
|
2019
|
+
}
|
|
2020
|
+
/**
|
|
2021
|
+
* Determine if an event should update the user-facing message based on mode.
|
|
2022
|
+
*
|
|
2023
|
+
* In team mode: only Team* events should update the user-facing message.
|
|
2024
|
+
* In agent mode: only Run* (non-Team) events should update the user-facing message.
|
|
2025
|
+
*
|
|
2026
|
+
* Certain events are always processed regardless of mode:
|
|
2027
|
+
* - CustomEvent, RunPaused, RunContinued (control flow events)
|
|
2028
|
+
*/
|
|
2029
|
+
shouldProcessForUserMessage(event) {
|
|
2030
|
+
if (event === RunEvent.CustomEvent || event === RunEvent.RunPaused || event === RunEvent.RunContinued) {
|
|
2031
|
+
return true;
|
|
2032
|
+
}
|
|
2033
|
+
const mode = this.configManager.getMode();
|
|
2034
|
+
const isTeam = this.isTeamEvent(event);
|
|
2035
|
+
if (mode === "team") {
|
|
2036
|
+
return isTeam;
|
|
2037
|
+
}
|
|
2038
|
+
return !isTeam;
|
|
2039
|
+
}
|
|
2040
|
+
/**
|
|
2041
|
+
* Emit member-specific events for internal team member activity.
|
|
2042
|
+
* Only emits when emitMemberEvents config option is true.
|
|
2043
|
+
*/
|
|
2044
|
+
emitMemberEvent(event, chunk) {
|
|
2045
|
+
if (!this.configManager.getEmitMemberEvents()) return;
|
|
2046
|
+
this.emit("member:event", chunk);
|
|
2047
|
+
if (event === RunEvent.RunStarted) {
|
|
2048
|
+
this.emit("member:started", chunk);
|
|
2049
|
+
} else if (event === RunEvent.RunContent) {
|
|
2050
|
+
this.emit("member:content", chunk);
|
|
2051
|
+
} else if (event === RunEvent.RunCompleted) {
|
|
2052
|
+
this.emit("member:completed", chunk);
|
|
2053
|
+
} else if (event === RunEvent.RunError) {
|
|
2054
|
+
this.emit("member:error", chunk);
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
1898
2057
|
/**
|
|
1899
2058
|
* Handle streaming chunk
|
|
1900
2059
|
*/
|
|
1901
2060
|
handleChunk(chunk, currentSessionId, messageContent) {
|
|
1902
2061
|
const event = chunk.event;
|
|
1903
2062
|
if (event === RunEvent.RunStarted || event === RunEvent.TeamRunStarted || event === RunEvent.ReasoningStarted || event === RunEvent.TeamReasoningStarted) {
|
|
1904
|
-
if (chunk.run_id) {
|
|
2063
|
+
if (this.shouldProcessForUserMessage(event) && chunk.run_id) {
|
|
1905
2064
|
this.currentRunId = chunk.run_id;
|
|
1906
2065
|
this.state.currentRunId = chunk.run_id;
|
|
1907
2066
|
this.emit("state:change", this.getState());
|
|
@@ -1938,6 +2097,10 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1938
2097
|
this.emit("state:change", this.getState());
|
|
1939
2098
|
return;
|
|
1940
2099
|
}
|
|
2100
|
+
if (!this.shouldProcessForUserMessage(event)) {
|
|
2101
|
+
this.emitMemberEvent(event, chunk);
|
|
2102
|
+
return;
|
|
2103
|
+
}
|
|
1941
2104
|
if (event === RunEvent.RunError || event === RunEvent.TeamRunError) {
|
|
1942
2105
|
const errorContent = chunk.content || "Error during run";
|
|
1943
2106
|
this.state.errorMessage = errorContent;
|
|
@@ -2236,6 +2399,7 @@ var AgnoClient = class extends EventEmitter {
|
|
|
2236
2399
|
this.emit("state:change", this.getState());
|
|
2237
2400
|
try {
|
|
2238
2401
|
const existingUIComponents = /* @__PURE__ */ new Map();
|
|
2402
|
+
const existingUserAttachments = [];
|
|
2239
2403
|
for (const message of this.messageStore.getMessages()) {
|
|
2240
2404
|
if (message.tool_calls) {
|
|
2241
2405
|
for (const toolCall of message.tool_calls) {
|
|
@@ -2244,6 +2408,13 @@ var AgnoClient = class extends EventEmitter {
|
|
|
2244
2408
|
}
|
|
2245
2409
|
}
|
|
2246
2410
|
}
|
|
2411
|
+
if (message.role === "user") {
|
|
2412
|
+
existingUserAttachments.push({
|
|
2413
|
+
images: message.images,
|
|
2414
|
+
audio: message.audio,
|
|
2415
|
+
files: message.files
|
|
2416
|
+
});
|
|
2417
|
+
}
|
|
2247
2418
|
}
|
|
2248
2419
|
const config = this.configManager.getConfig();
|
|
2249
2420
|
const entityType = this.configManager.getMode();
|
|
@@ -2276,6 +2447,24 @@ var AgnoClient = class extends EventEmitter {
|
|
|
2276
2447
|
}
|
|
2277
2448
|
}
|
|
2278
2449
|
}
|
|
2450
|
+
if (existingUserAttachments.length > 0) {
|
|
2451
|
+
let userIdx = 0;
|
|
2452
|
+
for (const message of messages) {
|
|
2453
|
+
if (message.role === "user" && userIdx < existingUserAttachments.length) {
|
|
2454
|
+
const saved = existingUserAttachments[userIdx];
|
|
2455
|
+
if (!message.images?.length && saved.images?.length) {
|
|
2456
|
+
message.images = saved.images;
|
|
2457
|
+
}
|
|
2458
|
+
if (!message.audio?.length && saved.audio?.length) {
|
|
2459
|
+
message.audio = saved.audio;
|
|
2460
|
+
}
|
|
2461
|
+
if (!message.files?.length && saved.files?.length) {
|
|
2462
|
+
message.files = saved.files;
|
|
2463
|
+
}
|
|
2464
|
+
userIdx++;
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2279
2468
|
this.messageStore.setMessages(messages);
|
|
2280
2469
|
Logger.debug("[AgnoClient] Session refreshed:", `${messages.length} messages`);
|
|
2281
2470
|
this.emit("message:refreshed", messages);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rodrigocoliveira/agno-client",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Core client library for Agno agents with streaming support and HITL frontend tool execution",
|
|
5
5
|
"author": "rodrigocoliveira",
|
|
6
6
|
"license": "MIT",
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
"types": "./dist/index.d.ts",
|
|
24
24
|
"exports": {
|
|
25
25
|
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
26
27
|
"import": "./dist/index.mjs",
|
|
27
|
-
"require": "./dist/index.js"
|
|
28
|
-
"types": "./dist/index.d.ts"
|
|
28
|
+
"require": "./dist/index.js"
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"files": [
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"eventemitter3": "^5.0.1",
|
|
37
|
-
"@rodrigocoliveira/agno-types": "1.0.
|
|
37
|
+
"@rodrigocoliveira/agno-types": "1.0.2"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"tsup": "^8.0.1",
|