@agno-hq/chat-react 0.3.2 → 0.3.4
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 +81 -5
- package/dist/chat/index.cjs +99 -83
- package/dist/chat/index.d.cts +80 -16
- package/dist/chat/index.d.ts +80 -16
- package/dist/chat/index.js +2 -2
- package/dist/{chunk-RE7ZT73K.js → chunk-5QKU7OPE.js} +2 -2
- package/dist/{chunk-RE7ZT73K.js.map → chunk-5QKU7OPE.js.map} +1 -1
- package/dist/{chunk-6V2YIPHF.js → chunk-BCVKAMSO.js} +22 -4
- package/dist/chunk-BCVKAMSO.js.map +1 -0
- package/dist/{chunk-Q73XHL35.cjs → chunk-ESV52ERB.cjs} +771 -444
- package/dist/chunk-ESV52ERB.cjs.map +1 -0
- package/dist/{chunk-2WM3CCFE.cjs → chunk-HBSF434L.cjs} +2 -2
- package/dist/{chunk-2WM3CCFE.cjs.map → chunk-HBSF434L.cjs.map} +1 -1
- package/dist/{chunk-XTP3TMEZ.js → chunk-OGDPK4Z3.js} +602 -279
- package/dist/chunk-OGDPK4Z3.js.map +1 -0
- package/dist/{chunk-55HQJGLP.cjs → chunk-Y34YRC5T.cjs} +22 -3
- package/dist/chunk-Y34YRC5T.cjs.map +1 -0
- package/dist/{client-DUyVqxU9.d.cts → client-Dwk6ThnW.d.cts} +24 -12
- package/dist/{client-DUyVqxU9.d.ts → client-Dwk6ThnW.d.ts} +24 -12
- package/dist/core/index.cjs +23 -23
- package/dist/core/index.d.cts +2 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +2 -2
- package/dist/index.cjs +122 -106
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/styles.css +79 -34
- package/package.json +1 -1
- package/dist/chunk-55HQJGLP.cjs.map +0 -1
- package/dist/chunk-6V2YIPHF.js.map +0 -1
- package/dist/chunk-Q73XHL35.cjs.map +0 -1
- package/dist/chunk-XTP3TMEZ.js.map +0 -1
|
@@ -1,10 +1,176 @@
|
|
|
1
|
-
import { AgnoClient, activityLabel, isSubRunEvent, applySubRunEvent, isStepEvent, applyStepEvent, isStartedEvent, isToolEvent, toolsFromEvent, mergeTool, isContentEvent, applyContentEvent, isReasoningStepEvent, isReasoningCompletedEvent, isFollowupsCompletedEvent, isPausedEvent, isCompletedEvent, isCancelledEvent, isErrorEvent, sessionRunsToMessages, isToolCompletedEvent } from './chunk-
|
|
2
|
-
import
|
|
1
|
+
import { AgnoClient, activityLabel, isSubRunEvent, applySubRunEvent, isStepEvent, applyStepEvent, isStartedEvent, isToolEvent, toolsFromEvent, mergeTool, isContentEvent, applyContentEvent, isReasoningStepEvent, reasoningStepsFromEvent, isReasoningCompletedEvent, isFollowupsCompletedEvent, isPausedEvent, isCompletedEvent, isCancelledEvent, isErrorEvent, sessionRunsToMessages, isToolCompletedEvent } from './chunk-BCVKAMSO.js';
|
|
2
|
+
import React8, { createContext, useMemo, useState, useRef, useEffect, useCallback, useContext, useId, isValidElement, cloneElement, useLayoutEffect, useReducer } from 'react';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
import { createPortal } from 'react-dom';
|
|
5
|
-
import { ChevronDown as ChevronDown$1, ArrowUp as ArrowUp$1, Paperclip as Paperclip$1, File, FileType2, FileAudio as FileAudio$1, FileVideo as FileVideo$1, Wrench as Wrench$1, BookOpen as BookOpen$1, Globe as Globe$1, Link, Brain as Brain$1, Box as Box$1, Plus as Plus$1, Check as Check$1, Copy as Copy$1, X, MemoryStick, RefreshCcw, Activity, Trash2, MessageSquare, LoaderCircle, Square } from 'lucide-react';
|
|
5
|
+
import { ChevronDown as ChevronDown$1, ArrowUp as ArrowUp$1, Paperclip as Paperclip$1, File, FileType2, FileAudio as FileAudio$1, FileVideo as FileVideo$1, Wrench as Wrench$1, BookOpen as BookOpen$1, Globe as Globe$1, Link as Link$1, Brain as Brain$1, Box as Box$1, Plus as Plus$1, Check as Check$1, Copy as Copy$1, X, MemoryStick, RefreshCcw, Activity, Trash2, MessageSquare, LoaderCircle, Square } from 'lucide-react';
|
|
6
6
|
import { Streamdown } from 'streamdown';
|
|
7
7
|
|
|
8
|
+
function useRunView(initialMessages = []) {
|
|
9
|
+
const [view, setView] = useState({
|
|
10
|
+
messages: initialMessages,
|
|
11
|
+
events: [],
|
|
12
|
+
status: "idle",
|
|
13
|
+
activity: null,
|
|
14
|
+
error: null
|
|
15
|
+
});
|
|
16
|
+
const viewRef = useRef(view);
|
|
17
|
+
const update = useCallback((key, action) => {
|
|
18
|
+
const value = typeof action === "function" ? action(viewRef.current[key]) : action;
|
|
19
|
+
if (Object.is(value, viewRef.current[key])) return;
|
|
20
|
+
viewRef.current = { ...viewRef.current, [key]: value };
|
|
21
|
+
setView(viewRef.current);
|
|
22
|
+
}, []);
|
|
23
|
+
const setters = useMemo(() => ({
|
|
24
|
+
setMessages: (action) => update("messages", action),
|
|
25
|
+
setEvents: (action) => update("events", action),
|
|
26
|
+
setStatus: (action) => update("status", action),
|
|
27
|
+
setActivity: (action) => update("activity", action),
|
|
28
|
+
setError: (action) => update("error", action)
|
|
29
|
+
}), [update]);
|
|
30
|
+
return { ...view, ...setters, viewRef };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// src/chat/streaming/bufferTextEvents.ts
|
|
34
|
+
var DEFAULT_STREAMING_OPTIONS = Object.freeze({
|
|
35
|
+
enabled: true,
|
|
36
|
+
flushIntervalMs: 150,
|
|
37
|
+
maxBufferEvents: 100,
|
|
38
|
+
maxBufferChars: 16384
|
|
39
|
+
});
|
|
40
|
+
var MAX_TIMEOUT_MS = 2147483647;
|
|
41
|
+
var RICH_FIELDS = [
|
|
42
|
+
"tool",
|
|
43
|
+
"tools",
|
|
44
|
+
"response_audio",
|
|
45
|
+
"images",
|
|
46
|
+
"videos",
|
|
47
|
+
"audio",
|
|
48
|
+
"image",
|
|
49
|
+
"references",
|
|
50
|
+
"citations",
|
|
51
|
+
"extra_data"
|
|
52
|
+
];
|
|
53
|
+
function isPlainText(event) {
|
|
54
|
+
return (event.event === "RunContent" || event.event === "TeamRunContent") && typeof event.content === "string" && event.content.length > 0 && RICH_FIELDS.every((key) => event[key] == null);
|
|
55
|
+
}
|
|
56
|
+
function isContinuationOf(previous, next) {
|
|
57
|
+
const keys = /* @__PURE__ */ new Set([...Object.keys(previous), ...Object.keys(next)]);
|
|
58
|
+
for (const key of keys) {
|
|
59
|
+
if (key === "content") continue;
|
|
60
|
+
const before = previous[key];
|
|
61
|
+
const after = next[key];
|
|
62
|
+
if (key === "event_index" && typeof before === "number" && typeof after === "number") {
|
|
63
|
+
if (after <= before) return false;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (!Object.is(before, after)) return false;
|
|
67
|
+
}
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
function boundedNumber(value, fallback, min) {
|
|
71
|
+
return value !== void 0 && Number.isFinite(value) && value >= min ? Math.min(Math.floor(value), MAX_TIMEOUT_MS) : fallback;
|
|
72
|
+
}
|
|
73
|
+
function bufferTextEvents(deliver, options = {}) {
|
|
74
|
+
const defaults = DEFAULT_STREAMING_OPTIONS;
|
|
75
|
+
const interval = boundedNumber(
|
|
76
|
+
options.flushIntervalMs,
|
|
77
|
+
defaults.flushIntervalMs,
|
|
78
|
+
0
|
|
79
|
+
);
|
|
80
|
+
const maxEvents = boundedNumber(
|
|
81
|
+
options.maxBufferEvents,
|
|
82
|
+
defaults.maxBufferEvents,
|
|
83
|
+
1
|
|
84
|
+
);
|
|
85
|
+
const maxChars = boundedNumber(
|
|
86
|
+
options.maxBufferChars,
|
|
87
|
+
defaults.maxBufferChars,
|
|
88
|
+
1
|
|
89
|
+
);
|
|
90
|
+
const enabled = (options.enabled ?? defaults.enabled) && interval > 0;
|
|
91
|
+
let events = [];
|
|
92
|
+
let chunks = [];
|
|
93
|
+
let chars = 0;
|
|
94
|
+
let hasText = false;
|
|
95
|
+
let disposed = false;
|
|
96
|
+
let timer;
|
|
97
|
+
const isHidden = () => typeof document !== "undefined" && document.visibilityState === "hidden";
|
|
98
|
+
const onVisibilityChange = () => {
|
|
99
|
+
if (isHidden()) flush();
|
|
100
|
+
};
|
|
101
|
+
const stopObserving = () => {
|
|
102
|
+
if (typeof document !== "undefined")
|
|
103
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
104
|
+
};
|
|
105
|
+
const cancelScheduled = () => {
|
|
106
|
+
stopObserving();
|
|
107
|
+
clearTimeout(timer);
|
|
108
|
+
timer = void 0;
|
|
109
|
+
};
|
|
110
|
+
const flush = () => {
|
|
111
|
+
cancelScheduled();
|
|
112
|
+
const batch = { events, chunks };
|
|
113
|
+
events = [];
|
|
114
|
+
chunks = [];
|
|
115
|
+
chars = 0;
|
|
116
|
+
if (!disposed && (batch.events.length || batch.chunks.length))
|
|
117
|
+
deliver(batch);
|
|
118
|
+
};
|
|
119
|
+
const schedule = () => {
|
|
120
|
+
if (timer !== void 0 || disposed) return;
|
|
121
|
+
if (isHidden()) return flush();
|
|
122
|
+
if (typeof document !== "undefined")
|
|
123
|
+
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
124
|
+
timer = setTimeout(() => {
|
|
125
|
+
timer = void 0;
|
|
126
|
+
flush();
|
|
127
|
+
}, interval);
|
|
128
|
+
};
|
|
129
|
+
const deliverNow = (event) => {
|
|
130
|
+
if (!disposed) deliver({ events: [event], chunks: [event] });
|
|
131
|
+
};
|
|
132
|
+
const append = (event) => {
|
|
133
|
+
const last = chunks[chunks.length - 1];
|
|
134
|
+
if (last && isContinuationOf(last, event)) {
|
|
135
|
+
chunks[chunks.length - 1] = {
|
|
136
|
+
...event,
|
|
137
|
+
content: String(last.content) + event.content
|
|
138
|
+
};
|
|
139
|
+
} else {
|
|
140
|
+
chunks.push(event);
|
|
141
|
+
}
|
|
142
|
+
events.push(event);
|
|
143
|
+
chars += String(event.content).length;
|
|
144
|
+
};
|
|
145
|
+
return {
|
|
146
|
+
push(event) {
|
|
147
|
+
if (disposed) return;
|
|
148
|
+
if (!enabled || !isPlainText(event)) {
|
|
149
|
+
flush();
|
|
150
|
+
hasText = false;
|
|
151
|
+
deliverNow(event);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (!hasText) {
|
|
155
|
+
hasText = true;
|
|
156
|
+
deliverNow(event);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
append(event);
|
|
160
|
+
if (events.length >= maxEvents || chars >= maxChars) flush();
|
|
161
|
+
else schedule();
|
|
162
|
+
},
|
|
163
|
+
flush,
|
|
164
|
+
dispose() {
|
|
165
|
+
disposed = true;
|
|
166
|
+
cancelScheduled();
|
|
167
|
+
events = [];
|
|
168
|
+
chunks = [];
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// src/chat/useAgnoChat.ts
|
|
8
174
|
var messageCounter = 0;
|
|
9
175
|
var nextId = () => `m${Date.now().toString(36)}-${(messageCounter++).toString(36)}`;
|
|
10
176
|
var nowSeconds = () => Math.floor(Date.now() / 1e3);
|
|
@@ -14,12 +180,20 @@ function useAgnoChat(options) {
|
|
|
14
180
|
if (options.client) return options.client;
|
|
15
181
|
return new AgnoClient({ baseUrl: options.baseUrl ?? "", headers: options.headers });
|
|
16
182
|
}, [options.client, options.baseUrl, JSON.stringify(options.headers)]);
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
183
|
+
const {
|
|
184
|
+
messages,
|
|
185
|
+
events,
|
|
186
|
+
status,
|
|
187
|
+
activity,
|
|
188
|
+
error,
|
|
189
|
+
viewRef,
|
|
190
|
+
setMessages,
|
|
191
|
+
setEvents,
|
|
192
|
+
setStatus,
|
|
193
|
+
setActivity,
|
|
194
|
+
setError
|
|
195
|
+
} = useRunView(options.initialMessages);
|
|
196
|
+
const currentEvent = events[events.length - 1] ?? null;
|
|
23
197
|
const [sessionId, setSessionId] = useState(options.sessionId);
|
|
24
198
|
const [sessions, setSessions] = useState([]);
|
|
25
199
|
const [sessionsLoading, setSessionsLoading] = useState(false);
|
|
@@ -29,10 +203,14 @@ function useAgnoChat(options) {
|
|
|
29
203
|
const backgroundRef = useRef(/* @__PURE__ */ new Map());
|
|
30
204
|
const activeMsgIdRef = useRef(null);
|
|
31
205
|
const runIdRef = useRef(void 0);
|
|
206
|
+
const streamingRef = useRef(options.streaming);
|
|
32
207
|
const entityRef = useRef(entity);
|
|
33
208
|
const sessionIdRef = useRef(options.sessionId);
|
|
34
209
|
const pendingSessionNameRef = useRef(void 0);
|
|
35
210
|
const bumpedSessionRef = useRef(void 0);
|
|
211
|
+
useEffect(() => {
|
|
212
|
+
streamingRef.current = options.streaming;
|
|
213
|
+
}, [options.streaming]);
|
|
36
214
|
useEffect(() => {
|
|
37
215
|
entityRef.current = entity;
|
|
38
216
|
}, [entity]);
|
|
@@ -52,44 +230,37 @@ function useAgnoChat(options) {
|
|
|
52
230
|
return [entry, ...rest];
|
|
53
231
|
});
|
|
54
232
|
}, []);
|
|
55
|
-
const viewRef = useRef({ messages, events, status, activity, error });
|
|
56
|
-
useEffect(() => {
|
|
57
|
-
viewRef.current = { messages, events, status, activity, error };
|
|
58
|
-
});
|
|
59
233
|
const writeMessages = useCallback(
|
|
60
234
|
(chan, fn) => {
|
|
61
235
|
const park = chan?.park;
|
|
62
236
|
if (park) park.messages = fn(park.messages);
|
|
63
237
|
else setMessages(fn);
|
|
64
238
|
},
|
|
65
|
-
[]
|
|
239
|
+
[setMessages]
|
|
66
240
|
);
|
|
67
|
-
const writeEvents = useCallback((chan,
|
|
68
|
-
const park = chan
|
|
69
|
-
if (park) park.events = [...park.events,
|
|
70
|
-
else
|
|
71
|
-
|
|
72
|
-
setCurrentEvent(e);
|
|
73
|
-
}
|
|
74
|
-
}, []);
|
|
241
|
+
const writeEvents = useCallback((chan, incoming) => {
|
|
242
|
+
const park = chan.park;
|
|
243
|
+
if (park) park.events = [...park.events, ...incoming];
|
|
244
|
+
else setEvents((previous) => [...previous, ...incoming]);
|
|
245
|
+
}, [setEvents]);
|
|
75
246
|
const writeStatus = useCallback((chan, status2) => {
|
|
76
247
|
const park = chan?.park;
|
|
77
248
|
if (park) park.status = status2;
|
|
78
249
|
else setStatus(status2);
|
|
79
|
-
}, []);
|
|
250
|
+
}, [setStatus]);
|
|
80
251
|
const writeActivity = useCallback((chan, activity2) => {
|
|
81
252
|
const park = chan?.park;
|
|
82
253
|
if (park) park.activity = activity2;
|
|
83
254
|
else setActivity(activity2);
|
|
84
|
-
}, []);
|
|
255
|
+
}, [setActivity]);
|
|
85
256
|
const writeError = useCallback((chan, message) => {
|
|
86
257
|
const park = chan?.park;
|
|
87
258
|
if (park) park.error = message;
|
|
88
259
|
else setError(message);
|
|
89
|
-
}, []);
|
|
260
|
+
}, [setError]);
|
|
90
261
|
const patchActive = useCallback(
|
|
91
262
|
(chan, patch) => {
|
|
92
|
-
const id = chan
|
|
263
|
+
const id = chan ? chan.messageId : activeMsgIdRef.current;
|
|
93
264
|
if (!id) return;
|
|
94
265
|
writeMessages(chan, (prev) => prev.map((m) => m.id === id ? patch(m) : m));
|
|
95
266
|
},
|
|
@@ -97,9 +268,6 @@ function useAgnoChat(options) {
|
|
|
97
268
|
);
|
|
98
269
|
const applyEvent = useCallback(
|
|
99
270
|
(chan, e) => {
|
|
100
|
-
writeEvents(chan, e);
|
|
101
|
-
patchActive(chan, (m) => ({ ...m, events: [...m.events ?? [], e] }));
|
|
102
|
-
onEvent?.(e);
|
|
103
271
|
const label2 = activityLabel(e);
|
|
104
272
|
if (label2) writeActivity(chan, label2);
|
|
105
273
|
if (e.session_id && !chan?.park && e.session_id !== sessionIdRef.current) {
|
|
@@ -118,7 +286,7 @@ function useAgnoChat(options) {
|
|
|
118
286
|
else runIdRef.current = e.run_id;
|
|
119
287
|
}
|
|
120
288
|
if (isSubRunEvent(e)) {
|
|
121
|
-
const kind = entityRef.current?.type === "workflow" ? "executor" : "member";
|
|
289
|
+
const kind = (chan?.entityType ?? entityRef.current?.type) === "workflow" ? "executor" : "member";
|
|
122
290
|
patchActive(chan, (m) => applySubRunEvent(m, e, kind));
|
|
123
291
|
return;
|
|
124
292
|
}
|
|
@@ -151,7 +319,7 @@ function useAgnoChat(options) {
|
|
|
151
319
|
return;
|
|
152
320
|
}
|
|
153
321
|
if (isReasoningStepEvent(e)) {
|
|
154
|
-
const incoming = e
|
|
322
|
+
const incoming = reasoningStepsFromEvent(e);
|
|
155
323
|
if (incoming.length) {
|
|
156
324
|
patchActive(chan, (m) => ({
|
|
157
325
|
...m,
|
|
@@ -161,8 +329,8 @@ function useAgnoChat(options) {
|
|
|
161
329
|
return;
|
|
162
330
|
}
|
|
163
331
|
if (isReasoningCompletedEvent(e)) {
|
|
164
|
-
const steps = e
|
|
165
|
-
if (steps
|
|
332
|
+
const steps = reasoningStepsFromEvent(e);
|
|
333
|
+
if (steps.length) patchActive(chan, (m) => ({ ...m, reasoning_steps: steps }));
|
|
166
334
|
return;
|
|
167
335
|
}
|
|
168
336
|
if (isFollowupsCompletedEvent(e)) {
|
|
@@ -178,7 +346,7 @@ function useAgnoChat(options) {
|
|
|
178
346
|
patchActive(chan, (m) => {
|
|
179
347
|
let tool_calls = m.tool_calls ?? [];
|
|
180
348
|
for (const t of pausedTools2) tool_calls = mergeTool(tool_calls, t);
|
|
181
|
-
return { ...m, status: "paused", streaming: false, requirements, tool_calls };
|
|
349
|
+
return { ...m, status: "paused", streaming: false, requirements, step_requirements: e.step_requirements ?? m.step_requirements, tool_calls };
|
|
182
350
|
});
|
|
183
351
|
return;
|
|
184
352
|
}
|
|
@@ -217,13 +385,11 @@ function useAgnoChat(options) {
|
|
|
217
385
|
}
|
|
218
386
|
},
|
|
219
387
|
[
|
|
220
|
-
onEvent,
|
|
221
388
|
onSessionId,
|
|
222
389
|
patchActive,
|
|
223
390
|
upsertSession,
|
|
224
391
|
writeActivity,
|
|
225
392
|
writeError,
|
|
226
|
-
writeEvents,
|
|
227
393
|
writeStatus
|
|
228
394
|
]
|
|
229
395
|
);
|
|
@@ -261,12 +427,11 @@ function useAgnoChat(options) {
|
|
|
261
427
|
bumpedSessionRef.current = park.bumped;
|
|
262
428
|
setMessages(park.messages);
|
|
263
429
|
setEvents(park.events);
|
|
264
|
-
setCurrentEvent(park.events[park.events.length - 1] ?? null);
|
|
265
430
|
setStatus(park.status);
|
|
266
431
|
setActivity(park.activity);
|
|
267
432
|
setError(park.error);
|
|
268
433
|
return true;
|
|
269
|
-
}, []);
|
|
434
|
+
}, [setMessages, setEvents, setStatus, setActivity, setError]);
|
|
270
435
|
const releaseCurrentRun = useCallback(() => {
|
|
271
436
|
const chan = channelRef.current;
|
|
272
437
|
if (!chan || chan.park) return;
|
|
@@ -282,29 +447,64 @@ function useAgnoChat(options) {
|
|
|
282
447
|
const drive = useCallback(
|
|
283
448
|
async (starter) => {
|
|
284
449
|
const controller = new AbortController();
|
|
285
|
-
|
|
450
|
+
let finished = false;
|
|
451
|
+
const isCurrent = () => !controller.signal.aborted && (channelRef.current === chan || Boolean(chan.park && backgroundRef.current.get(chan.park.sessionId) === chan));
|
|
452
|
+
const chan = {
|
|
453
|
+
controller,
|
|
454
|
+
park: null,
|
|
455
|
+
messageId: activeMsgIdRef.current,
|
|
456
|
+
entityType: entityRef.current?.type,
|
|
457
|
+
buffer: bufferTextEvents(({ events: incoming, chunks }) => {
|
|
458
|
+
if (!isCurrent()) return;
|
|
459
|
+
if (incoming.length) {
|
|
460
|
+
writeEvents(chan, incoming);
|
|
461
|
+
patchActive(chan, (m) => ({ ...m, events: [...m.events ?? [], ...incoming] }));
|
|
462
|
+
}
|
|
463
|
+
for (const chunk of chunks) applyEvent(chan, chunk);
|
|
464
|
+
}, streamingRef.current)
|
|
465
|
+
};
|
|
466
|
+
controller.signal.addEventListener("abort", () => chan.buffer.dispose(), { once: true });
|
|
286
467
|
channelRef.current = chan;
|
|
287
468
|
abortRef.current = controller;
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
469
|
+
writeError(chan, null);
|
|
470
|
+
writeStatus(chan, "streaming");
|
|
471
|
+
const complete = () => {
|
|
472
|
+
if (finished || !isCurrent()) return;
|
|
473
|
+
chan.buffer.flush();
|
|
474
|
+
finished = true;
|
|
475
|
+
chan.buffer.dispose();
|
|
476
|
+
writeActivity(chan, null);
|
|
477
|
+
patchActive(chan, (m) => m.streaming ? { ...m, streaming: false, status: "completed" } : m);
|
|
478
|
+
const status2 = chan.park?.status ?? viewRef.current.status;
|
|
479
|
+
if (status2 === "streaming") writeStatus(chan, "completed");
|
|
480
|
+
};
|
|
481
|
+
const fail = (err) => {
|
|
482
|
+
if (finished || !isCurrent()) return;
|
|
483
|
+
chan.buffer.flush();
|
|
484
|
+
finished = true;
|
|
485
|
+
chan.buffer.dispose();
|
|
486
|
+
patchActive(chan, (m) => ({ ...m, streaming: false, status: "error", error: err.message }));
|
|
487
|
+
writeActivity(chan, null);
|
|
488
|
+
writeError(chan, err.message);
|
|
489
|
+
writeStatus(chan, "error");
|
|
490
|
+
};
|
|
491
|
+
try {
|
|
492
|
+
await starter({
|
|
493
|
+
signal: controller.signal,
|
|
494
|
+
onEvent: (e) => {
|
|
495
|
+
if (finished || !isCurrent()) return;
|
|
496
|
+
onEvent?.(e);
|
|
497
|
+
if (isCurrent()) chan.buffer.push(e);
|
|
498
|
+
},
|
|
499
|
+
onError: fail,
|
|
500
|
+
onComplete: complete
|
|
501
|
+
});
|
|
502
|
+
complete();
|
|
503
|
+
} catch (error2) {
|
|
504
|
+
fail(error2 instanceof Error ? error2 : new Error(String(error2)));
|
|
505
|
+
} finally {
|
|
506
|
+
chan.buffer.dispose();
|
|
507
|
+
}
|
|
308
508
|
if (chan.park) {
|
|
309
509
|
const { sessionId: sessionId2 } = chan.park;
|
|
310
510
|
setBackgroundRunning((prev) => prev.filter((s) => s !== sessionId2));
|
|
@@ -313,7 +513,7 @@ function useAgnoChat(options) {
|
|
|
313
513
|
abortRef.current = null;
|
|
314
514
|
}
|
|
315
515
|
},
|
|
316
|
-
[applyEvent, patchActive, writeActivity, writeError, writeStatus]
|
|
516
|
+
[applyEvent, onEvent, patchActive, writeActivity, writeError, writeEvents, writeStatus]
|
|
317
517
|
);
|
|
318
518
|
const sendMessage = useCallback(
|
|
319
519
|
async (message, sendOptions) => {
|
|
@@ -342,7 +542,6 @@ function useAgnoChat(options) {
|
|
|
342
542
|
};
|
|
343
543
|
activeMsgIdRef.current = agentMsg.id;
|
|
344
544
|
setEvents([]);
|
|
345
|
-
setCurrentEvent(null);
|
|
346
545
|
setMessages((prev) => [...prev, userMsg, agentMsg]);
|
|
347
546
|
await drive(
|
|
348
547
|
(cb) => client.run({
|
|
@@ -356,7 +555,7 @@ function useAgnoChat(options) {
|
|
|
356
555
|
})
|
|
357
556
|
);
|
|
358
557
|
},
|
|
359
|
-
[client, drive, userId]
|
|
558
|
+
[client, drive, setEvents, setMessages, userId]
|
|
360
559
|
);
|
|
361
560
|
const continueRun = useCallback(
|
|
362
561
|
async (resolution) => {
|
|
@@ -366,7 +565,7 @@ function useAgnoChat(options) {
|
|
|
366
565
|
setError("No paused run to continue.");
|
|
367
566
|
return;
|
|
368
567
|
}
|
|
369
|
-
patchActive(null, (m) => ({ ...m, streaming: true, status: "streaming", requirements: void 0 }));
|
|
568
|
+
patchActive(null, (m) => ({ ...m, streaming: true, status: "streaming", requirements: void 0, step_requirements: void 0 }));
|
|
370
569
|
await drive(
|
|
371
570
|
(cb) => client.continueRun({
|
|
372
571
|
type: ent.type,
|
|
@@ -375,6 +574,7 @@ function useAgnoChat(options) {
|
|
|
375
574
|
sessionId: sessionIdRef.current,
|
|
376
575
|
userId,
|
|
377
576
|
tools: resolution.tools,
|
|
577
|
+
requirements: resolution.requirements,
|
|
378
578
|
stepRequirements: resolution.stepRequirements,
|
|
379
579
|
...cb
|
|
380
580
|
})
|
|
@@ -393,8 +593,12 @@ function useAgnoChat(options) {
|
|
|
393
593
|
const respondToConfirmation = useCallback(
|
|
394
594
|
async (approve) => {
|
|
395
595
|
const ent = entityRef.current;
|
|
596
|
+
if (ent?.type === "team" && activeMessage?.requirements?.length) {
|
|
597
|
+
await continueRun({ requirements: activeMessage.requirements.map((r) => ({ ...r, confirmation: approve })) });
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
396
600
|
if (ent?.type === "workflow") {
|
|
397
|
-
const reqs = (activeMessage?.requirements ?? []).map((r) => ({ ...r, confirmation: approve }));
|
|
601
|
+
const reqs = activeMessage?.step_requirements?.length ? activeMessage.step_requirements.map((r) => ({ ...r, confirmed: approve })) : (activeMessage?.requirements ?? []).map((r) => ({ ...r, confirmation: approve }));
|
|
398
602
|
await continueRun({ stepRequirements: reqs });
|
|
399
603
|
return;
|
|
400
604
|
}
|
|
@@ -406,6 +610,17 @@ function useAgnoChat(options) {
|
|
|
406
610
|
const submitUserInput = useCallback(
|
|
407
611
|
async (values) => {
|
|
408
612
|
const ent = entityRef.current;
|
|
613
|
+
if (ent?.type === "team" && activeMessage?.requirements?.length) {
|
|
614
|
+
const requirements = activeMessage.requirements.map((r) => ({
|
|
615
|
+
...r,
|
|
616
|
+
user_input_schema: (r.user_input_schema ?? r.tool_execution?.user_input_schema ?? []).map((f) => ({
|
|
617
|
+
...f,
|
|
618
|
+
value: f.name in values ? values[f.name] : f.value
|
|
619
|
+
}))
|
|
620
|
+
}));
|
|
621
|
+
await continueRun({ requirements });
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
409
624
|
if (ent?.type === "workflow") {
|
|
410
625
|
const reqs = (activeMessage?.requirements ?? []).map((r) => ({
|
|
411
626
|
...r,
|
|
@@ -430,15 +645,16 @@ function useAgnoChat(options) {
|
|
|
430
645
|
[activeMessage, continueRun, pausedTools]
|
|
431
646
|
);
|
|
432
647
|
const cancel = useCallback(async () => {
|
|
648
|
+
channelRef.current?.buffer.flush();
|
|
433
649
|
abortRef.current?.abort();
|
|
434
650
|
channelRef.current = null;
|
|
435
651
|
const ent = entityRef.current;
|
|
436
652
|
const runId = runIdRef.current;
|
|
437
|
-
|
|
438
|
-
|
|
653
|
+
writeStatus(null, "cancelled");
|
|
654
|
+
writeActivity(null, null);
|
|
439
655
|
patchActive(null, (m) => m.streaming ? { ...m, streaming: false, status: "cancelled" } : m);
|
|
440
656
|
if (ent && runId) await client.cancelRun(ent.type, ent.id, runId, sessionIdRef.current);
|
|
441
|
-
}, [client, patchActive]);
|
|
657
|
+
}, [client, patchActive, writeActivity, writeStatus]);
|
|
442
658
|
const refreshSessions = useCallback(async () => {
|
|
443
659
|
const ent = entityRef.current;
|
|
444
660
|
if (!ent) {
|
|
@@ -458,6 +674,14 @@ function useAgnoChat(options) {
|
|
|
458
674
|
setSessionsLoading(false);
|
|
459
675
|
}
|
|
460
676
|
}, [client]);
|
|
677
|
+
const clearRunView = useCallback(() => {
|
|
678
|
+
activeMsgIdRef.current = null;
|
|
679
|
+
runIdRef.current = void 0;
|
|
680
|
+
setEvents([]);
|
|
681
|
+
setStatus("idle");
|
|
682
|
+
setActivity(null);
|
|
683
|
+
setError(null);
|
|
684
|
+
}, [setEvents, setStatus, setActivity, setError]);
|
|
461
685
|
const loadSession = useCallback(
|
|
462
686
|
async (id) => {
|
|
463
687
|
const ent = entityRef.current;
|
|
@@ -468,13 +692,7 @@ function useAgnoChat(options) {
|
|
|
468
692
|
setSessionId(id);
|
|
469
693
|
onSessionId?.(id);
|
|
470
694
|
if (resumeRun(id)) return;
|
|
471
|
-
|
|
472
|
-
runIdRef.current = void 0;
|
|
473
|
-
setEvents([]);
|
|
474
|
-
setCurrentEvent(null);
|
|
475
|
-
setStatus("idle");
|
|
476
|
-
setActivity(null);
|
|
477
|
-
setError(null);
|
|
695
|
+
clearRunView();
|
|
478
696
|
try {
|
|
479
697
|
const runs = await client.getSessionRuns(ent.type, id, ent.db_id);
|
|
480
698
|
setMessages(sessionRunsToMessages(runs));
|
|
@@ -482,7 +700,7 @@ function useAgnoChat(options) {
|
|
|
482
700
|
setError(err instanceof Error ? err.message : String(err));
|
|
483
701
|
}
|
|
484
702
|
},
|
|
485
|
-
[client, onSessionId, releaseCurrentRun, resumeRun]
|
|
703
|
+
[client, clearRunView, onSessionId, releaseCurrentRun, resumeRun, setMessages]
|
|
486
704
|
);
|
|
487
705
|
const deleteSession = useCallback(
|
|
488
706
|
async (id) => {
|
|
@@ -497,29 +715,27 @@ function useAgnoChat(options) {
|
|
|
497
715
|
}
|
|
498
716
|
setSessions((prev) => prev.filter((s) => s.session_id !== id));
|
|
499
717
|
if (sessionIdRef.current === id) {
|
|
718
|
+
channelRef.current?.controller.abort();
|
|
719
|
+
channelRef.current = null;
|
|
720
|
+
abortRef.current = null;
|
|
721
|
+
clearRunView();
|
|
500
722
|
sessionIdRef.current = void 0;
|
|
501
723
|
setSessionId(void 0);
|
|
502
724
|
setMessages([]);
|
|
503
725
|
}
|
|
504
726
|
}
|
|
505
727
|
},
|
|
506
|
-
[client]
|
|
728
|
+
[client, clearRunView, setMessages]
|
|
507
729
|
);
|
|
508
730
|
const reset = useCallback(() => {
|
|
509
731
|
releaseCurrentRun();
|
|
510
|
-
|
|
511
|
-
runIdRef.current = void 0;
|
|
732
|
+
clearRunView();
|
|
512
733
|
sessionIdRef.current = void 0;
|
|
513
734
|
pendingSessionNameRef.current = void 0;
|
|
514
735
|
bumpedSessionRef.current = void 0;
|
|
515
736
|
setMessages([]);
|
|
516
|
-
setEvents([]);
|
|
517
|
-
setCurrentEvent(null);
|
|
518
|
-
setStatus("idle");
|
|
519
|
-
setActivity(null);
|
|
520
|
-
setError(null);
|
|
521
737
|
setSessionId(void 0);
|
|
522
|
-
}, [releaseCurrentRun]);
|
|
738
|
+
}, [clearRunView, releaseCurrentRun, setMessages]);
|
|
523
739
|
useEffect(() => {
|
|
524
740
|
const background = backgroundRef.current;
|
|
525
741
|
return () => {
|
|
@@ -643,7 +859,7 @@ var FileVideo = icon(FileVideo$1);
|
|
|
643
859
|
var Wrench = icon(Wrench$1);
|
|
644
860
|
var BookOpen = icon(BookOpen$1);
|
|
645
861
|
var Globe = icon(Globe$1);
|
|
646
|
-
var LinkIcon = icon(Link);
|
|
862
|
+
var LinkIcon = icon(Link$1);
|
|
647
863
|
var Brain = icon(Brain$1);
|
|
648
864
|
var Box = icon(Box$1);
|
|
649
865
|
var Plus = icon(Plus$1);
|
|
@@ -1220,6 +1436,16 @@ function Followups({
|
|
|
1220
1436
|
}
|
|
1221
1437
|
var isBoolField = (f) => f.field_type === "bool" || f.field_type === "boolean";
|
|
1222
1438
|
function buildAsks(message, entityType) {
|
|
1439
|
+
if (entityType === "workflow" && message.step_requirements?.length) {
|
|
1440
|
+
return message.step_requirements.map((r) => ({
|
|
1441
|
+
id: r.step_id,
|
|
1442
|
+
name: r.step_name,
|
|
1443
|
+
needsConfirmation: Boolean(r.requires_confirmation) && r.confirmed == null,
|
|
1444
|
+
fields: [],
|
|
1445
|
+
stepRequirement: r,
|
|
1446
|
+
unsupported: !r.requires_confirmation || Boolean(r.requires_user_input || r.requires_route_selection || r.requires_output_review)
|
|
1447
|
+
}));
|
|
1448
|
+
}
|
|
1223
1449
|
const fromTools = (message.tool_calls ?? []).filter((t) => t.requires_confirmation || t.requires_user_input).map((t) => ({
|
|
1224
1450
|
id: t.tool_call_id ?? `${t.tool_name}`,
|
|
1225
1451
|
name: t.tool_name,
|
|
@@ -1232,11 +1458,11 @@ function buildAsks(message, entityType) {
|
|
|
1232
1458
|
id: r.id,
|
|
1233
1459
|
name: r.tool_execution?.tool_name,
|
|
1234
1460
|
args: r.tool_execution?.tool_args,
|
|
1235
|
-
needsConfirmation: Boolean(r.tool_execution?.requires_confirmation) || r.confirmation == null,
|
|
1461
|
+
needsConfirmation: entityType === "workflow" ? Boolean(r.tool_execution?.requires_confirmation) || r.confirmation == null : Boolean(r.tool_execution?.requires_confirmation) && r.confirmation == null,
|
|
1236
1462
|
fields: r.user_input_schema ?? r.tool_execution?.user_input_schema ?? [],
|
|
1237
1463
|
requirement: r
|
|
1238
1464
|
}));
|
|
1239
|
-
if (entityType === "workflow") return fromReqs.length ? fromReqs : fromTools;
|
|
1465
|
+
if (entityType === "workflow" || entityType === "team") return fromReqs.length ? fromReqs : fromTools;
|
|
1240
1466
|
return fromTools.length ? fromTools : fromReqs;
|
|
1241
1467
|
}
|
|
1242
1468
|
function HumanInput({
|
|
@@ -1255,11 +1481,26 @@ function HumanInput({
|
|
|
1255
1481
|
const setValue = (id, name, value) => setValues((v) => ({ ...v, [id]: { ...v[id] ?? {}, [name]: value } }));
|
|
1256
1482
|
const valueFor = (ask, field) => values[ask.id]?.[field.name] ?? field.value ?? (isBoolField(field) ? false : "");
|
|
1257
1483
|
const fillFields = (ask) => ask.fields.map((f) => ({ ...f, value: valueFor(ask, f) }));
|
|
1258
|
-
const ready = asks.every((a) => !a.needsConfirmation || choices[a.id]);
|
|
1484
|
+
const ready = asks.every((a) => !a.unsupported && (!a.needsConfirmation || choices[a.id]));
|
|
1259
1485
|
const submit = () => {
|
|
1486
|
+
if (entityType === "team" && asks.every((a) => a.requirement)) {
|
|
1487
|
+
const requirements = asks.map((a) => ({
|
|
1488
|
+
...a.requirement,
|
|
1489
|
+
...a.needsConfirmation ? { confirmation: choices[a.id] === "confirm" } : {},
|
|
1490
|
+
...a.fields.length ? { user_input_schema: fillFields(a) } : {},
|
|
1491
|
+
...reasons[a.id] ? { confirmation_note: reasons[a.id] } : {}
|
|
1492
|
+
}));
|
|
1493
|
+
onResolve({ requirements });
|
|
1494
|
+
return;
|
|
1495
|
+
}
|
|
1260
1496
|
if (entityType === "workflow") {
|
|
1261
1497
|
const stepRequirements = asks.map((a) => {
|
|
1262
1498
|
const approved = a.needsConfirmation ? choices[a.id] === "confirm" : true;
|
|
1499
|
+
if (a.stepRequirement) return {
|
|
1500
|
+
...a.stepRequirement,
|
|
1501
|
+
confirmed: approved,
|
|
1502
|
+
...reasons[a.id] ? { rejection_feedback: reasons[a.id] } : {}
|
|
1503
|
+
};
|
|
1263
1504
|
return {
|
|
1264
1505
|
id: a.id,
|
|
1265
1506
|
confirmation: approved,
|
|
@@ -1272,7 +1513,7 @@ function HumanInput({
|
|
|
1272
1513
|
return;
|
|
1273
1514
|
}
|
|
1274
1515
|
const tools = asks.map((a) => {
|
|
1275
|
-
const base = a.tool ?? { tool_call_id: a.id, tool_name: a.name };
|
|
1516
|
+
const base = a.tool ?? a.requirement?.tool_execution ?? { tool_call_id: a.id, tool_name: a.name };
|
|
1276
1517
|
const approved = a.needsConfirmation ? choices[a.id] === "confirm" : true;
|
|
1277
1518
|
return {
|
|
1278
1519
|
...base,
|
|
@@ -1285,6 +1526,7 @@ function HumanInput({
|
|
|
1285
1526
|
};
|
|
1286
1527
|
return /* @__PURE__ */ jsxs("div", { className: cx("agno-hitl", className), children: [
|
|
1287
1528
|
/* @__PURE__ */ jsx("div", { className: "agno-hitl__title", children: "Your input is needed" }),
|
|
1529
|
+
asks.some((a) => a.unsupported) && /* @__PURE__ */ jsx("div", { className: "agno-hitl__notice", role: "status", children: "This workflow needs an input type this chat does not support yet." }),
|
|
1288
1530
|
asks.map((ask) => {
|
|
1289
1531
|
const choice = choices[ask.id];
|
|
1290
1532
|
const hasArgs = ask.args && Object.keys(ask.args).length > 0;
|
|
@@ -1393,11 +1635,14 @@ function sourceHost(url) {
|
|
|
1393
1635
|
}
|
|
1394
1636
|
}
|
|
1395
1637
|
function faviconUrl(url) {
|
|
1396
|
-
|
|
1638
|
+
return faviconFallbacks(url)[0];
|
|
1639
|
+
}
|
|
1640
|
+
function faviconFallbacks(url) {
|
|
1641
|
+
if (!url) return [];
|
|
1397
1642
|
try {
|
|
1398
|
-
return
|
|
1643
|
+
return ["/favicon.ico", "/favicon.svg"].map((path) => new URL(path, url).href);
|
|
1399
1644
|
} catch {
|
|
1400
|
-
return
|
|
1645
|
+
return [];
|
|
1401
1646
|
}
|
|
1402
1647
|
}
|
|
1403
1648
|
function displayUrl(url) {
|
|
@@ -1526,73 +1771,6 @@ var SourcesProvider = SourcesContext.Provider;
|
|
|
1526
1771
|
function useSources() {
|
|
1527
1772
|
return useContext(SourcesContext);
|
|
1528
1773
|
}
|
|
1529
|
-
var THEMES = { light: "github-light", dark: "monokai" };
|
|
1530
|
-
var highlighter;
|
|
1531
|
-
var booting;
|
|
1532
|
-
var loading = /* @__PURE__ */ new Map();
|
|
1533
|
-
var loaded = /* @__PURE__ */ new Set();
|
|
1534
|
-
var unsupported = /* @__PURE__ */ new Set();
|
|
1535
|
-
async function boot() {
|
|
1536
|
-
if (highlighter) return highlighter;
|
|
1537
|
-
booting ?? (booting = (async () => {
|
|
1538
|
-
const [{ createHighlighterCore }, { createJavaScriptRegexEngine }, { bundledThemes }] = await Promise.all([import('shiki/core'), import('shiki/engine/javascript'), import('shiki/themes')]);
|
|
1539
|
-
highlighter = await createHighlighterCore({
|
|
1540
|
-
themes: [bundledThemes[THEMES.light], bundledThemes[THEMES.dark]],
|
|
1541
|
-
langs: [],
|
|
1542
|
-
// No WASM: the JS engine keeps this a plain import. `forgiving` skips
|
|
1543
|
-
// the odd grammar rule it can't translate rather than failing the block.
|
|
1544
|
-
engine: createJavaScriptRegexEngine({ forgiving: true })
|
|
1545
|
-
});
|
|
1546
|
-
return highlighter;
|
|
1547
|
-
})());
|
|
1548
|
-
return booting;
|
|
1549
|
-
}
|
|
1550
|
-
function ensureLanguage(lang) {
|
|
1551
|
-
let pending = loading.get(lang);
|
|
1552
|
-
if (!pending) {
|
|
1553
|
-
pending = (async () => {
|
|
1554
|
-
const [core, { bundledLanguages }] = await Promise.all([boot(), import('shiki/langs')]);
|
|
1555
|
-
const grammar = bundledLanguages[lang];
|
|
1556
|
-
if (!grammar) {
|
|
1557
|
-
unsupported.add(lang);
|
|
1558
|
-
return;
|
|
1559
|
-
}
|
|
1560
|
-
await core.loadLanguage(grammar);
|
|
1561
|
-
loaded.add(lang);
|
|
1562
|
-
})().catch(() => {
|
|
1563
|
-
unsupported.add(lang);
|
|
1564
|
-
});
|
|
1565
|
-
loading.set(lang, pending);
|
|
1566
|
-
}
|
|
1567
|
-
return pending;
|
|
1568
|
-
}
|
|
1569
|
-
function normalizeLanguage(language) {
|
|
1570
|
-
const lang = language?.trim().toLowerCase();
|
|
1571
|
-
return lang || void 0;
|
|
1572
|
-
}
|
|
1573
|
-
function useHighlight(code, language) {
|
|
1574
|
-
const [, rerender] = useReducer((n) => n + 1, 0);
|
|
1575
|
-
const lang = normalizeLanguage(language);
|
|
1576
|
-
const ready = Boolean(lang && loaded.has(lang));
|
|
1577
|
-
useEffect(() => {
|
|
1578
|
-
if (!lang || ready || unsupported.has(lang)) return;
|
|
1579
|
-
let cancelled = false;
|
|
1580
|
-
void ensureLanguage(lang).then(() => {
|
|
1581
|
-
if (!cancelled) rerender();
|
|
1582
|
-
});
|
|
1583
|
-
return () => {
|
|
1584
|
-
cancelled = true;
|
|
1585
|
-
};
|
|
1586
|
-
}, [lang, ready]);
|
|
1587
|
-
return useMemo(() => {
|
|
1588
|
-
if (!lang || !ready || !highlighter) return null;
|
|
1589
|
-
try {
|
|
1590
|
-
return highlighter.codeToTokens(code, { lang, themes: THEMES, defaultColor: false }).tokens;
|
|
1591
|
-
} catch {
|
|
1592
|
-
return null;
|
|
1593
|
-
}
|
|
1594
|
-
}, [code, lang, ready]);
|
|
1595
|
-
}
|
|
1596
1774
|
var useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
|
|
1597
1775
|
var caches = /* @__PURE__ */ new WeakMap();
|
|
1598
1776
|
var inflight = /* @__PURE__ */ new WeakMap();
|
|
@@ -1649,10 +1827,11 @@ function Favicon({
|
|
|
1649
1827
|
size = 14,
|
|
1650
1828
|
className
|
|
1651
1829
|
}) {
|
|
1652
|
-
const
|
|
1653
|
-
const [
|
|
1654
|
-
|
|
1655
|
-
|
|
1830
|
+
const candidates = useMemo(() => faviconFallbacks(url), [url]);
|
|
1831
|
+
const [attempt, setAttempt] = useState(0);
|
|
1832
|
+
const src = candidates[attempt];
|
|
1833
|
+
useEffect(() => setAttempt(0), [url]);
|
|
1834
|
+
if (kind === "document" || !src) {
|
|
1656
1835
|
const Glyph2 = kind === "document" ? BookOpen : Globe;
|
|
1657
1836
|
return /* @__PURE__ */ jsx("span", { className: cx("agno-favicon", "agno-favicon--glyph", className), "aria-hidden": true, children: /* @__PURE__ */ jsx(Glyph2, { size }) });
|
|
1658
1837
|
}
|
|
@@ -1666,7 +1845,7 @@ function Favicon({
|
|
|
1666
1845
|
height: size,
|
|
1667
1846
|
loading: "lazy",
|
|
1668
1847
|
decoding: "async",
|
|
1669
|
-
onError: () =>
|
|
1848
|
+
onError: () => setAttempt((n) => n + 1),
|
|
1670
1849
|
"aria-hidden": true
|
|
1671
1850
|
}
|
|
1672
1851
|
);
|
|
@@ -1797,36 +1976,24 @@ function HoverPreview({
|
|
|
1797
1976
|
}
|
|
1798
1977
|
);
|
|
1799
1978
|
}
|
|
1800
|
-
function el(tag, className) {
|
|
1801
|
-
return function Element({ node: _node, className: _theirs, ...rest }) {
|
|
1802
|
-
return React7.createElement(tag, { className, ...rest });
|
|
1803
|
-
};
|
|
1804
|
-
}
|
|
1805
1979
|
function sourceForUrl(url, sources) {
|
|
1806
|
-
return url ? sources.find((
|
|
1980
|
+
return url ? sources.find((source) => source.url === url) : void 0;
|
|
1807
1981
|
}
|
|
1808
1982
|
function citationForLink(label2, href, ctx) {
|
|
1809
1983
|
if (!/^\d+$/.test(label2.trim())) return void 0;
|
|
1810
|
-
return sourceForUrl(href, ctx.sources) ?? ctx.sources.find((
|
|
1811
|
-
}
|
|
1812
|
-
function labelOf(children) {
|
|
1813
|
-
if (typeof children === "string") return children;
|
|
1814
|
-
if (Array.isArray(children) && children.length === 1 && typeof children[0] === "string") {
|
|
1815
|
-
return children[0];
|
|
1816
|
-
}
|
|
1817
|
-
return "";
|
|
1984
|
+
return sourceForUrl(href, ctx.sources) ?? ctx.sources.find((source) => source.index === Number(label2.trim()));
|
|
1818
1985
|
}
|
|
1819
1986
|
function CitationMarker({
|
|
1820
1987
|
source,
|
|
1821
1988
|
className,
|
|
1822
|
-
Link
|
|
1989
|
+
Link: Link2
|
|
1823
1990
|
}) {
|
|
1824
1991
|
const props = {
|
|
1825
1992
|
className: cx("agno-cite", className),
|
|
1826
1993
|
href: source.url ?? `#${source.anchorId}`,
|
|
1827
1994
|
"aria-label": `Source ${source.index}: ${source.title}`
|
|
1828
1995
|
};
|
|
1829
|
-
return /* @__PURE__ */ jsx(HoverPreview, { source, className: "agno-cite__wrap", children:
|
|
1996
|
+
return /* @__PURE__ */ jsx(HoverPreview, { source, className: "agno-cite__wrap", children: Link2 && source.url ? /* @__PURE__ */ jsx(Link2, { ...props, children: source.index }) : /* @__PURE__ */ jsx(
|
|
1830
1997
|
"a",
|
|
1831
1998
|
{
|
|
1832
1999
|
...props,
|
|
@@ -1836,6 +2003,73 @@ function CitationMarker({
|
|
|
1836
2003
|
}
|
|
1837
2004
|
) });
|
|
1838
2005
|
}
|
|
2006
|
+
var THEMES = { light: "github-light", dark: "monokai" };
|
|
2007
|
+
var highlighter;
|
|
2008
|
+
var booting;
|
|
2009
|
+
var loading = /* @__PURE__ */ new Map();
|
|
2010
|
+
var loaded = /* @__PURE__ */ new Set();
|
|
2011
|
+
var unsupported = /* @__PURE__ */ new Set();
|
|
2012
|
+
async function boot() {
|
|
2013
|
+
if (highlighter) return highlighter;
|
|
2014
|
+
booting ?? (booting = (async () => {
|
|
2015
|
+
const [{ createHighlighterCore }, { createJavaScriptRegexEngine }, { bundledThemes }] = await Promise.all([import('shiki/core'), import('shiki/engine/javascript'), import('shiki/themes')]);
|
|
2016
|
+
highlighter = await createHighlighterCore({
|
|
2017
|
+
themes: [bundledThemes[THEMES.light], bundledThemes[THEMES.dark]],
|
|
2018
|
+
langs: [],
|
|
2019
|
+
// No WASM: the JS engine keeps this a plain import. `forgiving` skips
|
|
2020
|
+
// the odd grammar rule it can't translate rather than failing the block.
|
|
2021
|
+
engine: createJavaScriptRegexEngine({ forgiving: true })
|
|
2022
|
+
});
|
|
2023
|
+
return highlighter;
|
|
2024
|
+
})());
|
|
2025
|
+
return booting;
|
|
2026
|
+
}
|
|
2027
|
+
function ensureLanguage(lang) {
|
|
2028
|
+
let pending = loading.get(lang);
|
|
2029
|
+
if (!pending) {
|
|
2030
|
+
pending = (async () => {
|
|
2031
|
+
const [core, { bundledLanguages }] = await Promise.all([boot(), import('shiki/langs')]);
|
|
2032
|
+
const grammar = bundledLanguages[lang];
|
|
2033
|
+
if (!grammar) {
|
|
2034
|
+
unsupported.add(lang);
|
|
2035
|
+
return;
|
|
2036
|
+
}
|
|
2037
|
+
await core.loadLanguage(grammar);
|
|
2038
|
+
loaded.add(lang);
|
|
2039
|
+
})().catch(() => {
|
|
2040
|
+
unsupported.add(lang);
|
|
2041
|
+
});
|
|
2042
|
+
loading.set(lang, pending);
|
|
2043
|
+
}
|
|
2044
|
+
return pending;
|
|
2045
|
+
}
|
|
2046
|
+
function normalizeLanguage(language) {
|
|
2047
|
+
const lang = language?.trim().toLowerCase();
|
|
2048
|
+
return lang || void 0;
|
|
2049
|
+
}
|
|
2050
|
+
function useHighlight(code, language) {
|
|
2051
|
+
const [, rerender] = useReducer((n) => n + 1, 0);
|
|
2052
|
+
const lang = normalizeLanguage(language);
|
|
2053
|
+
const ready = Boolean(lang && loaded.has(lang));
|
|
2054
|
+
useEffect(() => {
|
|
2055
|
+
if (!lang || ready || unsupported.has(lang)) return;
|
|
2056
|
+
let cancelled = false;
|
|
2057
|
+
void ensureLanguage(lang).then(() => {
|
|
2058
|
+
if (!cancelled) rerender();
|
|
2059
|
+
});
|
|
2060
|
+
return () => {
|
|
2061
|
+
cancelled = true;
|
|
2062
|
+
};
|
|
2063
|
+
}, [lang, ready]);
|
|
2064
|
+
return useMemo(() => {
|
|
2065
|
+
if (!lang || !ready || !highlighter) return null;
|
|
2066
|
+
try {
|
|
2067
|
+
return highlighter.codeToTokens(code, { lang, themes: THEMES, defaultColor: false }).tokens;
|
|
2068
|
+
} catch {
|
|
2069
|
+
return null;
|
|
2070
|
+
}
|
|
2071
|
+
}, [code, lang, ready]);
|
|
2072
|
+
}
|
|
1839
2073
|
var COPIED_FOR = 1600;
|
|
1840
2074
|
var CLIPBOARD_TIMEOUT = 400;
|
|
1841
2075
|
async function writeClipboard(text) {
|
|
@@ -1861,7 +2095,7 @@ async function writeClipboard(text) {
|
|
|
1861
2095
|
return false;
|
|
1862
2096
|
}
|
|
1863
2097
|
}
|
|
1864
|
-
function CopyButton({ text, className }) {
|
|
2098
|
+
function CopyButton({ text, label: label2 = "Copy", size = 14, className }) {
|
|
1865
2099
|
const [copied, setCopied] = useState(false);
|
|
1866
2100
|
useEffect(() => {
|
|
1867
2101
|
if (!copied) return;
|
|
@@ -1869,17 +2103,18 @@ function CopyButton({ text, className }) {
|
|
|
1869
2103
|
return () => clearTimeout(timer);
|
|
1870
2104
|
}, [copied]);
|
|
1871
2105
|
const copy = async () => {
|
|
1872
|
-
if (await writeClipboard(text())) setCopied(true);
|
|
2106
|
+
if (await writeClipboard(typeof text === "function" ? text() : text)) setCopied(true);
|
|
1873
2107
|
};
|
|
2108
|
+
const name = copied ? "Copied" : label2;
|
|
1874
2109
|
return /* @__PURE__ */ jsx(
|
|
1875
2110
|
"button",
|
|
1876
2111
|
{
|
|
1877
2112
|
type: "button",
|
|
1878
|
-
className: cx("agno-
|
|
2113
|
+
className: cx("agno-copy", copied && "is-copied", className),
|
|
1879
2114
|
onClick: copy,
|
|
1880
|
-
"aria-label":
|
|
1881
|
-
title:
|
|
1882
|
-
children: copied ? /* @__PURE__ */ jsx(Check, { size
|
|
2115
|
+
"aria-label": name,
|
|
2116
|
+
title: name,
|
|
2117
|
+
children: copied ? /* @__PURE__ */ jsx(Check, { size }) : /* @__PURE__ */ jsx(Copy, { size })
|
|
1883
2118
|
}
|
|
1884
2119
|
);
|
|
1885
2120
|
}
|
|
@@ -1887,15 +2122,20 @@ function textOf(children) {
|
|
|
1887
2122
|
if (typeof children === "string") return children;
|
|
1888
2123
|
if (typeof children === "number") return String(children);
|
|
1889
2124
|
if (Array.isArray(children)) return children.map(textOf).join("");
|
|
1890
|
-
if (
|
|
2125
|
+
if (React8.isValidElement(children))
|
|
2126
|
+
return textOf(children.props.children);
|
|
1891
2127
|
return "";
|
|
1892
2128
|
}
|
|
1893
2129
|
function fencedCode(children) {
|
|
1894
2130
|
const child = Array.isArray(children) ? children[0] : children;
|
|
1895
|
-
if (!
|
|
2131
|
+
if (!React8.isValidElement(
|
|
2132
|
+
child
|
|
2133
|
+
)) {
|
|
1896
2134
|
return { code: textOf(children) };
|
|
1897
2135
|
}
|
|
1898
|
-
const language = /(?:^|\s)language-([^\s]+)/.exec(
|
|
2136
|
+
const language = /(?:^|\s)language-([^\s]+)/.exec(
|
|
2137
|
+
child.props.className ?? ""
|
|
2138
|
+
)?.[1];
|
|
1899
2139
|
return { language, code: textOf(child.props.children).replace(/\n$/, "") };
|
|
1900
2140
|
}
|
|
1901
2141
|
function plainLines(code) {
|
|
@@ -1904,93 +2144,159 @@ function plainLines(code) {
|
|
|
1904
2144
|
function CodeBlock({
|
|
1905
2145
|
children,
|
|
1906
2146
|
copyClass,
|
|
1907
|
-
codeCopy
|
|
2147
|
+
codeCopy,
|
|
2148
|
+
streaming
|
|
1908
2149
|
}) {
|
|
1909
2150
|
const { language, code } = useMemo(() => fencedCode(children), [children]);
|
|
1910
|
-
const highlighted = useHighlight(code, language);
|
|
1911
|
-
const lines = highlighted ?? plainLines(code);
|
|
2151
|
+
const highlighted = useHighlight(streaming ? "" : code, language);
|
|
2152
|
+
const lines = streaming ? plainLines(code) : highlighted ?? plainLines(code);
|
|
1912
2153
|
const label2 = normalizeLanguage(language) ?? "text";
|
|
1913
2154
|
return /* @__PURE__ */ jsxs("div", { className: "agno-md-code-block", "data-language": label2, children: [
|
|
1914
2155
|
/* @__PURE__ */ jsxs("div", { className: "agno-md-code-head", children: [
|
|
1915
2156
|
/* @__PURE__ */ jsx("span", { className: "agno-md-code-lang", children: label2 }),
|
|
1916
|
-
codeCopy && /* @__PURE__ */ jsx(
|
|
2157
|
+
codeCopy && /* @__PURE__ */ jsx(
|
|
2158
|
+
CopyButton,
|
|
2159
|
+
{
|
|
2160
|
+
className: cx("agno-md-copy", copyClass),
|
|
2161
|
+
text: () => code,
|
|
2162
|
+
label: "Copy code",
|
|
2163
|
+
size: 13
|
|
2164
|
+
}
|
|
2165
|
+
)
|
|
1917
2166
|
] }),
|
|
1918
|
-
/* @__PURE__ */ jsx(
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
2167
|
+
/* @__PURE__ */ jsx(
|
|
2168
|
+
"pre",
|
|
2169
|
+
{
|
|
2170
|
+
className: "agno-md-pre",
|
|
2171
|
+
style: {
|
|
2172
|
+
"--agno-code-gutter": `${String(lines.length).length}ch`
|
|
2173
|
+
},
|
|
2174
|
+
children: /* @__PURE__ */ jsx("code", { className: language ? `language-${language}` : void 0, children: lines.map((tokens, i) => /* @__PURE__ */ jsxs(React8.Fragment, { children: [
|
|
2175
|
+
/* @__PURE__ */ jsx("span", { className: "agno-md-line", children: tokens.map((token, j) => /* @__PURE__ */ jsx(
|
|
2176
|
+
"span",
|
|
2177
|
+
{
|
|
2178
|
+
style: token.htmlStyle,
|
|
2179
|
+
children: token.content
|
|
2180
|
+
},
|
|
2181
|
+
j
|
|
2182
|
+
)) }),
|
|
2183
|
+
i < lines.length - 1 && "\n"
|
|
2184
|
+
] }, i)) })
|
|
2185
|
+
}
|
|
2186
|
+
)
|
|
1922
2187
|
] });
|
|
1923
2188
|
}
|
|
1924
|
-
|
|
1925
|
-
|
|
2189
|
+
var InlineRenderContext = createContext({
|
|
2190
|
+
sources: [],
|
|
2191
|
+
canResolve: false,
|
|
2192
|
+
codeCopy: true
|
|
2193
|
+
});
|
|
2194
|
+
function el(tag, className) {
|
|
2195
|
+
return function Element({
|
|
1926
2196
|
node: _node,
|
|
1927
2197
|
className: _theirs,
|
|
1928
|
-
href,
|
|
1929
|
-
children,
|
|
1930
2198
|
...rest
|
|
1931
2199
|
}) {
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
2200
|
+
return React8.createElement(tag, { className, ...rest });
|
|
2201
|
+
};
|
|
2202
|
+
}
|
|
2203
|
+
function Link({
|
|
2204
|
+
node: _node,
|
|
2205
|
+
className: _theirs,
|
|
2206
|
+
href,
|
|
2207
|
+
children,
|
|
2208
|
+
...rest
|
|
2209
|
+
}) {
|
|
2210
|
+
const ctx = useContext(InlineRenderContext);
|
|
2211
|
+
const cited = citationForLink(textOf(children), href, ctx);
|
|
2212
|
+
if (cited)
|
|
1937
2213
|
return /* @__PURE__ */ jsx(
|
|
1938
|
-
|
|
2214
|
+
CitationMarker,
|
|
1939
2215
|
{
|
|
1940
|
-
source:
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
kind: "url",
|
|
1944
|
-
url: href,
|
|
1945
|
-
title: labelOf(children) || sourceHost(href) || href
|
|
1946
|
-
},
|
|
1947
|
-
children: link
|
|
2216
|
+
source: cited,
|
|
2217
|
+
className: ctx.markerClass,
|
|
2218
|
+
Link: ctx.Link
|
|
1948
2219
|
}
|
|
1949
2220
|
);
|
|
1950
|
-
};
|
|
1951
|
-
const
|
|
1952
|
-
|
|
1953
|
-
return
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
sub: el("sub"),
|
|
1966
|
-
sup: el("sup"),
|
|
1967
|
-
h1: el("h2", "agno-md-heading"),
|
|
1968
|
-
h2: el("h3", "agno-md-heading"),
|
|
1969
|
-
h3: el("h4", "agno-md-heading"),
|
|
1970
|
-
h4: el("h5", "agno-md-heading"),
|
|
1971
|
-
h5: el("h6", "agno-md-heading"),
|
|
1972
|
-
h6: el("h6", "agno-md-heading"),
|
|
1973
|
-
ul: el("ul", "agno-md-list"),
|
|
1974
|
-
ol: el("ol", "agno-md-list"),
|
|
1975
|
-
li: el("li"),
|
|
1976
|
-
pre: function Pre({ children }) {
|
|
1977
|
-
return /* @__PURE__ */ jsx(CodeBlock, { copyClass: ctx.copyClass, codeCopy: ctx.codeCopy, children });
|
|
1978
|
-
},
|
|
1979
|
-
blockquote: el("blockquote", "agno-md-quote"),
|
|
1980
|
-
hr: el("hr", "agno-md-rule"),
|
|
1981
|
-
table: function Table({ node: _node, className: _theirs, ...rest }) {
|
|
1982
|
-
return /* @__PURE__ */ jsx("div", { className: "agno-md-table-wrap", children: /* @__PURE__ */ jsx("table", { className: "agno-md-table", ...rest }) });
|
|
1983
|
-
},
|
|
1984
|
-
thead: el("thead"),
|
|
1985
|
-
tbody: el("tbody"),
|
|
1986
|
-
tr: el("tr"),
|
|
1987
|
-
th: el("th"),
|
|
1988
|
-
td: el("td"),
|
|
1989
|
-
img: function Image({ node: _node, className: _theirs, ...rest }) {
|
|
1990
|
-
return /* @__PURE__ */ jsx("img", { className: "agno-md-img", ...rest });
|
|
2221
|
+
const link = ctx.Link && href ? /* @__PURE__ */ jsx(ctx.Link, { href, ...rest, children }) : /* @__PURE__ */ jsx("a", { href, target: "_blank", rel: "noreferrer noopener", ...rest, children });
|
|
2222
|
+
const source = sourceForUrl(href, ctx.sources);
|
|
2223
|
+
if (!href || !/^https?:\/\//i.test(href) || !source && !ctx.canResolve)
|
|
2224
|
+
return link;
|
|
2225
|
+
return /* @__PURE__ */ jsx(
|
|
2226
|
+
HoverPreview,
|
|
2227
|
+
{
|
|
2228
|
+
source: source ?? {
|
|
2229
|
+
index: 0,
|
|
2230
|
+
anchorId: "",
|
|
2231
|
+
kind: "url",
|
|
2232
|
+
url: href,
|
|
2233
|
+
title: textOf(children) || sourceHost(href) || href
|
|
2234
|
+
},
|
|
2235
|
+
children: link
|
|
1991
2236
|
}
|
|
1992
|
-
|
|
2237
|
+
);
|
|
2238
|
+
}
|
|
2239
|
+
function Code({ node: _node, className, ...rest }) {
|
|
2240
|
+
const fenced = typeof className === "string" && className.includes("language-");
|
|
2241
|
+
return /* @__PURE__ */ jsx("code", { className: fenced ? className : "agno-md-code", ...rest });
|
|
1993
2242
|
}
|
|
2243
|
+
function Pre({ children }) {
|
|
2244
|
+
const ctx = useContext(InlineRenderContext);
|
|
2245
|
+
return /* @__PURE__ */ jsx(
|
|
2246
|
+
CodeBlock,
|
|
2247
|
+
{
|
|
2248
|
+
copyClass: ctx.copyClass,
|
|
2249
|
+
codeCopy: ctx.codeCopy,
|
|
2250
|
+
streaming: ctx.streaming,
|
|
2251
|
+
children
|
|
2252
|
+
}
|
|
2253
|
+
);
|
|
2254
|
+
}
|
|
2255
|
+
function Table({ node: _node, className: _theirs, ...rest }) {
|
|
2256
|
+
return /* @__PURE__ */ jsx("div", { className: "agno-md-table-wrap", children: /* @__PURE__ */ jsx("table", { className: "agno-md-table", ...rest }) });
|
|
2257
|
+
}
|
|
2258
|
+
function Image({ node: _node, className: _theirs, ...rest }) {
|
|
2259
|
+
return /* @__PURE__ */ jsx("img", { className: "agno-md-img", ...rest });
|
|
2260
|
+
}
|
|
2261
|
+
var MARKDOWN_COMPONENTS = {
|
|
2262
|
+
a: Link,
|
|
2263
|
+
code: Code,
|
|
2264
|
+
p: el("p", "agno-md-p"),
|
|
2265
|
+
// Streamdown renders `**bold**` as a Tailwind-classed <span>, which is not
|
|
2266
|
+
// bold anywhere Tailwind isn't. These stay real elements, styled by the
|
|
2267
|
+
// browser and read correctly by a screen reader.
|
|
2268
|
+
strong: el("strong"),
|
|
2269
|
+
em: el("em"),
|
|
2270
|
+
del: el("del"),
|
|
2271
|
+
sub: el("sub"),
|
|
2272
|
+
sup: el("sup"),
|
|
2273
|
+
h1: el("h2", "agno-md-heading"),
|
|
2274
|
+
h2: el("h3", "agno-md-heading"),
|
|
2275
|
+
h3: el("h4", "agno-md-heading"),
|
|
2276
|
+
h4: el("h5", "agno-md-heading"),
|
|
2277
|
+
h5: el("h6", "agno-md-heading"),
|
|
2278
|
+
h6: el("h6", "agno-md-heading"),
|
|
2279
|
+
ul: el("ul", "agno-md-list"),
|
|
2280
|
+
ol: el("ol", "agno-md-list"),
|
|
2281
|
+
li: el("li"),
|
|
2282
|
+
pre: Pre,
|
|
2283
|
+
blockquote: el("blockquote", "agno-md-quote"),
|
|
2284
|
+
hr: el("hr", "agno-md-rule"),
|
|
2285
|
+
table: Table,
|
|
2286
|
+
thead: el("thead"),
|
|
2287
|
+
tbody: el("tbody"),
|
|
2288
|
+
tr: el("tr"),
|
|
2289
|
+
th: el("th"),
|
|
2290
|
+
td: el("td"),
|
|
2291
|
+
img: Image
|
|
2292
|
+
};
|
|
2293
|
+
var STREAMING_MOTION = {
|
|
2294
|
+
animation: "fadeIn",
|
|
2295
|
+
duration: 400,
|
|
2296
|
+
easing: "ease-out",
|
|
2297
|
+
sep: "word",
|
|
2298
|
+
stagger: 0
|
|
2299
|
+
};
|
|
1994
2300
|
function Markdown({
|
|
1995
2301
|
content,
|
|
1996
2302
|
className,
|
|
@@ -2007,30 +2313,33 @@ function Markdown({
|
|
|
2007
2313
|
const providerLink = useLinkComponent();
|
|
2008
2314
|
const cited = sources ?? fromMessage;
|
|
2009
2315
|
const copy = codeCopy ?? fromProvider ?? true;
|
|
2010
|
-
const
|
|
2011
|
-
const
|
|
2012
|
-
() =>
|
|
2316
|
+
const Link2 = linkComponent ?? providerLink;
|
|
2317
|
+
const inlineContext = useMemo(
|
|
2318
|
+
() => ({
|
|
2013
2319
|
sources: cited,
|
|
2014
2320
|
canResolve,
|
|
2015
2321
|
markerClass: cn.citationMarker,
|
|
2016
2322
|
copyClass: cn.copyButton,
|
|
2017
2323
|
codeCopy: copy,
|
|
2018
|
-
Link
|
|
2324
|
+
Link: Link2,
|
|
2325
|
+
streaming
|
|
2019
2326
|
}),
|
|
2020
|
-
[cited, canResolve, cn.citationMarker, cn.copyButton, copy,
|
|
2327
|
+
[cited, canResolve, cn.citationMarker, cn.copyButton, copy, Link2, streaming]
|
|
2021
2328
|
);
|
|
2022
2329
|
const text = useMemo(() => linkCitations(content, cited), [content, cited]);
|
|
2023
|
-
return /* @__PURE__ */ jsx(
|
|
2330
|
+
return /* @__PURE__ */ jsx(InlineRenderContext.Provider, { value: inlineContext, children: /* @__PURE__ */ jsx(
|
|
2024
2331
|
Streamdown,
|
|
2025
2332
|
{
|
|
2026
2333
|
className: cx("agno-md", className),
|
|
2027
|
-
components,
|
|
2334
|
+
components: MARKDOWN_COMPONENTS,
|
|
2028
2335
|
mode: streaming ? "streaming" : "static",
|
|
2029
2336
|
parseIncompleteMarkdown: streaming !== false,
|
|
2337
|
+
animated: streaming ? STREAMING_MOTION : false,
|
|
2338
|
+
isAnimating: Boolean(streaming),
|
|
2030
2339
|
...options,
|
|
2031
2340
|
children: text
|
|
2032
2341
|
}
|
|
2033
|
-
);
|
|
2342
|
+
) });
|
|
2034
2343
|
}
|
|
2035
2344
|
function statusOf(tool) {
|
|
2036
2345
|
if (tool.tool_call_error) return { label: "error", cls: "error" };
|
|
@@ -2152,7 +2461,7 @@ function stepsFromEvents(message, { hideReasoning, hideTools }) {
|
|
|
2152
2461
|
const key = `reasoning:${e.run_id ?? "run"}`;
|
|
2153
2462
|
const at = indexOf.get(key);
|
|
2154
2463
|
const previous = at != null ? steps[at].steps : [];
|
|
2155
|
-
const incoming = e
|
|
2464
|
+
const incoming = reasoningStepsFromEvent(e);
|
|
2156
2465
|
const completed = isReasoningCompletedEvent(e);
|
|
2157
2466
|
put(key, {
|
|
2158
2467
|
kind: "reasoning",
|
|
@@ -2428,7 +2737,7 @@ function SourceCard({
|
|
|
2428
2737
|
className
|
|
2429
2738
|
}) {
|
|
2430
2739
|
const cn = useResolvedClassNames();
|
|
2431
|
-
const
|
|
2740
|
+
const Link2 = useLinkComponent();
|
|
2432
2741
|
const { preview } = useLinkPreview(source.url, false);
|
|
2433
2742
|
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2434
2743
|
/* @__PURE__ */ jsx(
|
|
@@ -2444,8 +2753,8 @@ function SourceCard({
|
|
|
2444
2753
|
source.url && /* @__PURE__ */ jsx(LinkIcon, { className: "agno-source__link" })
|
|
2445
2754
|
] });
|
|
2446
2755
|
const classes = cx("agno-source", `agno-source--${source.kind}`, cn.sourceCard, className);
|
|
2447
|
-
if (source.url &&
|
|
2448
|
-
return /* @__PURE__ */ jsx(
|
|
2756
|
+
if (source.url && Link2) {
|
|
2757
|
+
return /* @__PURE__ */ jsx(Link2, { id: source.anchorId, className: classes, href: source.url, title: source.url, children: body });
|
|
2449
2758
|
}
|
|
2450
2759
|
return source.url ? /* @__PURE__ */ jsx(
|
|
2451
2760
|
"a",
|
|
@@ -2575,6 +2884,20 @@ function Citations({
|
|
|
2575
2884
|
] })
|
|
2576
2885
|
] });
|
|
2577
2886
|
}
|
|
2887
|
+
function MessageActions({
|
|
2888
|
+
message,
|
|
2889
|
+
hideCopy,
|
|
2890
|
+
children,
|
|
2891
|
+
className,
|
|
2892
|
+
classNames
|
|
2893
|
+
}) {
|
|
2894
|
+
const cn = useResolvedClassNames(classNames);
|
|
2895
|
+
if (hideCopy && !children) return null;
|
|
2896
|
+
return /* @__PURE__ */ jsxs("div", { className: cx("agno-msg__actions", cn.messageActions, className), role: "toolbar", "aria-label": "Message actions", children: [
|
|
2897
|
+
!hideCopy && /* @__PURE__ */ jsx(CopyButton, { className: cx("agno-msg__action", cn.messageCopyButton), text: message.content, label: "Copy message" }),
|
|
2898
|
+
children
|
|
2899
|
+
] });
|
|
2900
|
+
}
|
|
2578
2901
|
function audioSrc(a) {
|
|
2579
2902
|
if (a.url) return a.url;
|
|
2580
2903
|
if (a.base64_audio) return `data:${a.mime_type ?? "audio/mpeg"};base64,${a.base64_audio}`;
|
|
@@ -2615,6 +2938,8 @@ function Message({
|
|
|
2615
2938
|
hideReasoning,
|
|
2616
2939
|
hideTools,
|
|
2617
2940
|
hideSources,
|
|
2941
|
+
hideActions,
|
|
2942
|
+
actions,
|
|
2618
2943
|
onFollowup
|
|
2619
2944
|
}) {
|
|
2620
2945
|
const cn = useResolvedClassNames(classNames);
|
|
@@ -2662,10 +2987,7 @@ function Message({
|
|
|
2662
2987
|
classNames: cn
|
|
2663
2988
|
}
|
|
2664
2989
|
),
|
|
2665
|
-
content ? /* @__PURE__ */
|
|
2666
|
-
renderMarkdown ? renderMarkdown(content) : /* @__PURE__ */ jsx(Markdown, { content, className: cn.markdown, streaming: message.streaming }),
|
|
2667
|
-
message.streaming && /* @__PURE__ */ jsx("span", { className: "agno-msg__caret", "aria-hidden": true })
|
|
2668
|
-
] }) : isAgent && message.streaming && hasActivity && /* @__PURE__ */ jsxs("div", { className: "agno-msg__activity", role: "status", "aria-live": "polite", children: [
|
|
2990
|
+
content ? /* @__PURE__ */ jsx("div", { className: cx("agno-msg__content", cn.messageContent), children: renderMarkdown ? renderMarkdown(content) : /* @__PURE__ */ jsx(Markdown, { content, className: cn.markdown, streaming: message.streaming }) }) : isAgent && message.streaming && hasActivity && /* @__PURE__ */ jsxs("div", { className: "agno-msg__activity", role: "status", "aria-live": "polite", children: [
|
|
2669
2991
|
/* @__PURE__ */ jsx(GridLoader, {}),
|
|
2670
2992
|
/* @__PURE__ */ jsx("span", { className: "agno-msg__activity-label", children: activity ?? "Working..." })
|
|
2671
2993
|
] }),
|
|
@@ -2681,7 +3003,8 @@ function Message({
|
|
|
2681
3003
|
showSources && /* @__PURE__ */ jsx(Citations, { sources, classNames: cn }),
|
|
2682
3004
|
isAgent && onFollowup && !message.streaming && /* @__PURE__ */ jsx(Followups, { items: message.followups, onSelect: onFollowup, classNames: cn }),
|
|
2683
3005
|
message.error && /* @__PURE__ */ jsx("div", { className: "agno-msg__error", children: message.error }),
|
|
2684
|
-
children
|
|
3006
|
+
children,
|
|
3007
|
+
isAgent && !hideActions && !message.streaming && message.content && /* @__PURE__ */ jsx(MessageActions, { message, classNames: cn, children: actions })
|
|
2685
3008
|
] }) })
|
|
2686
3009
|
]
|
|
2687
3010
|
}
|
|
@@ -2741,7 +3064,7 @@ function MessageList({
|
|
|
2741
3064
|
items.length === 0 ? /* @__PURE__ */ jsx("div", { className: cx("agno-list__empty", cn.empty), children: emptyState ?? "Start the conversation." }) : /* @__PURE__ */ jsxs("div", { className: "agno-list__inner", children: [
|
|
2742
3065
|
items.map((m) => {
|
|
2743
3066
|
const live = m.streaming && runStatus === "streaming" ? runActivity : void 0;
|
|
2744
|
-
return renderMessage ? /* @__PURE__ */ jsx(
|
|
3067
|
+
return renderMessage ? /* @__PURE__ */ jsx(React8.Fragment, { children: renderMessage(m, live) }, m.id) : /* @__PURE__ */ jsx(
|
|
2745
3068
|
Message,
|
|
2746
3069
|
{
|
|
2747
3070
|
message: m,
|
|
@@ -3186,7 +3509,7 @@ function AgnoChat(props) {
|
|
|
3186
3509
|
};
|
|
3187
3510
|
}, [client, props.entity, props.entities, props.showEntityPicker]);
|
|
3188
3511
|
const entity = props.entity ?? selected;
|
|
3189
|
-
const chat = useAgnoChat({ client, entity, userId: props.userId });
|
|
3512
|
+
const chat = useAgnoChat({ client, entity, userId: props.userId, streaming: props.streaming });
|
|
3190
3513
|
const { refreshSessions } = chat;
|
|
3191
3514
|
useEffect(() => {
|
|
3192
3515
|
if (props.showSessions && entity) refreshSessions();
|
|
@@ -3498,6 +3821,6 @@ function EventLog({
|
|
|
3498
3821
|
] });
|
|
3499
3822
|
}
|
|
3500
3823
|
|
|
3501
|
-
export { AgnoChat, AgnoMark, ArrowUp, BehindTheScenes, BookOpen, Box, Brain, ChatBubble, ChatInput, ChatLauncher, ChatProvider, ChatWindow, Check, ChevronDown, Citations, Close, Copy, EntityBadge, EntitySelector, EventLog, Favicon, FileAudio, FileIcon, FilePreview, FileType, FileVideo, Followups, Globe, GridLoader, HoverPreview, HumanInput, LinkIcon, LinkPreviewCard, Markdown, MemberResponses, Memory, Message, MessageList, Multimedia, Paperclip, Plus, Pulse, QuickPrompts, Reasoning, Rerun, SessionList, SourceCard, SourcesProvider, Spinner, StatusIndicator, Stop, TeamGlyph, ToolCalls, Trash, WorkflowSteps, Wrench, admitFiles, behindTheScenesItems, behindTheScenesLabel, collectSources, cx, displayUrl, faviconUrl, fileAccepted, getProviderIcon, hasBehindTheScenes, linkCitations, normalizeFollowups, quickPromptLabel, quickPromptText, sourceHost, sourcesFromMarkdown, useAgnoChat, useChatContext, useLinkComponent, useLinkPreview, useOptionalChatContext, useResolvedChat, useResolvedClassNames, useSources, withoutSourcesLine, writeClipboard };
|
|
3502
|
-
//# sourceMappingURL=chunk-
|
|
3503
|
-
//# sourceMappingURL=chunk-
|
|
3824
|
+
export { AgnoChat, AgnoMark, ArrowUp, BehindTheScenes, BookOpen, Box, Brain, ChatBubble, ChatInput, ChatLauncher, ChatProvider, ChatWindow, Check, ChevronDown, Citations, Close, Copy, CopyButton, DEFAULT_STREAMING_OPTIONS, EntityBadge, EntitySelector, EventLog, Favicon, FileAudio, FileIcon, FilePreview, FileType, FileVideo, Followups, Globe, GridLoader, HoverPreview, HumanInput, LinkIcon, LinkPreviewCard, Markdown, MemberResponses, Memory, Message, MessageActions, MessageList, Multimedia, Paperclip, Plus, Pulse, QuickPrompts, Reasoning, Rerun, SessionList, SourceCard, SourcesProvider, Spinner, StatusIndicator, Stop, TeamGlyph, ToolCalls, Trash, WorkflowSteps, Wrench, admitFiles, behindTheScenesItems, behindTheScenesLabel, collectSources, cx, displayUrl, faviconFallbacks, faviconUrl, fileAccepted, getProviderIcon, hasBehindTheScenes, linkCitations, normalizeFollowups, quickPromptLabel, quickPromptText, sourceHost, sourcesFromMarkdown, useAgnoChat, useChatContext, useLinkComponent, useLinkPreview, useOptionalChatContext, useResolvedChat, useResolvedClassNames, useSources, withoutSourcesLine, writeClipboard };
|
|
3825
|
+
//# sourceMappingURL=chunk-OGDPK4Z3.js.map
|
|
3826
|
+
//# sourceMappingURL=chunk-OGDPK4Z3.js.map
|