@docyrus/ui-pro-ai-assistant 0.2.7 → 0.2.9

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.
@@ -9,10 +9,12 @@ export interface PromptFeatureFlags {
9
9
  files: boolean;
10
10
  }
11
11
  export interface AgentTriggerPromptProps {
12
+ agentId: string | null;
12
13
  capabilities: AgentCapabilities | null;
13
14
  models: Model[];
14
15
  suggestions: string[];
15
16
  placeholder?: string;
16
- onSubmit: (prompt: string, features: PromptFeatureFlags, modelId?: string) => void;
17
+ promptOptimizationChoice?: string | null;
18
+ onSubmit: (prompt: string, features: PromptFeatureFlags, modelId?: string, files?: File[]) => void;
17
19
  }
18
- export declare function AgentTriggerPrompt({ capabilities, models, suggestions, placeholder, onSubmit }: AgentTriggerPromptProps): import("react/jsx-runtime").JSX.Element;
20
+ export declare function AgentTriggerPrompt({ agentId, capabilities, models, suggestions, placeholder, promptOptimizationChoice, onSubmit }: AgentTriggerPromptProps): import("react/jsx-runtime").JSX.Element;
@@ -3,6 +3,6 @@ export interface AgentTriggerWidgetProps {
3
3
  agentIds: string[];
4
4
  className?: string;
5
5
  placeholder?: string;
6
- onSubmit?: (agentId: string, prompt: string, features: PromptFeatureFlags, modelId?: string) => void;
6
+ onSubmit?: (agentId: string, prompt: string, features: PromptFeatureFlags, modelId?: string, files?: File[]) => void;
7
7
  }
8
8
  export declare function AgentTriggerWidget({ agentIds, className, placeholder, onSubmit }: AgentTriggerWidgetProps): import("react/jsx-runtime").JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { type RefObject } from 'react';
2
2
  import { type DocyAssistantProps } from './types';
