@agno-hq/chat-react 0.3.0 → 0.3.1

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,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkROFIOWGX_cjs = require('./chunk-ROFIOWGX.cjs');
3
+ var chunk55HQJGLP_cjs = require('./chunk-55HQJGLP.cjs');
4
4
  var React7 = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var reactDom = require('react-dom');
@@ -18,7 +18,7 @@ function useAgnoChat(options) {
18
18
  const { entity, userId, onEvent, onSessionId } = options;
19
19
  const client = React7.useMemo(() => {
20
20
  if (options.client) return options.client;
21
- return new chunkROFIOWGX_cjs.AgnoClient({ baseUrl: options.baseUrl ?? "", headers: options.headers });
21
+ return new chunk55HQJGLP_cjs.AgnoClient({ baseUrl: options.baseUrl ?? "", headers: options.headers });
22
22
  }, [options.client, options.baseUrl, JSON.stringify(options.headers)]);
23
23
  const [messages, setMessages] = React7.useState(options.initialMessages ?? []);
24
24
  const [events, setEvents] = React7.useState([]);
@@ -106,7 +106,7 @@ function useAgnoChat(options) {
106
106
  writeEvents(chan, e);
107
107
  patchActive(chan, (m) => ({ ...m, events: [...m.events ?? [], e] }));
108
108
  onEvent?.(e);
109
- const label2 = chunkROFIOWGX_cjs.activityLabel(e);
109
+ const label2 = chunk55HQJGLP_cjs.activityLabel(e);
110
110
  if (label2) writeActivity(chan, label2);
111
111
  if (e.session_id && !chan?.park && e.session_id !== sessionIdRef.current) {
112
112
  sessionIdRef.current = e.session_id;
@@ -123,16 +123,16 @@ function useAgnoChat(options) {
123
123
  if (chan?.park) chan.park.runId = e.run_id;
124
124
  else runIdRef.current = e.run_id;
125
125
  }
126
- if (chunkROFIOWGX_cjs.isSubRunEvent(e)) {
126
+ if (chunk55HQJGLP_cjs.isSubRunEvent(e)) {
127
127
  const kind = entityRef.current?.type === "workflow" ? "executor" : "member";
128
- patchActive(chan, (m) => chunkROFIOWGX_cjs.applySubRunEvent(m, e, kind));
128
+ patchActive(chan, (m) => chunk55HQJGLP_cjs.applySubRunEvent(m, e, kind));
129
129
  return;
130
130
  }
131
- if (chunkROFIOWGX_cjs.isStepEvent(e)) {
132
- patchActive(chan, (m) => chunkROFIOWGX_cjs.applyStepEvent(m, e));
131
+ if (chunk55HQJGLP_cjs.isStepEvent(e)) {
132
+ patchActive(chan, (m) => chunk55HQJGLP_cjs.applyStepEvent(m, e));
133
133
  return;
134
134
  }
135
- if (chunkROFIOWGX_cjs.isStartedEvent(e)) {
135
+ if (chunk55HQJGLP_cjs.isStartedEvent(e)) {
136
136
  patchActive(chan, (m) => ({
137
137
  ...m,
138
138
  run_id: e.run_id ?? m.run_id,
@@ -141,22 +141,22 @@ function useAgnoChat(options) {
141
141
  }));
142
142
  return;
143
143
  }
144
- if (chunkROFIOWGX_cjs.isToolEvent(e)) {
145
- const incoming = chunkROFIOWGX_cjs.toolsFromEvent(e);
144
+ if (chunk55HQJGLP_cjs.isToolEvent(e)) {
145
+ const incoming = chunk55HQJGLP_cjs.toolsFromEvent(e);
146
146
  if (incoming.length) {
147
147
  patchActive(chan, (m) => {
148
148
  let tool_calls = m.tool_calls ?? [];
149
- for (const t of incoming) tool_calls = chunkROFIOWGX_cjs.mergeTool(tool_calls, t);
149
+ for (const t of incoming) tool_calls = chunk55HQJGLP_cjs.mergeTool(tool_calls, t);
150
150
  return { ...m, tool_calls };
151
151
  });
152
152
  }
153
153
  return;
154
154
  }
155
- if (chunkROFIOWGX_cjs.isContentEvent(e)) {
156
- patchActive(chan, (m) => chunkROFIOWGX_cjs.applyContentEvent(m, e));
155
+ if (chunk55HQJGLP_cjs.isContentEvent(e)) {
156
+ patchActive(chan, (m) => chunk55HQJGLP_cjs.applyContentEvent(m, e));
157
157
  return;
158
158
  }
159
- if (chunkROFIOWGX_cjs.isReasoningStepEvent(e)) {
159
+ if (chunk55HQJGLP_cjs.isReasoningStepEvent(e)) {
160
160
  const incoming = e.reasoning_steps ?? e.extra_data?.reasoning_steps ?? [];
161
161
  if (incoming.length) {
162
162
  patchActive(chan, (m) => ({
@@ -166,36 +166,36 @@ function useAgnoChat(options) {
166
166
  }
167
167
  return;
168
168
  }
169
- if (chunkROFIOWGX_cjs.isReasoningCompletedEvent(e)) {
169
+ if (chunk55HQJGLP_cjs.isReasoningCompletedEvent(e)) {
170
170
  const steps = e.reasoning_steps ?? e.extra_data?.reasoning_steps;
171
171
  if (steps?.length) patchActive(chan, (m) => ({ ...m, reasoning_steps: steps }));
172
172
  return;
173
173
  }
174
- if (chunkROFIOWGX_cjs.isFollowupsCompletedEvent(e)) {
174
+ if (chunk55HQJGLP_cjs.isFollowupsCompletedEvent(e)) {
175
175
  const followups = e.followups;
176
176
  if (followups?.length) patchActive(chan, (m) => ({ ...m, followups }));
177
177
  return;
178
178
  }
179
- if (chunkROFIOWGX_cjs.isPausedEvent(e)) {
179
+ if (chunk55HQJGLP_cjs.isPausedEvent(e)) {
180
180
  const requirements = e.requirements ?? [];
181
- const pausedTools2 = chunkROFIOWGX_cjs.toolsFromEvent(e);
181
+ const pausedTools2 = chunk55HQJGLP_cjs.toolsFromEvent(e);
182
182
  writeStatus(chan, "paused");
183
183
  writeActivity(chan, "Waiting for input");
184
184
  patchActive(chan, (m) => {
185
185
  let tool_calls = m.tool_calls ?? [];
186
- for (const t of pausedTools2) tool_calls = chunkROFIOWGX_cjs.mergeTool(tool_calls, t);
186
+ for (const t of pausedTools2) tool_calls = chunk55HQJGLP_cjs.mergeTool(tool_calls, t);
187
187
  return { ...m, status: "paused", streaming: false, requirements, tool_calls };
188
188
  });
189
189
  return;
190
190
  }
191
- if (chunkROFIOWGX_cjs.isCompletedEvent(e)) {
191
+ if (chunk55HQJGLP_cjs.isCompletedEvent(e)) {
192
192
  patchActive(chan, (m) => {
193
193
  const next = { ...m, streaming: false, status: "completed" };
194
194
  if (typeof e.content === "string" && e.content) next.content = e.content;
195
- const tools = chunkROFIOWGX_cjs.toolsFromEvent(e);
195
+ const tools = chunk55HQJGLP_cjs.toolsFromEvent(e);
196
196
  if (tools.length) {
197
197
  let tc = m.tool_calls ?? [];
198
- for (const t of tools) tc = chunkROFIOWGX_cjs.mergeTool(tc, t);
198
+ for (const t of tools) tc = chunk55HQJGLP_cjs.mergeTool(tc, t);
199
199
  next.tool_calls = tc;
200
200
  }
201
201
  if (e.reasoning_steps?.length) next.reasoning_steps = e.reasoning_steps;
@@ -209,12 +209,12 @@ function useAgnoChat(options) {
209
209
  });
210
210
  return;
211
211
  }
212
- if (chunkROFIOWGX_cjs.isCancelledEvent(e)) {
212
+ if (chunk55HQJGLP_cjs.isCancelledEvent(e)) {
213
213
  patchActive(chan, (m) => ({ ...m, streaming: false, status: "cancelled" }));
214
214
  writeStatus(chan, "cancelled");
215
215
  return;
216
216
  }
217
- if (chunkROFIOWGX_cjs.isErrorEvent(e)) {
217
+ if (chunk55HQJGLP_cjs.isErrorEvent(e)) {
218
218
  const msg = typeof e.content === "string" ? e.content : e.error || "Error during run";
219
219
  patchActive(chan, (m) => ({ ...m, streaming: false, status: "error", error: msg }));
220
220
  writeError(chan, msg);
@@ -483,7 +483,7 @@ function useAgnoChat(options) {
483
483
  setError(null);
484
484
  try {
485
485
  const runs = await client.getSessionRuns(ent.type, id, ent.db_id);
486
- setMessages(chunkROFIOWGX_cjs.sessionRunsToMessages(runs));
486
+ setMessages(chunk55HQJGLP_cjs.sessionRunsToMessages(runs));
487
487
  } catch (err) {
488
488
  setError(err instanceof Error ? err.message : String(err));
489
489
  }
@@ -583,6 +583,7 @@ function ChatProvider({
583
583
  renderMarkdown,
584
584
  resolveLinkPreview,
585
585
  codeCopy,
586
+ linkComponent,
586
587
  chat: externalChat,
587
588
  as,
588
589
  className,
@@ -593,8 +594,8 @@ function ChatProvider({
593
594
  const internal = useAgnoChat(externalChat ? { entity: null } : options);
594
595
  const chat = externalChat ?? internal;
595
596
  const value = React7.useMemo(
596
- () => ({ chat, classNames: classNames ?? {}, renderMarkdown, resolveLinkPreview, codeCopy }),
597
- [chat, classNames, renderMarkdown, resolveLinkPreview, codeCopy]
597
+ () => ({ chat, classNames: classNames ?? {}, renderMarkdown, resolveLinkPreview, codeCopy, linkComponent }),
598
+ [chat, classNames, renderMarkdown, resolveLinkPreview, codeCopy, linkComponent]
598
599
  );
599
600
  const Wrapper = as === false ? null : as ?? "div";
600
601
  return /* @__PURE__ */ jsxRuntime.jsx(ChatContext.Provider, { value, children: Wrapper ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -627,6 +628,9 @@ function useResolvedChat(explicit) {
627
628
  function useCodeCopy() {
628
629
  return useOptionalChatContext()?.codeCopy;
629
630
  }
631
+ function useLinkComponent() {
632
+ return useOptionalChatContext()?.linkComponent;
633
+ }
630
634
  function useResolvedClassNames(explicit) {
631
635
  const ctx = useOptionalChatContext();
632
636
  return React7.useMemo(() => ({ ...ctx?.classNames, ...explicit }), [ctx?.classNames, explicit]);
@@ -639,11 +643,13 @@ var ChevronDown = icon(lucideReact.ChevronDown);
639
643
  var ArrowUp = icon(lucideReact.ArrowUp);
640
644
  var Paperclip = icon(lucideReact.Paperclip);
641
645
  var FileIcon = icon(lucideReact.File);
646
+ var FileType = icon(lucideReact.FileType2);
642
647
  var FileAudio = icon(lucideReact.FileAudio);
643
648
  var FileVideo = icon(lucideReact.FileVideo);
644
649
  var Wrench = icon(lucideReact.Wrench);
645
650
  var BookOpen = icon(lucideReact.BookOpen);
646
651
  var Globe = icon(lucideReact.Globe);
652
+ var LinkIcon = icon(lucideReact.Link);
647
653
  var Brain = icon(lucideReact.Brain);
648
654
  var Box = icon(lucideReact.Box);
649
655
  var Plus = icon(lucideReact.Plus);
@@ -846,7 +852,16 @@ function ChatLauncher({
846
852
  function markFor(type) {
847
853
  if (type.startsWith("audio/")) return FileAudio;
848
854
  if (type.startsWith("video/")) return FileVideo;
849
- return FileIcon;
855
+ return FileType;
856
+ }
857
+ function formatSize(bytes) {
858
+ return bytes >= 1024 * 1024 ? `${Math.round(bytes / (1024 * 1024) * 10) / 10}MB` : `${Math.max(1, Math.round(bytes / 1024))}KB`;
859
+ }
860
+ function kindOf(file) {
861
+ const dot = file.name.lastIndexOf(".");
862
+ if (dot > 0 && dot < file.name.length - 1) return file.name.slice(dot + 1);
863
+ const subtype = file.type.split("/")[1];
864
+ return subtype || "file";
850
865
  }
851
866
  function Item({ file, onRemove }) {
852
867
  const isImage = file.type.startsWith("image/");
@@ -861,15 +876,19 @@ function Item({ file, onRemove }) {
861
876
  };
862
877
  }, [file, isImage]);
863
878
  const Mark = markFor(file.type);
864
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "agno-file", children: [
865
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "agno-file__remove", onClick: onRemove, "aria-label": `Remove ${file.name}`, children: /* @__PURE__ */ jsxRuntime.jsx(Close, { size: 12 }) }),
866
- isImage && url ? /* @__PURE__ */ jsxRuntime.jsx("img", { className: "agno-file__thumb", src: url, alt: file.name }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "agno-file__card", children: [
879
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("agno-file", isImage && url ? "agno-file--image" : "agno-file--card"), children: [
880
+ isImage && url ? /* @__PURE__ */ jsxRuntime.jsx("img", { className: "agno-file__thumb", src: url, alt: file.name }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
867
881
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "agno-file__mark", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(Mark, { size: 16 }) }),
868
882
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "agno-file__meta", children: [
869
883
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "agno-file__name", title: file.name, children: file.name }),
870
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "agno-file__type", children: file.type || "file" })
884
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "agno-file__type", children: [
885
+ kindOf(file),
886
+ " \u2022 ",
887
+ formatSize(file.size)
888
+ ] })
871
889
  ] })
872
- ] })
890
+ ] }),
891
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "agno-file__remove", onClick: onRemove, "aria-label": `Remove ${file.name}`, children: /* @__PURE__ */ jsxRuntime.jsx(Close, { size: 12 }) })
873
892
  ] });
874
893
  }
875
894
  function FilePreview({ files, onRemove, onClear, className }) {
@@ -879,20 +898,51 @@ function FilePreview({ files, onRemove, onClear, className }) {
879
898
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "agno-files__count", children: [
880
899
  files.length,
881
900
  " ",
882
- files.length > 1 ? "files" : "file",
883
- " attached"
901
+ files.length > 1 ? "attachments" : "attachment"
884
902
  ] }),
885
903
  onClear && /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "agno-files__clear", onClick: onClear, children: [
886
- /* @__PURE__ */ jsxRuntime.jsx(Close, { size: 12 }),
887
- "clear ",
888
- files.length > 1 ? "all" : ""
904
+ /* @__PURE__ */ jsxRuntime.jsx(Close, { size: 14 }),
905
+ "clear all"
889
906
  ] })
890
907
  ] }),
891
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "agno-files__row", children: files.map((file, i) => /* @__PURE__ */ jsxRuntime.jsx(Item, { file, onRemove: () => onRemove(i) }, `${file.name}-${file.lastModified}-${i}`)) })
908
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "agno-files__strip", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "agno-files__row", children: files.map((file, i) => /* @__PURE__ */ jsxRuntime.jsx(Item, { file, onRemove: () => onRemove(i) }, `${file.name}-${file.lastModified}-${i}`)) }) })
892
909
  ] });
