@agno-hq/chat-react 0.3.2 → 0.3.3
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 +35 -5
- package/dist/chat/index.cjs +94 -82
- package/dist/chat/index.d.cts +67 -15
- package/dist/chat/index.d.ts +67 -15
- package/dist/chat/index.js +1 -1
- package/dist/{chunk-Q73XHL35.cjs → chunk-3IEYJIYJ.cjs} +232 -207
- package/dist/chunk-3IEYJIYJ.cjs.map +1 -0
- package/dist/{chunk-XTP3TMEZ.js → chunk-E4CFQ457.js} +85 -63
- package/dist/chunk-E4CFQ457.js.map +1 -0
- package/dist/index.cjs +95 -83
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/styles.css +57 -19
- package/package.json +9 -11
- package/dist/chunk-Q73XHL35.cjs.map +0 -1
- package/dist/chunk-XTP3TMEZ.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunk55HQJGLP_cjs = require('./chunk-55HQJGLP.cjs');
|
|
4
|
-
var
|
|
4
|
+
var React8 = require('react');
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
var reactDom = require('react-dom');
|
|
7
7
|
var lucideReact = require('lucide-react');
|
|
@@ -9,43 +9,43 @@ var streamdown = require('streamdown');
|
|
|
9
9
|
|
|
10
10
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
11
|
|
|
12
|
-
var
|
|
12
|
+
var React8__default = /*#__PURE__*/_interopDefault(React8);
|
|
13
13
|
|
|
14
14
|
var messageCounter = 0;
|
|
15
15
|
var nextId = () => `m${Date.now().toString(36)}-${(messageCounter++).toString(36)}`;
|
|
16
16
|
var nowSeconds = () => Math.floor(Date.now() / 1e3);
|
|
17
17
|
function useAgnoChat(options) {
|
|
18
18
|
const { entity, userId, onEvent, onSessionId } = options;
|
|
19
|
-
const client =
|
|
19
|
+
const client = React8.useMemo(() => {
|
|
20
20
|
if (options.client) return options.client;
|
|
21
21
|
return new chunk55HQJGLP_cjs.AgnoClient({ baseUrl: options.baseUrl ?? "", headers: options.headers });
|
|
22
22
|
}, [options.client, options.baseUrl, JSON.stringify(options.headers)]);
|
|
23
|
-
const [messages, setMessages] =
|
|
24
|
-
const [events, setEvents] =
|
|
25
|
-
const [currentEvent, setCurrentEvent] =
|
|
26
|
-
const [status, setStatus] =
|
|
27
|
-
const [activity, setActivity] =
|
|
28
|
-
const [error, setError] =
|
|
29
|
-
const [sessionId, setSessionId] =
|
|
30
|
-
const [sessions, setSessions] =
|
|
31
|
-
const [sessionsLoading, setSessionsLoading] =
|
|
32
|
-
const [backgroundRunning, setBackgroundRunning] =
|
|
33
|
-
const abortRef =
|
|
34
|
-
const channelRef =
|
|
35
|
-
const backgroundRef =
|
|
36
|
-
const activeMsgIdRef =
|
|
37
|
-
const runIdRef =
|
|
38
|
-
const entityRef =
|
|
39
|
-
const sessionIdRef =
|
|
40
|
-
const pendingSessionNameRef =
|
|
41
|
-
const bumpedSessionRef =
|
|
42
|
-
|
|
23
|
+
const [messages, setMessages] = React8.useState(options.initialMessages ?? []);
|
|
24
|
+
const [events, setEvents] = React8.useState([]);
|
|
25
|
+
const [currentEvent, setCurrentEvent] = React8.useState(null);
|
|
26
|
+
const [status, setStatus] = React8.useState("idle");
|
|
27
|
+
const [activity, setActivity] = React8.useState(null);
|
|
28
|
+
const [error, setError] = React8.useState(null);
|
|
29
|
+
const [sessionId, setSessionId] = React8.useState(options.sessionId);
|
|
30
|
+
const [sessions, setSessions] = React8.useState([]);
|
|
31
|
+
const [sessionsLoading, setSessionsLoading] = React8.useState(false);
|
|
32
|
+
const [backgroundRunning, setBackgroundRunning] = React8.useState([]);
|
|
33
|
+
const abortRef = React8.useRef(null);
|
|
34
|
+
const channelRef = React8.useRef(null);
|
|
35
|
+
const backgroundRef = React8.useRef(/* @__PURE__ */ new Map());
|
|
36
|
+
const activeMsgIdRef = React8.useRef(null);
|
|
37
|
+
const runIdRef = React8.useRef(void 0);
|
|
38
|
+
const entityRef = React8.useRef(entity);
|
|
39
|
+
const sessionIdRef = React8.useRef(options.sessionId);
|
|
40
|
+
const pendingSessionNameRef = React8.useRef(void 0);
|
|
41
|
+
const bumpedSessionRef = React8.useRef(void 0);
|
|
42
|
+
React8.useEffect(() => {
|
|
43
43
|
entityRef.current = entity;
|
|
44
44
|
}, [entity]);
|
|
45
|
-
|
|
45
|
+
React8.useEffect(() => {
|
|
46
46
|
sessionIdRef.current = sessionId;
|
|
47
47
|
}, [sessionId]);
|
|
48
|
-
const upsertSession =
|
|
48
|
+
const upsertSession = React8.useCallback((id, createdAt) => {
|
|
49
49
|
setSessions((prev) => {
|
|
50
50
|
const existing = prev.find((s) => s.session_id === id);
|
|
51
51
|
const rest = prev.filter((s) => s.session_id !== id);
|
|
@@ -58,11 +58,11 @@ function useAgnoChat(options) {
|
|
|
58
58
|
return [entry, ...rest];
|
|
59
59
|
});
|
|
60
60
|
}, []);
|
|
61
|
-
const viewRef =
|
|
62
|
-
|
|
61
|
+
const viewRef = React8.useRef({ messages, events, status, activity, error });
|
|
62
|
+
React8.useEffect(() => {
|
|
63
63
|
viewRef.current = { messages, events, status, activity, error };
|
|
64
64
|
});
|
|
65
|
-
const writeMessages =
|
|
65
|
+
const writeMessages = React8.useCallback(
|
|
66
66
|
(chan, fn) => {
|
|
67
67
|
const park = chan?.park;
|
|
68
68
|
if (park) park.messages = fn(park.messages);
|
|
@@ -70,7 +70,7 @@ function useAgnoChat(options) {
|
|
|
70
70
|
},
|
|
71
71
|
[]
|
|
72
72
|
);
|
|
73
|
-
const writeEvents =
|
|
73
|
+
const writeEvents = React8.useCallback((chan, e) => {
|
|
74
74
|
const park = chan?.park;
|
|
75
75
|
if (park) park.events = [...park.events, e];
|
|
76
76
|
else {
|
|
@@ -78,22 +78,22 @@ function useAgnoChat(options) {
|
|
|
78
78
|
setCurrentEvent(e);
|
|
79
79
|
}
|
|
80
80
|
}, []);
|
|
81
|
-
const writeStatus =
|
|
81
|
+
const writeStatus = React8.useCallback((chan, status2) => {
|
|
82
82
|
const park = chan?.park;
|
|
83
83
|
if (park) park.status = status2;
|
|
84
84
|
else setStatus(status2);
|
|
85
85
|
}, []);
|
|
86
|
-
const writeActivity =
|
|
86
|
+
const writeActivity = React8.useCallback((chan, activity2) => {
|
|
87
87
|
const park = chan?.park;
|
|
88
88
|
if (park) park.activity = activity2;
|
|
89
89
|
else setActivity(activity2);
|
|
90
90
|
}, []);
|
|
91
|
-
const writeError =
|
|
91
|
+
const writeError = React8.useCallback((chan, message) => {
|
|
92
92
|
const park = chan?.park;
|
|
93
93
|
if (park) park.error = message;
|
|
94
94
|
else setError(message);
|
|
95
95
|
}, []);
|
|
96
|
-
const patchActive =
|
|
96
|
+
const patchActive = React8.useCallback(
|
|
97
97
|
(chan, patch) => {
|
|
98
98
|
const id = chan?.park ? chan.park.activeMsgId : activeMsgIdRef.current;
|
|
99
99
|
if (!id) return;
|
|
@@ -101,7 +101,7 @@ function useAgnoChat(options) {
|
|
|
101
101
|
},
|
|
102
102
|
[writeMessages]
|
|
103
103
|
);
|
|
104
|
-
const applyEvent =
|
|
104
|
+
const applyEvent = React8.useCallback(
|
|
105
105
|
(chan, e) => {
|
|
106
106
|
writeEvents(chan, e);
|
|
107
107
|
patchActive(chan, (m) => ({ ...m, events: [...m.events ?? [], e] }));
|
|
@@ -233,7 +233,7 @@ function useAgnoChat(options) {
|
|
|
233
233
|
writeStatus
|
|
234
234
|
]
|
|
235
235
|
);
|
|
236
|
-
const parkRun =
|
|
236
|
+
const parkRun = React8.useCallback((chan, sessionId2) => {
|
|
237
237
|
const view = viewRef.current;
|
|
238
238
|
chan.park = {
|
|
239
239
|
sessionId: sessionId2,
|
|
@@ -253,7 +253,7 @@ function useAgnoChat(options) {
|
|
|
253
253
|
activeMsgIdRef.current = null;
|
|
254
254
|
runIdRef.current = void 0;
|
|
255
255
|
}, []);
|
|
256
|
-
const resumeRun =
|
|
256
|
+
const resumeRun = React8.useCallback((sessionId2) => {
|
|
257
257
|
const chan = backgroundRef.current.get(sessionId2);
|
|
258
258
|
const park = chan?.park;
|
|
259
259
|
if (!chan || !park) return false;
|
|
@@ -273,7 +273,7 @@ function useAgnoChat(options) {
|
|
|
273
273
|
setError(park.error);
|
|
274
274
|
return true;
|
|
275
275
|
}, []);
|
|
276
|
-
const releaseCurrentRun =
|
|
276
|
+
const releaseCurrentRun = React8.useCallback(() => {
|
|
277
277
|
const chan = channelRef.current;
|
|
278
278
|
if (!chan || chan.park) return;
|
|
279
279
|
const from = sessionIdRef.current;
|
|
@@ -285,7 +285,7 @@ function useAgnoChat(options) {
|
|
|
285
285
|
abortRef.current = null;
|
|
286
286
|
}
|
|
287
287
|
}, [parkRun]);
|
|
288
|
-
const drive =
|
|
288
|
+
const drive = React8.useCallback(
|
|
289
289
|
async (starter) => {
|
|
290
290
|
const controller = new AbortController();
|
|
291
291
|
const chan = { controller, park: null };
|
|
@@ -321,7 +321,7 @@ function useAgnoChat(options) {
|
|
|
321
321
|
},
|
|
322
322
|
[applyEvent, patchActive, writeActivity, writeError, writeStatus]
|
|
323
323
|
);
|
|
324
|
-
const sendMessage =
|
|
324
|
+
const sendMessage = React8.useCallback(
|
|
325
325
|
async (message, sendOptions) => {
|
|
326
326
|
const ent = entityRef.current;
|
|
327
327
|
if (!ent) {
|
|
@@ -364,7 +364,7 @@ function useAgnoChat(options) {
|
|
|
364
364
|
},
|
|
365
365
|
[client, drive, userId]
|
|
366
366
|
);
|
|
367
|
-
const continueRun =
|
|
367
|
+
const continueRun = React8.useCallback(
|
|
368
368
|
async (resolution) => {
|
|
369
369
|
const ent = entityRef.current;
|
|
370
370
|
const runId = runIdRef.current;
|
|
@@ -388,15 +388,15 @@ function useAgnoChat(options) {
|
|
|
388
388
|
},
|
|
389
389
|
[client, drive, patchActive, userId]
|
|
390
390
|
);
|
|
391
|
-
const activeMessage =
|
|
391
|
+
const activeMessage = React8.useMemo(
|
|
392
392
|
() => messages.find((m) => m.id === activeMsgIdRef.current) ?? null,
|
|
393
393
|
[messages]
|
|
394
394
|
);
|
|
395
|
-
const pausedTools =
|
|
395
|
+
const pausedTools = React8.useMemo(
|
|
396
396
|
() => (activeMessage?.tool_calls ?? []).filter((t) => t.requires_confirmation || t.requires_user_input),
|
|
397
397
|
[activeMessage]
|
|
398
398
|
);
|
|
399
|
-
const respondToConfirmation =
|
|
399
|
+
const respondToConfirmation = React8.useCallback(
|
|
400
400
|
async (approve) => {
|
|
401
401
|
const ent = entityRef.current;
|
|
402
402
|
if (ent?.type === "workflow") {
|
|
@@ -409,7 +409,7 @@ function useAgnoChat(options) {
|
|
|
409
409
|
},
|
|
410
410
|
[activeMessage, continueRun, pausedTools]
|
|
411
411
|
);
|
|
412
|
-
const submitUserInput =
|
|
412
|
+
const submitUserInput = React8.useCallback(
|
|
413
413
|
async (values) => {
|
|
414
414
|
const ent = entityRef.current;
|
|
415
415
|
if (ent?.type === "workflow") {
|
|
@@ -435,7 +435,7 @@ function useAgnoChat(options) {
|
|
|
435
435
|
},
|
|
436
436
|
[activeMessage, continueRun, pausedTools]
|
|
437
437
|
);
|
|
438
|
-
const cancel =
|
|
438
|
+
const cancel = React8.useCallback(async () => {
|
|
439
439
|
abortRef.current?.abort();
|
|
440
440
|
channelRef.current = null;
|
|
441
441
|
const ent = entityRef.current;
|
|
@@ -445,7 +445,7 @@ function useAgnoChat(options) {
|
|
|
445
445
|
patchActive(null, (m) => m.streaming ? { ...m, streaming: false, status: "cancelled" } : m);
|
|
446
446
|
if (ent && runId) await client.cancelRun(ent.type, ent.id, runId, sessionIdRef.current);
|
|
447
447
|
}, [client, patchActive]);
|
|
448
|
-
const refreshSessions =
|
|
448
|
+
const refreshSessions = React8.useCallback(async () => {
|
|
449
449
|
const ent = entityRef.current;
|
|
450
450
|
if (!ent) {
|
|
451
451
|
setSessions([]);
|
|
@@ -464,7 +464,7 @@ function useAgnoChat(options) {
|
|
|
464
464
|
setSessionsLoading(false);
|
|
465
465
|
}
|
|
466
466
|
}, [client]);
|
|
467
|
-
const loadSession =
|
|
467
|
+
const loadSession = React8.useCallback(
|
|
468
468
|
async (id) => {
|
|
469
469
|
const ent = entityRef.current;
|
|
470
470
|
if (!ent) return;
|
|
@@ -490,7 +490,7 @@ function useAgnoChat(options) {
|
|
|
490
490
|
},
|
|
491
491
|
[client, onSessionId, releaseCurrentRun, resumeRun]
|
|
492
492
|
);
|
|
493
|
-
const deleteSession =
|
|
493
|
+
const deleteSession = React8.useCallback(
|
|
494
494
|
async (id) => {
|
|
495
495
|
const ent = entityRef.current;
|
|
496
496
|
const ok = await client.deleteSession(id, ent?.db_id);
|
|
@@ -511,7 +511,7 @@ function useAgnoChat(options) {
|
|
|
511
511
|
},
|
|
512
512
|
[client]
|
|
513
513
|
);
|
|
514
|
-
const reset =
|
|
514
|
+
const reset = React8.useCallback(() => {
|
|
515
515
|
releaseCurrentRun();
|
|
516
516
|
activeMsgIdRef.current = null;
|
|
517
517
|
runIdRef.current = void 0;
|
|
@@ -526,7 +526,7 @@ function useAgnoChat(options) {
|
|
|
526
526
|
setError(null);
|
|
527
527
|
setSessionId(void 0);
|
|
528
528
|
}, [releaseCurrentRun]);
|
|
529
|
-
|
|
529
|
+
React8.useEffect(() => {
|
|
530
530
|
const background = backgroundRef.current;
|
|
531
531
|
return () => {
|
|
532
532
|
abortRef.current?.abort();
|
|
@@ -534,7 +534,7 @@ function useAgnoChat(options) {
|
|
|
534
534
|
background.clear();
|
|
535
535
|
};
|
|
536
536
|
}, []);
|
|
537
|
-
const streamingMessage =
|
|
537
|
+
const streamingMessage = React8.useMemo(
|
|
538
538
|
() => messages.find((m) => m.role === "agent" && m.streaming) ?? null,
|
|
539
539
|
[messages]
|
|
540
540
|
);
|
|
@@ -576,7 +576,7 @@ function cx(...parts) {
|
|
|
576
576
|
const out = parts.filter(Boolean).join(" ");
|
|
577
577
|
return out || void 0;
|
|
578
578
|
}
|
|
579
|
-
var ChatContext =
|
|
579
|
+
var ChatContext = React8.createContext(null);
|
|
580
580
|
function ChatProvider({
|
|
581
581
|
children,
|
|
582
582
|
classNames,
|
|
@@ -593,7 +593,7 @@ function ChatProvider({
|
|
|
593
593
|
}) {
|
|
594
594
|
const internal = useAgnoChat(externalChat ? { entity: null } : options);
|
|
595
595
|
const chat = externalChat ?? internal;
|
|
596
|
-
const value =
|
|
596
|
+
const value = React8.useMemo(
|
|
597
597
|
() => ({ chat, classNames: classNames ?? {}, renderMarkdown, resolveLinkPreview, codeCopy, linkComponent }),
|
|
598
598
|
[chat, classNames, renderMarkdown, resolveLinkPreview, codeCopy, linkComponent]
|
|
599
599
|
);
|
|
@@ -608,12 +608,12 @@ function ChatProvider({
|
|
|
608
608
|
) : children });
|
|
609
609
|
}
|
|
610
610
|
function useChatContext() {
|
|
611
|
-
const value =
|
|
611
|
+
const value = React8.useContext(ChatContext);
|
|
612
612
|
if (!value) throw new Error("useChatContext must be used inside a <ChatProvider>");
|
|
613
613
|
return value;
|
|
614
614
|
}
|
|
615
615
|
function useOptionalChatContext() {
|
|
616
|
-
return
|
|
616
|
+
return React8.useContext(ChatContext);
|
|
617
617
|
}
|
|
618
618
|
function useResolvedChat(explicit) {
|
|
619
619
|
const ctx = useOptionalChatContext();
|
|
@@ -633,7 +633,7 @@ function useLinkComponent() {
|
|
|
633
633
|
}
|
|
634
634
|
function useResolvedClassNames(explicit) {
|
|
635
635
|
const ctx = useOptionalChatContext();
|
|
636
|
-
return
|
|
636
|
+
return React8.useMemo(() => ({ ...ctx?.classNames, ...explicit }), [ctx?.classNames, explicit]);
|
|
637
637
|
}
|
|
638
638
|
var STROKE = 1.5;
|
|
639
639
|
var icon = (Component, defaultSize = 16) => function Icon({ size = defaultSize, className }) {
|
|
@@ -778,19 +778,19 @@ function ChatLauncher({
|
|
|
778
778
|
portal = true,
|
|
779
779
|
className
|
|
780
780
|
}) {
|
|
781
|
-
const [uncontrolledOpen, setUncontrolledOpen] =
|
|
781
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React8.useState(defaultOpen);
|
|
782
782
|
const isOpen = open ?? uncontrolledOpen;
|
|
783
|
-
const opened =
|
|
783
|
+
const opened = React8.useRef(isOpen);
|
|
784
784
|
if (isOpen) opened.current = true;
|
|
785
785
|
const mounted = keepMounted ? opened.current : isOpen;
|
|
786
|
-
const setOpen =
|
|
786
|
+
const setOpen = React8.useCallback(
|
|
787
787
|
(next) => {
|
|
788
788
|
if (open === void 0) setUncontrolledOpen(next);
|
|
789
789
|
onOpenChange?.(next);
|
|
790
790
|
},
|
|
791
791
|
[open, onOpenChange]
|
|
792
792
|
);
|
|
793
|
-
|
|
793
|
+
React8.useEffect(() => {
|
|
794
794
|
if (!isOpen || !closeOnEscape) return;
|
|
795
795
|
const onKeyDown = (e) => {
|
|
796
796
|
if (e.key === "Escape") setOpen(false);
|
|
@@ -798,7 +798,7 @@ function ChatLauncher({
|
|
|
798
798
|
document.addEventListener("keydown", onKeyDown);
|
|
799
799
|
return () => document.removeEventListener("keydown", onKeyDown);
|
|
800
800
|
}, [isOpen, closeOnEscape, setOpen]);
|
|
801
|
-
|
|
801
|
+
React8.useEffect(() => {
|
|
802
802
|
if (!isOpen || panel !== "fullscreen") return;
|
|
803
803
|
const previous = document.body.style.overflow;
|
|
804
804
|
document.body.style.overflow = "hidden";
|
|
@@ -806,8 +806,8 @@ function ChatLauncher({
|
|
|
806
806
|
document.body.style.overflow = previous;
|
|
807
807
|
};
|
|
808
808
|
}, [isOpen, panel]);
|
|
809
|
-
const [canPortal, setCanPortal] =
|
|
810
|
-
|
|
809
|
+
const [canPortal, setCanPortal] = React8.useState(false);
|
|
810
|
+
React8.useEffect(() => setCanPortal(true), []);
|
|
811
811
|
const classes = [
|
|
812
812
|
"agno-launcher",
|
|
813
813
|
`agno-launcher--${position}`,
|
|
@@ -863,8 +863,8 @@ function kindOf(file) {
|
|
|
863
863
|
}
|
|
864
864
|
function Item({ file, onRemove }) {
|
|
865
865
|
const isImage = file.type.startsWith("image/");
|
|
866
|
-
const [url, setUrl] =
|
|
867
|
-
|
|
866
|
+
const [url, setUrl] = React8.useState(null);
|
|
867
|
+
React8.useEffect(() => {
|
|
868
868
|
if (!isImage) return;
|
|
869
869
|
const objectUrl = URL.createObjectURL(file);
|
|
870
870
|
setUrl(objectUrl);
|
|
@@ -968,24 +968,24 @@ function ChatInput({
|
|
|
968
968
|
}) {
|
|
969
969
|
const ctx = useOptionalChatContext();
|
|
970
970
|
const cn = useResolvedClassNames(classNames);
|
|
971
|
-
const [internal, setInternal] =
|
|
971
|
+
const [internal, setInternal] = React8.useState("");
|
|
972
972
|
const value = controlled ?? internal;
|
|
973
973
|
const setValue = (next) => {
|
|
974
974
|
if (controlled === void 0) setInternal(next);
|
|
975
975
|
onValueChange?.(next);
|
|
976
976
|
};
|
|
977
|
-
const [files, setFilesState] =
|
|
978
|
-
const filesRef =
|
|
977
|
+
const [files, setFilesState] = React8.useState([]);
|
|
978
|
+
const filesRef = React8.useRef([]);
|
|
979
979
|
const setFiles = (next) => {
|
|
980
980
|
filesRef.current = next;
|
|
981
981
|
setFilesState(next);
|
|
982
982
|
};
|
|
983
|
-
const [fileError, setFileError] =
|
|
984
|
-
const [dragging, setDragging] =
|
|
985
|
-
const dragDepth =
|
|
986
|
-
const fileRef =
|
|
987
|
-
const textareaRef =
|
|
988
|
-
const setTextareaRef =
|
|
983
|
+
const [fileError, setFileError] = React8.useState(null);
|
|
984
|
+
const [dragging, setDragging] = React8.useState(false);
|
|
985
|
+
const dragDepth = React8.useRef(0);
|
|
986
|
+
const fileRef = React8.useRef(null);
|
|
987
|
+
const textareaRef = React8.useRef(null);
|
|
988
|
+
const setTextareaRef = React8.useCallback(
|
|
989
989
|
(el2) => {
|
|
990
990
|
textareaRef.current = el2;
|
|
991
991
|
if (typeof externalRef === "function") externalRef(el2);
|
|
@@ -993,14 +993,14 @@ function ChatInput({
|
|
|
993
993
|
},
|
|
994
994
|
[externalRef]
|
|
995
995
|
);
|
|
996
|
-
const adjustHeight =
|
|
996
|
+
const adjustHeight = React8.useCallback(() => {
|
|
997
997
|
const el2 = textareaRef.current;
|
|
998
998
|
if (!el2 || renderTextarea) return;
|
|
999
999
|
const { min, max } = compact ? BOUNDS.compact : BOUNDS.dock;
|
|
1000
1000
|
el2.style.height = `${min}px`;
|
|
1001
1001
|
el2.style.height = `${Math.min(Math.max(el2.scrollHeight, min), max)}px`;
|
|
1002
1002
|
}, [renderTextarea, compact]);
|
|
1003
|
-
|
|
1003
|
+
React8.useEffect(adjustHeight, [value, adjustHeight]);
|
|
1004
1004
|
const send = onSend ?? ((message, attached) => void ctx?.chat.sendMessage(message, attached ? { files: attached } : void 0));
|
|
1005
1005
|
const stop = onStop ?? (ctx ? () => void ctx.chat.cancel() : void 0);
|
|
1006
1006
|
const isBusy = busy ?? ctx?.chat.isStreaming ?? false;
|
|
@@ -1252,11 +1252,11 @@ function HumanInput({
|
|
|
1252
1252
|
onResolve,
|
|
1253
1253
|
className
|
|
1254
1254
|
}) {
|
|
1255
|
-
const asks =
|
|
1256
|
-
const [choices, setChoices] =
|
|
1257
|
-
const [values, setValues] =
|
|
1258
|
-
const [reasons, setReasons] =
|
|
1259
|
-
const [openArgs, setOpenArgs] =
|
|
1255
|
+
const asks = React8.useMemo(() => buildAsks(message, entityType), [message, entityType]);
|
|
1256
|
+
const [choices, setChoices] = React8.useState({});
|
|
1257
|
+
const [values, setValues] = React8.useState({});
|
|
1258
|
+
const [reasons, setReasons] = React8.useState({});
|
|
1259
|
+
const [openArgs, setOpenArgs] = React8.useState({});
|
|
1260
1260
|
if (asks.length === 0) return null;
|
|
1261
1261
|
const setValue = (id, name, value) => setValues((v) => ({ ...v, [id]: { ...v[id] ?? {}, [name]: value } }));
|
|
1262
1262
|
const valueFor = (ask, field) => values[ask.id]?.[field.name] ?? field.value ?? (isBoolField(field) ? false : "");
|
|
@@ -1399,11 +1399,14 @@ function sourceHost(url) {
|
|
|
1399
1399
|
}
|
|
1400
1400
|
}
|
|
1401
1401
|
function faviconUrl(url) {
|
|
1402
|
-
|
|
1402
|
+
return faviconFallbacks(url)[0];
|
|
1403
|
+
}
|
|
1404
|
+
function faviconFallbacks(url) {
|
|
1405
|
+
if (!url) return [];
|
|
1403
1406
|
try {
|
|
1404
|
-
return
|
|
1407
|
+
return ["/favicon.ico", "/favicon.svg"].map((path) => new URL(path, url).href);
|
|
1405
1408
|
} catch {
|
|
1406
|
-
return
|
|
1409
|
+
return [];
|
|
1407
1410
|
}
|
|
1408
1411
|
}
|
|
1409
1412
|
function displayUrl(url) {
|
|
@@ -1527,10 +1530,10 @@ function linkCitations(content, sources) {
|
|
|
1527
1530
|
);
|
|
1528
1531
|
}).join("");
|
|
1529
1532
|
}
|
|
1530
|
-
var SourcesContext =
|
|
1533
|
+
var SourcesContext = React8.createContext([]);
|
|
1531
1534
|
var SourcesProvider = SourcesContext.Provider;
|
|
1532
1535
|
function useSources() {
|
|
1533
|
-
return
|
|
1536
|
+
return React8.useContext(SourcesContext);
|
|
1534
1537
|
}
|
|
1535
1538
|
var THEMES = { light: "github-light", dark: "monokai" };
|
|
1536
1539
|
var highlighter;
|
|
@@ -1577,10 +1580,10 @@ function normalizeLanguage(language) {
|
|
|
1577
1580
|
return lang || void 0;
|
|
1578
1581
|
}
|
|
1579
1582
|
function useHighlight(code, language) {
|
|
1580
|
-
const [, rerender] =
|
|
1583
|
+
const [, rerender] = React8.useReducer((n) => n + 1, 0);
|
|
1581
1584
|
const lang = normalizeLanguage(language);
|
|
1582
1585
|
const ready = Boolean(lang && loaded.has(lang));
|
|
1583
|
-
|
|
1586
|
+
React8.useEffect(() => {
|
|
1584
1587
|
if (!lang || ready || unsupported.has(lang)) return;
|
|
1585
1588
|
let cancelled = false;
|
|
1586
1589
|
void ensureLanguage(lang).then(() => {
|
|
@@ -1590,7 +1593,7 @@ function useHighlight(code, language) {
|
|
|
1590
1593
|
cancelled = true;
|
|
1591
1594
|
};
|
|
1592
1595
|
}, [lang, ready]);
|
|
1593
|
-
return
|
|
1596
|
+
return React8.useMemo(() => {
|
|
1594
1597
|
if (!lang || !ready || !highlighter) return null;
|
|
1595
1598
|
try {
|
|
1596
1599
|
return highlighter.codeToTokens(code, { lang, themes: THEMES, defaultColor: false }).tokens;
|
|
@@ -1599,7 +1602,7 @@ function useHighlight(code, language) {
|
|
|
1599
1602
|
}
|
|
1600
1603
|
}, [code, lang, ready]);
|
|
1601
1604
|
}
|
|
1602
|
-
var useIsomorphicLayoutEffect = typeof window === "undefined" ?
|
|
1605
|
+
var useIsomorphicLayoutEffect = typeof window === "undefined" ? React8.useEffect : React8.useLayoutEffect;
|
|
1603
1606
|
var caches = /* @__PURE__ */ new WeakMap();
|
|
1604
1607
|
var inflight = /* @__PURE__ */ new WeakMap();
|
|
1605
1608
|
function cacheFor(store, key) {
|
|
@@ -1616,9 +1619,9 @@ function useLinkPreviewResolver() {
|
|
|
1616
1619
|
function useLinkPreview(url, enabled) {
|
|
1617
1620
|
const resolve = useLinkPreviewResolver();
|
|
1618
1621
|
const cached = url && resolve ? cacheFor(caches, resolve).get(url) : void 0;
|
|
1619
|
-
const [preview, setPreview] =
|
|
1620
|
-
const [loading2, setLoading] =
|
|
1621
|
-
|
|
1622
|
+
const [preview, setPreview] = React8.useState(cached ?? null);
|
|
1623
|
+
const [loading2, setLoading] = React8.useState(false);
|
|
1624
|
+
React8.useEffect(() => {
|
|
1622
1625
|
if (!enabled || !url || !resolve) return;
|
|
1623
1626
|
const store = cacheFor(caches, resolve);
|
|
1624
1627
|
if (store.has(url)) {
|
|
@@ -1655,10 +1658,11 @@ function Favicon({
|
|
|
1655
1658
|
size = 14,
|
|
1656
1659
|
className
|
|
1657
1660
|
}) {
|
|
1658
|
-
const
|
|
1659
|
-
const [
|
|
1660
|
-
|
|
1661
|
-
|
|
1661
|
+
const candidates = React8.useMemo(() => faviconFallbacks(url), [url]);
|
|
1662
|
+
const [attempt, setAttempt] = React8.useState(0);
|
|
1663
|
+
const src = candidates[attempt];
|
|
1664
|
+
React8.useEffect(() => setAttempt(0), [url]);
|
|
1665
|
+
if (kind === "document" || !src) {
|
|
1662
1666
|
const Glyph2 = kind === "document" ? BookOpen : Globe;
|
|
1663
1667
|
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cx("agno-favicon", "agno-favicon--glyph", className), "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(Glyph2, { size }) });
|
|
1664
1668
|
}
|
|
@@ -1672,7 +1676,7 @@ function Favicon({
|
|
|
1672
1676
|
height: size,
|
|
1673
1677
|
loading: "lazy",
|
|
1674
1678
|
decoding: "async",
|
|
1675
|
-
onError: () =>
|
|
1679
|
+
onError: () => setAttempt((n) => n + 1),
|
|
1676
1680
|
"aria-hidden": true
|
|
1677
1681
|
}
|
|
1678
1682
|
);
|
|
@@ -1701,7 +1705,7 @@ var GAP = 8;
|
|
|
1701
1705
|
var OPEN_DELAY = 140;
|
|
1702
1706
|
var CLOSE_DELAY = 120;
|
|
1703
1707
|
function usePlacement(anchor, open, { width = PREVIEW_WIDTH, align = "center" } = {}) {
|
|
1704
|
-
const [placement, setPlacement] =
|
|
1708
|
+
const [placement, setPlacement] = React8.useState(null);
|
|
1705
1709
|
useIsomorphicLayoutEffect(() => {
|
|
1706
1710
|
if (!open || !anchor) return;
|
|
1707
1711
|
const place = () => {
|
|
@@ -1731,15 +1735,15 @@ function HoverPreview({
|
|
|
1731
1735
|
disabled,
|
|
1732
1736
|
className
|
|
1733
1737
|
}) {
|
|
1734
|
-
const [open, setOpen] =
|
|
1735
|
-
const [awake, setAwake] =
|
|
1736
|
-
const [anchor, setAnchor] =
|
|
1737
|
-
const timer =
|
|
1738
|
-
const id =
|
|
1738
|
+
const [open, setOpen] = React8.useState(false);
|
|
1739
|
+
const [awake, setAwake] = React8.useState(false);
|
|
1740
|
+
const [anchor, setAnchor] = React8.useState(null);
|
|
1741
|
+
const timer = React8.useRef(null);
|
|
1742
|
+
const id = React8.useId();
|
|
1739
1743
|
const cn = useResolvedClassNames();
|
|
1740
1744
|
const { preview, loading: loading2 } = useLinkPreview(source.url, awake);
|
|
1741
1745
|
const placement = usePlacement(anchor, open);
|
|
1742
|
-
const schedule =
|
|
1746
|
+
const schedule = React8.useCallback((next) => {
|
|
1743
1747
|
if (timer.current) clearTimeout(timer.current);
|
|
1744
1748
|
timer.current = setTimeout(
|
|
1745
1749
|
() => {
|
|
@@ -1749,13 +1753,13 @@ function HoverPreview({
|
|
|
1749
1753
|
next ? OPEN_DELAY : CLOSE_DELAY
|
|
1750
1754
|
);
|
|
1751
1755
|
}, []);
|
|
1752
|
-
|
|
1756
|
+
React8.useEffect(
|
|
1753
1757
|
() => () => {
|
|
1754
1758
|
if (timer.current) clearTimeout(timer.current);
|
|
1755
1759
|
},
|
|
1756
1760
|
[]
|
|
1757
1761
|
);
|
|
1758
|
-
|
|
1762
|
+
React8.useEffect(() => {
|
|
1759
1763
|
if (!open) return;
|
|
1760
1764
|
const onKey = (e) => {
|
|
1761
1765
|
if (e.key === "Escape") setOpen(false);
|
|
@@ -1763,10 +1767,10 @@ function HoverPreview({
|
|
|
1763
1767
|
document.addEventListener("keydown", onKey);
|
|
1764
1768
|
return () => document.removeEventListener("keydown", onKey);
|
|
1765
1769
|
}, [open]);
|
|
1766
|
-
const [mounted, setMounted] =
|
|
1767
|
-
|
|
1770
|
+
const [mounted, setMounted] = React8.useState(false);
|
|
1771
|
+
React8.useEffect(() => setMounted(true), []);
|
|
1768
1772
|
if (disabled) return children;
|
|
1769
|
-
const trigger =
|
|
1773
|
+
const trigger = React8.isValidElement(children) ? React8.cloneElement(children, {
|
|
1770
1774
|
"aria-describedby": open ? id : void 0
|
|
1771
1775
|
}) : children;
|
|
1772
1776
|
const light = anchor?.closest(".agno-light") ? "agno-light" : void 0;
|
|
@@ -1803,45 +1807,6 @@ function HoverPreview({
|
|
|
1803
1807
|
}
|
|
1804
1808
|
);
|
|
1805
1809
|
}
|
|
1806
|
-
function el(tag, className) {
|
|
1807
|
-
return function Element({ node: _node, className: _theirs, ...rest }) {
|
|
1808
|
-
return React7__default.default.createElement(tag, { className, ...rest });
|
|
1809
|
-
};
|
|
1810
|
-
}
|
|
1811
|
-
function sourceForUrl(url, sources) {
|
|
1812
|
-
return url ? sources.find((s) => s.url === url) : void 0;
|
|
1813
|
-
}
|
|
1814
|
-
function citationForLink(label2, href, ctx) {
|
|
1815
|
-
if (!/^\d+$/.test(label2.trim())) return void 0;
|
|
1816
|
-
return sourceForUrl(href, ctx.sources) ?? ctx.sources.find((s) => s.index === Number(label2.trim()));
|
|
1817
|
-
}
|
|
1818
|
-
function labelOf(children) {
|
|
1819
|
-
if (typeof children === "string") return children;
|
|
1820
|
-
if (Array.isArray(children) && children.length === 1 && typeof children[0] === "string") {
|
|
1821
|
-
return children[0];
|
|
1822
|
-
}
|
|
1823
|
-
return "";
|
|
1824
|
-
}
|
|
1825
|
-
function CitationMarker({
|
|
1826
|
-
source,
|
|
1827
|
-
className,
|
|
1828
|
-
Link
|
|
1829
|
-
}) {
|
|
1830
|
-
const props = {
|
|
1831
|
-
className: cx("agno-cite", className),
|
|
1832
|
-
href: source.url ?? `#${source.anchorId}`,
|
|
1833
|
-
"aria-label": `Source ${source.index}: ${source.title}`
|
|
1834
|
-
};
|
|
1835
|
-
return /* @__PURE__ */ jsxRuntime.jsx(HoverPreview, { source, className: "agno-cite__wrap", children: Link && source.url ? /* @__PURE__ */ jsxRuntime.jsx(Link, { ...props, children: source.index }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1836
|
-
"a",
|
|
1837
|
-
{
|
|
1838
|
-
...props,
|
|
1839
|
-
target: source.url ? "_blank" : void 0,
|
|
1840
|
-
rel: source.url ? "noreferrer noopener" : void 0,
|
|
1841
|
-
children: source.index
|
|
1842
|
-
}
|
|
1843
|
-
) });
|
|
1844
|
-
}
|
|
1845
1810
|
var COPIED_FOR = 1600;
|
|
1846
1811
|
var CLIPBOARD_TIMEOUT = 400;
|
|
1847
1812
|
async function writeClipboard(text) {
|
|
@@ -1867,38 +1832,78 @@ async function writeClipboard(text) {
|
|
|
1867
1832
|
return false;
|
|
1868
1833
|
}
|
|
1869
1834
|
}
|
|
1870
|
-
function CopyButton({ text, className }) {
|
|
1871
|
-
const [copied, setCopied] =
|
|
1872
|
-
|
|
1835
|
+
function CopyButton({ text, label: label2 = "Copy", size = 14, className }) {
|
|
1836
|
+
const [copied, setCopied] = React8.useState(false);
|
|
1837
|
+
React8.useEffect(() => {
|
|
1873
1838
|
if (!copied) return;
|
|
1874
1839
|
const timer = setTimeout(() => setCopied(false), COPIED_FOR);
|
|
1875
1840
|
return () => clearTimeout(timer);
|
|
1876
1841
|
}, [copied]);
|
|
1877
1842
|
const copy = async () => {
|
|
1878
|
-
if (await writeClipboard(text())) setCopied(true);
|
|
1843
|
+
if (await writeClipboard(typeof text === "function" ? text() : text)) setCopied(true);
|
|
1879
1844
|
};
|
|
1845
|
+
const name = copied ? "Copied" : label2;
|
|
1880
1846
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1881
1847
|
"button",
|
|
1882
1848
|
{
|
|
1883
1849
|
type: "button",
|
|
1884
|
-
className: cx("agno-
|
|
1850
|
+
className: cx("agno-copy", copied && "is-copied", className),
|
|
1885
1851
|
onClick: copy,
|
|
1886
|
-
"aria-label":
|
|
1887
|
-
title:
|
|
1888
|
-
children: copied ? /* @__PURE__ */ jsxRuntime.jsx(Check, { size
|
|
1852
|
+
"aria-label": name,
|
|
1853
|
+
title: name,
|
|
1854
|
+
children: copied ? /* @__PURE__ */ jsxRuntime.jsx(Check, { size }) : /* @__PURE__ */ jsxRuntime.jsx(Copy, { size })
|
|
1889
1855
|
}
|
|
1890
1856
|
);
|
|
1891
1857
|
}
|
|
1858
|
+
function el(tag, className) {
|
|
1859
|
+
return function Element({ node: _node, className: _theirs, ...rest }) {
|
|
1860
|
+
return React8__default.default.createElement(tag, { className, ...rest });
|
|
1861
|
+
};
|
|
1862
|
+
}
|
|
1863
|
+
function sourceForUrl(url, sources) {
|
|
1864
|
+
return url ? sources.find((s) => s.url === url) : void 0;
|
|
1865
|
+
}
|
|
1866
|
+
function citationForLink(label2, href, ctx) {
|
|
1867
|
+
if (!/^\d+$/.test(label2.trim())) return void 0;
|
|
1868
|
+
return sourceForUrl(href, ctx.sources) ?? ctx.sources.find((s) => s.index === Number(label2.trim()));
|
|
1869
|
+
}
|
|
1870
|
+
function labelOf(children) {
|
|
1871
|
+
if (typeof children === "string") return children;
|
|
1872
|
+
if (Array.isArray(children) && children.length === 1 && typeof children[0] === "string") {
|
|
1873
|
+
return children[0];
|
|
1874
|
+
}
|
|
1875
|
+
return "";
|
|
1876
|
+
}
|
|
1877
|
+
function CitationMarker({
|
|
1878
|
+
source,
|
|
1879
|
+
className,
|
|
1880
|
+
Link
|
|
1881
|
+
}) {
|
|
1882
|
+
const props = {
|
|
1883
|
+
className: cx("agno-cite", className),
|
|
1884
|
+
href: source.url ?? `#${source.anchorId}`,
|
|
1885
|
+
"aria-label": `Source ${source.index}: ${source.title}`
|
|
1886
|
+
};
|
|
1887
|
+
return /* @__PURE__ */ jsxRuntime.jsx(HoverPreview, { source, className: "agno-cite__wrap", children: Link && source.url ? /* @__PURE__ */ jsxRuntime.jsx(Link, { ...props, children: source.index }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1888
|
+
"a",
|
|
1889
|
+
{
|
|
1890
|
+
...props,
|
|
1891
|
+
target: source.url ? "_blank" : void 0,
|
|
1892
|
+
rel: source.url ? "noreferrer noopener" : void 0,
|
|
1893
|
+
children: source.index
|
|
1894
|
+
}
|
|
1895
|
+
) });
|
|
1896
|
+
}
|
|
1892
1897
|
function textOf(children) {
|
|
1893
1898
|
if (typeof children === "string") return children;
|
|
1894
1899
|
if (typeof children === "number") return String(children);
|
|
1895
1900
|
if (Array.isArray(children)) return children.map(textOf).join("");
|
|
1896
|
-
if (
|
|
1901
|
+
if (React8__default.default.isValidElement(children)) return textOf(children.props.children);
|
|
1897
1902
|
return "";
|
|
1898
1903
|
}
|
|
1899
1904
|
function fencedCode(children) {
|
|
1900
1905
|
const child = Array.isArray(children) ? children[0] : children;
|
|
1901
|
-
if (!
|
|
1906
|
+
if (!React8__default.default.isValidElement(child)) {
|
|
1902
1907
|
return { code: textOf(children) };
|
|
1903
1908
|
}
|
|
1904
1909
|
const language = /(?:^|\s)language-([^\s]+)/.exec(child.props.className ?? "")?.[1];
|
|
@@ -1912,16 +1917,16 @@ function CodeBlock({
|
|
|
1912
1917
|
copyClass,
|
|
1913
1918
|
codeCopy
|
|
1914
1919
|
}) {
|
|
1915
|
-
const { language, code } =
|
|
1920
|
+
const { language, code } = React8.useMemo(() => fencedCode(children), [children]);
|
|
1916
1921
|
const highlighted = useHighlight(code, language);
|
|
1917
1922
|
const lines = highlighted ?? plainLines(code);
|
|
1918
1923
|
const label2 = normalizeLanguage(language) ?? "text";
|
|
1919
1924
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "agno-md-code-block", "data-language": label2, children: [
|
|
1920
1925
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "agno-md-code-head", children: [
|
|
1921
1926
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "agno-md-code-lang", children: label2 }),
|
|
1922
|
-
codeCopy && /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { className: copyClass, text: () => code })
|
|
1927
|
+
codeCopy && /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { className: cx("agno-md-copy", copyClass), text: () => code, label: "Copy code", size: 13 })
|
|
1923
1928
|
] }),
|
|
1924
|
-
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "agno-md-pre", style: { "--agno-code-gutter": `${String(lines.length).length}ch` }, children: /* @__PURE__ */ jsxRuntime.jsx("code", { className: language ? `language-${language}` : void 0, children: lines.map((tokens, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1929
|
+
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: "agno-md-pre", style: { "--agno-code-gutter": `${String(lines.length).length}ch` }, children: /* @__PURE__ */ jsxRuntime.jsx("code", { className: language ? `language-${language}` : void 0, children: lines.map((tokens, i) => /* @__PURE__ */ jsxRuntime.jsxs(React8__default.default.Fragment, { children: [
|
|
1925
1930
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "agno-md-line", children: tokens.map((token, j) => /* @__PURE__ */ jsxRuntime.jsx("span", { style: token.htmlStyle, children: token.content }, j)) }),
|
|
1926
1931
|
i < lines.length - 1 && "\n"
|
|
1927
1932
|
] }, i)) }) })
|
|
@@ -2014,7 +2019,7 @@ function Markdown({
|
|
|
2014
2019
|
const cited = sources ?? fromMessage;
|
|
2015
2020
|
const copy = codeCopy ?? fromProvider ?? true;
|
|
2016
2021
|
const Link = linkComponent ?? providerLink;
|
|
2017
|
-
const components =
|
|
2022
|
+
const components = React8.useMemo(
|
|
2018
2023
|
() => elementsFor({
|
|
2019
2024
|
sources: cited,
|
|
2020
2025
|
canResolve,
|
|
@@ -2025,7 +2030,7 @@ function Markdown({
|
|
|
2025
2030
|
}),
|
|
2026
2031
|
[cited, canResolve, cn.citationMarker, cn.copyButton, copy, Link]
|
|
2027
2032
|
);
|
|
2028
|
-
const text =
|
|
2033
|
+
const text = React8.useMemo(() => linkCitations(content, cited), [content, cited]);
|
|
2029
2034
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2030
2035
|
streamdown.Streamdown,
|
|
2031
2036
|
{
|
|
@@ -2049,7 +2054,7 @@ function hasDetail(tool) {
|
|
|
2049
2054
|
return Boolean(tool.tool_args && Object.keys(tool.tool_args).length) || tool.result != null;
|
|
2050
2055
|
}
|
|
2051
2056
|
function ToolCalls({ tools }) {
|
|
2052
|
-
const [openIndex, setOpenIndex] =
|
|
2057
|
+
const [openIndex, setOpenIndex] = React8.useState(null);
|
|
2053
2058
|
if (!tools || tools.length === 0) return null;
|
|
2054
2059
|
const open = openIndex != null ? tools[openIndex] : void 0;
|
|
2055
2060
|
const openStatus = open ? statusOf(open) : void 0;
|
|
@@ -2286,7 +2291,7 @@ function Step({
|
|
|
2286
2291
|
busy,
|
|
2287
2292
|
children
|
|
2288
2293
|
}) {
|
|
2289
|
-
const [open, setOpen] =
|
|
2294
|
+
const [open, setOpen] = React8.useState(false);
|
|
2290
2295
|
if (!children) {
|
|
2291
2296
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "agno-bts__step", children: [
|
|
2292
2297
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "agno-bts__step-label", children: label2 }),
|
|
@@ -2331,7 +2336,7 @@ function BehindTheScenes({
|
|
|
2331
2336
|
className,
|
|
2332
2337
|
classNames
|
|
2333
2338
|
}) {
|
|
2334
|
-
const [open, setOpen] =
|
|
2339
|
+
const [open, setOpen] = React8.useState(defaultOpen);
|
|
2335
2340
|
const items = behindTheScenesItems(message, { hideReasoning, hideTools });
|
|
2336
2341
|
if (items.length === 0) return null;
|
|
2337
2342
|
const label2 = behindTheScenesLabel(message, streaming, activity);
|
|
@@ -2468,22 +2473,22 @@ function SourceCard({
|
|
|
2468
2473
|
}
|
|
2469
2474
|
var LIST_WIDTH = 240;
|
|
2470
2475
|
function SourcesOverflow({ sources }) {
|
|
2471
|
-
const [open, setOpen] =
|
|
2472
|
-
const [anchor, setAnchor] =
|
|
2473
|
-
const timer =
|
|
2474
|
-
const id =
|
|
2476
|
+
const [open, setOpen] = React8.useState(false);
|
|
2477
|
+
const [anchor, setAnchor] = React8.useState(null);
|
|
2478
|
+
const timer = React8.useRef(null);
|
|
2479
|
+
const id = React8.useId();
|
|
2475
2480
|
const placement = usePlacement(anchor, open, { width: LIST_WIDTH, align: "start" });
|
|
2476
|
-
const schedule =
|
|
2481
|
+
const schedule = React8.useCallback((next) => {
|
|
2477
2482
|
if (timer.current) clearTimeout(timer.current);
|
|
2478
2483
|
timer.current = setTimeout(() => setOpen(next), next ? OPEN_DELAY : CLOSE_DELAY);
|
|
2479
2484
|
}, []);
|
|
2480
|
-
|
|
2485
|
+
React8.useEffect(
|
|
2481
2486
|
() => () => {
|
|
2482
2487
|
if (timer.current) clearTimeout(timer.current);
|
|
2483
2488
|
},
|
|
2484
2489
|
[]
|
|
2485
2490
|
);
|
|
2486
|
-
|
|
2491
|
+
React8.useEffect(() => {
|
|
2487
2492
|
if (!open) return;
|
|
2488
2493
|
const onKey = (e) => {
|
|
2489
2494
|
if (e.key === "Escape") setOpen(false);
|
|
@@ -2491,8 +2496,8 @@ function SourcesOverflow({ sources }) {
|
|
|
2491
2496
|
document.addEventListener("keydown", onKey);
|
|
2492
2497
|
return () => document.removeEventListener("keydown", onKey);
|
|
2493
2498
|
}, [open]);
|
|
2494
|
-
const [mounted, setMounted] =
|
|
2495
|
-
|
|
2499
|
+
const [mounted, setMounted] = React8.useState(false);
|
|
2500
|
+
React8.useEffect(() => setMounted(true), []);
|
|
2496
2501
|
const light = anchor?.closest(".agno-light") ? "agno-light" : void 0;
|
|
2497
2502
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2498
2503
|
"span",
|
|
@@ -2564,8 +2569,8 @@ function Citations({
|
|
|
2564
2569
|
classNames
|
|
2565
2570
|
}) {
|
|
2566
2571
|
const cn = useResolvedClassNames(classNames);
|
|
2567
|
-
const uid =
|
|
2568
|
-
const sources =
|
|
2572
|
+
const uid = React8.useId();
|
|
2573
|
+
const sources = React8.useMemo(
|
|
2569
2574
|
() => given ?? collectSources(references, citations, uid),
|
|
2570
2575
|
[given, references, citations, uid]
|
|
2571
2576
|
);
|
|
@@ -2581,6 +2586,20 @@ function Citations({
|
|
|
2581
2586
|
] })
|
|
2582
2587
|
] });
|
|
2583
2588
|
}
|
|
2589
|
+
function MessageActions({
|
|
2590
|
+
message,
|
|
2591
|
+
hideCopy,
|
|
2592
|
+
children,
|
|
2593
|
+
className,
|
|
2594
|
+
classNames
|
|
2595
|
+
}) {
|
|
2596
|
+
const cn = useResolvedClassNames(classNames);
|
|
2597
|
+
if (hideCopy && !children) return null;
|
|
2598
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("agno-msg__actions", cn.messageActions, className), role: "toolbar", "aria-label": "Message actions", children: [
|
|
2599
|
+
!hideCopy && /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { className: cx("agno-msg__action", cn.messageCopyButton), text: message.content, label: "Copy message" }),
|
|
2600
|
+
children
|
|
2601
|
+
] });
|
|
2602
|
+
}
|
|
2584
2603
|
function audioSrc(a) {
|
|
2585
2604
|
if (a.url) return a.url;
|
|
2586
2605
|
if (a.base64_audio) return `data:${a.mime_type ?? "audio/mpeg"};base64,${a.base64_audio}`;
|
|
@@ -2621,11 +2640,13 @@ function Message({
|
|
|
2621
2640
|
hideReasoning,
|
|
2622
2641
|
hideTools,
|
|
2623
2642
|
hideSources,
|
|
2643
|
+
hideActions,
|
|
2644
|
+
actions,
|
|
2624
2645
|
onFollowup
|
|
2625
2646
|
}) {
|
|
2626
2647
|
const cn = useResolvedClassNames(classNames);
|
|
2627
|
-
const uid =
|
|
2628
|
-
const sources =
|
|
2648
|
+
const uid = React8.useId();
|
|
2649
|
+
const sources = React8.useMemo(() => {
|
|
2629
2650
|
const cited = collectSources(message.references, message.citations, uid);
|
|
2630
2651
|
return cited.length ? cited : sourcesFromMarkdown(message.content, uid);
|
|
2631
2652
|
}, [message.references, message.citations, message.content, uid]);
|
|
@@ -2633,7 +2654,7 @@ function Message({
|
|
|
2633
2654
|
const isAgent = message.role === "agent";
|
|
2634
2655
|
const hasSources = isAgent && !hideSources && sources.length > 0;
|
|
2635
2656
|
const showSources = hasSources && !message.streaming;
|
|
2636
|
-
const content =
|
|
2657
|
+
const content = React8.useMemo(
|
|
2637
2658
|
() => hasSources && message.content ? withoutSourcesLine(message.content) : message.content,
|
|
2638
2659
|
[message.content, hasSources]
|
|
2639
2660
|
);
|
|
@@ -2687,7 +2708,8 @@ function Message({
|
|
|
2687
2708
|
showSources && /* @__PURE__ */ jsxRuntime.jsx(Citations, { sources, classNames: cn }),
|
|
2688
2709
|
isAgent && onFollowup && !message.streaming && /* @__PURE__ */ jsxRuntime.jsx(Followups, { items: message.followups, onSelect: onFollowup, classNames: cn }),
|
|
2689
2710
|
message.error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "agno-msg__error", children: message.error }),
|
|
2690
|
-
children
|
|
2711
|
+
children,
|
|
2712
|
+
isAgent && !hideActions && !message.streaming && message.content && /* @__PURE__ */ jsxRuntime.jsx(MessageActions, { message, classNames: cn, children: actions })
|
|
2691
2713
|
] }) })
|
|
2692
2714
|
]
|
|
2693
2715
|
}
|
|
@@ -2714,10 +2736,10 @@ function MessageList({
|
|
|
2714
2736
|
const runActivity = activity !== void 0 ? activity : ctx?.chat.activity;
|
|
2715
2737
|
const markdown = renderMarkdown ?? ctx?.renderMarkdown;
|
|
2716
2738
|
const kind = entityType ?? ctx?.chat.entityType;
|
|
2717
|
-
const endRef =
|
|
2718
|
-
const stick =
|
|
2719
|
-
const userScrolled =
|
|
2720
|
-
const containerRef =
|
|
2739
|
+
const endRef = React8.useRef(null);
|
|
2740
|
+
const stick = React8.useRef(true);
|
|
2741
|
+
const userScrolled = React8.useRef(false);
|
|
2742
|
+
const containerRef = React8.useRef(null);
|
|
2721
2743
|
const markUserScroll = () => {
|
|
2722
2744
|
userScrolled.current = true;
|
|
2723
2745
|
};
|
|
@@ -2729,7 +2751,7 @@ function MessageList({
|
|
|
2729
2751
|
else if (userScrolled.current) stick.current = false;
|
|
2730
2752
|
userScrolled.current = false;
|
|
2731
2753
|
};
|
|
2732
|
-
|
|
2754
|
+
React8.useEffect(() => {
|
|
2733
2755
|
if (stick.current) endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
|
|
2734
2756
|
}, [items, runActivity, runStatus]);
|
|
2735
2757
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -2747,7 +2769,7 @@ function MessageList({
|
|
|
2747
2769
|
items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cx("agno-list__empty", cn.empty), children: emptyState ?? "Start the conversation." }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "agno-list__inner", children: [
|
|
2748
2770
|
items.map((m) => {
|
|
2749
2771
|
const live = m.streaming && runStatus === "streaming" ? runActivity : void 0;
|
|
2750
|
-
return renderMessage ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2772
|
+
return renderMessage ? /* @__PURE__ */ jsxRuntime.jsx(React8__default.default.Fragment, { children: renderMessage(m, live) }, m.id) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2751
2773
|
Message,
|
|
2752
2774
|
{
|
|
2753
2775
|
message: m,
|
|
@@ -3018,10 +3040,10 @@ function EntitySelector({
|
|
|
3018
3040
|
classNames
|
|
3019
3041
|
}) {
|
|
3020
3042
|
const cn = useResolvedClassNames(classNames);
|
|
3021
|
-
const [open, setOpen] =
|
|
3022
|
-
const rootRef =
|
|
3043
|
+
const [open, setOpen] = React8.useState(false);
|
|
3044
|
+
const rootRef = React8.useRef(null);
|
|
3023
3045
|
const key = (e) => `${e.type}:${e.id}`;
|
|
3024
|
-
|
|
3046
|
+
React8.useEffect(() => {
|
|
3025
3047
|
if (!open) return;
|
|
3026
3048
|
const onDocClick = (e) => {
|
|
3027
3049
|
if (rootRef.current && !rootRef.current.contains(e.target)) setOpen(false);
|
|
@@ -3170,14 +3192,14 @@ function SessionList({
|
|
|
3170
3192
|
] });
|
|
3171
3193
|
}
|
|
3172
3194
|
function AgnoChat(props) {
|
|
3173
|
-
const client =
|
|
3195
|
+
const client = React8.useMemo(
|
|
3174
3196
|
() => props.client ?? new chunk55HQJGLP_cjs.AgnoClient({ baseUrl: props.baseUrl ?? "", headers: props.headers }),
|
|
3175
3197
|
[props.client, props.baseUrl, props.headers]
|
|
3176
3198
|
);
|
|
3177
|
-
const [discovered, setDiscovered] =
|
|
3178
|
-
const [selected, setSelected] =
|
|
3179
|
-
const [discoveryDone, setDiscoveryDone] =
|
|
3180
|
-
|
|
3199
|
+
const [discovered, setDiscovered] = React8.useState(props.entities ?? []);
|
|
3200
|
+
const [selected, setSelected] = React8.useState(props.defaultEntity ?? null);
|
|
3201
|
+
const [discoveryDone, setDiscoveryDone] = React8.useState(Boolean(props.entity || props.entities));
|
|
3202
|
+
React8.useEffect(() => {
|
|
3181
3203
|
if (props.entity && !props.showEntityPicker || props.entities) return;
|
|
3182
3204
|
let cancelled = false;
|
|
3183
3205
|
setDiscoveryDone(false);
|
|
@@ -3194,10 +3216,10 @@ function AgnoChat(props) {
|
|
|
3194
3216
|
const entity = props.entity ?? selected;
|
|
3195
3217
|
const chat = useAgnoChat({ client, entity, userId: props.userId });
|
|
3196
3218
|
const { refreshSessions } = chat;
|
|
3197
|
-
|
|
3219
|
+
React8.useEffect(() => {
|
|
3198
3220
|
if (props.showSessions && entity) refreshSessions();
|
|
3199
3221
|
}, [props.showSessions, entity?.type, entity?.id, refreshSessions]);
|
|
3200
|
-
|
|
3222
|
+
React8.useEffect(() => {
|
|
3201
3223
|
if (props.showSessions && entity && chat.status === "completed") refreshSessions();
|
|
3202
3224
|
}, [chat.status]);
|
|
3203
3225
|
const onSelect = (e) => {
|
|
@@ -3212,7 +3234,7 @@ function AgnoChat(props) {
|
|
|
3212
3234
|
const noEntities = !props.entity && discoveryDone && entities.length === 0;
|
|
3213
3235
|
const launcher = props.mode === "launcher";
|
|
3214
3236
|
const fullscreen = props.panel === "fullscreen";
|
|
3215
|
-
const [selfOpen, setSelfOpen] =
|
|
3237
|
+
const [selfOpen, setSelfOpen] = React8.useState(props.defaultOpen ?? false);
|
|
3216
3238
|
const isOpen = props.open ?? selfOpen;
|
|
3217
3239
|
const setOpen = (next) => {
|
|
3218
3240
|
if (props.open === void 0) setSelfOpen(next);
|
|
@@ -3337,7 +3359,7 @@ function Reasoning({
|
|
|
3337
3359
|
steps,
|
|
3338
3360
|
defaultOpen = false
|
|
3339
3361
|
}) {
|
|
3340
|
-
const [open, setOpen] =
|
|
3362
|
+
const [open, setOpen] = React8.useState(defaultOpen);
|
|
3341
3363
|
if (!steps || steps.length === 0) return null;
|
|
3342
3364
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "agno-reasoning", children: [
|
|
3343
3365
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -3383,7 +3405,7 @@ function statusDot(status) {
|
|
|
3383
3405
|
return "running";
|
|
3384
3406
|
}
|
|
3385
3407
|
function MemberCard({ member, renderMarkdown }) {
|
|
3386
|
-
const [open, setOpen] =
|
|
3408
|
+
const [open, setOpen] = React8.useState(true);
|
|
3387
3409
|
const label2 = member.kind === "executor" ? "Step executor" : "Member";
|
|
3388
3410
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "agno-member", children: [
|
|
3389
3411
|
/* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "agno-member__head", onClick: () => setOpen((v) => !v), "aria-expanded": open, children: [
|
|
@@ -3415,7 +3437,7 @@ function MemberResponses({
|
|
|
3415
3437
|
] });
|
|
3416
3438
|
}
|
|
3417
3439
|
function StepRow({ step, renderMarkdown }) {
|
|
3418
|
-
const [open, setOpen] =
|
|
3440
|
+
const [open, setOpen] = React8.useState(false);
|
|
3419
3441
|
const hasBody = Boolean(step.content || step.error);
|
|
3420
3442
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `agno-step agno-step--${step.status}`, children: [
|
|
3421
3443
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -3485,9 +3507,9 @@ function EventLog({
|
|
|
3485
3507
|
autoScroll = true,
|
|
3486
3508
|
maxHeight = 240
|
|
3487
3509
|
}) {
|
|
3488
|
-
const ref =
|
|
3489
|
-
const rows =
|
|
3490
|
-
|
|
3510
|
+
const ref = React8.useRef(null);
|
|
3511
|
+
const rows = React8.useMemo(() => fold(events), [events]);
|
|
3512
|
+
React8.useEffect(() => {
|
|
3491
3513
|
if (autoScroll && ref.current) ref.current.scrollTop = ref.current.scrollHeight;
|
|
3492
3514
|
}, [rows, autoScroll]);
|
|
3493
3515
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "agno-eventlog", ref, style: { maxHeight }, children: [
|
|
@@ -3521,6 +3543,7 @@ exports.ChevronDown = ChevronDown;
|
|
|
3521
3543
|
exports.Citations = Citations;
|
|
3522
3544
|
exports.Close = Close;
|
|
3523
3545
|
exports.Copy = Copy;
|
|
3546
|
+
exports.CopyButton = CopyButton;
|
|
3524
3547
|
exports.EntityBadge = EntityBadge;
|
|
3525
3548
|
exports.EntitySelector = EntitySelector;
|
|
3526
3549
|
exports.EventLog = EventLog;
|
|
@@ -3541,6 +3564,7 @@ exports.Markdown = Markdown;
|
|
|
3541
3564
|
exports.MemberResponses = MemberResponses;
|
|
3542
3565
|
exports.Memory = Memory;
|
|
3543
3566
|
exports.Message = Message;
|
|
3567
|
+
exports.MessageActions = MessageActions;
|
|
3544
3568
|
exports.MessageList = MessageList;
|
|
3545
3569
|
exports.Multimedia = Multimedia;
|
|
3546
3570
|
exports.Paperclip = Paperclip;
|
|
@@ -3566,6 +3590,7 @@ exports.behindTheScenesLabel = behindTheScenesLabel;
|
|
|
3566
3590
|
exports.collectSources = collectSources;
|
|
3567
3591
|
exports.cx = cx;
|
|
3568
3592
|
exports.displayUrl = displayUrl;
|
|
3593
|
+
exports.faviconFallbacks = faviconFallbacks;
|
|
3569
3594
|
exports.faviconUrl = faviconUrl;
|
|
3570
3595
|
exports.fileAccepted = fileAccepted;
|
|
3571
3596
|
exports.getProviderIcon = getProviderIcon;
|
|
@@ -3586,5 +3611,5 @@ exports.useResolvedClassNames = useResolvedClassNames;
|
|
|
3586
3611
|
exports.useSources = useSources;
|
|
3587
3612
|
exports.withoutSourcesLine = withoutSourcesLine;
|
|
3588
3613
|
exports.writeClipboard = writeClipboard;
|
|
3589
|
-
//# sourceMappingURL=chunk-
|
|
3590
|
-
//# sourceMappingURL=chunk-
|
|
3614
|
+
//# sourceMappingURL=chunk-3IEYJIYJ.cjs.map
|
|
3615
|
+
//# sourceMappingURL=chunk-3IEYJIYJ.cjs.map
|