@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.
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var chunk55HQJGLP_cjs = require('./chunk-55HQJGLP.cjs');
4
- var React7 = require('react');
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 React7__default = /*#__PURE__*/_interopDefault(React7);
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 = React7.useMemo(() => {
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] = React7.useState(options.initialMessages ?? []);
24
- const [events, setEvents] = React7.useState([]);
25
- const [currentEvent, setCurrentEvent] = React7.useState(null);
26
- const [status, setStatus] = React7.useState("idle");
27
- const [activity, setActivity] = React7.useState(null);
28
- const [error, setError] = React7.useState(null);
29
- const [sessionId, setSessionId] = React7.useState(options.sessionId);
30
- const [sessions, setSessions] = React7.useState([]);
31
- const [sessionsLoading, setSessionsLoading] = React7.useState(false);
32
- const [backgroundRunning, setBackgroundRunning] = React7.useState([]);
33
- const abortRef = React7.useRef(null);
34
- const channelRef = React7.useRef(null);
35
- const backgroundRef = React7.useRef(/* @__PURE__ */ new Map());
36
- const activeMsgIdRef = React7.useRef(null);
37
- const runIdRef = React7.useRef(void 0);
38
- const entityRef = React7.useRef(entity);
39
- const sessionIdRef = React7.useRef(options.sessionId);
40
- const pendingSessionNameRef = React7.useRef(void 0);
41
- const bumpedSessionRef = React7.useRef(void 0);
42
- React7.useEffect(() => {
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
- React7.useEffect(() => {
45
+ React8.useEffect(() => {
46
46
  sessionIdRef.current = sessionId;
47
47
  }, [sessionId]);
48
- const upsertSession = React7.useCallback((id, createdAt) => {
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 = React7.useRef({ messages, events, status, activity, error });
62
- React7.useEffect(() => {
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 = React7.useCallback(
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 = React7.useCallback((chan, e) => {
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 = React7.useCallback((chan, status2) => {
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 = React7.useCallback((chan, activity2) => {
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 = React7.useCallback((chan, message) => {
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 = React7.useCallback(
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 = React7.useCallback(
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 = React7.useCallback((chan, sessionId2) => {
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 = React7.useCallback((sessionId2) => {
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 = React7.useCallback(() => {
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 = React7.useCallback(
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 = React7.useCallback(
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 = React7.useCallback(
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 = React7.useMemo(
391
+ const activeMessage = React8.useMemo(
392
392
  () => messages.find((m) => m.id === activeMsgIdRef.current) ?? null,
393
393
  [messages]
394
394
  );
395
- const pausedTools = React7.useMemo(
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 = React7.useCallback(
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 = React7.useCallback(
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 = React7.useCallback(async () => {
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 = React7.useCallback(async () => {
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 = React7.useCallback(
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 = React7.useCallback(
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 = React7.useCallback(() => {
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
- React7.useEffect(() => {
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 = React7.useMemo(
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 = React7.createContext(null);
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 = React7.useMemo(
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 = React7.useContext(ChatContext);
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 React7.useContext(ChatContext);
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 React7.useMemo(() => ({ ...ctx?.classNames, ...explicit }), [ctx?.classNames, explicit]);
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] = React7.useState(defaultOpen);
781
+ const [uncontrolledOpen, setUncontrolledOpen] = React8.useState(defaultOpen);
782
782
  const isOpen = open ?? uncontrolledOpen;
783
- const opened = React7.useRef(isOpen);
783
+ const opened = React8.useRef(isOpen);
784
784
  if (isOpen) opened.current = true;
785
785
  const mounted = keepMounted ? opened.current : isOpen;
786
- const setOpen = React7.useCallback(
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
- React7.useEffect(() => {
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
- React7.useEffect(() => {
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] = React7.useState(false);
810
- React7.useEffect(() => setCanPortal(true), []);
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] = React7.useState(null);
867
- React7.useEffect(() => {
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] = React7.useState("");
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] = React7.useState([]);
978
- const filesRef = React7.useRef([]);
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] = React7.useState(null);
984
- const [dragging, setDragging] = React7.useState(false);
985
- const dragDepth = React7.useRef(0);
986
- const fileRef = React7.useRef(null);
987
- const textareaRef = React7.useRef(null);
988
- const setTextareaRef = React7.useCallback(
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 = React7.useCallback(() => {
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
- React7.useEffect(adjustHeight, [value, adjustHeight]);
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 = React7.useMemo(() => buildAsks(message, entityType), [message, entityType]);
1256
- const [choices, setChoices] = React7.useState({});
1257
- const [values, setValues] = React7.useState({});
1258
- const [reasons, setReasons] = React7.useState({});
1259
- const [openArgs, setOpenArgs] = React7.useState({});
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
- if (!url) return void 0;
1402
+ return faviconFallbacks(url)[0];
1403
+ }
1404
+ function faviconFallbacks(url) {
1405
+ if (!url) return [];
1403
1406
  try {
1404
- return new URL("/favicon.ico", url).href;
1407
+ return ["/favicon.ico", "/favicon.svg"].map((path) => new URL(path, url).href);
1405
1408
  } catch {
1406
- return void 0;
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 = React7.createContext([]);
1533
+ var SourcesContext = React8.createContext([]);
1531
1534
  var SourcesProvider = SourcesContext.Provider;
1532
1535
  function useSources() {
1533
- return React7.useContext(SourcesContext);
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] = React7.useReducer((n) => n + 1, 0);
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
- React7.useEffect(() => {
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 React7.useMemo(() => {
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" ? React7.useEffect : React7.useLayoutEffect;
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] = React7.useState(cached ?? null);
1620
- const [loading2, setLoading] = React7.useState(false);
1621
- React7.useEffect(() => {
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 src = faviconUrl(url);
1659
- const [failed, setFailed] = React7.useState(false);
1660
- React7.useEffect(() => setFailed(false), [src]);
1661
- if (kind === "document" || !src || failed) {
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: () => setFailed(true),
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] = React7.useState(null);
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] = React7.useState(false);
1735
- const [awake, setAwake] = React7.useState(false);
1736
- const [anchor, setAnchor] = React7.useState(null);
1737
- const timer = React7.useRef(null);
1738
- const id = React7.useId();
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 = React7.useCallback((next) => {
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
- React7.useEffect(
1756
+ React8.useEffect(
1753
1757
  () => () => {
1754
1758
  if (timer.current) clearTimeout(timer.current);
1755
1759
  },
1756
1760
  []
1757
1761
  );
1758
- React7.useEffect(() => {
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] = React7.useState(false);
1767
- React7.useEffect(() => setMounted(true), []);
1770
+ const [mounted, setMounted] = React8.useState(false);
1771
+ React8.useEffect(() => setMounted(true), []);
1768
1772
  if (disabled) return children;
1769
- const trigger = React7.isValidElement(children) ? React7.cloneElement(children, {
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] = React7.useState(false);
1872
- React7.useEffect(() => {
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-md-copy", copied && "is-copied", className),
1850
+ className: cx("agno-copy", copied && "is-copied", className),
1885
1851
  onClick: copy,
1886
- "aria-label": copied ? "Copied" : "Copy code",
1887
- title: copied ? "Copied" : "Copy code",
1888
- children: copied ? /* @__PURE__ */ jsxRuntime.jsx(Check, { size: 13 }) : /* @__PURE__ */ jsxRuntime.jsx(Copy, { size: 13 })
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 (React7__default.default.isValidElement(children)) return textOf(children.props.children);
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 (!React7__default.default.isValidElement(child)) {
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 } = React7.useMemo(() => fencedCode(children), [children]);
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(React7__default.default.Fragment, { children: [
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 = React7.useMemo(
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 = React7.useMemo(() => linkCitations(content, cited), [content, cited]);
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] = React7.useState(null);
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] = React7.useState(false);
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] = React7.useState(defaultOpen);
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] = React7.useState(false);
2472
- const [anchor, setAnchor] = React7.useState(null);
2473
- const timer = React7.useRef(null);
2474
- const id = React7.useId();
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 = React7.useCallback((next) => {
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
- React7.useEffect(
2485
+ React8.useEffect(
2481
2486
  () => () => {
2482
2487
  if (timer.current) clearTimeout(timer.current);
2483
2488
  },
2484
2489
  []
2485
2490
  );
2486
- React7.useEffect(() => {
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] = React7.useState(false);
2495
- React7.useEffect(() => setMounted(true), []);
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 = React7.useId();
2568
- const sources = React7.useMemo(
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 = React7.useId();
2628
- const sources = React7.useMemo(() => {
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 = React7.useMemo(
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 = React7.useRef(null);
2718
- const stick = React7.useRef(true);
2719
- const userScrolled = React7.useRef(false);
2720
- const containerRef = React7.useRef(null);
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
- React7.useEffect(() => {
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(React7__default.default.Fragment, { children: renderMessage(m, live) }, m.id) : /* @__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] = React7.useState(false);
3022
- const rootRef = React7.useRef(null);
3043
+ const [open, setOpen] = React8.useState(false);
3044
+ const rootRef = React8.useRef(null);
3023
3045
  const key = (e) => `${e.type}:${e.id}`;
3024
- React7.useEffect(() => {
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 = React7.useMemo(
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] = React7.useState(props.entities ?? []);
3178
- const [selected, setSelected] = React7.useState(props.defaultEntity ?? null);
3179
- const [discoveryDone, setDiscoveryDone] = React7.useState(Boolean(props.entity || props.entities));
3180
- React7.useEffect(() => {
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
- React7.useEffect(() => {
3219
+ React8.useEffect(() => {
3198
3220
  if (props.showSessions && entity) refreshSessions();
3199
3221
  }, [props.showSessions, entity?.type, entity?.id, refreshSessions]);
3200
- React7.useEffect(() => {
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] = React7.useState(props.defaultOpen ?? false);
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] = React7.useState(defaultOpen);
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] = React7.useState(true);
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] = React7.useState(false);
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 = React7.useRef(null);
3489
- const rows = React7.useMemo(() => fold(events), [events]);
3490
- React7.useEffect(() => {
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-Q73XHL35.cjs.map
3590
- //# sourceMappingURL=chunk-Q73XHL35.cjs.map
3614
+ //# sourceMappingURL=chunk-3IEYJIYJ.cjs.map
3615
+ //# sourceMappingURL=chunk-3IEYJIYJ.cjs.map