893
910
  }
894
- var MIN_HEIGHT = 31;
895
- var MAX_HEIGHT = 213;
911
+ var BOUNDS = {
912
+ dock: { min: 31, max: 213 },
913
+ compact: { min: 24, max: 120 }
914
+ };
915
+ function fileAccepted(file, accept) {
916
+ if (!accept) return true;
917
+ const name = file.name.toLowerCase();
918
+ const type = file.type.toLowerCase();
919
+ return accept.split(",").map((rule) => rule.trim().toLowerCase()).filter(Boolean).some((rule) => {
920
+ if (rule.startsWith(".")) return name.endsWith(rule);
921
+ if (rule.endsWith("/*")) return type.startsWith(rule.slice(0, -1));
922
+ return type === rule;
923
+ });
924
+ }
925
+ function admitFiles(current, incoming, limits) {
926
+ const { accept, maxFiles, maxFileSize, maxTotalSize } = limits;
927
+ const files = [...current];
928
+ let total = current.reduce((sum, f) => sum + f.size, 0);
929
+ let error = null;
930
+ const refuse = (reason) => {
931
+ error ?? (error = reason);
932
+ };
933
+ for (const file of incoming) {
934
+ if (!fileAccepted(file, accept)) refuse("Cannot add this file type");
935
+ else if (maxFileSize != null && file.size > maxFileSize) refuse(`Cannot add files over ${formatSize(maxFileSize)}`);
936
+ else if (maxFiles != null && files.length >= maxFiles) refuse(`Cannot add more than ${maxFiles} attachments`);
937
+ else if (maxTotalSize != null && total + file.size > maxTotalSize) refuse("Cannot add more files");
938
+ else {
939
+ files.push(file);
940
+ total += file.size;
941
+ }
942
+ }
943
+ return { files, error };
944
+ }
945
+ var hasFiles = (e) => Array.from(e.dataTransfer.types).includes("Files");
896
946
  function ChatInput({
897
947
  onSend,
898
948
  onStop,
@@ -900,6 +950,19 @@ function ChatInput({
900
950
  busy,
901
951
  placeholder,
902
952
  allowFiles = false,
953
+ compact = false,
954
+ accept,
955
+ maxFiles,
956
+ maxFileSize,
957
+ maxTotalSize,
958
+ value: controlled,
959
+ onValueChange,
960
+ textareaRef: externalRef,
961
+ textareaProps,
962
+ renderTextarea,
963
+ above,
964
+ below,
965
+ dropLabel = "Drop files to attach",
903
966
  leading,
904
967
  trailing,
905
968
  className,
@@ -907,109 +970,213 @@ function ChatInput({
907
970
  }) {
908
971
  const ctx = useOptionalChatContext();
909
972
  const cn = useResolvedClassNames(classNames);
910
- const [value, setValue] = React7.useState("");
911
- const [files, setFiles] = React7.useState([]);
973
+ const [internal, setInternal] = React7.useState("");
974
+ const value = controlled ?? internal;
975
+ const setValue = (next) => {
976
+ if (controlled === void 0) setInternal(next);
977
+ onValueChange?.(next);
978
+ };
979
+ const [files, setFilesState] = React7.useState([]);
980
+ const filesRef = React7.useRef([]);
981
+ const setFiles = (next) => {
982
+ filesRef.current = next;
983
+ setFilesState(next);
984
+ };
985
+ const [fileError, setFileError] = React7.useState(null);
986
+ const [dragging, setDragging] = React7.useState(false);
987
+ const dragDepth = React7.useRef(0);
912
988
  const fileRef = React7.useRef(null);
913
989
  const textareaRef = React7.useRef(null);
990
+ const setTextareaRef = React7.useCallback(
991
+ (el2) => {
992
+ textareaRef.current = el2;
993
+ if (typeof externalRef === "function") externalRef(el2);
994
+ else if (externalRef) externalRef.current = el2;
995
+ },
996
+ [externalRef]
997
+ );
914
998
  const adjustHeight = React7.useCallback(() => {
915
999
  const el2 = textareaRef.current;
916
- if (!el2) return;
917
- el2.style.height = `${MIN_HEIGHT}px`;
918
- el2.style.height = `${Math.min(Math.max(el2.scrollHeight, MIN_HEIGHT), MAX_HEIGHT)}px`;
919
- }, []);
1000
+ if (!el2 || renderTextarea) return;
1001
+ const { min, max } = compact ? BOUNDS.compact : BOUNDS.dock;
1002
+ el2.style.height = `${min}px`;
1003
+ el2.style.height = `${Math.min(Math.max(el2.scrollHeight, min), max)}px`;
1004
+ }, [renderTextarea, compact]);
920
1005
  React7.useEffect(adjustHeight, [value, adjustHeight]);
921
1006
  const send = onSend ?? ((message, attached) => void ctx?.chat.sendMessage(message, attached ? { files: attached } : void 0));
922
1007
  const stop = onStop ?? (ctx ? () => void ctx.chat.cancel() : void 0);
923
1008
  const isBusy = busy ?? ctx?.chat.isStreaming ?? false;
924
1009
  const isDisabled = disabled ?? ctx?.chat.isPaused ?? false;
925
- const submit = () => {
1010
+ const limits = { accept, maxFiles, maxFileSize, maxTotalSize };
1011
+ const addFiles = (incoming) => {
1012
+ if (!incoming.length) return;
1013
+ const next = admitFiles(filesRef.current, incoming, limits);
1014
+ setFiles(next.files);
1015
+ setFileError(next.error);
1016
+ if (fileRef.current) fileRef.current.value = "";
1017
+ };
1018
+ const submit = async () => {
926
1019
  const text = value.trim();
927
1020
  if (!text && files.length === 0) return;
928
- send(text, files.length ? files : void 0);
1021
+ const sent = files.length ? files : void 0;
1022
+ const result = await send(text, sent);
1023
+ if (result === false) return;
929
1024
  setValue("");
930
1025
  setFiles([]);
1026
+ setFileError(null);
931
1027
  };
932
1028
  const canSend = !isDisabled && !isBusy && (Boolean(value.trim()) || files.length > 0);
933
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cx("agno-input", cn.input, className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "agno-input__dock", children: [
1029
+ const onKeyDown = (e) => {
1030
+ textareaProps?.onKeyDown?.(e);
1031
+ if (e.defaultPrevented) return;
1032
+ if (e.key === "Enter" && !e.nativeEvent.isComposing && !e.shiftKey) {
1033
+ e.preventDefault();
1034
+ if (canSend) void submit();
1035
+ }
1036
+ };
1037
+ const onDragEnter = (e) => {
1038
+ if (!allowFiles || !hasFiles(e)) return;
1039
+ e.preventDefault();
1040
+ dragDepth.current += 1;
1041
+ setDragging(true);
1042
+ };
1043
+ const onDragOver = (e) => {
1044
+ if (!allowFiles || !hasFiles(e)) return;
1045
+ e.preventDefault();
1046
+ e.dataTransfer.dropEffect = "copy";
1047
+ };
1048
+ const onDragLeave = (e) => {
1049
+ if (!allowFiles || dragDepth.current === 0) return;
1050
+ e.preventDefault();
1051
+ dragDepth.current = Math.max(0, dragDepth.current - 1);
1052
+ if (dragDepth.current === 0) setDragging(false);
1053
+ };
1054
+ const onDrop = (e) => {
1055
+ if (!allowFiles || !hasFiles(e)) return;
1056
+ e.preventDefault();
1057
+ dragDepth.current = 0;
1058
+ setDragging(false);
1059
+ addFiles(Array.from(e.dataTransfer.files));
1060
+ textareaRef.current?.focus();
1061
+ };
1062
+ const fieldProps = {
1063
+ rows: 1,
1064
+ ...textareaProps,
1065
+ ref: setTextareaRef,
1066
+ className: cx("agno-input__textarea", cn.textarea, textareaProps?.className),
1067
+ value,
1068
+ placeholder: placeholder ?? (isBusy ? "Running..." : "Ask anything..."),
1069
+ disabled: isDisabled,
1070
+ onChange: (e) => {
1071
+ setValue(e.target.value);
1072
+ textareaProps?.onChange?.(e);
1073
+ },
1074
+ onKeyDown
1075
+ };
1076
+ const iconSize = compact ? 14 : 16;
1077
+ const field = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "agno-input__field", children: renderTextarea ? renderTextarea(fieldProps) : /* @__PURE__ */ jsxRuntime.jsx("textarea", { ...fieldProps }) });
1078
+ const attach = allowFiles && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
934
1079
  /* @__PURE__ */ jsxRuntime.jsx(
935
- FilePreview,
1080
+ "button",
936
1081
  {
937
- files,
938
- onRemove: (i) => setFiles((prev) => prev.filter((_, j) => j !== i)),
939
- onClear: () => setFiles([]),
940
- className: cn.files
1082
+ type: "button",
1083
+ className: cx("agno-btn", compact ? "agno-btn--ghost" : "agno-btn--outline", "agno-btn--icon", cn.attachButton),
1084
+ onClick: () => fileRef.current?.click(),
1085
+ disabled: isDisabled,
1086
+ "aria-label": files.length ? `Attach files; ${files.length} attached` : "Attach files",
1087
+ title: files.length ? files.map((f) => f.name).join(", ") : void 0,
1088
+ children: /* @__PURE__ */ jsxRuntime.jsx(Paperclip, { size: iconSize })
941
1089
  }
942
1090
  ),
943
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "agno-input__field", children: /* @__PURE__ */ jsxRuntime.jsx(
944
- "textarea",
1091
+ /* @__PURE__ */ jsxRuntime.jsx(
1092
+ "input",
945
1093
  {
946
- ref: textareaRef,
947
- className: cx("agno-input__textarea", cn.textarea),
948
- value,
949
- placeholder: placeholder ?? (isBusy ? "Running..." : "Ask anything..."),
950
- disabled: isDisabled,
951
- rows: 1,
952
- onChange: (e) => setValue(e.target.value),
953
- onKeyDown: (e) => {
954
- if (e.key === "Enter" && !e.nativeEvent.isComposing && !e.shiftKey) {
955
- e.preventDefault();
956
- if (canSend) submit();
957
- }
958
- }
1094
+ ref: fileRef,
1095
+ type: "file",
1096
+ multiple: true,
1097
+ hidden: true,
1098
+ accept,
1099
+ onChange: (e) => addFiles(Array.from(e.target.files ?? []))
959
1100
  }
960
- ) }),
961
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("agno-input__row", cn.inputRow), children: [
962
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "agno-input__actions", children: [
963
- leading,
964
- allowFiles && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
965
- /* @__PURE__ */ jsxRuntime.jsx(
966
- "button",
967
- {
968
- type: "button",
969
- className: cx("agno-btn", "agno-btn--outline", "agno-btn--icon", cn.attachButton),
970
- onClick: () => fileRef.current?.click(),
971
- disabled: isDisabled,
972
- "aria-label": "Attach files",
973
- children: /* @__PURE__ */ jsxRuntime.jsx(Paperclip, { size: 16 })
974
- }
975
- ),
976
- /* @__PURE__ */ jsxRuntime.jsx(
977
- "input",
978
- {
979
- ref: fileRef,
980
- type: "file",
981
- multiple: true,
982
- hidden: true,
983
- onChange: (e) => setFiles((prev) => [...prev, ...Array.from(e.target.files ?? [])])
984
- }
985
- )
986
- ] })
987
- ] }),
988
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "agno-input__actions", children: [
989
- trailing,
990
- isBusy && stop ? /* @__PURE__ */ jsxRuntime.jsx(
991
- "button",
992
- {
993
- type: "button",
994
- className: cx("agno-btn", "agno-btn--destructive", "agno-btn--icon", cn.stopButton),
995
- onClick: stop,
996
- "aria-label": "Stop",
997
- children: /* @__PURE__ */ jsxRuntime.jsx(Stop, { size: 16 })
998
- }
999
- ) : /* @__PURE__ */ jsxRuntime.jsx(
1000
- "button",
1101
+ )
1102
+ ] });
1103
+ const primary = isBusy && stop ? /* @__PURE__ */ jsxRuntime.jsx(
1104
+ "button",
1105
+ {
1106
+ type: "button",
1107
+ className: cx("agno-btn", "agno-btn--destructive", "agno-btn--icon", cn.stopButton),
1108
+ onClick: stop,
1109
+ "aria-label": "Stop",
1110
+ children: /* @__PURE__ */ jsxRuntime.jsx(Stop, { size: iconSize })
1111
+ }
1112
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1113
+ "button",
1114
+ {
1115
+ type: "button",
1116
+ className: cx("agno-btn", "agno-btn--icon", cn.sendButton),
1117
+ onClick: () => void submit(),
1118
+ disabled: !canSend,
1119
+ "aria-label": "Send",
1120
+ children: /* @__PURE__ */ jsxRuntime.jsx(ArrowUp, { size: iconSize })
1121
+ }
1122
+ );
1123
+ return /* @__PURE__ */ jsxRuntime.jsx(
1124
+ "div",
1125
+ {
1126
+ className: cx("agno-input", compact && "agno-input--compact", cn.input, className),
1127
+ "data-dragging": dragging ? "true" : void 0,
1128
+ onDragEnter,
1129
+ onDragOver,
1130
+ onDragLeave,
1131
+ onDrop,
1132
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "agno-input__dock", children: [
1133
+ dragging && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("agno-input__drop", cn.dropOverlay), "aria-hidden": true, children: [
1134
+ /* @__PURE__ */ jsxRuntime.jsx(Paperclip, { size: 16 }),
1135
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: dropLabel })
1136
+ ] }),
1137
+ above,
1138
+ /* @__PURE__ */ jsxRuntime.jsx(
1139
+ FilePreview,
1001
1140
  {
1002
- type: "button",
1003
- className: cx("agno-btn", "agno-btn--icon", cn.sendButton),
1004
- onClick: submit,
1005
- disabled: !canSend,
1006
- "aria-label": "Send",
1007
- children: /* @__PURE__ */ jsxRuntime.jsx(ArrowUp, { size: 16 })
1141
+ files,
1142
+ onRemove: (i) => {
1143
+ setFiles(filesRef.current.filter((_, j) => j !== i));
1144
+ setFileError(null);
1145
+ },
1146
+ onClear: () => {
1147
+ setFiles([]);
1148
+ setFileError(null);
1149
+ },
1150
+ className: cn.files
1008
1151
  }
1009
- )
1152
+ ),
1153
+ fileError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: cx("agno-input__error", cn.fileError), role: "alert", children: fileError }),
1154
+ compact ? (
1155
+ // One line: the field, then every control beside it.
1156
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("agno-input__row", cn.inputRow), children: [
1157
+ leading,
1158
+ field,
1159
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "agno-input__actions", children: [
1160
+ attach,
1161
+ trailing,
1162
+ primary
1163
+ ] })
1164
+ ] })
1165
+ ) : field,
1166
+ below,
1167
+ !compact && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cx("agno-input__row", cn.inputRow), children: [
1168
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "agno-input__actions", children: [
1169
+ leading,
1170
+ attach
1171
+ ] }),
1172
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "agno-input__actions", children: [
1173
+ trailing,
1174
+ primary
1175
+ ] })
1176
+ ] })
1010
1177
  ] })
