@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,5 +1,5 @@
1
1
  import { AgnoClient, activityLabel, isSubRunEvent, applySubRunEvent, isStepEvent, applyStepEvent, isStartedEvent, isToolEvent, toolsFromEvent, mergeTool, isContentEvent, applyContentEvent, isReasoningStepEvent, isReasoningCompletedEvent, isFollowupsCompletedEvent, isPausedEvent, isCompletedEvent, isCancelledEvent, isErrorEvent, sessionRunsToMessages, isToolCompletedEvent } from './chunk-6V2YIPHF.js';
2
- import React7, { createContext, useMemo, useState, useRef, useEffect, useCallback, useContext, useId, isValidElement, cloneElement, useLayoutEffect, useReducer } from 'react';
2
+ import React8, { createContext, useMemo, useState, useRef, useEffect, useCallback, useContext, useId, isValidElement, cloneElement, useLayoutEffect, useReducer } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { createPortal } from 'react-dom';
5
5
  import { ChevronDown as ChevronDown$1, ArrowUp as ArrowUp$1, Paperclip as Paperclip$1, File, FileType2, FileAudio as FileAudio$1, FileVideo as FileVideo$1, Wrench as Wrench$1, BookOpen as BookOpen$1, Globe as Globe$1, Link, Brain as Brain$1, Box as Box$1, Plus as Plus$1, Check as Check$1, Copy as Copy$1, X, MemoryStick, RefreshCcw, Activity, Trash2, MessageSquare, LoaderCircle, Square } from 'lucide-react';
@@ -1393,11 +1393,14 @@ function sourceHost(url) {
1393
1393
  }
1394
1394
  }
1395
1395
  function faviconUrl(url) {
1396
- if (!url) return void 0;
1396
+ return faviconFallbacks(url)[0];
1397
+ }
1398
+ function faviconFallbacks(url) {
1399
+ if (!url) return [];
1397
1400
  try {
1398
- return new URL("/favicon.ico", url).href;
1401
+ return ["/favicon.ico", "/favicon.svg"].map((path) => new URL(path, url).href);
1399
1402
  } catch {
1400
- return void 0;
1403
+ return [];
1401
1404
  }
1402
1405
  }
