@antipopp/agno-client 0.9.0 → 0.11.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/README.md +30 -1
- package/dist/index.d.mts +43 -19
- package/dist/index.d.ts +43 -19
- package/dist/index.js +1135 -478
- package/dist/index.mjs +1137 -478
- package/package.json +8 -4
package/dist/index.mjs
CHANGED
|
@@ -1,85 +1,9 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { RunEvent as RunEvent2 } from "@antipopp/agno-types";
|
|
3
|
+
|
|
1
4
|
// src/client.ts
|
|
2
|
-
import EventEmitter from "eventemitter3";
|
|
3
5
|
import { RunEvent } from "@antipopp/agno-types";
|
|
4
|
-
|
|
5
|
-
// src/stores/message-store.ts
|
|
6
|
-
var MessageStore = class {
|
|
7
|
-
constructor() {
|
|
8
|
-
this.messages = [];
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Get all messages
|
|
12
|
-
*/
|
|
13
|
-
getMessages() {
|
|
14
|
-
return [...this.messages];
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Set messages (replaces all)
|
|
18
|
-
*/
|
|
19
|
-
setMessages(messages) {
|
|
20
|
-
this.messages = [...messages];
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Add a message
|
|
24
|
-
*/
|
|
25
|
-
addMessage(message) {
|
|
26
|
-
this.messages = [...this.messages, message];
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Update the last message
|
|
30
|
-
*/
|
|
31
|
-
updateLastMessage(updater) {
|
|
32
|
-
if (this.messages.length === 0)
|
|
33
|
-
return void 0;
|
|
34
|
-
const lastMessage = this.messages[this.messages.length - 1];
|
|
35
|
-
const updatedMessage = updater(lastMessage);
|
|
36
|
-
this.messages = [
|
|
37
|
-
...this.messages.slice(0, -1),
|
|
38
|
-
updatedMessage
|
|
39
|
-
];
|
|
40
|
-
return updatedMessage;
|
|
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
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Remove last N messages
|
|
59
|
-
*/
|
|
60
|
-
removeLastMessages(count) {
|
|
61
|
-
this.messages = this.messages.slice(0, -count);
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Clear all messages
|
|
65
|
-
*/
|
|
66
|
-
clear() {
|
|
67
|
-
this.messages = [];
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Get the last message
|
|
71
|
-
*/
|
|
72
|
-
getLastMessage() {
|
|
73
|
-
return this.messages.length > 0 ? this.messages[this.messages.length - 1] : void 0;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Check if last message has streaming error
|
|
77
|
-
*/
|
|
78
|
-
hasLastMessageError() {
|
|
79
|
-
const lastMessage = this.getLastMessage();
|
|
80
|
-
return lastMessage?.streamingError === true;
|
|
81
|
-
}
|
|
82
|
-
};
|
|
6
|
+
import EventEmitter from "eventemitter3";
|
|
83
7
|
|
|
84
8
|
// src/managers/config-manager.ts
|
|
85
9
|
var ConfigManager = class {
|
|
@@ -224,6 +148,18 @@ var ConfigManager = class {
|
|
|
224
148
|
setParams(params) {
|
|
225
149
|
this.updateField("params", params);
|
|
226
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Get global dependencies
|
|
153
|
+
*/
|
|
154
|
+
getDependencies() {
|
|
155
|
+
return this.config.dependencies;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Set global dependencies
|
|
159
|
+
*/
|
|
160
|
+
setDependencies(dependencies) {
|
|
161
|
+
this.updateField("dependencies", dependencies);
|
|
162
|
+
}
|
|
227
163
|
/**
|
|
228
164
|
* Get current entity ID (agent or team based on mode)
|
|
229
165
|
*/
|
|
@@ -237,14 +173,14 @@ var ConfigManager = class {
|
|
|
237
173
|
const mode = this.getMode();
|
|
238
174
|
const endpoint = this.getEndpoint();
|
|
239
175
|
const entityId = this.getCurrentEntityId();
|
|
240
|
-
if (!entityId)
|
|
176
|
+
if (!entityId) {
|
|
241
177
|
return null;
|
|
178
|
+
}
|
|
242
179
|
const encodedEntityId = encodeURIComponent(entityId);
|
|
243
180
|
if (mode === "team") {
|
|
244
181
|
return `${endpoint}/teams/${encodedEntityId}/runs`;
|
|
245
|
-
} else {
|
|
246
|
-
return `${endpoint}/agents/${encodedEntityId}/runs`;
|
|
247
182
|
}
|
|
183
|
+
return `${endpoint}/agents/${encodedEntityId}/runs`;
|
|
248
184
|
}
|
|
249
185
|
/**
|
|
250
186
|
* Build request headers by merging global headers, per-request headers, and auth token.
|
|
@@ -267,7 +203,7 @@ var ConfigManager = class {
|
|
|
267
203
|
}
|
|
268
204
|
const authToken = this.getAuthToken();
|
|
269
205
|
if (authToken) {
|
|
270
|
-
headers
|
|
206
|
+
headers.Authorization = `Bearer ${authToken}`;
|
|
271
207
|
}
|
|
272
208
|
return headers;
|
|
273
209
|
}
|
|
@@ -291,6 +227,29 @@ var ConfigManager = class {
|
|
|
291
227
|
}
|
|
292
228
|
return new URLSearchParams(params);
|
|
293
229
|
}
|
|
230
|
+
/**
|
|
231
|
+
* Build dependencies by merging global dependencies and per-request dependencies.
|
|
232
|
+
* Merge order (lowest to highest precedence):
|
|
233
|
+
* 1. Global dependencies from config
|
|
234
|
+
* 2. Per-request dependencies (overrides global)
|
|
235
|
+
*
|
|
236
|
+
* @param perRequestDependencies - Optional dependencies for this specific request
|
|
237
|
+
* @returns Merged dependencies object, or undefined if no dependencies are configured
|
|
238
|
+
*/
|
|
239
|
+
buildDependencies(perRequestDependencies) {
|
|
240
|
+
const dependencies = {};
|
|
241
|
+
const globalDependencies = this.getDependencies();
|
|
242
|
+
if (globalDependencies) {
|
|
243
|
+
Object.assign(dependencies, globalDependencies);
|
|
244
|
+
}
|
|
245
|
+
if (perRequestDependencies) {
|
|
246
|
+
Object.assign(dependencies, perRequestDependencies);
|
|
247
|
+
}
|
|
248
|
+
if (Object.keys(dependencies).length === 0) {
|
|
249
|
+
return void 0;
|
|
250
|
+
}
|
|
251
|
+
return dependencies;
|
|
252
|
+
}
|
|
294
253
|
};
|
|
295
254
|
|
|
296
255
|
// src/managers/session-manager.ts
|
|
@@ -377,75 +336,470 @@ var SessionManager = class {
|
|
|
377
336
|
convertRunsToMessages(runs) {
|
|
378
337
|
const messages = [];
|
|
379
338
|
for (const run of runs) {
|
|
380
|
-
const timestamp =
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
if (run.tools && Array.isArray(run.tools)) {
|
|
390
|
-
for (const tool of run.tools) {
|
|
391
|
-
const toolObj = tool;
|
|
392
|
-
const toolCall = {
|
|
393
|
-
role: "tool",
|
|
394
|
-
content: toolObj.content ?? "",
|
|
395
|
-
tool_call_id: toolObj.tool_call_id ?? "",
|
|
396
|
-
tool_name: toolObj.tool_name ?? "",
|
|
397
|
-
tool_args: toolObj.tool_args ?? {},
|
|
398
|
-
tool_call_error: toolObj.tool_call_error ?? false,
|
|
399
|
-
metrics: toolObj.metrics ?? { time: 0 },
|
|
400
|
-
created_at: timestamp
|
|
401
|
-
};
|
|
402
|
-
toolCalls.push(toolCall);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
if (run.reasoning_messages && Array.isArray(run.reasoning_messages)) {
|
|
406
|
-
for (const msg of run.reasoning_messages) {
|
|
407
|
-
const reasoningMsg = msg;
|
|
408
|
-
if (reasoningMsg.role === "tool") {
|
|
409
|
-
toolCalls.push({
|
|
410
|
-
role: "tool",
|
|
411
|
-
content: reasoningMsg.content ?? "",
|
|
412
|
-
tool_call_id: reasoningMsg.tool_call_id ?? "",
|
|
413
|
-
tool_name: reasoningMsg.tool_name ?? "",
|
|
414
|
-
tool_args: reasoningMsg.tool_args ?? {},
|
|
415
|
-
tool_call_error: reasoningMsg.tool_call_error ?? false,
|
|
416
|
-
metrics: reasoningMsg.metrics ?? { time: 0 },
|
|
417
|
-
created_at: reasoningMsg.created_at ?? timestamp
|
|
418
|
-
});
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
let contentStr = "";
|
|
423
|
-
if (typeof run.content === "string") {
|
|
424
|
-
contentStr = run.content;
|
|
425
|
-
} else if (run.content && typeof run.content === "object") {
|
|
426
|
-
contentStr = JSON.stringify(run.content);
|
|
339
|
+
const timestamp = this.getRunTimestamp(run);
|
|
340
|
+
const inputMedia = this.mergeInputMedia(
|
|
341
|
+
this.extractInputMedia(run.input_media),
|
|
342
|
+
this.extractInputMediaFromMessages(run.messages)
|
|
343
|
+
);
|
|
344
|
+
if (run.run_input || this.hasAnyMedia(inputMedia)) {
|
|
345
|
+
messages.push(
|
|
346
|
+
this.buildUserMessage(run.run_input ?? "", timestamp, inputMedia)
|
|
347
|
+
);
|
|
427
348
|
}
|
|
428
|
-
const
|
|
429
|
-
reasoning_messages: run.reasoning_messages,
|
|
430
|
-
reasoning_steps: run.reasoning_steps,
|
|
431
|
-
references: run.references
|
|
432
|
-
} : void 0;
|
|
349
|
+
const toolCalls = this.extractToolCalls(run, timestamp);
|
|
433
350
|
messages.push({
|
|
434
351
|
role: "agent",
|
|
435
|
-
content:
|
|
352
|
+
content: this.normalizeRunContent(run.content),
|
|
436
353
|
tool_calls: toolCalls.length > 0 ? toolCalls : void 0,
|
|
437
|
-
extra_data:
|
|
438
|
-
images: run.images,
|
|
439
|
-
videos: run.videos,
|
|
440
|
-
audio: run.audio,
|
|
441
|
-
|
|
354
|
+
extra_data: this.buildExtraData(run),
|
|
355
|
+
images: this.normalizeImages(run.images),
|
|
356
|
+
videos: this.normalizeVideos(run.videos),
|
|
357
|
+
audio: this.normalizeAudio(run.audio),
|
|
358
|
+
files: this.normalizeFiles(run.files),
|
|
359
|
+
response_audio: run.response_audio ?? void 0,
|
|
442
360
|
created_at: timestamp + 1
|
|
443
361
|
// Agent response is slightly after user message
|
|
444
362
|
});
|
|
445
363
|
}
|
|
446
364
|
return messages;
|
|
447
365
|
}
|
|
366
|
+
getRunTimestamp(run) {
|
|
367
|
+
return run.created_at ? new Date(run.created_at).getTime() / 1e3 : Math.floor(Date.now() / 1e3);
|
|
368
|
+
}
|
|
369
|
+
buildUserMessage(content, createdAt, media) {
|
|
370
|
+
return {
|
|
371
|
+
role: "user",
|
|
372
|
+
content,
|
|
373
|
+
images: media?.images,
|
|
374
|
+
videos: media?.videos,
|
|
375
|
+
audio: media?.audio,
|
|
376
|
+
files: media?.files,
|
|
377
|
+
created_at: createdAt
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
hasAnyMedia(media) {
|
|
381
|
+
return Boolean(
|
|
382
|
+
media.images && media.images.length > 0 || media.videos && media.videos.length > 0 || media.audio && media.audio.length > 0 || media.files && media.files.length > 0
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
isRecord(value) {
|
|
386
|
+
return typeof value === "object" && value !== null;
|
|
387
|
+
}
|
|
388
|
+
getStringValue(record, key) {
|
|
389
|
+
const value = record[key];
|
|
390
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
391
|
+
}
|
|
392
|
+
getNumberOrStringValue(record, key) {
|
|
393
|
+
const value = record[key];
|
|
394
|
+
return typeof value === "number" || typeof value === "string" ? value : void 0;
|
|
395
|
+
}
|
|
396
|
+
buildDataUrl(content, mimeType, fallbackMimeType) {
|
|
397
|
+
const safeMimeType = mimeType || fallbackMimeType;
|
|
398
|
+
return `data:${safeMimeType};base64,${content}`;
|
|
399
|
+
}
|
|
400
|
+
normalizeImage(item) {
|
|
401
|
+
if (!this.isRecord(item)) {
|
|
402
|
+
return void 0;
|
|
403
|
+
}
|
|
404
|
+
const mimeType = this.getStringValue(item, "mime_type");
|
|
405
|
+
const content = this.getStringValue(item, "content");
|
|
406
|
+
const url = this.getStringValue(item, "url") || (content ? this.buildDataUrl(content, mimeType, "image/png") : void 0);
|
|
407
|
+
if (!url) {
|
|
408
|
+
return void 0;
|
|
409
|
+
}
|
|
410
|
+
return {
|
|
411
|
+
url,
|
|
412
|
+
revised_prompt: this.getStringValue(item, "revised_prompt"),
|
|
413
|
+
original_prompt: this.getStringValue(item, "original_prompt"),
|
|
414
|
+
alt_text: this.getStringValue(item, "alt_text"),
|
|
415
|
+
id: this.getStringValue(item, "id"),
|
|
416
|
+
mime_type: mimeType,
|
|
417
|
+
format: this.getStringValue(item, "format")
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
normalizeVideo(item) {
|
|
421
|
+
if (!this.isRecord(item)) {
|
|
422
|
+
return void 0;
|
|
423
|
+
}
|
|
424
|
+
const mimeType = this.getStringValue(item, "mime_type");
|
|
425
|
+
const content = this.getStringValue(item, "content");
|
|
426
|
+
const url = this.getStringValue(item, "url") || (content ? this.buildDataUrl(content, mimeType, "video/mp4") : void 0);
|
|
427
|
+
const normalized = {
|
|
428
|
+
url,
|
|
429
|
+
id: this.getNumberOrStringValue(item, "id"),
|
|
430
|
+
eta: this.getNumberOrStringValue(item, "eta"),
|
|
431
|
+
mime_type: mimeType,
|
|
432
|
+
format: this.getStringValue(item, "format"),
|
|
433
|
+
original_prompt: this.getStringValue(item, "original_prompt"),
|
|
434
|
+
revised_prompt: this.getStringValue(item, "revised_prompt"),
|
|
435
|
+
width: typeof item.width === "number" ? item.width : void 0,
|
|
436
|
+
height: typeof item.height === "number" ? item.height : void 0,
|
|
437
|
+
fps: typeof item.fps === "number" ? item.fps : void 0,
|
|
438
|
+
duration: typeof item.duration === "number" ? item.duration : void 0
|
|
439
|
+
};
|
|
440
|
+
if (normalized.url || normalized.id !== void 0 || normalized.eta !== void 0) {
|
|
441
|
+
return normalized;
|
|
442
|
+
}
|
|
443
|
+
return void 0;
|
|
444
|
+
}
|
|
445
|
+
normalizeAudioEntry(item) {
|
|
446
|
+
if (!this.isRecord(item)) {
|
|
447
|
+
return void 0;
|
|
448
|
+
}
|
|
449
|
+
const mimeType = this.getStringValue(item, "mime_type");
|
|
450
|
+
const content = this.getStringValue(item, "content");
|
|
451
|
+
const url = this.getStringValue(item, "url") || (content ? this.buildDataUrl(content, mimeType, "audio/wav") : void 0);
|
|
452
|
+
const normalized = {
|
|
453
|
+
base64_audio: this.getStringValue(item, "base64_audio"),
|
|
454
|
+
mime_type: mimeType,
|
|
455
|
+
url,
|
|
456
|
+
id: this.getNumberOrStringValue(item, "id"),
|
|
457
|
+
content,
|
|
458
|
+
channels: typeof item.channels === "number" ? item.channels : void 0,
|
|
459
|
+
sample_rate: typeof item.sample_rate === "number" ? item.sample_rate : void 0,
|
|
460
|
+
format: this.getStringValue(item, "format"),
|
|
461
|
+
duration: typeof item.duration === "number" ? item.duration : void 0
|
|
462
|
+
};
|
|
463
|
+
if (normalized.url || normalized.base64_audio || normalized.content || normalized.id !== void 0) {
|
|
464
|
+
return normalized;
|
|
465
|
+
}
|
|
466
|
+
return void 0;
|
|
467
|
+
}
|
|
468
|
+
normalizeFileEntry(item) {
|
|
469
|
+
if (!this.isRecord(item)) {
|
|
470
|
+
return void 0;
|
|
471
|
+
}
|
|
472
|
+
const normalized = {
|
|
473
|
+
id: this.getStringValue(item, "id"),
|
|
474
|
+
url: this.getStringValue(item, "url"),
|
|
475
|
+
filename: this.getStringValue(item, "filename"),
|
|
476
|
+
name: this.getStringValue(item, "name"),
|
|
477
|
+
mime_type: this.getStringValue(item, "mime_type"),
|
|
478
|
+
format: this.getStringValue(item, "format"),
|
|
479
|
+
size: typeof item.size === "number" ? item.size : void 0
|
|
480
|
+
};
|
|
481
|
+
if (normalized.url || normalized.filename || normalized.name || normalized.id) {
|
|
482
|
+
return normalized;
|
|
483
|
+
}
|
|
484
|
+
return void 0;
|
|
485
|
+
}
|
|
486
|
+
normalizeArray(value, normalizer) {
|
|
487
|
+
if (!Array.isArray(value)) {
|
|
488
|
+
return void 0;
|
|
489
|
+
}
|
|
490
|
+
const items = value.map((item) => normalizer(item)).filter((item) => item !== void 0);
|
|
491
|
+
return items.length > 0 ? items : void 0;
|
|
492
|
+
}
|
|
493
|
+
normalizeImages(value) {
|
|
494
|
+
return this.normalizeArray(value, (item) => this.normalizeImage(item));
|
|
495
|
+
}
|
|
496
|
+
normalizeVideos(value) {
|
|
497
|
+
return this.normalizeArray(value, (item) => this.normalizeVideo(item));
|
|
498
|
+
}
|
|
499
|
+
normalizeAudio(value) {
|
|
500
|
+
return this.normalizeArray(value, (item) => this.normalizeAudioEntry(item));
|
|
501
|
+
}
|
|
502
|
+
normalizeFiles(value) {
|
|
503
|
+
return this.normalizeArray(value, (item) => this.normalizeFileEntry(item));
|
|
504
|
+
}
|
|
505
|
+
extractInputMedia(inputMedia) {
|
|
506
|
+
if (!this.isRecord(inputMedia)) {
|
|
507
|
+
return {};
|
|
508
|
+
}
|
|
509
|
+
return {
|
|
510
|
+
images: this.normalizeImages(inputMedia.images),
|
|
511
|
+
videos: this.normalizeVideos(inputMedia.videos),
|
|
512
|
+
audio: this.normalizeAudio(inputMedia.audios ?? inputMedia.audio),
|
|
513
|
+
files: this.normalizeFiles(inputMedia.files)
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
extractInputMediaFromMessages(messages) {
|
|
517
|
+
if (!Array.isArray(messages)) {
|
|
518
|
+
return {};
|
|
519
|
+
}
|
|
520
|
+
for (const message of messages) {
|
|
521
|
+
if (!this.isRecord(message)) {
|
|
522
|
+
continue;
|
|
523
|
+
}
|
|
524
|
+
if (this.getStringValue(message, "role") !== "user") {
|
|
525
|
+
continue;
|
|
526
|
+
}
|
|
527
|
+
const media = {
|
|
528
|
+
images: this.normalizeImages(message.images ?? message.image),
|
|
529
|
+
videos: this.normalizeVideos(message.videos ?? message.video),
|
|
530
|
+
audio: this.normalizeAudio(message.audios ?? message.audio),
|
|
531
|
+
files: this.normalizeFiles(message.files)
|
|
532
|
+
};
|
|
533
|
+
if (this.hasAnyMedia(media)) {
|
|
534
|
+
return media;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
return {};
|
|
538
|
+
}
|
|
539
|
+
mergeInputMedia(primary, fallback) {
|
|
540
|
+
return {
|
|
541
|
+
images: primary.images ?? fallback.images,
|
|
542
|
+
videos: primary.videos ?? fallback.videos,
|
|
543
|
+
audio: primary.audio ?? fallback.audio,
|
|
544
|
+
files: primary.files ?? fallback.files
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
normalizeRunContent(content) {
|
|
548
|
+
if (typeof content === "string") {
|
|
549
|
+
return content;
|
|
550
|
+
}
|
|
551
|
+
if (content && typeof content === "object") {
|
|
552
|
+
return JSON.stringify(content);
|
|
553
|
+
}
|
|
554
|
+
return "";
|
|
555
|
+
}
|
|
556
|
+
buildToolCall(rawTool, fallbackTimestamp) {
|
|
557
|
+
return {
|
|
558
|
+
role: "tool",
|
|
559
|
+
content: rawTool.content ?? "",
|
|
560
|
+
tool_call_id: rawTool.tool_call_id ?? "",
|
|
561
|
+
tool_name: rawTool.tool_name ?? "",
|
|
562
|
+
tool_args: rawTool.tool_args ?? {},
|
|
563
|
+
tool_call_error: rawTool.tool_call_error ?? false,
|
|
564
|
+
metrics: rawTool.metrics ?? { time: 0 },
|
|
565
|
+
created_at: rawTool.created_at ?? fallbackTimestamp
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
extractToolCalls(run, timestamp) {
|
|
569
|
+
const toolCalls = [];
|
|
570
|
+
if (run.tools && Array.isArray(run.tools)) {
|
|
571
|
+
for (const tool of run.tools) {
|
|
572
|
+
toolCalls.push(this.buildToolCall(tool, timestamp));
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
if (run.reasoning_messages && Array.isArray(run.reasoning_messages)) {
|
|
576
|
+
for (const message of run.reasoning_messages) {
|
|
577
|
+
if (message.role === "tool") {
|
|
578
|
+
toolCalls.push(this.buildToolCall(message, timestamp));
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
return toolCalls;
|
|
583
|
+
}
|
|
584
|
+
buildExtraData(run) {
|
|
585
|
+
if (!(run.reasoning_messages || run.reasoning_steps || run.references)) {
|
|
586
|
+
return void 0;
|
|
587
|
+
}
|
|
588
|
+
return {
|
|
589
|
+
reasoning_messages: run.reasoning_messages,
|
|
590
|
+
reasoning_steps: run.reasoning_steps,
|
|
591
|
+
references: run.references
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
// src/parsers/stream-parser.ts
|
|
597
|
+
var StreamResponseHttpError = class extends Error {
|
|
598
|
+
constructor(status, message) {
|
|
599
|
+
super(message);
|
|
600
|
+
this.name = "StreamResponseHttpError";
|
|
601
|
+
this.status = status;
|
|
602
|
+
}
|
|
448
603
|
};
|
|
604
|
+
function isLegacyFormat(data) {
|
|
605
|
+
return typeof data === "object" && data !== null && "event" in data && !("data" in data) && typeof data.event === "string";
|
|
606
|
+
}
|
|
607
|
+
function convertNewFormatToLegacy(newFormatData) {
|
|
608
|
+
const { event, data } = newFormatData;
|
|
609
|
+
let parsedData;
|
|
610
|
+
if (typeof data === "string") {
|
|
611
|
+
try {
|
|
612
|
+
parsedData = JSON.parse(data);
|
|
613
|
+
} catch {
|
|
614
|
+
parsedData = {};
|
|
615
|
+
}
|
|
616
|
+
} else {
|
|
617
|
+
parsedData = data;
|
|
618
|
+
}
|
|
619
|
+
return {
|
|
620
|
+
event,
|
|
621
|
+
...parsedData
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
function processChunk(chunk, onChunk) {
|
|
625
|
+
onChunk(chunk);
|
|
626
|
+
}
|
|
627
|
+
function updateJsonParserState(char, state) {
|
|
628
|
+
if (state.inString) {
|
|
629
|
+
if (state.escapeNext) {
|
|
630
|
+
state.escapeNext = false;
|
|
631
|
+
return false;
|
|
632
|
+
}
|
|
633
|
+
if (char === "\\") {
|
|
634
|
+
state.escapeNext = true;
|
|
635
|
+
return false;
|
|
636
|
+
}
|
|
637
|
+
if (char === '"') {
|
|
638
|
+
state.inString = false;
|
|
639
|
+
}
|
|
640
|
+
return false;
|
|
641
|
+
}
|
|
642
|
+
if (char === '"') {
|
|
643
|
+
state.inString = true;
|
|
644
|
+
return false;
|
|
645
|
+
}
|
|
646
|
+
if (char === "{") {
|
|
647
|
+
state.braceCount++;
|
|
648
|
+
return false;
|
|
649
|
+
}
|
|
650
|
+
if (char !== "}") {
|
|
651
|
+
return false;
|
|
652
|
+
}
|
|
653
|
+
state.braceCount--;
|
|
654
|
+
return state.braceCount === 0;
|
|
655
|
+
}
|
|
656
|
+
function findJsonSlice(buffer, fromIndex) {
|
|
657
|
+
const startIndex = buffer.indexOf("{", fromIndex);
|
|
658
|
+
if (startIndex === -1) {
|
|
659
|
+
return void 0;
|
|
660
|
+
}
|
|
661
|
+
const parserState = {
|
|
662
|
+
braceCount: 0,
|
|
663
|
+
inString: false,
|
|
664
|
+
escapeNext: false
|
|
665
|
+
};
|
|
666
|
+
for (let i = startIndex; i < buffer.length; i++) {
|
|
667
|
+
const isJsonComplete = updateJsonParserState(buffer[i], parserState);
|
|
668
|
+
if (isJsonComplete) {
|
|
669
|
+
return { startIndex, endIndex: i };
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
return void 0;
|
|
673
|
+
}
|
|
674
|
+
function logChunkParseError(error, jsonString, position) {
|
|
675
|
+
if (typeof process === "undefined" || process.env?.NODE_ENV !== "development") {
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
console.error("Failed to parse JSON chunk:", {
|
|
679
|
+
error,
|
|
680
|
+
chunk: jsonString.substring(0, 100) + (jsonString.length > 100 ? "..." : ""),
|
|
681
|
+
position
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
function processJsonSlice(jsonString, startIndex, onChunk) {
|
|
685
|
+
try {
|
|
686
|
+
const parsed = JSON.parse(jsonString);
|
|
687
|
+
if (isLegacyFormat(parsed)) {
|
|
688
|
+
processChunk(parsed, onChunk);
|
|
689
|
+
} else {
|
|
690
|
+
processChunk(convertNewFormatToLegacy(parsed), onChunk);
|
|
691
|
+
}
|
|
692
|
+
return true;
|
|
693
|
+
} catch (error) {
|
|
694
|
+
logChunkParseError(error, jsonString, startIndex);
|
|
695
|
+
if (jsonString.length > 1e4) {
|
|
696
|
+
throw new Error(
|
|
697
|
+
`Failed to parse large JSON chunk at position ${startIndex}`
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
return false;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
function parseBuffer(buffer, onChunk) {
|
|
704
|
+
let searchIndex = 0;
|
|
705
|
+
let remainingBuffer = buffer;
|
|
706
|
+
while (true) {
|
|
707
|
+
const jsonSlice = findJsonSlice(remainingBuffer, searchIndex);
|
|
708
|
+
if (!jsonSlice) {
|
|
709
|
+
break;
|
|
710
|
+
}
|
|
711
|
+
const jsonString = remainingBuffer.slice(
|
|
712
|
+
jsonSlice.startIndex,
|
|
713
|
+
jsonSlice.endIndex + 1
|
|
714
|
+
);
|
|
715
|
+
const parsed = processJsonSlice(jsonString, jsonSlice.startIndex, onChunk);
|
|
716
|
+
if (!parsed) {
|
|
717
|
+
searchIndex = jsonSlice.startIndex + 1;
|
|
718
|
+
continue;
|
|
719
|
+
}
|
|
720
|
+
remainingBuffer = remainingBuffer.slice(jsonSlice.endIndex + 1).trim();
|
|
721
|
+
searchIndex = 0;
|
|
722
|
+
}
|
|
723
|
+
return remainingBuffer;
|
|
724
|
+
}
|
|
725
|
+
function buildRequestHeaders(headers, requestBody) {
|
|
726
|
+
return {
|
|
727
|
+
...!(requestBody instanceof FormData) && {
|
|
728
|
+
"Content-Type": "application/json"
|
|
729
|
+
},
|
|
730
|
+
...headers
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
async function buildErrorMessage(response) {
|
|
734
|
+
const defaultMessage = `HTTP ${response.status}: ${response.statusText}`;
|
|
735
|
+
const contentType = response.headers.get("content-type");
|
|
736
|
+
if (!contentType?.includes("application/json")) {
|
|
737
|
+
return defaultMessage;
|
|
738
|
+
}
|
|
739
|
+
try {
|
|
740
|
+
const errorData = await response.json();
|
|
741
|
+
return errorData.detail || errorData.message || defaultMessage;
|
|
742
|
+
} catch {
|
|
743
|
+
return defaultMessage;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
async function consumeResponseStream(body, onChunk, onComplete) {
|
|
747
|
+
const reader = body.getReader();
|
|
748
|
+
const decoder = new TextDecoder();
|
|
749
|
+
let buffer = "";
|
|
750
|
+
while (true) {
|
|
751
|
+
const { done, value } = await reader.read();
|
|
752
|
+
if (done) {
|
|
753
|
+
parseBuffer(buffer, onChunk);
|
|
754
|
+
onComplete();
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
buffer += decoder.decode(value, { stream: true });
|
|
758
|
+
buffer = parseBuffer(buffer, onChunk);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
async function streamResponse(options) {
|
|
762
|
+
const {
|
|
763
|
+
apiUrl,
|
|
764
|
+
headers = {},
|
|
765
|
+
params,
|
|
766
|
+
requestBody,
|
|
767
|
+
onChunk,
|
|
768
|
+
onError,
|
|
769
|
+
onComplete,
|
|
770
|
+
signal
|
|
771
|
+
} = options;
|
|
772
|
+
const finalUrl = params?.toString() ? `${apiUrl}?${params.toString()}` : apiUrl;
|
|
773
|
+
try {
|
|
774
|
+
const response = await fetch(finalUrl, {
|
|
775
|
+
method: "POST",
|
|
776
|
+
headers: buildRequestHeaders(headers, requestBody),
|
|
777
|
+
body: requestBody instanceof FormData ? requestBody : JSON.stringify(requestBody),
|
|
778
|
+
signal
|
|
779
|
+
});
|
|
780
|
+
if (!response.ok) {
|
|
781
|
+
const errorMessage = await buildErrorMessage(response);
|
|
782
|
+
throw new StreamResponseHttpError(response.status, errorMessage);
|
|
783
|
+
}
|
|
784
|
+
if (!response.body) {
|
|
785
|
+
throw new Error("No response body");
|
|
786
|
+
}
|
|
787
|
+
await consumeResponseStream(response.body, onChunk, onComplete);
|
|
788
|
+
} catch (error) {
|
|
789
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
if (error instanceof Error) {
|
|
793
|
+
onError(error);
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
if (typeof error === "object" && error !== null && "detail" in error) {
|
|
797
|
+
onError(new Error(String(error.detail)));
|
|
798
|
+
} else {
|
|
799
|
+
onError(new Error(String(error)));
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
}
|
|
449
803
|
|
|
450
804
|
// src/processors/event-processor.ts
|
|
451
805
|
import { RunEvent as RunEventEnum } from "@antipopp/agno-types";
|
|
@@ -470,14 +824,18 @@ function processToolCall(toolCall, prevToolCalls = []) {
|
|
|
470
824
|
);
|
|
471
825
|
if (existingToolCallIndex >= 0) {
|
|
472
826
|
const updatedToolCalls = [...prevToolCalls];
|
|
473
|
-
updatedToolCalls[existingToolCallIndex]
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
827
|
+
const existing = updatedToolCalls[existingToolCallIndex];
|
|
828
|
+
const merged = { ...existing, ...toolCall };
|
|
829
|
+
if (existing.external_execution && existing.result !== void 0) {
|
|
830
|
+
merged.result = existing.result;
|
|
831
|
+
}
|
|
832
|
+
if (existing.ui_component !== void 0 && !toolCall.ui_component) {
|
|
833
|
+
merged.ui_component = existing.ui_component;
|
|
834
|
+
}
|
|
835
|
+
updatedToolCalls[existingToolCallIndex] = merged;
|
|
477
836
|
return updatedToolCalls;
|
|
478
|
-
} else {
|
|
479
|
-
return [...prevToolCalls, toolCall];
|
|
480
837
|
}
|
|
838
|
+
return [...prevToolCalls, toolCall];
|
|
481
839
|
}
|
|
482
840
|
function processChunkToolCalls(chunk, existingToolCalls = []) {
|
|
483
841
|
let updatedToolCalls = [...existingToolCalls];
|
|
@@ -495,6 +853,105 @@ var EventProcessor = class {
|
|
|
495
853
|
constructor() {
|
|
496
854
|
this.lastContent = "";
|
|
497
855
|
}
|
|
856
|
+
appendRunContent(chunk, updatedMessage) {
|
|
857
|
+
if (typeof chunk.content === "string") {
|
|
858
|
+
const uniqueContent = chunk.content.replace(this.lastContent, "");
|
|
859
|
+
updatedMessage.content = updatedMessage.content + uniqueContent;
|
|
860
|
+
this.lastContent = chunk.content;
|
|
861
|
+
return;
|
|
862
|
+
}
|
|
863
|
+
if (typeof chunk.content !== "string" && chunk.content !== null) {
|
|
864
|
+
const jsonBlock = getJsonMarkdown(chunk.content);
|
|
865
|
+
updatedMessage.content = updatedMessage.content + jsonBlock;
|
|
866
|
+
this.lastContent = jsonBlock;
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
applyRunContentFields(chunk, lastMessage, updatedMessage) {
|
|
870
|
+
this.appendRunContent(chunk, updatedMessage);
|
|
871
|
+
updatedMessage.tool_calls = processChunkToolCalls(
|
|
872
|
+
chunk,
|
|
873
|
+
lastMessage.tool_calls
|
|
874
|
+
);
|
|
875
|
+
if (chunk.extra_data?.reasoning_steps) {
|
|
876
|
+
updatedMessage.extra_data = {
|
|
877
|
+
...updatedMessage.extra_data,
|
|
878
|
+
reasoning_steps: chunk.extra_data.reasoning_steps
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
if (chunk.extra_data?.references) {
|
|
882
|
+
updatedMessage.extra_data = {
|
|
883
|
+
...updatedMessage.extra_data,
|
|
884
|
+
references: chunk.extra_data.references
|
|
885
|
+
};
|
|
886
|
+
}
|
|
887
|
+
updatedMessage.created_at = chunk.created_at ?? lastMessage.created_at;
|
|
888
|
+
if (chunk.images) {
|
|
889
|
+
updatedMessage.images = chunk.images;
|
|
890
|
+
}
|
|
891
|
+
if (chunk.image) {
|
|
892
|
+
const existingImages = updatedMessage.images ?? lastMessage.images ?? [];
|
|
893
|
+
const hasImage = existingImages.some((image) => {
|
|
894
|
+
if (image.id && chunk.image?.id) {
|
|
895
|
+
return image.id === chunk.image.id;
|
|
896
|
+
}
|
|
897
|
+
return image.url === chunk.image?.url;
|
|
898
|
+
});
|
|
899
|
+
if (!hasImage) {
|
|
900
|
+
updatedMessage.images = [...existingImages, chunk.image];
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
if (chunk.videos) {
|
|
904
|
+
updatedMessage.videos = chunk.videos;
|
|
905
|
+
}
|
|
906
|
+
if (chunk.audio) {
|
|
907
|
+
updatedMessage.audio = chunk.audio;
|
|
908
|
+
}
|
|
909
|
+
if (chunk.files) {
|
|
910
|
+
updatedMessage.files = chunk.files;
|
|
911
|
+
}
|
|
912
|
+
if (chunk.response_audio?.transcript && typeof chunk.response_audio.transcript === "string") {
|
|
913
|
+
updatedMessage.response_audio = {
|
|
914
|
+
...updatedMessage.response_audio,
|
|
915
|
+
transcript: (updatedMessage.response_audio?.transcript || "") + chunk.response_audio.transcript
|
|
916
|
+
};
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
applyCompletedFields(chunk, lastMessage, updatedMessage) {
|
|
920
|
+
let updatedContent;
|
|
921
|
+
if (typeof chunk.content === "string") {
|
|
922
|
+
updatedContent = chunk.content;
|
|
923
|
+
} else {
|
|
924
|
+
try {
|
|
925
|
+
updatedContent = JSON.stringify(chunk.content);
|
|
926
|
+
} catch {
|
|
927
|
+
updatedContent = "Error parsing response";
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
updatedMessage.content = updatedContent;
|
|
931
|
+
updatedMessage.tool_calls = processChunkToolCalls(
|
|
932
|
+
chunk,
|
|
933
|
+
lastMessage.tool_calls
|
|
934
|
+
);
|
|
935
|
+
const completedImages = chunk.images ?? (chunk.image ? [chunk.image] : void 0);
|
|
936
|
+
updatedMessage.images = completedImages ?? lastMessage.images;
|
|
937
|
+
updatedMessage.videos = chunk.videos ?? lastMessage.videos;
|
|
938
|
+
updatedMessage.audio = chunk.audio ?? lastMessage.audio;
|
|
939
|
+
updatedMessage.files = chunk.files ?? lastMessage.files;
|
|
940
|
+
updatedMessage.response_audio = chunk.response_audio;
|
|
941
|
+
updatedMessage.created_at = chunk.created_at ?? lastMessage.created_at;
|
|
942
|
+
updatedMessage.extra_data = {
|
|
943
|
+
reasoning_steps: chunk.extra_data?.reasoning_steps ?? lastMessage.extra_data?.reasoning_steps,
|
|
944
|
+
references: chunk.extra_data?.references ?? lastMessage.extra_data?.references
|
|
945
|
+
};
|
|
946
|
+
}
|
|
947
|
+
appendReasoningSteps(chunk, lastMessage, updatedMessage) {
|
|
948
|
+
const existingSteps = lastMessage.extra_data?.reasoning_steps ?? [];
|
|
949
|
+
const incomingSteps = chunk.extra_data?.reasoning_steps ?? [];
|
|
950
|
+
updatedMessage.extra_data = {
|
|
951
|
+
...updatedMessage.extra_data,
|
|
952
|
+
reasoning_steps: [...existingSteps, ...incomingSteps]
|
|
953
|
+
};
|
|
954
|
+
}
|
|
498
955
|
/**
|
|
499
956
|
* Process a chunk and update the last message
|
|
500
957
|
*/
|
|
@@ -521,58 +978,13 @@ var EventProcessor = class {
|
|
|
521
978
|
break;
|
|
522
979
|
case RunEventEnum.RunContent:
|
|
523
980
|
case RunEventEnum.TeamRunContent:
|
|
524
|
-
|
|
525
|
-
const uniqueContent = chunk.content.replace(this.lastContent, "");
|
|
526
|
-
updatedMessage.content = updatedMessage.content + uniqueContent;
|
|
527
|
-
this.lastContent = chunk.content;
|
|
528
|
-
} else if (typeof chunk.content !== "string" && chunk.content !== null) {
|
|
529
|
-
const jsonBlock = getJsonMarkdown(chunk.content);
|
|
530
|
-
updatedMessage.content = updatedMessage.content + jsonBlock;
|
|
531
|
-
this.lastContent = jsonBlock;
|
|
532
|
-
}
|
|
533
|
-
updatedMessage.tool_calls = processChunkToolCalls(
|
|
534
|
-
chunk,
|
|
535
|
-
lastMessage.tool_calls
|
|
536
|
-
);
|
|
537
|
-
if (chunk.extra_data?.reasoning_steps) {
|
|
538
|
-
updatedMessage.extra_data = {
|
|
539
|
-
...updatedMessage.extra_data,
|
|
540
|
-
reasoning_steps: chunk.extra_data.reasoning_steps
|
|
541
|
-
};
|
|
542
|
-
}
|
|
543
|
-
if (chunk.extra_data?.references) {
|
|
544
|
-
updatedMessage.extra_data = {
|
|
545
|
-
...updatedMessage.extra_data,
|
|
546
|
-
references: chunk.extra_data.references
|
|
547
|
-
};
|
|
548
|
-
}
|
|
549
|
-
updatedMessage.created_at = chunk.created_at ?? lastMessage.created_at;
|
|
550
|
-
if (chunk.images) {
|
|
551
|
-
updatedMessage.images = chunk.images;
|
|
552
|
-
}
|
|
553
|
-
if (chunk.videos) {
|
|
554
|
-
updatedMessage.videos = chunk.videos;
|
|
555
|
-
}
|
|
556
|
-
if (chunk.audio) {
|
|
557
|
-
updatedMessage.audio = chunk.audio;
|
|
558
|
-
}
|
|
559
|
-
if (chunk.response_audio?.transcript && typeof chunk.response_audio.transcript === "string") {
|
|
560
|
-
const transcript = chunk.response_audio.transcript;
|
|
561
|
-
updatedMessage.response_audio = {
|
|
562
|
-
...updatedMessage.response_audio,
|
|
563
|
-
transcript: (updatedMessage.response_audio?.transcript || "") + transcript
|
|
564
|
-
};
|
|
565
|
-
}
|
|
981
|
+
this.applyRunContentFields(chunk, lastMessage, updatedMessage);
|
|
566
982
|
break;
|
|
567
983
|
case RunEventEnum.ReasoningStep:
|
|
568
|
-
case RunEventEnum.TeamReasoningStep:
|
|
569
|
-
|
|
570
|
-
const incomingSteps = chunk.extra_data?.reasoning_steps ?? [];
|
|
571
|
-
updatedMessage.extra_data = {
|
|
572
|
-
...updatedMessage.extra_data,
|
|
573
|
-
reasoning_steps: [...existingSteps, ...incomingSteps]
|
|
574
|
-
};
|
|
984
|
+
case RunEventEnum.TeamReasoningStep: {
|
|
985
|
+
this.appendReasoningSteps(chunk, lastMessage, updatedMessage);
|
|
575
986
|
break;
|
|
987
|
+
}
|
|
576
988
|
case RunEventEnum.ReasoningCompleted:
|
|
577
989
|
case RunEventEnum.TeamReasoningCompleted:
|
|
578
990
|
if (chunk.extra_data?.reasoning_steps) {
|
|
@@ -583,31 +995,10 @@ var EventProcessor = class {
|
|
|
583
995
|
}
|
|
584
996
|
break;
|
|
585
997
|
case RunEventEnum.RunCompleted:
|
|
586
|
-
case RunEventEnum.TeamRunCompleted:
|
|
587
|
-
|
|
588
|
-
if (typeof chunk.content === "string") {
|
|
589
|
-
updatedContent = chunk.content;
|
|
590
|
-
} else {
|
|
591
|
-
try {
|
|
592
|
-
updatedContent = JSON.stringify(chunk.content);
|
|
593
|
-
} catch {
|
|
594
|
-
updatedContent = "Error parsing response";
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
updatedMessage.content = updatedContent;
|
|
598
|
-
updatedMessage.tool_calls = processChunkToolCalls(
|
|
599
|
-
chunk,
|
|
600
|
-
lastMessage.tool_calls
|
|
601
|
-
);
|
|
602
|
-
updatedMessage.images = chunk.images ?? lastMessage.images;
|
|
603
|
-
updatedMessage.videos = chunk.videos ?? lastMessage.videos;
|
|
604
|
-
updatedMessage.response_audio = chunk.response_audio;
|
|
605
|
-
updatedMessage.created_at = chunk.created_at ?? lastMessage.created_at;
|
|
606
|
-
updatedMessage.extra_data = {
|
|
607
|
-
reasoning_steps: chunk.extra_data?.reasoning_steps ?? lastMessage.extra_data?.reasoning_steps,
|
|
608
|
-
references: chunk.extra_data?.references ?? lastMessage.extra_data?.references
|
|
609
|
-
};
|
|
998
|
+
case RunEventEnum.TeamRunCompleted: {
|
|
999
|
+
this.applyCompletedFields(chunk, lastMessage, updatedMessage);
|
|
610
1000
|
break;
|
|
1001
|
+
}
|
|
611
1002
|
case RunEventEnum.UpdatingMemory:
|
|
612
1003
|
case RunEventEnum.TeamMemoryUpdateStarted:
|
|
613
1004
|
case RunEventEnum.TeamMemoryUpdateCompleted:
|
|
@@ -619,6 +1010,8 @@ var EventProcessor = class {
|
|
|
619
1010
|
case RunEventEnum.TeamRunCancelled:
|
|
620
1011
|
updatedMessage.streamingError = true;
|
|
621
1012
|
break;
|
|
1013
|
+
default:
|
|
1014
|
+
break;
|
|
622
1015
|
}
|
|
623
1016
|
return updatedMessage;
|
|
624
1017
|
}
|
|
@@ -630,166 +1023,95 @@ var EventProcessor = class {
|
|
|
630
1023
|
}
|
|
631
1024
|
};
|
|
632
1025
|
|
|
633
|
-
// src/
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
let inString = false;
|
|
663
|
-
let escapeNext = false;
|
|
664
|
-
let jsonEndIndex = -1;
|
|
665
|
-
let i = jsonStartIndex;
|
|
666
|
-
for (; i < buffer.length; i++) {
|
|
667
|
-
const char = buffer[i];
|
|
668
|
-
if (inString) {
|
|
669
|
-
if (escapeNext) {
|
|
670
|
-
escapeNext = false;
|
|
671
|
-
} else if (char === "\\") {
|
|
672
|
-
escapeNext = true;
|
|
673
|
-
} else if (char === '"') {
|
|
674
|
-
inString = false;
|
|
675
|
-
}
|
|
676
|
-
} else {
|
|
677
|
-
if (char === '"') {
|
|
678
|
-
inString = true;
|
|
679
|
-
} else if (char === "{") {
|
|
680
|
-
braceCount++;
|
|
681
|
-
} else if (char === "}") {
|
|
682
|
-
braceCount--;
|
|
683
|
-
if (braceCount === 0) {
|
|
684
|
-
jsonEndIndex = i;
|
|
685
|
-
break;
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
if (jsonEndIndex !== -1) {
|
|
691
|
-
const jsonString = buffer.slice(jsonStartIndex, jsonEndIndex + 1);
|
|
692
|
-
try {
|
|
693
|
-
const parsed = JSON.parse(jsonString);
|
|
694
|
-
if (isLegacyFormat(parsed)) {
|
|
695
|
-
processChunk(parsed, onChunk);
|
|
696
|
-
} else {
|
|
697
|
-
const legacyChunk = convertNewFormatToLegacy(parsed);
|
|
698
|
-
processChunk(legacyChunk, onChunk);
|
|
699
|
-
}
|
|
700
|
-
} catch (error) {
|
|
701
|
-
if (typeof process !== "undefined" && process.env?.NODE_ENV === "development") {
|
|
702
|
-
console.error("Failed to parse JSON chunk:", {
|
|
703
|
-
error,
|
|
704
|
-
chunk: jsonString.substring(0, 100) + (jsonString.length > 100 ? "..." : ""),
|
|
705
|
-
position: jsonStartIndex
|
|
706
|
-
});
|
|
707
|
-
}
|
|
708
|
-
if (jsonString.length > 1e4) {
|
|
709
|
-
throw new Error(`Failed to parse large JSON chunk at position ${jsonStartIndex}`);
|
|
710
|
-
}
|
|
711
|
-
jsonStartIndex = buffer.indexOf("{", jsonStartIndex + 1);
|
|
712
|
-
continue;
|
|
713
|
-
}
|
|
714
|
-
currentIndex = jsonEndIndex + 1;
|
|
715
|
-
buffer = buffer.slice(currentIndex).trim();
|
|
716
|
-
currentIndex = 0;
|
|
717
|
-
jsonStartIndex = buffer.indexOf("{", currentIndex);
|
|
718
|
-
} else {
|
|
719
|
-
break;
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
return buffer;
|
|
723
|
-
}
|
|
724
|
-
async function streamResponse(options) {
|
|
725
|
-
const {
|
|
726
|
-
apiUrl,
|
|
727
|
-
headers = {},
|
|
728
|
-
params,
|
|
729
|
-
requestBody,
|
|
730
|
-
onChunk,
|
|
731
|
-
onError,
|
|
732
|
-
onComplete,
|
|
733
|
-
signal
|
|
734
|
-
} = options;
|
|
735
|
-
let buffer = "";
|
|
736
|
-
const finalUrl = params && params.toString() ? `${apiUrl}?${params.toString()}` : apiUrl;
|
|
737
|
-
try {
|
|
738
|
-
const response = await fetch(finalUrl, {
|
|
739
|
-
method: "POST",
|
|
740
|
-
headers: {
|
|
741
|
-
...!(requestBody instanceof FormData) && {
|
|
742
|
-
"Content-Type": "application/json"
|
|
743
|
-
},
|
|
744
|
-
...headers
|
|
745
|
-
},
|
|
746
|
-
body: requestBody instanceof FormData ? requestBody : JSON.stringify(requestBody),
|
|
747
|
-
signal
|
|
748
|
-
});
|
|
749
|
-
if (!response.ok) {
|
|
750
|
-
let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
|
|
751
|
-
const contentType = response.headers.get("content-type");
|
|
752
|
-
if (contentType?.includes("application/json")) {
|
|
753
|
-
try {
|
|
754
|
-
const errorData = await response.json();
|
|
755
|
-
errorMessage = errorData.detail || errorData.message || errorMessage;
|
|
756
|
-
} catch {
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
throw new Error(errorMessage);
|
|
760
|
-
}
|
|
761
|
-
if (!response.body) {
|
|
762
|
-
throw new Error("No response body");
|
|
1026
|
+
// src/stores/message-store.ts
|
|
1027
|
+
var MessageStore = class {
|
|
1028
|
+
constructor() {
|
|
1029
|
+
this.messages = [];
|
|
1030
|
+
}
|
|
1031
|
+
/**
|
|
1032
|
+
* Get all messages
|
|
1033
|
+
*/
|
|
1034
|
+
getMessages() {
|
|
1035
|
+
return [...this.messages];
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Set messages (replaces all)
|
|
1039
|
+
*/
|
|
1040
|
+
setMessages(messages) {
|
|
1041
|
+
this.messages = [...messages];
|
|
1042
|
+
}
|
|
1043
|
+
/**
|
|
1044
|
+
* Add a message
|
|
1045
|
+
*/
|
|
1046
|
+
addMessage(message) {
|
|
1047
|
+
this.messages = [...this.messages, message];
|
|
1048
|
+
}
|
|
1049
|
+
/**
|
|
1050
|
+
* Update the last message
|
|
1051
|
+
*/
|
|
1052
|
+
updateLastMessage(updater) {
|
|
1053
|
+
if (this.messages.length === 0) {
|
|
1054
|
+
return void 0;
|
|
763
1055
|
}
|
|
764
|
-
const
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
while (true) {
|
|
768
|
-
const { done, value } = await reader.read();
|
|
769
|
-
if (done) {
|
|
770
|
-
buffer = parseBuffer(buffer, onChunk);
|
|
771
|
-
onComplete();
|
|
772
|
-
return;
|
|
773
|
-
}
|
|
774
|
-
buffer += decoder.decode(value, { stream: true });
|
|
775
|
-
buffer = parseBuffer(buffer, onChunk);
|
|
776
|
-
}
|
|
777
|
-
};
|
|
778
|
-
await processStream();
|
|
779
|
-
} catch (error) {
|
|
780
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
781
|
-
return;
|
|
1056
|
+
const lastMessage = this.messages.at(-1);
|
|
1057
|
+
if (!lastMessage) {
|
|
1058
|
+
return void 0;
|
|
782
1059
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
1060
|
+
const updatedMessage = updater(lastMessage);
|
|
1061
|
+
this.messages = [...this.messages.slice(0, -1), updatedMessage];
|
|
1062
|
+
return updatedMessage;
|
|
1063
|
+
}
|
|
1064
|
+
/**
|
|
1065
|
+
* Update a specific message by index
|
|
1066
|
+
*/
|
|
1067
|
+
updateMessage(index, updater) {
|
|
1068
|
+
if (index < 0 || index >= this.messages.length) {
|
|
1069
|
+
return void 0;
|
|
787
1070
|
}
|
|
1071
|
+
const message = this.messages[index];
|
|
1072
|
+
const updatedMessage = updater(message);
|
|
1073
|
+
this.messages = [
|
|
1074
|
+
...this.messages.slice(0, index),
|
|
1075
|
+
updatedMessage,
|
|
1076
|
+
...this.messages.slice(index + 1)
|
|
1077
|
+
];
|
|
1078
|
+
return updatedMessage;
|
|
788
1079
|
}
|
|
789
|
-
|
|
1080
|
+
/**
|
|
1081
|
+
* Remove last N messages
|
|
1082
|
+
*/
|
|
1083
|
+
removeLastMessages(count) {
|
|
1084
|
+
this.messages = this.messages.slice(0, -count);
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* Clear all messages
|
|
1088
|
+
*/
|
|
1089
|
+
clear() {
|
|
1090
|
+
this.messages = [];
|
|
1091
|
+
}
|
|
1092
|
+
/**
|
|
1093
|
+
* Get the last message
|
|
1094
|
+
*/
|
|
1095
|
+
getLastMessage() {
|
|
1096
|
+
return this.messages.length > 0 ? this.messages.at(-1) : void 0;
|
|
1097
|
+
}
|
|
1098
|
+
/**
|
|
1099
|
+
* Check if last message has streaming error
|
|
1100
|
+
*/
|
|
1101
|
+
hasLastMessageError() {
|
|
1102
|
+
const lastMessage = this.getLastMessage();
|
|
1103
|
+
return lastMessage?.streamingError === true;
|
|
1104
|
+
}
|
|
1105
|
+
};
|
|
790
1106
|
|
|
791
1107
|
// src/utils/logger.ts
|
|
792
|
-
var SENSITIVE_KEYS = [
|
|
1108
|
+
var SENSITIVE_KEYS = [
|
|
1109
|
+
"authToken",
|
|
1110
|
+
"Authorization",
|
|
1111
|
+
"token",
|
|
1112
|
+
"password",
|
|
1113
|
+
"apiKey"
|
|
1114
|
+
];
|
|
793
1115
|
function sanitizeObject(obj) {
|
|
794
1116
|
if (obj === null || obj === void 0) {
|
|
795
1117
|
return obj;
|
|
@@ -817,36 +1139,36 @@ function sanitizeObject(obj) {
|
|
|
817
1139
|
function isDevelopment() {
|
|
818
1140
|
return typeof process !== "undefined" && process.env?.NODE_ENV === "development";
|
|
819
1141
|
}
|
|
820
|
-
var Logger =
|
|
1142
|
+
var Logger = {
|
|
821
1143
|
/**
|
|
822
1144
|
* Log debug information (only in development)
|
|
823
1145
|
*/
|
|
824
|
-
|
|
1146
|
+
debug(message, data) {
|
|
825
1147
|
if (isDevelopment()) {
|
|
826
1148
|
const sanitized = data ? sanitizeObject(data) : void 0;
|
|
827
1149
|
console.debug(`[DEBUG] ${message}`, sanitized || "");
|
|
828
1150
|
}
|
|
829
|
-
}
|
|
1151
|
+
},
|
|
830
1152
|
/**
|
|
831
1153
|
* Log informational messages (only in development)
|
|
832
1154
|
*/
|
|
833
|
-
|
|
1155
|
+
info(message, data) {
|
|
834
1156
|
if (isDevelopment()) {
|
|
835
1157
|
const sanitized = data ? sanitizeObject(data) : void 0;
|
|
836
1158
|
console.info(`[INFO] ${message}`, sanitized || "");
|
|
837
1159
|
}
|
|
838
|
-
}
|
|
1160
|
+
},
|
|
839
1161
|
/**
|
|
840
1162
|
* Log warnings (always logs)
|
|
841
1163
|
*/
|
|
842
|
-
|
|
1164
|
+
warn(message, data) {
|
|
843
1165
|
const sanitized = data ? sanitizeObject(data) : void 0;
|
|
844
1166
|
console.warn(`[WARN] ${message}`, sanitized || "");
|
|
845
|
-
}
|
|
1167
|
+
},
|
|
846
1168
|
/**
|
|
847
1169
|
* Log errors (always logs)
|
|
848
1170
|
*/
|
|
849
|
-
|
|
1171
|
+
error(message, data) {
|
|
850
1172
|
const sanitized = data ? sanitizeObject(data) : void 0;
|
|
851
1173
|
console.error(`[ERROR] ${message}`, sanitized || "");
|
|
852
1174
|
}
|
|
@@ -864,19 +1186,104 @@ function toSafeISOString(timestamp) {
|
|
|
864
1186
|
}
|
|
865
1187
|
return new Date(ts).toISOString();
|
|
866
1188
|
}
|
|
1189
|
+
function getFileName(file, index) {
|
|
1190
|
+
if ("name" in file && typeof file.name === "string" && file.name) {
|
|
1191
|
+
return file.name;
|
|
1192
|
+
}
|
|
1193
|
+
return `file-${index}`;
|
|
1194
|
+
}
|
|
1195
|
+
function getFileFormat(mimeType) {
|
|
1196
|
+
if (!mimeType) {
|
|
1197
|
+
return void 0;
|
|
1198
|
+
}
|
|
1199
|
+
const [, subtype] = mimeType.split("/");
|
|
1200
|
+
if (!subtype) {
|
|
1201
|
+
return void 0;
|
|
1202
|
+
}
|
|
1203
|
+
return subtype.split(";")[0]?.trim().toLowerCase() || void 0;
|
|
1204
|
+
}
|
|
1205
|
+
function createPreviewUrl(file) {
|
|
1206
|
+
if (typeof URL === "undefined" || typeof URL.createObjectURL !== "function") {
|
|
1207
|
+
return void 0;
|
|
1208
|
+
}
|
|
1209
|
+
try {
|
|
1210
|
+
return URL.createObjectURL(file);
|
|
1211
|
+
} catch {
|
|
1212
|
+
return void 0;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
function buildMessageMediaPayload(files) {
|
|
1216
|
+
const images = [];
|
|
1217
|
+
const videos = [];
|
|
1218
|
+
const audio = [];
|
|
1219
|
+
const fileAttachments = [];
|
|
1220
|
+
const objectUrls = [];
|
|
1221
|
+
files.forEach((file, index) => {
|
|
1222
|
+
const filename = getFileName(file, index);
|
|
1223
|
+
const mimeType = file.type || "application/octet-stream";
|
|
1224
|
+
const format = getFileFormat(mimeType);
|
|
1225
|
+
const previewUrl = createPreviewUrl(file);
|
|
1226
|
+
if (previewUrl) {
|
|
1227
|
+
objectUrls.push(previewUrl);
|
|
1228
|
+
}
|
|
1229
|
+
if (mimeType.startsWith("image/") && previewUrl) {
|
|
1230
|
+
images.push({
|
|
1231
|
+
url: previewUrl,
|
|
1232
|
+
mime_type: mimeType,
|
|
1233
|
+
format
|
|
1234
|
+
});
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
1237
|
+
if (mimeType.startsWith("video/")) {
|
|
1238
|
+
videos.push({
|
|
1239
|
+
url: previewUrl,
|
|
1240
|
+
id: filename,
|
|
1241
|
+
mime_type: mimeType,
|
|
1242
|
+
format
|
|
1243
|
+
});
|
|
1244
|
+
return;
|
|
1245
|
+
}
|
|
1246
|
+
if (mimeType.startsWith("audio/")) {
|
|
1247
|
+
audio.push({
|
|
1248
|
+
url: previewUrl,
|
|
1249
|
+
id: filename,
|
|
1250
|
+
mime_type: mimeType,
|
|
1251
|
+
format
|
|
1252
|
+
});
|
|
1253
|
+
return;
|
|
1254
|
+
}
|
|
1255
|
+
fileAttachments.push({
|
|
1256
|
+
filename,
|
|
1257
|
+
name: filename,
|
|
1258
|
+
mime_type: mimeType,
|
|
1259
|
+
format,
|
|
1260
|
+
size: file.size,
|
|
1261
|
+
url: previewUrl
|
|
1262
|
+
});
|
|
1263
|
+
});
|
|
1264
|
+
return {
|
|
1265
|
+
images: images.length > 0 ? images : void 0,
|
|
1266
|
+
videos: videos.length > 0 ? videos : void 0,
|
|
1267
|
+
audio: audio.length > 0 ? audio : void 0,
|
|
1268
|
+
files: fileAttachments.length > 0 ? fileAttachments : void 0,
|
|
1269
|
+
objectUrls
|
|
1270
|
+
};
|
|
1271
|
+
}
|
|
867
1272
|
var AgnoClient = class extends EventEmitter {
|
|
868
1273
|
constructor(config) {
|
|
869
1274
|
super();
|
|
870
|
-
// toolCallId -> UIComponentSpec
|
|
871
1275
|
this.runCompletedSuccessfully = false;
|
|
1276
|
+
this.currentAbortController = null;
|
|
872
1277
|
this.messageStore = new MessageStore();
|
|
873
1278
|
this.configManager = new ConfigManager(config);
|
|
874
1279
|
this.sessionManager = new SessionManager();
|
|
875
1280
|
this.eventProcessor = new EventProcessor();
|
|
876
1281
|
this.pendingUISpecs = /* @__PURE__ */ new Map();
|
|
1282
|
+
this.localAttachmentUrls = /* @__PURE__ */ new Set();
|
|
877
1283
|
this.state = {
|
|
878
1284
|
isStreaming: false,
|
|
879
1285
|
isRefreshing: false,
|
|
1286
|
+
isCancelling: false,
|
|
880
1287
|
isEndpointActive: false,
|
|
881
1288
|
agents: [],
|
|
882
1289
|
teams: [],
|
|
@@ -915,12 +1322,99 @@ var AgnoClient = class extends EventEmitter {
|
|
|
915
1322
|
* Clear all messages
|
|
916
1323
|
*/
|
|
917
1324
|
clearMessages() {
|
|
1325
|
+
this.revokeAttachmentUrlsFromMessages(this.messageStore.getMessages());
|
|
1326
|
+
this.localAttachmentUrls.clear();
|
|
918
1327
|
this.messageStore.clear();
|
|
919
1328
|
this.configManager.setSessionId(void 0);
|
|
920
1329
|
this.pendingUISpecs.clear();
|
|
921
1330
|
this.emit("message:update", this.messageStore.getMessages());
|
|
922
1331
|
this.emit("state:change", this.getState());
|
|
923
1332
|
}
|
|
1333
|
+
/**
|
|
1334
|
+
* Cancel an active or paused run
|
|
1335
|
+
*/
|
|
1336
|
+
async cancelRun() {
|
|
1337
|
+
if (!(this.state.isStreaming || this.state.isPaused)) {
|
|
1338
|
+
throw new Error("No active or paused run to cancel");
|
|
1339
|
+
}
|
|
1340
|
+
const runId = this.state.pausedRunId || this.currentRunId;
|
|
1341
|
+
if (this.currentAbortController) {
|
|
1342
|
+
this.currentAbortController.abort();
|
|
1343
|
+
this.currentAbortController = null;
|
|
1344
|
+
}
|
|
1345
|
+
this.state.isCancelling = true;
|
|
1346
|
+
this.emit("state:change", this.getState());
|
|
1347
|
+
const cancelErrorMessage = runId ? await this.requestBackendCancel(runId) : this.logMissingRunIdForCancel();
|
|
1348
|
+
this.state.isStreaming = false;
|
|
1349
|
+
this.state.isPaused = false;
|
|
1350
|
+
this.state.isCancelling = false;
|
|
1351
|
+
this.state.pausedRunId = void 0;
|
|
1352
|
+
this.state.toolsAwaitingExecution = void 0;
|
|
1353
|
+
this.currentRunId = void 0;
|
|
1354
|
+
if (cancelErrorMessage) {
|
|
1355
|
+
this.state.errorMessage = cancelErrorMessage;
|
|
1356
|
+
this.emit("message:error", cancelErrorMessage);
|
|
1357
|
+
}
|
|
1358
|
+
this.emit("run:cancelled", { runId });
|
|
1359
|
+
this.emit("state:change", this.getState());
|
|
1360
|
+
}
|
|
1361
|
+
logMissingRunIdForCancel() {
|
|
1362
|
+
Logger.warn(
|
|
1363
|
+
"[AgnoClient] No run ID available, skipping backend cancel request"
|
|
1364
|
+
);
|
|
1365
|
+
return void 0;
|
|
1366
|
+
}
|
|
1367
|
+
async requestBackendCancel(runId) {
|
|
1368
|
+
const runUrl = this.configManager.getRunUrl();
|
|
1369
|
+
if (!runUrl) {
|
|
1370
|
+
const message = "Run cancelled locally, but backend cancel could not be sent: no agent or team selected";
|
|
1371
|
+
Logger.warn(`[AgnoClient] ${message}`);
|
|
1372
|
+
return message;
|
|
1373
|
+
}
|
|
1374
|
+
const cancelUrl = `${runUrl}/${runId}/cancel`;
|
|
1375
|
+
const headers = this.configManager.buildRequestHeaders();
|
|
1376
|
+
try {
|
|
1377
|
+
const response = await fetch(cancelUrl, {
|
|
1378
|
+
method: "POST",
|
|
1379
|
+
headers
|
|
1380
|
+
});
|
|
1381
|
+
if (response.ok) {
|
|
1382
|
+
return void 0;
|
|
1383
|
+
}
|
|
1384
|
+
if (response.status === 401 || response.status === 403) {
|
|
1385
|
+
const message = `Run cancelled locally, but backend cancel was rejected (${response.status})`;
|
|
1386
|
+
Logger.warn(`[AgnoClient] ${message}`);
|
|
1387
|
+
return message;
|
|
1388
|
+
}
|
|
1389
|
+
Logger.warn(
|
|
1390
|
+
`[AgnoClient] Backend cancel returned ${response.status} \u2014 run may have already completed`
|
|
1391
|
+
);
|
|
1392
|
+
return void 0;
|
|
1393
|
+
} catch (error) {
|
|
1394
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
1395
|
+
const message = `Run cancelled locally, but backend cancel failed: ${reason}`;
|
|
1396
|
+
Logger.warn(`[AgnoClient] ${message}`);
|
|
1397
|
+
return message;
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
/**
|
|
1401
|
+
* Abort the active stream without calling the backend cancel endpoint.
|
|
1402
|
+
* Since streamResponse handles AbortError by returning silently
|
|
1403
|
+
* (no onComplete/onError called), state cleanup is done here.
|
|
1404
|
+
*/
|
|
1405
|
+
abortStream() {
|
|
1406
|
+
if (!this.state.isStreaming) {
|
|
1407
|
+
return;
|
|
1408
|
+
}
|
|
1409
|
+
if (this.currentAbortController) {
|
|
1410
|
+
this.currentAbortController.abort();
|
|
1411
|
+
this.currentAbortController = null;
|
|
1412
|
+
}
|
|
1413
|
+
this.state.isStreaming = false;
|
|
1414
|
+
this.currentRunId = void 0;
|
|
1415
|
+
this.emit("stream:end");
|
|
1416
|
+
this.emit("state:change", this.getState());
|
|
1417
|
+
}
|
|
924
1418
|
/**
|
|
925
1419
|
* Send a message to the agent/team (streaming)
|
|
926
1420
|
*/
|
|
@@ -941,16 +1435,30 @@ var AgnoClient = class extends EventEmitter {
|
|
|
941
1435
|
if (typeof message === "string") {
|
|
942
1436
|
formData.append("message", message);
|
|
943
1437
|
}
|
|
1438
|
+
if (options?.files) {
|
|
1439
|
+
options.files.forEach((file, index) => {
|
|
1440
|
+
formData.append("files", file, getFileName(file, index));
|
|
1441
|
+
});
|
|
1442
|
+
}
|
|
1443
|
+
const requestFiles = formData.getAll("files").filter((entry) => typeof entry !== "string");
|
|
1444
|
+
const userMessageMedia = buildMessageMediaPayload(requestFiles);
|
|
1445
|
+
this.trackAttachmentUrls(userMessageMedia.objectUrls);
|
|
1446
|
+
const userMessageContent = String(formData.get("message") ?? "");
|
|
944
1447
|
const lastMessage = this.messageStore.getLastMessage();
|
|
945
1448
|
if (lastMessage?.streamingError) {
|
|
946
1449
|
const secondLast = this.messageStore.getMessages()[this.messageStore.getMessages().length - 2];
|
|
947
1450
|
if (secondLast?.role === "user") {
|
|
1451
|
+
this.revokeAttachmentUrlsFromMessages([secondLast, lastMessage]);
|
|
948
1452
|
this.messageStore.removeLastMessages(2);
|
|
949
1453
|
}
|
|
950
1454
|
}
|
|
951
1455
|
this.messageStore.addMessage({
|
|
952
1456
|
role: "user",
|
|
953
|
-
content:
|
|
1457
|
+
content: userMessageContent,
|
|
1458
|
+
images: userMessageMedia.images,
|
|
1459
|
+
videos: userMessageMedia.videos,
|
|
1460
|
+
audio: userMessageMedia.audio,
|
|
1461
|
+
files: userMessageMedia.files,
|
|
954
1462
|
created_at: Math.floor(Date.now() / 1e3)
|
|
955
1463
|
});
|
|
956
1464
|
this.messageStore.addMessage({
|
|
@@ -964,33 +1472,42 @@ var AgnoClient = class extends EventEmitter {
|
|
|
964
1472
|
this.eventProcessor.reset();
|
|
965
1473
|
let newSessionId = this.configManager.getSessionId();
|
|
966
1474
|
try {
|
|
967
|
-
formData.
|
|
968
|
-
formData.
|
|
1475
|
+
formData.set("stream", "true");
|
|
1476
|
+
formData.set("session_id", newSessionId ?? "");
|
|
969
1477
|
const userId = this.configManager.getUserId();
|
|
970
1478
|
if (userId) {
|
|
971
|
-
formData.
|
|
1479
|
+
formData.set("user_id", userId);
|
|
1480
|
+
}
|
|
1481
|
+
const dependencies = this.configManager.buildDependencies(
|
|
1482
|
+
options?.dependencies
|
|
1483
|
+
);
|
|
1484
|
+
if (dependencies) {
|
|
1485
|
+
formData.set("dependencies", JSON.stringify(dependencies));
|
|
972
1486
|
}
|
|
973
1487
|
const headers = this.configManager.buildRequestHeaders(options?.headers);
|
|
974
1488
|
const params = this.configManager.buildQueryString(options?.params);
|
|
1489
|
+
this.currentAbortController = new AbortController();
|
|
975
1490
|
await streamResponse({
|
|
976
1491
|
apiUrl: runUrl,
|
|
977
1492
|
headers,
|
|
978
1493
|
params,
|
|
979
1494
|
requestBody: formData,
|
|
1495
|
+
signal: this.currentAbortController.signal,
|
|
980
1496
|
onChunk: (chunk) => {
|
|
981
|
-
this.handleChunk(chunk, newSessionId,
|
|
982
|
-
if (chunk.event === RunEvent.RunStarted || chunk.event === RunEvent.TeamRunStarted || chunk.event === RunEvent.ReasoningStarted || chunk.event === RunEvent.TeamReasoningStarted) {
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
this.configManager.setSessionId(chunk.session_id);
|
|
986
|
-
}
|
|
1497
|
+
this.handleChunk(chunk, newSessionId, userMessageContent);
|
|
1498
|
+
if ((chunk.event === RunEvent.RunStarted || chunk.event === RunEvent.TeamRunStarted || chunk.event === RunEvent.ReasoningStarted || chunk.event === RunEvent.TeamReasoningStarted) && chunk.session_id) {
|
|
1499
|
+
newSessionId = chunk.session_id;
|
|
1500
|
+
this.configManager.setSessionId(chunk.session_id);
|
|
987
1501
|
}
|
|
988
1502
|
},
|
|
989
1503
|
onError: (error) => {
|
|
1504
|
+
this.currentAbortController = null;
|
|
990
1505
|
this.handleError(error, newSessionId);
|
|
991
1506
|
},
|
|
992
1507
|
onComplete: async () => {
|
|
1508
|
+
this.currentAbortController = null;
|
|
993
1509
|
this.state.isStreaming = false;
|
|
1510
|
+
this.currentRunId = void 0;
|
|
994
1511
|
this.emit("stream:end");
|
|
995
1512
|
this.emit("message:complete", this.messageStore.getMessages());
|
|
996
1513
|
this.emit("state:change", this.getState());
|
|
@@ -1001,6 +1518,7 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1001
1518
|
}
|
|
1002
1519
|
});
|
|
1003
1520
|
} catch (error) {
|
|
1521
|
+
this.currentAbortController = null;
|
|
1004
1522
|
this.handleError(
|
|
1005
1523
|
error instanceof Error ? error : new Error(String(error)),
|
|
1006
1524
|
newSessionId
|
|
@@ -1012,20 +1530,21 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1012
1530
|
*/
|
|
1013
1531
|
handleChunk(chunk, currentSessionId, messageContent) {
|
|
1014
1532
|
const event = chunk.event;
|
|
1015
|
-
if (event === RunEvent.RunStarted || event === RunEvent.TeamRunStarted
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1533
|
+
if ((event === RunEvent.RunStarted || event === RunEvent.TeamRunStarted) && chunk.run_id) {
|
|
1534
|
+
this.currentRunId = chunk.run_id;
|
|
1535
|
+
}
|
|
1536
|
+
if ((event === RunEvent.RunStarted || event === RunEvent.TeamRunStarted || event === RunEvent.ReasoningStarted || event === RunEvent.TeamReasoningStarted) && chunk.session_id && (!currentSessionId || currentSessionId !== chunk.session_id)) {
|
|
1537
|
+
const sessionData = {
|
|
1538
|
+
session_id: chunk.session_id,
|
|
1539
|
+
session_name: messageContent,
|
|
1540
|
+
created_at: toSafeISOString(chunk.created_at)
|
|
1541
|
+
};
|
|
1542
|
+
const sessionExists = this.state.sessions.some(
|
|
1543
|
+
(s) => s.session_id === chunk.session_id
|
|
1544
|
+
);
|
|
1545
|
+
if (!sessionExists) {
|
|
1546
|
+
this.state.sessions = [sessionData, ...this.state.sessions];
|
|
1547
|
+
this.emit("session:created", sessionData);
|
|
1029
1548
|
}
|
|
1030
1549
|
}
|
|
1031
1550
|
if (event === RunEvent.RunPaused) {
|
|
@@ -1085,6 +1604,73 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1085
1604
|
this.emit("stream:end");
|
|
1086
1605
|
this.emit("state:change", this.getState());
|
|
1087
1606
|
}
|
|
1607
|
+
trackAttachmentUrls(urls) {
|
|
1608
|
+
for (const url of urls) {
|
|
1609
|
+
this.localAttachmentUrls.add(url);
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
collectAttachmentUrls(message) {
|
|
1613
|
+
const imageUrls = message.images?.map((image) => image.url) ?? [];
|
|
1614
|
+
const videoUrls = message.videos?.map((video) => video.url).filter((url) => Boolean(url)) ?? [];
|
|
1615
|
+
const audioUrls = message.audio?.map((audio) => audio.url).filter((url) => Boolean(url)) ?? [];
|
|
1616
|
+
const fileUrls = message.files?.map((file) => file.url).filter((url) => Boolean(url)) ?? [];
|
|
1617
|
+
return [...imageUrls, ...videoUrls, ...audioUrls, ...fileUrls];
|
|
1618
|
+
}
|
|
1619
|
+
revokeAttachmentUrls(urls) {
|
|
1620
|
+
if (typeof URL === "undefined" || typeof URL.revokeObjectURL !== "function") {
|
|
1621
|
+
return;
|
|
1622
|
+
}
|
|
1623
|
+
for (const url of urls) {
|
|
1624
|
+
if (!this.localAttachmentUrls.has(url)) {
|
|
1625
|
+
continue;
|
|
1626
|
+
}
|
|
1627
|
+
URL.revokeObjectURL(url);
|
|
1628
|
+
this.localAttachmentUrls.delete(url);
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
revokeAttachmentUrlsFromMessages(messages) {
|
|
1632
|
+
const urls = [];
|
|
1633
|
+
for (const message of messages) {
|
|
1634
|
+
if (!message) {
|
|
1635
|
+
continue;
|
|
1636
|
+
}
|
|
1637
|
+
urls.push(...this.collectAttachmentUrls(message));
|
|
1638
|
+
}
|
|
1639
|
+
this.revokeAttachmentUrls(urls);
|
|
1640
|
+
}
|
|
1641
|
+
collectExistingUIComponents() {
|
|
1642
|
+
const existingUIComponents = /* @__PURE__ */ new Map();
|
|
1643
|
+
for (const message of this.messageStore.getMessages()) {
|
|
1644
|
+
if (!message.tool_calls) {
|
|
1645
|
+
continue;
|
|
1646
|
+
}
|
|
1647
|
+
for (const toolCall of message.tool_calls) {
|
|
1648
|
+
if (toolCall.ui_component) {
|
|
1649
|
+
existingUIComponents.set(
|
|
1650
|
+
toolCall.tool_call_id,
|
|
1651
|
+
toolCall.ui_component
|
|
1652
|
+
);
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
return existingUIComponents;
|
|
1657
|
+
}
|
|
1658
|
+
restoreUIComponents(messages, uiComponents) {
|
|
1659
|
+
if (uiComponents.size === 0) {
|
|
1660
|
+
return;
|
|
1661
|
+
}
|
|
1662
|
+
for (const message of messages) {
|
|
1663
|
+
if (!message.tool_calls) {
|
|
1664
|
+
continue;
|
|
1665
|
+
}
|
|
1666
|
+
for (const toolCall of message.tool_calls) {
|
|
1667
|
+
const uiComponent = uiComponents.get(toolCall.tool_call_id);
|
|
1668
|
+
if (uiComponent) {
|
|
1669
|
+
toolCall.ui_component = uiComponent;
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1088
1674
|
/**
|
|
1089
1675
|
* Refresh messages from the session API after run completion.
|
|
1090
1676
|
* Replaces streamed messages with authoritative session data.
|
|
@@ -1097,19 +1683,14 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1097
1683
|
Logger.debug("[AgnoClient] Cannot refresh: no session ID");
|
|
1098
1684
|
return;
|
|
1099
1685
|
}
|
|
1686
|
+
if (this.state.isStreaming) {
|
|
1687
|
+
Logger.debug("[AgnoClient] Skipping refresh: stream is active");
|
|
1688
|
+
return;
|
|
1689
|
+
}
|
|
1100
1690
|
this.state.isRefreshing = true;
|
|
1101
1691
|
this.emit("state:change", this.getState());
|
|
1102
1692
|
try {
|
|
1103
|
-
const existingUIComponents =
|
|
1104
|
-
for (const message of this.messageStore.getMessages()) {
|
|
1105
|
-
if (message.tool_calls) {
|
|
1106
|
-
for (const toolCall of message.tool_calls) {
|
|
1107
|
-
if (toolCall.ui_component) {
|
|
1108
|
-
existingUIComponents.set(toolCall.tool_call_id, toolCall.ui_component);
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1693
|
+
const existingUIComponents = this.collectExistingUIComponents();
|
|
1113
1694
|
const config = this.configManager.getConfig();
|
|
1114
1695
|
const entityType = this.configManager.getMode();
|
|
1115
1696
|
const dbId = this.configManager.getDbId() || "";
|
|
@@ -1125,27 +1706,28 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1125
1706
|
userId,
|
|
1126
1707
|
params
|
|
1127
1708
|
);
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
const toolCall = message.tool_calls[i];
|
|
1134
|
-
const uiComponent = existingUIComponents.get(toolCall.tool_call_id);
|
|
1135
|
-
if (uiComponent) {
|
|
1136
|
-
message.tool_calls[i].ui_component = uiComponent;
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1709
|
+
if (this.state.isStreaming) {
|
|
1710
|
+
Logger.debug(
|
|
1711
|
+
"[AgnoClient] Aborting refresh: stream started during fetch"
|
|
1712
|
+
);
|
|
1713
|
+
return;
|
|
1141
1714
|
}
|
|
1715
|
+
const messages = this.sessionManager.convertSessionToMessages(response);
|
|
1716
|
+
this.restoreUIComponents(messages, existingUIComponents);
|
|
1717
|
+
this.revokeAttachmentUrlsFromMessages(this.messageStore.getMessages());
|
|
1142
1718
|
this.messageStore.setMessages(messages);
|
|
1143
|
-
Logger.debug(
|
|
1719
|
+
Logger.debug(
|
|
1720
|
+
"[AgnoClient] Session refreshed:",
|
|
1721
|
+
`${messages.length} messages`
|
|
1722
|
+
);
|
|
1144
1723
|
this.emit("message:refreshed", messages);
|
|
1145
1724
|
this.emit("message:update", messages);
|
|
1146
1725
|
} catch (error) {
|
|
1147
1726
|
Logger.error("[AgnoClient] Failed to refresh session:", error);
|
|
1148
|
-
this.emit(
|
|
1727
|
+
this.emit(
|
|
1728
|
+
"message:error",
|
|
1729
|
+
`Session refresh failed: ${error instanceof Error ? error.message : String(error)}`
|
|
1730
|
+
);
|
|
1149
1731
|
} finally {
|
|
1150
1732
|
this.state.isRefreshing = false;
|
|
1151
1733
|
this.emit("state:change", this.getState());
|
|
@@ -1160,7 +1742,11 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1160
1742
|
const entityType = this.configManager.getMode();
|
|
1161
1743
|
const dbId = this.configManager.getDbId() || "";
|
|
1162
1744
|
const userId = this.configManager.getUserId();
|
|
1163
|
-
Logger.debug("[AgnoClient] Loading session with:", {
|
|
1745
|
+
Logger.debug("[AgnoClient] Loading session with:", {
|
|
1746
|
+
entityType,
|
|
1747
|
+
dbId,
|
|
1748
|
+
userId
|
|
1749
|
+
});
|
|
1164
1750
|
const headers = this.configManager.buildRequestHeaders();
|
|
1165
1751
|
const params = this.configManager.buildQueryString(options?.params);
|
|
1166
1752
|
const response = await this.sessionManager.fetchSession(
|
|
@@ -1173,7 +1759,11 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1173
1759
|
params
|
|
1174
1760
|
);
|
|
1175
1761
|
const messages = this.sessionManager.convertSessionToMessages(response);
|
|
1176
|
-
Logger.debug(
|
|
1762
|
+
Logger.debug(
|
|
1763
|
+
"[AgnoClient] Setting messages to store:",
|
|
1764
|
+
`${messages.length} messages`
|
|
1765
|
+
);
|
|
1766
|
+
this.revokeAttachmentUrlsFromMessages(this.messageStore.getMessages());
|
|
1177
1767
|
this.messageStore.setMessages(messages);
|
|
1178
1768
|
this.configManager.setSessionId(sessionId);
|
|
1179
1769
|
Logger.debug("[AgnoClient] Emitting events...");
|
|
@@ -1242,7 +1832,9 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1242
1832
|
}
|
|
1243
1833
|
const existingToolCalls = lastMessage.tool_calls || [];
|
|
1244
1834
|
const existingIds = new Set(existingToolCalls.map((t) => t.tool_call_id));
|
|
1245
|
-
const newToolCalls = toolCalls.filter(
|
|
1835
|
+
const newToolCalls = toolCalls.filter(
|
|
1836
|
+
(t) => !existingIds.has(t.tool_call_id)
|
|
1837
|
+
);
|
|
1246
1838
|
if (newToolCalls.length > 0) {
|
|
1247
1839
|
this.messageStore.updateLastMessage((msg) => ({
|
|
1248
1840
|
...msg,
|
|
@@ -1289,8 +1881,9 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1289
1881
|
* Batches all updates to emit only one message:update event
|
|
1290
1882
|
*/
|
|
1291
1883
|
applyPendingUISpecs() {
|
|
1292
|
-
if (this.pendingUISpecs.size === 0)
|
|
1884
|
+
if (this.pendingUISpecs.size === 0) {
|
|
1293
1885
|
return;
|
|
1886
|
+
}
|
|
1294
1887
|
const messages = this.messageStore.getMessages();
|
|
1295
1888
|
const updatedMessages = [];
|
|
1296
1889
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
@@ -1322,9 +1915,9 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1322
1915
|
}
|
|
1323
1916
|
}
|
|
1324
1917
|
if (updatedMessages.length > 0) {
|
|
1325
|
-
|
|
1918
|
+
for (const { index, message } of updatedMessages) {
|
|
1326
1919
|
this.messageStore.updateMessage(index, () => message);
|
|
1327
|
-
}
|
|
1920
|
+
}
|
|
1328
1921
|
this.emit("message:update", this.messageStore.getMessages());
|
|
1329
1922
|
}
|
|
1330
1923
|
}
|
|
@@ -1345,22 +1938,55 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1345
1938
|
"HITL (Human-in-the-Loop) frontend tool execution is not supported for teams. Only agents support the continue endpoint."
|
|
1346
1939
|
);
|
|
1347
1940
|
}
|
|
1348
|
-
if (!this.state.isPaused
|
|
1941
|
+
if (!(this.state.isPaused && this.state.pausedRunId)) {
|
|
1349
1942
|
throw new Error("No paused run to continue");
|
|
1350
1943
|
}
|
|
1351
1944
|
const runUrl = this.configManager.getRunUrl();
|
|
1352
1945
|
if (!runUrl) {
|
|
1353
1946
|
throw new Error("No agent or team selected");
|
|
1354
1947
|
}
|
|
1355
|
-
const
|
|
1356
|
-
|
|
1948
|
+
const pausedRunId = this.state.pausedRunId;
|
|
1949
|
+
const continueUrl = `${runUrl}/${pausedRunId}/continue`;
|
|
1357
1950
|
this.state.isStreaming = true;
|
|
1358
|
-
this.
|
|
1951
|
+
this.state.errorMessage = void 0;
|
|
1359
1952
|
this.emit("state:change", this.getState());
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1953
|
+
let hasContinued = false;
|
|
1954
|
+
let streamError;
|
|
1955
|
+
const markRunContinued = (runId) => {
|
|
1956
|
+
if (hasContinued) {
|
|
1957
|
+
return;
|
|
1958
|
+
}
|
|
1959
|
+
hasContinued = true;
|
|
1960
|
+
this.state.isPaused = false;
|
|
1961
|
+
this.state.toolsAwaitingExecution = void 0;
|
|
1962
|
+
this.emit("run:continued", { runId: runId || pausedRunId });
|
|
1963
|
+
this.emit("state:change", this.getState());
|
|
1964
|
+
};
|
|
1965
|
+
const handleContinueError = (error) => {
|
|
1966
|
+
streamError = error;
|
|
1967
|
+
this.state.isStreaming = false;
|
|
1968
|
+
this.state.errorMessage = error.message;
|
|
1969
|
+
const isConflictError = error instanceof StreamResponseHttpError && error.status === 409;
|
|
1970
|
+
if (isConflictError || !hasContinued) {
|
|
1971
|
+
this.state.isPaused = true;
|
|
1972
|
+
} else {
|
|
1973
|
+
this.state.isPaused = false;
|
|
1974
|
+
this.state.pausedRunId = void 0;
|
|
1975
|
+
this.state.toolsAwaitingExecution = void 0;
|
|
1976
|
+
this.messageStore.updateLastMessage((msg) => ({
|
|
1977
|
+
...msg,
|
|
1978
|
+
streamingError: true
|
|
1979
|
+
}));
|
|
1980
|
+
}
|
|
1981
|
+
this.emit("message:error", error.message);
|
|
1982
|
+
this.emit("stream:end");
|
|
1983
|
+
this.emit("state:change", this.getState());
|
|
1984
|
+
};
|
|
1985
|
+
const cleanedTools = tools.map(
|
|
1986
|
+
({ ui_component: _uiComponent, ...tool }) => {
|
|
1987
|
+
return tool;
|
|
1988
|
+
}
|
|
1989
|
+
);
|
|
1364
1990
|
const formData = new FormData();
|
|
1365
1991
|
formData.append("tools", JSON.stringify(cleanedTools));
|
|
1366
1992
|
formData.append("stream", "true");
|
|
@@ -1374,36 +2000,45 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1374
2000
|
}
|
|
1375
2001
|
const headers = this.configManager.buildRequestHeaders(options?.headers);
|
|
1376
2002
|
const params = this.configManager.buildQueryString(options?.params);
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
}
|
|
1389
|
-
|
|
1390
|
-
|
|
2003
|
+
this.currentAbortController = new AbortController();
|
|
2004
|
+
await streamResponse({
|
|
2005
|
+
apiUrl: continueUrl,
|
|
2006
|
+
headers,
|
|
2007
|
+
params,
|
|
2008
|
+
requestBody: formData,
|
|
2009
|
+
signal: this.currentAbortController.signal,
|
|
2010
|
+
onChunk: (chunk) => {
|
|
2011
|
+
const event = chunk.event;
|
|
2012
|
+
if (!hasContinued && event !== RunEvent.RunPaused) {
|
|
2013
|
+
markRunContinued(chunk.run_id);
|
|
2014
|
+
}
|
|
2015
|
+
this.handleChunk(chunk, currentSessionId, "");
|
|
2016
|
+
},
|
|
2017
|
+
onError: (error) => {
|
|
2018
|
+
this.currentAbortController = null;
|
|
2019
|
+
handleContinueError(error);
|
|
2020
|
+
},
|
|
2021
|
+
onComplete: async () => {
|
|
2022
|
+
this.currentAbortController = null;
|
|
2023
|
+
if (!(hasContinued || this.state.isPaused)) {
|
|
2024
|
+
markRunContinued(pausedRunId);
|
|
2025
|
+
}
|
|
2026
|
+
this.state.isStreaming = false;
|
|
2027
|
+
if (!this.state.isPaused) {
|
|
1391
2028
|
this.state.pausedRunId = void 0;
|
|
1392
2029
|
this.state.toolsAwaitingExecution = void 0;
|
|
1393
|
-
this.emit("stream:end");
|
|
1394
|
-
this.emit("message:complete", this.messageStore.getMessages());
|
|
1395
|
-
this.emit("state:change", this.getState());
|
|
1396
|
-
if (this.runCompletedSuccessfully) {
|
|
1397
|
-
this.runCompletedSuccessfully = false;
|
|
1398
|
-
await this.refreshSessionMessages();
|
|
1399
|
-
}
|
|
1400
2030
|
}
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
2031
|
+
this.emit("stream:end");
|
|
2032
|
+
this.emit("message:complete", this.messageStore.getMessages());
|
|
2033
|
+
this.emit("state:change", this.getState());
|
|
2034
|
+
if (this.runCompletedSuccessfully) {
|
|
2035
|
+
this.runCompletedSuccessfully = false;
|
|
2036
|
+
await this.refreshSessionMessages();
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
2039
|
+
});
|
|
2040
|
+
if (streamError) {
|
|
2041
|
+
throw streamError;
|
|
1407
2042
|
}
|
|
1408
2043
|
}
|
|
1409
2044
|
/**
|
|
@@ -1488,7 +2123,7 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1488
2123
|
const currentConfig = this.configManager.getConfig();
|
|
1489
2124
|
const hasAgentConfigured = currentConfig.agentId;
|
|
1490
2125
|
const hasTeamConfigured = currentConfig.teamId;
|
|
1491
|
-
if (!hasAgentConfigured
|
|
2126
|
+
if (!(hasAgentConfigured || hasTeamConfigured)) {
|
|
1492
2127
|
if (agents.length > 0) {
|
|
1493
2128
|
const firstAgent = agents[0];
|
|
1494
2129
|
this.configManager.updateConfig({
|
|
@@ -1509,10 +2144,34 @@ var AgnoClient = class extends EventEmitter {
|
|
|
1509
2144
|
}
|
|
1510
2145
|
return { agents, teams };
|
|
1511
2146
|
}
|
|
2147
|
+
/**
|
|
2148
|
+
* Dispose of the client and clean up all resources.
|
|
2149
|
+
* Call this method when the client is no longer needed to prevent memory leaks.
|
|
2150
|
+
* After calling dispose(), the client instance should not be reused.
|
|
2151
|
+
*/
|
|
2152
|
+
dispose() {
|
|
2153
|
+
if (this.currentAbortController) {
|
|
2154
|
+
this.currentAbortController.abort();
|
|
2155
|
+
this.currentAbortController = null;
|
|
2156
|
+
}
|
|
2157
|
+
this.removeAllListeners();
|
|
2158
|
+
this.revokeAttachmentUrlsFromMessages(this.messageStore.getMessages());
|
|
2159
|
+
this.localAttachmentUrls.clear();
|
|
2160
|
+
this.messageStore.clear();
|
|
2161
|
+
this.pendingUISpecs.clear();
|
|
2162
|
+
this.eventProcessor.reset();
|
|
2163
|
+
this.state.isStreaming = false;
|
|
2164
|
+
this.state.isRefreshing = false;
|
|
2165
|
+
this.state.isEndpointActive = false;
|
|
2166
|
+
this.state.agents = [];
|
|
2167
|
+
this.state.teams = [];
|
|
2168
|
+
this.state.sessions = [];
|
|
2169
|
+
this.state.isPaused = false;
|
|
2170
|
+
this.state.pausedRunId = void 0;
|
|
2171
|
+
this.state.toolsAwaitingExecution = void 0;
|
|
2172
|
+
this.state.errorMessage = void 0;
|
|
2173
|
+
}
|
|
1512
2174
|
};
|
|
1513
|
-
|
|
1514
|
-
// src/index.ts
|
|
1515
|
-
import { RunEvent as RunEvent2 } from "@antipopp/agno-types";
|
|
1516
2175
|
export {
|
|
1517
2176
|
AgnoClient,
|
|
1518
2177
|
Logger,
|