1011
- ] })
1012
- ] }) });
1178
+ }
1179
+ );
1013
1180
  }
1014
1181
  function normalizeFollowups(items) {
1015
1182
  if (!items?.length) return [];
@@ -1532,20 +1699,15 @@ var PREVIEW_WIDTH = 320;
1532
1699
  var GAP = 8;
1533
1700
  var OPEN_DELAY = 140;
1534
1701
  var CLOSE_DELAY = 120;
1535
- function usePlacement(anchor, open) {
1702
+ function usePlacement(anchor, open, { width = PREVIEW_WIDTH, align = "center" } = {}) {
1536
1703
  const [placement, setPlacement] = React7.useState(null);
1537
1704
  useIsomorphicLayoutEffect(() => {
1538
1705
  if (!open || !anchor) return;
1539
1706
  const place = () => {
1540
1707
  const rect = anchor.getBoundingClientRect();
1541
1708
  const side = rect.top > 220 ? "top" : "bottom";
1542
- const left = Math.max(
1543
- GAP,
1544
- Math.min(
1545
- rect.left + rect.width / 2 - PREVIEW_WIDTH / 2,
1546
- window.innerWidth - PREVIEW_WIDTH - GAP
1547
- )
1548
- );
1709
+ const wanted = align === "center" ? rect.left + rect.width / 2 - width / 2 : rect.left;
1710
+ const left = Math.max(GAP, Math.min(wanted, window.innerWidth - width - GAP));
1549
1711
  setPlacement({
1550
1712
  top: side === "top" ? rect.top - GAP : rect.bottom + GAP,
1551
1713
  left,
@@ -1559,7 +1721,7 @@ function usePlacement(anchor, open) {
1559
1721
  window.removeEventListener("scroll", place, true);
1560
1722
  window.removeEventListener("resize", place);
1561
1723
  };
1562
- }, [anchor, open]);
1724
+ }, [anchor, open, width, align]);
1563
1725
  return placement;
1564
1726
  }
1565
1727
  function HoverPreview({
@@ -1661,16 +1823,20 @@ function labelOf(children) {
1661
1823
  }
1662
1824
  function CitationMarker({
1663
1825
  source,
1664
- className
1826
+ className,
1827
+ Link
1665
1828
  }) {
1666
- return /* @__PURE__ */ jsxRuntime.jsx(HoverPreview, { source, className: "agno-cite__wrap", children: /* @__PURE__ */ jsxRuntime.jsx(
1829
+ const props = {
1830
+ className: cx("agno-cite", className),
1831
+ href: source.url ?? `#${source.anchorId}`,
1832
+ "aria-label": `Source ${source.index}: ${source.title}`
1833
+ };
1834
+ 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(
1667
1835
  "a",
1668
1836
  {
1669
- className: cx("agno-cite", className),
1670
- href: source.url ?? `#${source.anchorId}`,
1837
+ ...props,
1671
1838
  target: source.url ? "_blank" : void 0,
1672
1839
  rel: source.url ? "noreferrer noopener" : void 0,
1673
- "aria-label": `Source ${source.index}: ${source.title}`,
1674
1840
  children: source.index
1675
1841
  }
1676
1842
  ) });
@@ -1769,8 +1935,8 @@ function elementsFor(ctx) {
1769
1935
  ...rest
1770
1936
  }) {
1771
1937
  const cited = citationForLink(labelOf(children), href, ctx);
1772
- if (cited) return /* @__PURE__ */ jsxRuntime.jsx(CitationMarker, { source: cited, className: ctx.markerClass });
1773
- const link = /* @__PURE__ */ jsxRuntime.jsx("a", { href, target: "_blank", rel: "noreferrer noopener", ...rest, children });
1938
+ if (cited) return /* @__PURE__ */ jsxRuntime.jsx(CitationMarker, { source: cited, className: ctx.markerClass, Link: ctx.Link });
1939
+ const link = ctx.Link && href ? /* @__PURE__ */ jsxRuntime.jsx(ctx.Link, { href, ...rest, children }) : /* @__PURE__ */ jsxRuntime.jsx("a", { href, target: "_blank", rel: "noreferrer noopener", ...rest, children });
1774
1940
  const source = sourceForUrl(href, ctx.sources);
1775
1941
  if (!href || !/^https?:\/\//i.test(href) || !source && !ctx.canResolve) return link;
1776
1942
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -1836,23 +2002,27 @@ function Markdown({
1836
2002
  sources,
1837
2003
  streaming,
1838
2004
  codeCopy,
2005
+ linkComponent,
1839
2006
  options
1840
2007
  }) {
1841
2008
  const fromMessage = useSources();
1842
2009
  const cn = useResolvedClassNames();
1843
2010
  const canResolve = Boolean(useLinkPreviewResolver());
1844
2011
  const fromProvider = useCodeCopy();
2012
+ const providerLink = useLinkComponent();
1845
2013
  const cited = sources ?? fromMessage;
1846
2014
  const copy = codeCopy ?? fromProvider ?? true;
2015
+ const Link = linkComponent ?? providerLink;
1847
2016
  const components = React7.useMemo(
1848
2017
  () => elementsFor({
1849
2018
  sources: cited,
1850
2019
  canResolve,
1851
2020
  markerClass: cn.citationMarker,
1852
2021
  copyClass: cn.copyButton,
1853
- codeCopy: copy
2022
+ codeCopy: copy,
2023
+ Link
1854
2024
  }),
1855
- [cited, canResolve, cn.citationMarker, cn.copyButton, copy]
2025
+ [cited, canResolve, cn.citationMarker, cn.copyButton, copy, Link]
1856
2026
  );
1857
2027
  const text = React7.useMemo(() => linkCitations(content, cited), [content, cited]);
1858
2028
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -1936,7 +2106,7 @@ function isNoiseEvent(e) {
1936
2106
  }
1937
2107
  var isMemoryEvent = (e) => eventName(e).includes("MemoryUpdate");
1938
2108
  var isMemoryCompleted = (e) => eventName(e).includes("MemoryUpdateCompleted");
1939
- var isReasoningEvent = (e) => chunkROFIOWGX_cjs.isReasoningStepEvent(e) || chunkROFIOWGX_cjs.isReasoningCompletedEvent(e) || eventName(e).includes("ReasoningStarted");
2109
+ var isReasoningEvent = (e) => chunk55HQJGLP_cjs.isReasoningStepEvent(e) || chunk55HQJGLP_cjs.isReasoningCompletedEvent(e) || eventName(e).includes("ReasoningStarted");
1940
2110
  function formatDuration(seconds) {
1941
2111
  return seconds < 10 ? `${seconds.toFixed(1)}s` : `${Math.round(seconds)}s`;
1942
2112
  }
@@ -1970,14 +2140,14 @@ function stepsFromEvents(message, { hideReasoning, hideTools }) {
1970
2140
  if (member) put(`member:${runId}`, { kind: "member", id: `member-${runId}`, member });
1971
2141
  continue;
1972
2142
  }
1973
- if (chunkROFIOWGX_cjs.isToolEvent(e)) {
2143
+ if (chunk55HQJGLP_cjs.isToolEvent(e)) {
1974
2144
  if (hideTools) continue;
1975
- for (const tool of chunkROFIOWGX_cjs.toolsFromEvent(e)) {
2145
+ for (const tool of chunk55HQJGLP_cjs.toolsFromEvent(e)) {
1976
2146
  const key = `tool:${tool.tool_call_id ?? tool.tool_name}`;
1977
2147
  const at = indexOf.get(key);
1978
2148
  const previous = at != null ? steps[at].tool : void 0;
1979
2149
  const merged = { ...previous, ...tool };
1980
- if (!chunkROFIOWGX_cjs.isToolCompletedEvent(e) && previous?.result != null) merged.result = previous.result;
2150
+ if (!chunk55HQJGLP_cjs.isToolCompletedEvent(e) && previous?.result != null) merged.result = previous.result;
1981
2151
  put(key, { kind: "tool", id: key, tool: merged });
1982
2152
  }
1983
2153
  continue;
@@ -1988,7 +2158,7 @@ function stepsFromEvents(message, { hideReasoning, hideTools }) {
1988
2158
  const at = indexOf.get(key);
1989
2159
  const previous = at != null ? steps[at].steps : [];
1990
2160
  const incoming = e.reasoning_steps ?? e.extra_data?.reasoning_steps ?? [];
1991
- const completed = chunkROFIOWGX_cjs.isReasoningCompletedEvent(e);
2161
+ const completed = chunk55HQJGLP_cjs.isReasoningCompletedEvent(e);
1992
2162
  put(key, {
1993
2163
  kind: "reasoning",
1994
2164
  id: key,
@@ -2023,7 +2193,7 @@ function stepsFromEvents(message, { hideReasoning, hideTools }) {
2023
2193
  label: "Run Continued",
2024
2194
  icon: "continued"
2025
2195
  });
2026
- } else if (chunkROFIOWGX_cjs.isCompletedEvent(e)) {
2196
+ } else if (chunk55HQJGLP_cjs.isCompletedEvent(e)) {
2027
2197
  put(`completed:${runKey}`, {
2028
2198
  kind: "status",
2029
2199
  id: `completed-${runKey}`,
@@ -2031,16 +2201,16 @@ function stepsFromEvents(message, { hideReasoning, hideTools }) {
2031
2201
  detail: durationOf(e),
2032
2202
  icon: "run"
2033
2203
  });
2034
- } else if (chunkROFIOWGX_cjs.isPausedEvent(e)) {
2204
+ } else if (chunk55HQJGLP_cjs.isPausedEvent(e)) {
2035
2205
  put(`paused:${runKey}`, { kind: "status", id: `paused-${runKey}`, label: "Run Paused", icon: "run" });
2036
- } else if (chunkROFIOWGX_cjs.isCancelledEvent(e)) {
2206
+ } else if (chunk55HQJGLP_cjs.isCancelledEvent(e)) {
2037
2207
  put(`cancelled:${runKey}`, {
2038
2208
  kind: "status",
2039
2209
  id: `cancelled-${runKey}`,
2040
2210
  label: "Run Cancelled",
2041
2211
  icon: "run"
2042
2212
  });
2043
- } else if (chunkROFIOWGX_cjs.isErrorEvent(e)) {
2213
+ } else if (chunk55HQJGLP_cjs.isErrorEvent(e)) {
2044
2214
  const detail = typeof e.content === "string" ? e.content : e.error;
2045
2215
  put(`error:${runKey}`, { kind: "status", id: `error-${runKey}`, label: detail || "Run Error", icon: "run" });
2046
2216
  }
@@ -2088,7 +2258,7 @@ function runDuration(message) {
2088
2258
  function liveActivity(message) {
2089
2259
  const events = message.events ?? [];
2090
2260
  for (let i = events.length - 1; i >= 0; i--) {
2091
- const label2 = chunkROFIOWGX_cjs.activityLabel(events[i]);
2261
+ const label2 = chunk55HQJGLP_cjs.activityLabel(events[i]);
2092
2262
  if (label2) return label2;
2093
2263
  }
2094
2264
  return message.activity ?? null;
@@ -2263,12 +2433,25 @@ function SourceCard({
2263
2433
  className
2264
2434
  }) {
2265
2435
  const cn = useResolvedClassNames();
2436
+ const Link = useLinkComponent();
2266
2437
  const { preview } = useLinkPreview(source.url, false);
2267
2438
  const body = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2268
- /* @__PURE__ */ jsxRuntime.jsx(Favicon, { url: preview?.favicon ?? source.url, kind: source.kind }),
2269
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "agno-source__title", children: preview?.title ?? source.title })
2439
+ /* @__PURE__ */ jsxRuntime.jsx(
2440
+ Favicon,
2441
+ {
2442
+ className: "agno-source__icon",
2443
+ url: preview?.favicon ?? source.url,
2444
+ kind: source.kind,
2445
+ size: 24
2446
+ }
2447
+ ),
2448
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "agno-source__title", children: preview?.title ?? source.title }),
2449
+ source.url && /* @__PURE__ */ jsxRuntime.jsx(LinkIcon, { className: "agno-source__link" })
2270
2450
  ] });
2271
2451
  const classes = cx("agno-source", `agno-source--${source.kind}`, cn.sourceCard, className);
2452
+ if (source.url && Link) {
2453
+ return /* @__PURE__ */ jsxRuntime.jsx(Link, { id: source.anchorId, className: classes, href: source.url, title: source.url, children: body });
2454
+ }
2272
2455
  return source.url ? /* @__PURE__ */ jsxRuntime.jsx(
2273
2456
  "a",
2274
2457
  {
@@ -2282,33 +2465,118 @@ function SourceCard({
2282
2465
  }
2283
2466
  ) : /* @__PURE__ */ jsxRuntime.jsx("div", { id: source.anchorId, className: classes, children: body });
2284
2467
  }
2468
+ var LIST_WIDTH = 240;
2469
+ function SourcesOverflow({ sources }) {
2470
+ const [open, setOpen] = React7.useState(false);
2471
+ const [anchor, setAnchor] = React7.useState(null);
2472
+ const timer = React7.useRef(null);
2473
+ const id = React7.useId();
2474
+ const placement = usePlacement(anchor, open, { width: LIST_WIDTH, align: "start" });
2475
+ const schedule = React7.useCallback((next) => {
2476
+ if (timer.current) clearTimeout(timer.current);
2477
+ timer.current = setTimeout(() => setOpen(next), next ? OPEN_DELAY : CLOSE_DELAY);
2478
+ }, []);
2479
+ React7.useEffect(
2480
+ () => () => {
2481
+ if (timer.current) clearTimeout(timer.current);
2482
+ },
2483
+ []
2484
+ );
2485
+ React7.useEffect(() => {
2486
+ if (!open) return;
2487
+ const onKey = (e) => {
2488
+ if (e.key === "Escape") setOpen(false);
2489
+ };
2490
+ document.addEventListener("keydown", onKey);
2491
+ return () => document.removeEventListener("keydown", onKey);
2492
+ }, [open]);
2493
+ const [mounted, setMounted] = React7.useState(false);
2494
+ React7.useEffect(() => setMounted(true), []);
2495
+ const light = anchor?.closest(".agno-light") ? "agno-light" : void 0;
2496
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2497
+ "span",
2498
+ {
2499
+ className: "agno-sources__overflow",
2500
+ ref: setAnchor,
2501
+ onMouseEnter: () => schedule(true),
2502
+ onMouseLeave: () => schedule(false),
2503
+ children: [
2504
+ /* @__PURE__ */ jsxRuntime.jsxs(
2505
+ "button",
2506
+ {
2507
+ type: "button",
2508
+ className: "agno-sources__more",
2509
+ "aria-label": `${sources.length} more sources`,
2510
+ "aria-expanded": open,
2511
+ "aria-controls": open ? id : void 0,
2512
+ onClick: () => setOpen((v) => !v),
2513
+ onFocus: () => setOpen(true),
2514
+ onBlur: () => schedule(false),
2515
+ children: [
2516
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "agno-sources__stack", "aria-hidden": true, children: sources.slice(0, 3).map((source) => /* @__PURE__ */ jsxRuntime.jsx(
2517
+ Favicon,
2518
+ {
2519
+ className: "agno-sources__stack-icon",
2520
+ url: source.url,
2521
+ kind: source.kind,
2522
+ size: 24
2523
+ },
2524
+ source.anchorId
2525
+ )) }),
2526
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "agno-sources__more-label", children: [
2527
+ "+",
2528
+ sources.length,
2529
+ " more"
2530
+ ] })
2531
+ ]
2532
+ }
2533
+ ),
2534
+ mounted && open && placement && reactDom.createPortal(
2535
+ /* @__PURE__ */ jsxRuntime.jsx(
2536
+ "div",
2537
+ {
2538
+ id,
2539
+ role: "group",
2540
+ "aria-label": "More sources",
2541
+ className: cx("agno-sources__list", `agno-sources__list--${placement.side}`, light),
2542
+ style: { top: placement.top, left: placement.left, width: LIST_WIDTH },
2543
+ onMouseEnter: () => schedule(true),
2544
+ onMouseLeave: () => schedule(false),
2545
+ onFocus: () => schedule(true),
2546
+ onBlur: () => schedule(false),
2547
+ children: sources.map((source) => /* @__PURE__ */ jsxRuntime.jsx(SourceCard, { source, className: "agno-source--row" }, source.anchorId))
2548
+ }
2549
+ ),
2550
+ document.body
2551
+ )
2552
+ ]
2553
+ }
2554
+ );
2555
+ }
2285
2556
  function Citations({
2286
2557
  references,
2287
2558
  citations,
2288
2559
  sources: given,
2289
- title = "Sources",
2290
- max = 4,
2560
+ title = "Sources used",
2561
+ max = 3,
2291
2562
  className,
2292
2563
  classNames
2293
2564
  }) {
2294
2565
  const cn = useResolvedClassNames(classNames);
2295
2566
  const uid = React7.useId();
2296
- const [expanded, setExpanded] = React7.useState(false);
2297
2567
  const sources = React7.useMemo(
2298
2568
  () => given ?? collectSources(references, citations, uid),
2299
2569
  [given, references, citations, uid]
2300
2570
  );
2301
2571
  if (sources.length === 0) return null;
2302
- const limit = max > 0 && !expanded ? max : sources.length;
2572
+ const limit = max > 0 ? max : sources.length;
2303
2573
  const visible = sources.slice(0, limit);
2304
- const hidden = sources.length - visible.length;
2574
+ const hidden = sources.slice(limit);
2305
2575
  return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: cx("agno-sources", cn.citations, className), "aria-label": title, children: [
2306
2576
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "agno-sources__head", children: title }),
2307
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "agno-sources__grid", children: visible.map((source) => /* @__PURE__ */ jsxRuntime.jsx(SourceCard, { source }, source.anchorId)) }),
2308
- hidden > 0 && /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "agno-sources__more", onClick: () => setExpanded(true), children: [
2309
- "Show ",
2310
- hidden,
2311
- " more"
2577
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "agno-sources__grid", children: [
2578
+ visible.map((source) => /* @__PURE__ */ jsxRuntime.jsx(SourceCard, { source }, source.anchorId)),
2579
+ hidden.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(SourcesOverflow, { sources: hidden })
2312
2580
  ] })
2313
2581
  ] });