1403
1406
  function displayUrl(url) {
@@ -1649,10 +1652,11 @@ function Favicon({
1649
1652
  size = 14,
1650
1653
  className
1651
1654
  }) {
1652
- const src = faviconUrl(url);
1653
- const [failed, setFailed] = useState(false);
1654
- useEffect(() => setFailed(false), [src]);
1655
- if (kind === "document" || !src || failed) {
1655
+ const candidates = useMemo(() => faviconFallbacks(url), [url]);
1656
+ const [attempt, setAttempt] = useState(0);
1657
+ const src = candidates[attempt];
1658
+ useEffect(() => setAttempt(0), [url]);
1659
+ if (kind === "document" || !src) {
1656
1660
  const Glyph2 = kind === "document" ? BookOpen : Globe;
1657
1661
  return /* @__PURE__ */ jsx("span", { className: cx("agno-favicon", "agno-favicon--glyph", className), "aria-hidden": true, children: /* @__PURE__ */ jsx(Glyph2, { size }) });
1658
1662
  }
@@ -1666,7 +1670,7 @@ function Favicon({
1666
1670
  height: size,
1667
1671
  loading: "lazy",
1668
1672
  decoding: "async",
1669
- onError: () => setFailed(true),
1673
+ onError: () => setAttempt((n) => n + 1),
1670
1674
  "aria-hidden": true
1671
1675
  }
1672
1676
  );
@@ -1797,45 +1801,6 @@ function HoverPreview({
1797
1801
  }
1798
1802
  );
1799
1803
  }
1800
- function el(tag, className) {
1801
- return function Element({ node: _node, className: _theirs, ...rest }) {
1802
- return React7.createElement(tag, { className, ...rest });
1803
- };
1804
- }
1805
- function sourceForUrl(url, sources) {
1806
- return url ? sources.find((s) => s.url === url) : void 0;
1807
- }
1808
- function citationForLink(label2, href, ctx) {
1809
- if (!/^\d+$/.test(label2.trim())) return void 0;
1810
- return sourceForUrl(href, ctx.sources) ?? ctx.sources.find((s) => s.index === Number(label2.trim()));
1811
- }
1812
- function labelOf(children) {
1813
- if (typeof children === "string") return children;
1814
- if (Array.isArray(children) && children.length === 1 && typeof children[0] === "string") {
1815
- return children[0];
1816
- }
1817
- return "";
1818
- }
1819
- function CitationMarker({
1820
- source,
1821
- className,
1822
- Link
1823
- }) {
1824
- const props = {
1825
- className: cx("agno-cite", className),
1826
- href: source.url ?? `#${source.anchorId}`,
1827
- "aria-label": `Source ${source.index}: ${source.title}`
1828
- };
1829
- return /* @__PURE__ */ jsx(HoverPreview, { source, className: "agno-cite__wrap", children: Link && source.url ? /* @__PURE__ */ jsx(Link, { ...props, children: source.index }) : /* @__PURE__ */ jsx(
1830
- "a",
1831
- {
1832
- ...props,
1833
- target: source.url ? "_blank" : void 0,
1834
- rel: source.url ? "noreferrer noopener" : void 0,
1835
- children: source.index
1836
- }
1837
- ) });
1838
- }
1839
1804
  var COPIED_FOR = 1600;
1840
1805
  var CLIPBOARD_TIMEOUT = 400;
1841
1806
  async function writeClipboard(text) {
@@ -1861,7 +1826,7 @@ async function writeClipboard(text) {
1861
1826
  return false;
1862
1827
  }
1863
1828
  }
1864
- function CopyButton({ text, className }) {
1829
+ function CopyButton({ text, label: label2 = "Copy", size = 14, className }) {
1865
1830
  const [copied, setCopied] = useState(false);
1866
1831
  useEffect(() => {
1867
1832
  if (!copied) return;
@@ -1869,30 +1834,70 @@ function CopyButton({ text, className }) {
1869
1834
  return () => clearTimeout(timer);
1870
1835
  }, [copied]);
1871
1836
  const copy = async () => {
1872
- if (await writeClipboard(text())) setCopied(true);
1837
+ if (await writeClipboard(typeof text === "function" ? text() : text)) setCopied(true);
1873
1838
  };
1839
+ const name = copied ? "Copied" : label2;
1874
1840
  return /* @__PURE__ */ jsx(
1875
1841
  "button",
1876
1842
  {
1877
1843
  type: "button",
1878
- className: cx("agno-md-copy", copied && "is-copied", className),
1844
+ className: cx("agno-copy", copied && "is-copied", className),
1879
1845
  onClick: copy,
1880
- "aria-label": copied ? "Copied" : "Copy code",
1881
- title: copied ? "Copied" : "Copy code",
1882
- children: copied ? /* @__PURE__ */ jsx(Check, { size: 13 }) : /* @__PURE__ */ jsx(Copy, { size: 13 })
1846
+ "aria-label": name,
1847
+ title: name,
1848
+ children: copied ? /* @__PURE__ */ jsx(Check, { size }) : /* @__PURE__ */ jsx(Copy, { size })
1883
1849
  }
1884
1850
  );
1885
1851
  }
1852
+ function el(tag, className) {
1853
+ return function Element({ node: _node, className: _theirs, ...rest }) {
1854
+ return React8.createElement(tag, { className, ...rest });
1855
+ };
1856
+ }
1857
+ function sourceForUrl(url, sources) {
1858
+ return url ? sources.find((s) => s.url === url) : void 0;
1859
+ }
1860
+ function citationForLink(label2, href, ctx) {
1861
+ if (!/^\d+$/.test(label2.trim())) return void 0;
1862
+ return sourceForUrl(href, ctx.sources) ?? ctx.sources.find((s) => s.index === Number(label2.trim()));
1863
+ }
1864
+ function labelOf(children) {
1865
+ if (typeof children === "string") return children;
1866
+ if (Array.isArray(children) && children.length === 1 && typeof children[0] === "string") {
1867
+ return children[0];
1868
+ }
1869
+ return "";
1870
+ }
1871
+ function CitationMarker({
1872
+ source,
1873
+ className,
1874
+ Link
1875
+ }) {
1876
+ const props = {
1877
+ className: cx("agno-cite", className),
1878
+ href: source.url ?? `#${source.anchorId}`,
1879
+ "aria-label": `Source ${source.index}: ${source.title}`
1880
+ };
1881
+ return /* @__PURE__ */ jsx(HoverPreview, { source, className: "agno-cite__wrap", children: Link && source.url ? /* @__PURE__ */ jsx(Link, { ...props, children: source.index }) : /* @__PURE__ */ jsx(
1882
+ "a",
1883
+ {
1884
+ ...props,
1885
+ target: source.url ? "_blank" : void 0,
1886
+ rel: source.url ? "noreferrer noopener" : void 0,
1887
+ children: source.index
1888
+ }
1889
+ ) });
1890
+ }
1886
1891
  function textOf(children) {
1887
1892
  if (typeof children === "string") return children;
1888
1893
  if (typeof children === "number") return String(children);
1889
1894
  if (Array.isArray(children)) return children.map(textOf).join("");
1890
- if (React7.isValidElement(children)) return textOf(children.props.children);
1895
+ if (React8.isValidElement(children)) return textOf(children.props.children);
1891
1896
  return "";
1892
1897
  }
1893
1898
  function fencedCode(children) {
1894
1899
  const child = Array.isArray(children) ? children[0] : children;
1895
- if (!React7.isValidElement(child)) {
1900
+ if (!React8.isValidElement(child)) {
1896
1901
  return { code: textOf(children) };
1897
1902
  }
1898
1903
  const language = /(?:^|\s)language-([^\s]+)/.exec(child.props.className ?? "")?.[1];
@@ -1913,9 +1918,9 @@ function CodeBlock({
1913
1918
  return /* @__PURE__ */ jsxs("div", { className: "agno-md-code-block", "data-language": label2, children: [
1914
1919
  /* @__PURE__ */ jsxs("div", { className: "agno-md-code-head", children: [
1915
1920
  /* @__PURE__ */ jsx("span", { className: "agno-md-code-lang", children: label2 }),
1916
- codeCopy && /* @__PURE__ */ jsx(CopyButton, { className: copyClass, text: () => code })
1921
+ codeCopy && /* @__PURE__ */ jsx(CopyButton, { className: cx("agno-md-copy", copyClass), text: () => code, label: "Copy code", size: 13 })
1917
1922
  ] }),
1918
- /* @__PURE__ */ jsx("pre", { className: "agno-md-pre", style: { "--agno-code-gutter": `${String(lines.length).length}ch` }, children: /* @__PURE__ */ jsx("code", { className: language ? `language-${language}` : void 0, children: lines.map((tokens, i) => /* @__PURE__ */ jsxs(React7.Fragment, { children: [
1923
+ /* @__PURE__ */ jsx("pre", { className: "agno-md-pre", style: { "--agno-code-gutter": `${String(lines.length).length}ch` }, children: /* @__PURE__ */ jsx("code", { className: language ? `language-${language}` : void 0, children: lines.map((tokens, i) => /* @__PURE__ */ jsxs(React8.Fragment, { children: [
1919
1924
  /* @__PURE__ */ jsx("span", { className: "agno-md-line", children: tokens.map((token, j) => /* @__PURE__ */ jsx("span", { style: token.htmlStyle, children: token.content }, j)) }),
1920
1925
  i < lines.length - 1 && "\n"
1921
1926
  ] }, i)) }) })
@@ -2575,6 +2580,20 @@ function Citations({
2575
2580
  ] })
2576
2581
  ] });
2577
2582
  }
2583
+ function MessageActions({
2584
+ message,
2585
+ hideCopy,
2586
+ children,
2587
+ className,
2588
+ classNames
2589
+ }) {
2590
+ const cn = useResolvedClassNames(classNames);
2591
+ if (hideCopy && !children) return null;
2592
+ return /* @__PURE__ */ jsxs("div", { className: cx("agno-msg__actions", cn.messageActions, className), role: "toolbar", "aria-label": "Message actions", children: [
2593
+ !hideCopy && /* @__PURE__ */ jsx(CopyButton, { className: cx("agno-msg__action", cn.messageCopyButton), text: message.content, label: "Copy message" }),
2594
+ children
2595
+ ] });
2596
+ }
2578
2597
  function audioSrc(a) {
2579
2598
  if (a.url) return a.url;
2580
2599
  if (a.base64_audio) return `data:${a.mime_type ?? "audio/mpeg"};base64,${a.base64_audio}`;
@@ -2615,6 +2634,8 @@ function Message({
2615
2634
  hideReasoning,
2616
2635
  hideTools,
2617
2636
  hideSources,
2637
+ hideActions,
2638
+ actions,
2618
2639
  onFollowup
2619
2640
  }) {
2620
2641
  const cn = useResolvedClassNames(classNames);
@@ -2681,7 +2702,8 @@ function Message({
2681
2702
  showSources && /* @__PURE__ */ jsx(Citations, { sources, classNames: cn }),
2682
2703
  isAgent && onFollowup && !message.streaming && /* @__PURE__ */ jsx(Followups, { items: message.followups, onSelect: onFollowup, classNames: cn }),
2683
2704
  message.error && /* @__PURE__ */ jsx("div", { className: "agno-msg__error", children: message.error }),
2684
- children
2705
+ children,
2706
+ isAgent && !hideActions && !message.streaming && message.content && /* @__PURE__ */ jsx(MessageActions, { message, classNames: cn, children: actions })
2685
2707
  ] }) })
2686
2708
  ]
2687
2709
  }
@@ -2741,7 +2763,7 @@ function MessageList({
2741
2763
  items.length === 0 ? /* @__PURE__ */ jsx("div", { className: cx("agno-list__empty", cn.empty), children: emptyState ?? "Start the conversation." }) : /* @__PURE__ */ jsxs("div", { className: "agno-list__inner", children: [
2742
2764
  items.map((m) => {
2743
2765
  const live = m.streaming && runStatus === "streaming" ? runActivity : void 0;
2744
- return renderMessage ? /* @__PURE__ */ jsx(React7.Fragment, { children: renderMessage(m, live) }, m.id) : /* @__PURE__ */ jsx(
2766
+ return renderMessage ? /* @__PURE__ */ jsx(React8.Fragment, { children: renderMessage(m, live) }, m.id) : /* @__PURE__ */ jsx(
2745
2767
  Message,
2746
2768
  {
2747
2769
  message: m,
@@ -3498,6 +3520,6 @@ function EventLog({
3498
3520
  ] });
3499
3521
  }
3500
3522
 
3501
- export { AgnoChat, AgnoMark, ArrowUp, BehindTheScenes, BookOpen, Box, Brain, ChatBubble, ChatInput, ChatLauncher, ChatProvider, ChatWindow, Check, ChevronDown, Citations, Close, Copy, EntityBadge, EntitySelector, EventLog, Favicon, FileAudio, FileIcon, FilePreview, FileType, FileVideo, Followups, Globe, GridLoader, HoverPreview, HumanInput, LinkIcon, LinkPreviewCard, Markdown, MemberResponses, Memory, Message, MessageList, Multimedia, Paperclip, Plus, Pulse, QuickPrompts, Reasoning, Rerun, SessionList, SourceCard, SourcesProvider, Spinner, StatusIndicator, Stop, TeamGlyph, ToolCalls, Trash, WorkflowSteps, Wrench, admitFiles, behindTheScenesItems, behindTheScenesLabel, collectSources, cx, displayUrl, faviconUrl, fileAccepted, getProviderIcon, hasBehindTheScenes, linkCitations, normalizeFollowups, quickPromptLabel, quickPromptText, sourceHost, sourcesFromMarkdown, useAgnoChat, useChatContext, useLinkComponent, useLinkPreview, useOptionalChatContext, useResolvedChat, useResolvedClassNames, useSources, withoutSourcesLine, writeClipboard };
3502
- //# sourceMappingURL=chunk-XTP3TMEZ.js.map
3503
- //# sourceMappingURL=chunk-XTP3TMEZ.js.map
3523
+ export { AgnoChat, AgnoMark, ArrowUp, BehindTheScenes, BookOpen, Box, Brain, ChatBubble, ChatInput, ChatLauncher, ChatProvider, ChatWindow, Check, ChevronDown, Citations, Close, Copy, CopyButton, EntityBadge, EntitySelector, EventLog, Favicon, FileAudio, FileIcon, FilePreview, FileType, FileVideo, Followups, Globe, GridLoader, HoverPreview, HumanInput, LinkIcon, LinkPreviewCard, Markdown, MemberResponses, Memory, Message, MessageActions, MessageList, Multimedia, Paperclip, Plus, Pulse, QuickPrompts, Reasoning, Rerun, SessionList, SourceCard, SourcesProvider, Spinner, StatusIndicator, Stop, TeamGlyph, ToolCalls, Trash, WorkflowSteps, Wrench, admitFiles, behindTheScenesItems, behindTheScenesLabel, collectSources, cx, displayUrl, faviconFallbacks, faviconUrl, fileAccepted, getProviderIcon, hasBehindTheScenes, linkCitations, normalizeFollowups, quickPromptLabel, quickPromptText, sourceHost, sourcesFromMarkdown, useAgnoChat, useChatContext, useLinkComponent, useLinkPreview, useOptionalChatContext, useResolvedChat, useResolvedClassNames, useSources, withoutSourcesLine, writeClipboard };
3524
+ //# sourceMappingURL=chunk-E4CFQ457.js.map
3525
+ //# sourceMappingURL=chunk-E4CFQ457.js.map