3
- export declare const DocyAssistant: ({ ref, isOpen, onClose, supportWebSearch, supportThinking, supportFiles, supportDocumentSearch, supportDeepResearch, supportMultiModels, supportWorkCanvas, apiEndpoint, title: titleProp, description: descriptionProp, placeholder: placeholderProp, logo, footerText: footerTextProp, variant, renderMode, enableSidebar, enableNavDropdown, enableVoice, enableMicrophone, tenantAiAgentId, onMessageSend, onVoiceStart, onVoiceEnd, className, defaultFullscreen, hideExpand, hideCloseButton, hideAgentSelector, hideBorder, showHeader, agentSelectorUrl, baseAgentSelectorUrl, onAgentChange, initialPrompt, ...props }: DocyAssistantProps & {
3
+ export declare const DocyAssistant: ({ ref, isOpen, onClose, supportWebSearch, supportThinking, supportFiles, supportDocumentSearch, supportDeepResearch, supportMultiModels, supportWorkCanvas, apiEndpoint, title: titleProp, description: descriptionProp, placeholder: placeholderProp, logo, footerText: footerTextProp, variant, renderMode, enableSidebar, enableNavDropdown, enableVoice, enableMicrophone, tenantAiAgentId, onMessageSend, onVoiceStart, onVoiceEnd, className, defaultFullscreen, hideExpand, hideCloseButton, hideAgentSelector, hideBorder, showHeader, agentSelectorUrl, baseAgentSelectorUrl, onAgentChange, initialPrompt, initialModelId, initialFeatures, initialFiles, ...props }: DocyAssistantProps & {
4
4
  ref?: RefObject<HTMLDivElement | null>;
5
5
  }) => import("react/jsx-runtime").JSX.Element;
@@ -9,6 +9,7 @@ export interface AgentTriggerData {
9
9
  capabilities: AgentCapabilities;
10
10
  models: Model[];
11
11
  standardSuggestions: string[];
12
+ promptOptimizationChoice: string | null;
12
13
  }
13
14
  export interface UseAgentsDataResult {
14
15
  agents: AgentTriggerData[];
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import { Input } from '@docyrus/ui-pro-shared/components/input';
9
9
  import { Tabs as Tabs$1, TabsList as TabsList$1, TabsTrigger as TabsTrigger$1, TabsContent as TabsContent$1 } from '@docyrus/ui-pro-shared/components/tabs';
10
10
  import { cn } from '@docyrus/ui-pro-shared/lib/utils';
11
11
  import { DefaultChatTransport, lastAssistantMessageIsCompleteWithToolCalls } from 'ai';
12
- import { PilcrowIcon, Heading1Icon, Heading2Icon, Heading3Icon, SquareIcon, ListIcon, ListOrderedIcon, ChevronDownIcon, Code2Icon, QuoteIcon, LightbulbIcon, Columns3Icon, GripVertical, FileUpIcon, TableIcon, ImageIcon, FilmIcon, AudioLinesIcon, TableOfContentsIcon, RadicalIcon, RectangleVerticalIcon, CalendarIcon, PlusIcon, FileCodeIcon, MinusIcon, ChevronRightIcon, ListTree, PenToolIcon, Link2Icon, Check, Copy, FilesIcon, Link, Text, ExternalLink, Unlink, Bold, Italic, Underline, Strikethrough, Code2, MoreHorizontal, ArrowLeftIcon, ArrowRightIcon, Minus, Plus, CircleArrowDown, Minimize2, Trash2, FileUp, CheckCircle2, FileText, Loader2, CornerDownLeftIcon, PencilLineIcon, MessageSquareTextIcon, MessagesSquareIcon, ArrowUpIcon, CheckIcon, CaptionsIcon, ZoomInIcon, CircleArrowDownIcon, MoveUpRightIcon, MoreHorizontalIcon, Eye, Pencil, PlusCircle, HelpCircle, Maximize2, X, Download, FileSpreadsheet, ChevronDown, Search, Globe, CheckCircle, FolderOpen, User, ArrowRight, MapPin, CalendarClock, List, RefreshCw, FilePlus, XIcon, CornerUpLeftIcon, AlbumIcon, FeatherIcon, ListMinusIcon, ListPlusIcon, ListEnd, Wand, LanguagesIcon, BadgeHelpIcon, PenLineIcon, SearchIcon, MusicIcon, CompassIcon, SmileIcon, LeafIcon, ClockIcon, AppleIcon, FlagIcon, StarIcon, DeleteIcon, AlignLeft, AlignCenter, AlignRight, RotateCcw, AlertTriangle, XCircle, AlertCircle, ArrowUpDown, ArrowDownToLine, PenLine, PencilIcon, TrashIcon, RefreshCwIcon, PaintRoller, MessageSquareText, ArrowLeft, ChevronLeft, Bot, ChevronRight, Brain, Lightbulb, BookOpen, PenTool, SlidersHorizontal, Mic, RefreshCcw, Code, Star, Trash, Edit, FolderInput, Archive, Sparkles, PanelLeft, MessageSquare, NotebookText, CirclePlus, MoreVertical, FileSearch, Microscope, Ruler, AudioLines, BrainCircuit, File as File$1, Plug, Inbox, Menu, LayoutDashboard, Table2, WandSparklesIcon, ArrowUpToLineIcon, BoldIcon, ItalicIcon, UnderlineIcon, StrikethroughIcon, HighlighterIcon, Undo2Icon, Redo2Icon, ArrowDownToLineIcon, AlignLeftIcon, AlignCenterIcon, AlignRightIcon, AlignJustifyIcon, ListOrdered, ListTodoIcon, ListCollapseIcon, Table, Grid3x3Icon, Combine, Ungroup, ArrowUp, ArrowDown, Trash2Icon, LinkIcon, WrapText, OutdentIcon, IndentIcon, EyeIcon, PenIcon } from 'lucide-react';
12
+ import { PilcrowIcon, Heading1Icon, Heading2Icon, Heading3Icon, SquareIcon, ListIcon, ListOrderedIcon, ChevronDownIcon, Code2Icon, QuoteIcon, LightbulbIcon, Columns3Icon, GripVertical, FileUpIcon, TableIcon, ImageIcon, FilmIcon, AudioLinesIcon, TableOfContentsIcon, RadicalIcon, RectangleVerticalIcon, CalendarIcon, PlusIcon, FileCodeIcon, MinusIcon, ChevronRightIcon, ListTree, PenToolIcon, Link2Icon, Check, Copy, FilesIcon, Link, Text, ExternalLink, Unlink, Bold, Italic, Underline, Strikethrough, Code2, MoreHorizontal, ArrowLeftIcon, ArrowRightIcon, Minus, Plus, CircleArrowDown, Minimize2, Trash2, FileUp, CheckCircle2, FileText, Loader2, CornerDownLeftIcon, PencilLineIcon, MessageSquareTextIcon, MessagesSquareIcon, ArrowUpIcon, CheckIcon, CaptionsIcon, ZoomInIcon, CircleArrowDownIcon, MoveUpRightIcon, MoreHorizontalIcon, Eye, Pencil, PlusCircle, HelpCircle, Maximize2, X, Download, FileSpreadsheet, ChevronDown, Search, Globe, CheckCircle, FolderOpen, User, ArrowRight, MapPin, CalendarClock, List, RefreshCw, FilePlus, XIcon, CornerUpLeftIcon, AlbumIcon, FeatherIcon, ListMinusIcon, ListPlusIcon, ListEnd, Wand, LanguagesIcon, BadgeHelpIcon, PenLineIcon, SearchIcon, MusicIcon, CompassIcon, SmileIcon, LeafIcon, ClockIcon, AppleIcon, FlagIcon, StarIcon, DeleteIcon, AlignLeft, AlignCenter, AlignRight, RotateCcw, AlertTriangle, XCircle, AlertCircle, ArrowUpDown, ArrowDownToLine, PenLine, PencilIcon, TrashIcon, RefreshCwIcon, PaintRoller, MessageSquareText, ArrowLeft, ChevronLeft, Bot, ChevronRight, Brain, Lightbulb, BookOpen, PenTool, SlidersHorizontal, Wand2, Mic, RefreshCcw, Code, Star, Trash, Edit, FolderInput, Archive, Sparkles, PanelLeft, MessageSquare, NotebookText, CirclePlus, MoreVertical, FileSearch, Microscope, Ruler, AudioLines, BrainCircuit, File as File$1, Plug, Inbox, Menu, LayoutDashboard, Table2, WandSparklesIcon, ArrowUpToLineIcon, BoldIcon, ItalicIcon, UnderlineIcon, StrikethroughIcon, HighlighterIcon, Undo2Icon, Redo2Icon, ArrowDownToLineIcon, AlignLeftIcon, AlignCenterIcon, AlignRightIcon, AlignJustifyIcon, ListOrdered, ListTodoIcon, ListCollapseIcon, Table, Grid3x3Icon, Combine, Ungroup, ArrowUp, ArrowDown, Trash2Icon, LinkIcon, WrapText, OutdentIcon, IndentIcon, EyeIcon, PenIcon } from 'lucide-react';
13
13
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
14
14
  import { AsyncTokenManager, RestApiClient } from '@docyrus/api-client';
15
15
  import { TooltipProvider, Tooltip as Tooltip$1, TooltipTrigger, TooltipContent } from '@docyrus/ui-pro-shared/components/tooltip';
@@ -2552,7 +2552,8 @@ function toAgentTriggerData(id, data) {
2552
2552
  description: agent.description ?? null,
2553
2553
  capabilities: extractCapabilities(agent),
2554
2554
  models: agent.models ?? [],
2555
- standardSuggestions: agent.standardSuggestions ?? agent.standard_suggestions ?? []
2555
+ standardSuggestions: agent.standardSuggestions ?? agent.standard_suggestions ?? [],
2556
+ promptOptimizationChoice: agent.promptOptimizationChoice ?? agent.prompt_optimization_choice ?? null
2556
2557
  };
2557
2558
  }
2558
2559
  function useAgentsData(agentIds) {
@@ -24677,6 +24678,9 @@ var DocyAssistant = ({
24677
24678
  baseAgentSelectorUrl = "/ai/agent-deployments/base",
24678
24679
  onAgentChange,
24679
24680
  initialPrompt,
24681
+ initialModelId,
24682
+ initialFeatures,
24683
+ initialFiles,
24680
24684
  ...props
24681
24685
  }) => {
24682
24686
  const config3 = useAssistantConfig();
@@ -24949,11 +24953,11 @@ var DocyAssistant = ({
24949
24953
  uiActions.setActiveTab(0);
24950
24954
  setMessages([]);
24951
24955
  };
24952
- const handleSendMessage = async (e, options3) => {
24956
+ const handleSendMessage = async (e, options3, overrideText) => {
24953
24957
  e?.preventDefault();
24954
- if (!input.trim()) return;
24958
+ const messageText = (overrideText ?? input).trim();
24959
+ if (!messageText) return;
24955
24960
  messageOptionsRef.current = options3;
24956
- const messageText = input.trim();
24957
24961
  let currentThreadId = selectedSessionIdRef.current;
24958
24962
  if (!currentThreadId) {
24959
24963
  const subject = messageText.substring(0, 100);
@@ -25024,9 +25028,42 @@ var DocyAssistant = ({
25024
25028
  if (!initialPrompt || initialPromptSentRef.current) return;
25025
25029
  initialPromptSentRef.current = true;
25026
25030
  setInput(initialPrompt);
25027
- setTimeout(() => {
25028
- handleSendMessage();
25029
- }, 300);
25031
+ const buildOptionsAndSend = async () => {
25032
+ const initialOptions = {};
25033
+ if (initialModelId) initialOptions.modelId = initialModelId;
25034
+ if (initialFeatures) {
25035
+ initialOptions.supportWebSearch = initialFeatures.webSearch;
25036
+ initialOptions.supportThinking = initialFeatures.thinking;
25037
+ initialOptions.supportDeepResearch = initialFeatures.deepResearch;
25038
+ initialOptions.supportDocumentSearch = initialFeatures.documentSearch;
25039
+ initialOptions.supportWorkCanvas = initialFeatures.workCanvas;
25040
+ initialOptions.supportFiles = initialFeatures.files;
25041
+ }
25042
+ if (initialFiles && initialFiles.length > 0) {
25043
+ const fileData = [];
25044
+ for (const file of initialFiles) {
25045
+ try {
25046
+ const url = await new Promise((resolve, reject) => {
25047
+ const reader = new FileReader();
25048
+ reader.onload = () => resolve(reader.result);
25049
+ reader.onerror = reject;
25050
+ reader.readAsDataURL(file);
25051
+ });
25052
+ fileData.push({ url, mediaType: file.type, filename: file.name });
25053
+ } catch {
25054
+ }
25055
+ }
25056
+ if (fileData.length > 0) {
25057
+ initialOptions.files = fileData;
25058
+ }
25059
+ }
25060
+ void handleSendMessage(
25061
+ void 0,
25062
+ Object.keys(initialOptions).length > 0 ? initialOptions : void 0,
25063
+ initialPrompt
25064
+ );
25065
+ };
25066
+ void buildOptionsAndSend();
25030
25067
  }, [initialPrompt]);
25031
25068
  const handleInputChange = useCallback((e) => {
25032
25069
  setInput(e.target.value);
@@ -25847,6 +25884,7 @@ var CAPABILITY_TOGGLES = [
25847
25884
  labelKey: "tools.file_upload"
25848
25885
  }
25849
25886
  ];
25887
+ var ACCEPTED_FILE_TYPES = ".pdf,.doc,.docx,.txt,.csv,.xlsx,.xls,.json,.xml,.png,.jpg,.jpeg,.gif,.webp";
25850
25888
  function ToggleSwitch({
25851
25889
  checked,
25852
25890
  onChange,
@@ -25889,13 +25927,16 @@ function useClickOutside(ref, open, onClose) {
25889
25927
  }, [ref, open, onClose]);
25890
25928
  }
25891
25929
  function AgentTriggerPrompt({
25930
+ agentId,
25892
25931
  capabilities,
25893
25932
  models,
25894
25933
  suggestions,
25895
25934
  placeholder,
25935
+ promptOptimizationChoice,
25896
25936
  onSubmit
25897
25937
  }) {
25898
25938
  const { t } = useAssistantTranslation();
25939
+ const apiClient = useApiClient();
25899
25940
  const [prompt, setPrompt] = useState("");
25900
25941
  const [selectedModel, setSelectedModel] = useState(
25901
25942
  models[0]
@@ -25915,9 +25956,24 @@ function AgentTriggerPrompt({
25915
25956
  const settingsRef = useRef(null);
25916
25957
  const modelRef = useRef(null);
25917
25958
  const reasoningRef = useRef(null);
25959
+ const [attachedFiles, setAttachedFiles] = useState([]);
25960
+ const fileInputRef = useRef(null);
25961
+ const [generatedSuggestions, setGeneratedSuggestions] = useState([]);
25962
+ const [isGeneratingSuggestions, setIsGeneratingSuggestions] = useState(false);
25963
+ const [isRecording, setIsRecording] = useState(false);
25964
+ const [isTranscribing, setIsTranscribing] = useState(false);
25965
+ const mediaRecorderRef = useRef(null);
25966
+ const audioChunksRef = useRef([]);
25967
+ const [isOptimizing, setIsOptimizing] = useState(false);
25968
+ const showOptimize = promptOptimizationChoice === "manual";
25918
25969
  useClickOutside(settingsRef, settingsOpen, () => setSettingsOpen(false));
25919
25970
  useClickOutside(modelRef, modelDropdownOpen, () => setModelDropdownOpen(false));
25920
25971
  useClickOutside(reasoningRef, reasoningDropdownOpen, () => setReasoningDropdownOpen(false));
25972
+ useEffect(() => {
25973
+ if (models.length > 0 && !models.find((m) => m.id === selectedModel?.id)) {
25974
+ setSelectedModel(models[0]);
25975
+ }
25976
+ }, [models, selectedModel?.id]);
25921
25977
  const hasThinking = capabilities?.supportThinking || selectedModel?.supportThinking;
25922
25978
  const reasoningLevels = useMemo(
25923
25979
  () => hasThinking ? selectedModel?.reasoningLevels ?? [] : [],
@@ -25934,16 +25990,130 @@ function AgentTriggerPrompt({
25934
25990
  const toggleFeature = useCallback((key) => {
25935
25991
  setFeatures((prev) => ({ ...prev, [key]: !prev[key] }));
25936
25992
  }, []);
25993
+ const allSuggestions = useMemo(() => {
25994
+ const set = /* @__PURE__ */ new Set([...suggestions, ...generatedSuggestions]);
25995
+ return [...set];
25996
+ }, [suggestions, generatedSuggestions]);
25997
+ const generateSuggestions = useCallback(async () => {
25998
+ if (!agentId || isGeneratingSuggestions) return;
25999
+ setIsGeneratingSuggestions(true);
26000
+ try {
26001
+ const res = await apiClient.post(`/ai/agents/${agentId}/suggestions`, {
26002
+ prompt: prompt || void 0
26003
+ });
26004
+ if (res.success && res.data) {
26005
+ const data = res.data;
26006
+ if (data.promptSuggestions?.length) {
26007
+ setGeneratedSuggestions(data.promptSuggestions);
26008
+ }
26009
+ }
26010
+ } catch {
26011
+ } finally {
26012
+ setIsGeneratingSuggestions(false);
26013
+ }
26014
+ }, [
26015
+ agentId,
26016
+ apiClient,
26017
+ isGeneratingSuggestions,
26018
+ prompt
26019
+ ]);
26020
+ const handleFileSelect = useCallback(() => {
26021
+ fileInputRef.current?.click();
26022
+ }, []);
26023
+ const handleFileChange = useCallback((e) => {
26024
+ const { files } = e.target;
26025
+ if (!files) return;
26026
+ setAttachedFiles((prev) => [...prev, ...Array.from(files)]);
26027
+ e.target.value = "";
26028
+ }, []);
26029
+ const removeFile = useCallback((index) => {
26030
+ setAttachedFiles((prev) => prev.filter((_, i) => i !== index));
26031
+ }, []);
26032
+ const startRecording = useCallback(async () => {
26033
+ try {
26034
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
26035
+ const mediaRecorder = new MediaRecorder(stream);
26036
+ audioChunksRef.current = [];
26037
+ mediaRecorder.ondataavailable = (e) => {
26038
+ if (e.data.size > 0) {
26039
+ audioChunksRef.current.push(e.data);
26040
+ }
26041
+ };
26042
+ mediaRecorder.onstop = async () => {
26043
+ stream.getTracks().forEach((track) => track.stop());
26044
+ const audioBlob = new Blob(audioChunksRef.current, { type: "audio/webm" });
26045
+ if (audioBlob.size === 0) return;
26046
+ setIsTranscribing(true);
26047
+ try {
26048
+ const formData = new FormData();
26049
+ formData.append("file", audioBlob, "recording.webm");
26050
+ const res = await apiClient.post("/ai/transcribe", formData);
26051
+ if (res.success && res.data) {
26052
+ const data = res.data;
26053
+ const transcript = data.transcription?.text || "";
26054
+ if (transcript) {
26055
+ setPrompt((prev) => prev ? `${prev} ${transcript}` : transcript);
26056
+ }
26057
+ }
26058
+ } catch {
26059
+ } finally {
26060
+ setIsTranscribing(false);
26061
+ }
26062
+ };
26063
+ mediaRecorderRef.current = mediaRecorder;
26064
+ mediaRecorder.start();
26065
+ setIsRecording(true);
26066
+ } catch {
26067
+ }
26068
+ }, [apiClient]);
26069
+ const stopRecording = useCallback(() => {
26070
+ if (mediaRecorderRef.current && mediaRecorderRef.current.state === "recording") {
26071
+ mediaRecorderRef.current.stop();
26072
+ setIsRecording(false);
26073
+ }
26074
+ }, []);
26075
+ const handleMicClick = useCallback(() => {
26076
+ if (isRecording) {
26077
+ stopRecording();
26078
+ } else {
26079
+ void startRecording();
26080
+ }
26081
+ }, [isRecording, startRecording, stopRecording]);
26082
+ const optimizePrompt = useCallback(async () => {
26083
+ if (!agentId || !prompt.trim() || isOptimizing) return;
26084
+ setIsOptimizing(true);
26085
+ try {
26086
+ const res = await apiClient.post(`/ai/agents/${agentId}/optimize`, {
26087
+ prompt: prompt.trim()
26088
+ });
26089
+ if (res.success && res.data) {
26090
+ const data = res.data;
26091
+ if (data.optimizedPrompt) {
26092
+ setPrompt(data.optimizedPrompt);
26093
+ }
26094
+ }
26095
+ } catch {
26096
+ } finally {
26097
+ setIsOptimizing(false);
26098
+ }
26099
+ }, [
26100
+ agentId,
26101
+ apiClient,
26102
+ isOptimizing,
26103
+ prompt
26104
+ ]);
25937
26105
  const handleSubmit = useCallback(() => {
25938
26106
  const trimmed = prompt.trim();
25939
26107
  if (!trimmed) return;
25940
- onSubmit(trimmed, features, selectedModel?.id);
26108
+ onSubmit(trimmed, features, selectedModel?.id, attachedFiles.length > 0 ? attachedFiles : void 0);
25941
26109
  setPrompt("");
26110
+ setAttachedFiles([]);
25942
26111
  }, [
25943
26112
  prompt,
25944
26113
  features,
25945
26114
  selectedModel,
25946
- onSubmit
26115
+ onSubmit,
26116
+ attachedFiles
25947
26117
  ]);
25948
26118
  const handleKeyDown = useCallback(
25949
26119
  (e) => {
@@ -25966,17 +26136,32 @@ function AgentTriggerPrompt({
25966
26136
  return true;
25967
26137
  }) : [];
25968
26138
  return /* @__PURE__ */ jsxs("div", { className: "mt-4 mb-1 w-full max-w-[54rem]", children: [
25969
- suggestions.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center gap-2", children: [
25970
- /* @__PURE__ */ jsx(
26139
+ /* @__PURE__ */ jsx(
26140
+ "input",
26141
+ {
26142
+ ref: fileInputRef,
26143
+ type: "file",
26144
+ multiple: true,
26145
+ accept: ACCEPTED_FILE_TYPES,
26146
+ className: "hidden",
26147
+ onChange: handleFileChange
26148
+ }
26149
+ ),
26150
+ agentId && /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center gap-2", children: [
26151
+ isGeneratingSuggestions ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-xs font-medium text-muted-foreground", children: [
26152
+ /* @__PURE__ */ jsx(Loader2, { className: "size-4 animate-spin" }),
26153
+ /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap", children: "Generating suggestions..." })
26154
+ ] }) : /* @__PURE__ */ jsx(
25971
26155
  "button",
25972
26156
  {
25973
26157
  type: "button",
25974
- title: t("common.generate_suggestions") || "Generate Suggestions",
26158
+ title: "Generate Suggestions",
26159
+ onClick: generateSuggestions,
25975
26160
  className: "flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground transition-colors hover:bg-muted/80 hover:text-foreground",
25976
26161
  children: /* @__PURE__ */ jsx(Plus, { className: "size-4" })
25977
26162
  }
25978
26163
  ),
25979
- /* @__PURE__ */ jsx("div", { className: "suggestions-container flex items-center gap-2 overflow-x-auto", children: suggestions.map((s) => /* @__PURE__ */ jsx(
26164
+ allSuggestions.length > 0 && /* @__PURE__ */ jsx("div", { className: "suggestions-container flex items-center gap-2 overflow-x-auto", children: allSuggestions.map((s) => /* @__PURE__ */ jsx(
25980
26165
  "button",
25981
26166
  {
25982
26167
  type: "button",
@@ -26000,6 +26185,26 @@ function AgentTriggerPrompt({
26000
26185
  rows: 2
26001
26186
  }
26002
26187
  ),
26188
+ attachedFiles.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2 px-3 pb-2", children: attachedFiles.map((file, index) => /* @__PURE__ */ jsxs(
26189
+ "div",
26190
+ {
26191
+ className: "flex items-center gap-1.5 rounded-md border border-border bg-background px-2 py-1 text-xs text-foreground",
26192
+ children: [
26193
+ /* @__PURE__ */ jsx(FileUp, { className: "size-3.5 text-muted-foreground" }),
26194
+ /* @__PURE__ */ jsx("span", { className: "max-w-32 truncate", children: file.name }),
26195
+ /* @__PURE__ */ jsx(
26196
+ "button",
26197
+ {
26198
+ type: "button",
26199
+ onClick: () => removeFile(index),
26200
+ className: "ml-0.5 text-muted-foreground transition-colors hover:text-foreground",
26201
+ children: /* @__PURE__ */ jsx(X, { className: "size-3" })
26202
+ }
26203
+ )
26204
+ ]
26205
+ },
26206
+ `${file.name}-${index}`
26207
+ )) }),
26003
26208
  /* @__PURE__ */ jsxs("div", { className: "flex h-10 items-center justify-between px-2", children: [
26004
26209
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
26005
26210
  capabilities?.supportFiles && /* @__PURE__ */ jsx(
@@ -26007,6 +26212,7 @@ function AgentTriggerPrompt({
26007
26212
  {
26008
26213
  type: "button",
26009
26214
  title: t("tools.file_upload"),
26215
+ onClick: handleFileSelect,
26010
26216
  className: "flex size-7 items-center justify-center rounded text-muted-foreground transition-colors hover:text-foreground",
26011
26217
  children: /* @__PURE__ */ jsx(Plus, { className: "size-5" })
26012
26218
  }
@@ -26120,14 +26326,34 @@ function AgentTriggerPrompt({
26120
26326
  )) })
26121
26327
  ] })
26122
26328
  ] }),
26123
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsx(
26124
- "button",
26125
- {
26126
- type: "button",
26127
- className: "flex size-7 items-center justify-center rounded text-muted-foreground transition-colors hover:text-foreground",
26128
- children: /* @__PURE__ */ jsx(Mic, { className: "size-5" })
26129
- }
26130
- ) })
26329
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
26330
+ showOptimize && /* @__PURE__ */ jsx(
26331
+ "button",
26332
+ {
26333
+ type: "button",
26334
+ title: t("common.optimize_prompt") || "Optimize Prompt",
26335
+ disabled: isOptimizing || !prompt.trim(),
26336
+ onClick: () => void optimizePrompt(),
26337
+ className: "flex size-7 items-center justify-center rounded text-muted-foreground transition-colors hover:text-foreground disabled:opacity-50",
26338
+ children: isOptimizing ? /* @__PURE__ */ jsx(Loader2, { className: "size-5 animate-spin" }) : /* @__PURE__ */ jsx(Wand2, { className: "size-5" })
26339
+ }
26340
+ ),
26341
+ /* @__PURE__ */ jsx(
26342
+ "button",
26343
+ {
26344
+ type: "button",
26345
+ title: isRecording ? t("common.stop_recording") || "Stop Recording" : t("common.start_recording") || "Start Recording",
26346
+ disabled: isTranscribing,
26347
+ onClick: handleMicClick,
26348
+ className: cn(
26349
+ "flex size-7 items-center justify-center rounded transition-colors",
26350
+ isRecording ? "text-red-500 animate-pulse hover:text-red-600" : "text-muted-foreground hover:text-foreground",
26351
+ isTranscribing && "opacity-50"
26352
+ ),
26353
+ children: isTranscribing ? /* @__PURE__ */ jsx(Loader2, { className: "size-5 animate-spin" }) : /* @__PURE__ */ jsx(Mic, { className: "size-5" })
26354
+ }
26355
+ )
26356
+ ] })
26131
26357
  ] })
26132
26358
  ] })
26133
26359
  ] });
@@ -26158,9 +26384,9 @@ function AgentTriggerWidget({
26158
26384
  [agents.length]
26159
26385
  );
26160
26386
  const handlePromptSubmit = useCallback(
26161
- (prompt, features, modelId) => {
26387
+ (prompt, features, modelId, files) => {
26162
26388
  if (!currentAgent) return;
26163
- onSubmit?.(currentAgent.id, prompt, features, modelId);
26389
+ onSubmit?.(currentAgent.id, prompt, features, modelId, files);
26164
26390
  },
26165
26391
  [currentAgent, onSubmit]
26166
26392
  );
@@ -26244,9 +26470,11 @@ function AgentTriggerWidget({
26244
26470
  /* @__PURE__ */ jsx("div", { className: "flex h-fit w-full grow items-end justify-center px-6 pb-6", children: /* @__PURE__ */ jsx(
26245
26471
  AgentTriggerPrompt,
26246
26472
  {
26473
+ agentId: currentAgent?.id ?? null,
26247
26474
  capabilities: currentAgent?.capabilities ?? null,
26248
26475
  models: currentAgent?.models ?? [],
26249
26476
  suggestions: currentAgent?.standardSuggestions ?? [],
26477
+ promptOptimizationChoice: currentAgent?.promptOptimizationChoice,
26250
26478
  placeholder,
26251
26479
  onSubmit: handlePromptSubmit
26252
26480
  }