2314
2582
  }
@@ -2524,6 +2792,7 @@ function ChatWindow({
2524
2792
  userInitials,
2525
2793
  emptyState,
2526
2794
  allowFiles,
2795
+ compactInput,
2527
2796
  disabled,
2528
2797
  renderMarkdown,
2529
2798
  showErrors,
@@ -2532,6 +2801,7 @@ function ChatWindow({
2532
2801
  hideFollowups,
2533
2802
  onFollowup,
2534
2803
  followupsTitle,
2804
+ renderMessage,
2535
2805
  header,
2536
2806
  composer,
2537
2807
  className,
@@ -2558,6 +2828,7 @@ function ChatWindow({
2558
2828
  renderMarkdown: markdown,
2559
2829
  classNames: cn,
2560
2830
  emptyState,
2831
+ renderMessage,
2561
2832
  footer: pausedMessage ? /* @__PURE__ */ jsxRuntime.jsx(
2562
2833
  HumanInput,
2563
2834
  {
@@ -2600,6 +2871,7 @@ function ChatWindow({
2600
2871
  disabled: disabled || chat.isPaused,
2601
2872
  placeholder,
2602
2873
  allowFiles,
2874
+ compact: compactInput,
2603
2875
  classNames: cn
2604
2876
  }
2605
2877
  )
@@ -2897,7 +3169,7 @@ function SessionList({
2897
3169
  }
2898
3170
  function AgnoChat(props) {
2899
3171
  const client = React7.useMemo(
2900
- () => props.client ?? new chunkROFIOWGX_cjs.AgnoClient({ baseUrl: props.baseUrl ?? "", headers: props.headers }),
3172
+ () => props.client ?? new chunk55HQJGLP_cjs.AgnoClient({ baseUrl: props.baseUrl ?? "", headers: props.headers }),
2901
3173
  [props.client, props.baseUrl, props.headers]
2902
3174
  );
2903
3175
  const [discovered, setDiscovered] = React7.useState(props.entities ?? []);
@@ -2988,6 +3260,7 @@ function AgnoChat(props) {
2988
3260
  chat,
2989
3261
  placeholder: props.placeholder,
2990
3262
  allowFiles: props.allowFiles ?? true,
3263
+ compactInput: props.compactInput,
2991
3264
  disabled: !entity,
2992
3265
  renderMarkdown: props.renderMarkdown,
2993
3266
  showErrors: props.showErrors,
@@ -3005,6 +3278,7 @@ function AgnoChat(props) {
3005
3278
  disabled: !entity || chat.isPaused,
3006
3279
  placeholder: props.placeholder,
3007
3280
  allowFiles: props.allowFiles ?? true,
3281
+ compact: props.compactInput,
3008
3282
  classNames: cn,
3009
3283
  trailing: showPicker ? /* @__PURE__ */ jsxRuntime.jsx(
3010
3284
  EntitySelector,
@@ -3033,6 +3307,7 @@ function AgnoChat(props) {
3033
3307
  renderMarkdown: props.renderMarkdown,
3034
3308
  resolveLinkPreview: props.resolveLinkPreview,
3035
3309
  codeCopy: props.codeCopy,
3310
+ linkComponent: props.linkComponent,
3036
3311
  as: false,
3037
3312
  children: root
3038
3313
  }
@@ -3199,7 +3474,7 @@ function fold(events) {
3199
3474
  last.created_at = e.created_at ?? last.created_at;
3200
3475
  continue;
3201
3476
  }
3202
- rows.push({ event: name, source, count: 1, created_at: e.created_at, detail: chunkROFIOWGX_cjs.activityLabel(e) });
3477
+ rows.push({ event: name, source, count: 1, created_at: e.created_at, detail: chunk55HQJGLP_cjs.activityLabel(e) });
3203
3478
  }
3204
3479
  return rows;
3205
3480
  }
@@ -3251,12 +3526,14 @@ exports.Favicon = Favicon;
3251
3526
  exports.FileAudio = FileAudio;
3252
3527
  exports.FileIcon = FileIcon;
3253
3528
  exports.FilePreview = FilePreview;
3529
+ exports.FileType = FileType;
3254
3530
  exports.FileVideo = FileVideo;
3255
3531
  exports.Followups = Followups;
3256
3532
  exports.Globe = Globe;
3257
3533
  exports.GridLoader = GridLoader;
3258
3534
  exports.HoverPreview = HoverPreview;
3259
3535
  exports.HumanInput = HumanInput;
3536
+ exports.LinkIcon = LinkIcon;
3260
3537
  exports.LinkPreviewCard = LinkPreviewCard;
3261
3538
  exports.Markdown = Markdown;
3262
3539
  exports.MemberResponses = MemberResponses;
@@ -3281,12 +3558,14 @@ exports.ToolCalls = ToolCalls;
3281
3558
  exports.Trash = Trash;
3282
3559
  exports.WorkflowSteps = WorkflowSteps;
3283
3560
  exports.Wrench = Wrench;
3561
+ exports.admitFiles = admitFiles;
3284
3562
  exports.behindTheScenesItems = behindTheScenesItems;
3285
3563
  exports.behindTheScenesLabel = behindTheScenesLabel;
3286
3564
  exports.collectSources = collectSources;
3287
3565
  exports.cx = cx;
3288
3566
  exports.displayUrl = displayUrl;
3289
3567
  exports.faviconUrl = faviconUrl;
3568
+ exports.fileAccepted = fileAccepted;
3290
3569
  exports.getProviderIcon = getProviderIcon;
3291
3570
  exports.hasBehindTheScenes = hasBehindTheScenes;
3292
3571
  exports.linkCitations = linkCitations;
@@ -3297,6 +3576,7 @@ exports.sourceHost = sourceHost;
3297
3576
  exports.sourcesFromMarkdown = sourcesFromMarkdown;
3298
3577
  exports.useAgnoChat = useAgnoChat;
3299
3578
  exports.useChatContext = useChatContext;
3579
+ exports.useLinkComponent = useLinkComponent;
3300
3580
  exports.useLinkPreview = useLinkPreview;
3301
3581
  exports.useOptionalChatContext = useOptionalChatContext;
3302
3582
  exports.useResolvedChat = useResolvedChat;
@@ -3304,5 +3584,5 @@ exports.useResolvedClassNames = useResolvedClassNames;
3304
3584
  exports.useSources = useSources;
3305
3585
  exports.withoutSourcesLine = withoutSourcesLine;
3306
3586
  exports.writeClipboard = writeClipboard;
3307
- //# sourceMappingURL=chunk-ERCKKOF4.cjs.map
3308
- //# sourceMappingURL=chunk-ERCKKOF4.cjs.map
3587
+ //# sourceMappingURL=chunk-JEPFGKHH.cjs.map
3588
+ //# sourceMappingURL=chunk-JEPFGKHH.cjs.map