@docyrus/ui-pro-ai-assistant 0.2.8 → 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();
@@ -25024,7 +25028,42 @@ var DocyAssistant = ({
25024
25028
  if (!initialPrompt || initialPromptSentRef.current) return;
25025
25029
  initialPromptSentRef.current = true;
25026
25030
  setInput(initialPrompt);
25027
- void handleSendMessage(void 0, void 0, initialPrompt);
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();
25028
25067
  }, [initialPrompt]);
25029
25068
  const handleInputChange = useCallback((e) => {
25030
25069
  setInput(e.target.value);
@@ -25845,6 +25884,7 @@ var CAPABILITY_TOGGLES = [
25845
25884
  labelKey: "tools.file_upload"
25846
25885
  }
25847
25886
  ];
25887
+ var ACCEPTED_FILE_TYPES = ".pdf,.doc,.docx,.txt,.csv,.xlsx,.xls,.json,.xml,.png,.jpg,.jpeg,.gif,.webp";
25848
25888
  function ToggleSwitch({
25849
25889
  checked,
25850
25890
  onChange,
@@ -25887,13 +25927,16 @@ function useClickOutside(ref, open, onClose) {
25887
25927
  }, [ref, open, onClose]);
25888
25928
  }
25889
25929
  function AgentTriggerPrompt({
25930
+ agentId,
25890
25931
  capabilities,
25891
25932
  models,
25892
25933
  suggestions,
25893
25934
  placeholder,
25935
+ promptOptimizationChoice,
25894
25936
  onSubmit
25895
25937
  }) {
25896
25938
  const { t } = useAssistantTranslation();
25939
+ const apiClient = useApiClient();
25897
25940
  const [prompt, setPrompt] = useState("");
25898
25941
  const [selectedModel, setSelectedModel] = useState(
25899
25942
  models[0]
@@ -25913,9 +25956,24 @@ function AgentTriggerPrompt({
25913
25956
  const settingsRef = useRef(null);
25914
25957
  const modelRef = useRef(null);
25915
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";
25916
25969
  useClickOutside(settingsRef, settingsOpen, () => setSettingsOpen(false));
25917
25970
  useClickOutside(modelRef, modelDropdownOpen, () => setModelDropdownOpen(false));
25918
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]);
25919
25977
  const hasThinking = capabilities?.supportThinking || selectedModel?.supportThinking;
25920
25978
  const reasoningLevels = useMemo(
25921
25979
  () => hasThinking ? selectedModel?.reasoningLevels ?? [] : [],
@@ -25932,16 +25990,130 @@ function AgentTriggerPrompt({
25932
25990
  const toggleFeature = useCallback((key) => {
25933
25991
  setFeatures((prev) => ({ ...prev, [key]: !prev[key] }));
25934
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
+ ]);
25935
26105
  const handleSubmit = useCallback(() => {
25936
26106
  const trimmed = prompt.trim();
25937
26107
  if (!trimmed) return;
25938
- onSubmit(trimmed, features, selectedModel?.id);
26108
+ onSubmit(trimmed, features, selectedModel?.id, attachedFiles.length > 0 ? attachedFiles : void 0);
25939
26109
  setPrompt("");
26110
+ setAttachedFiles([]);
25940
26111
  }, [
25941
26112
  prompt,
25942
26113
  features,
25943
26114
  selectedModel,
25944
- onSubmit
26115
+ onSubmit,
26116
+ attachedFiles
25945
26117
  ]);
25946
26118
  const handleKeyDown = useCallback(
25947
26119
  (e) => {
@@ -25964,17 +26136,32 @@ function AgentTriggerPrompt({
25964
26136
  return true;
25965
26137
  }) : [];
25966
26138
  return /* @__PURE__ */ jsxs("div", { className: "mt-4 mb-1 w-full max-w-[54rem]", children: [
25967
- suggestions.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center gap-2", children: [
25968
- /* @__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(
25969
26155
  "button",
25970
26156
  {
25971
26157
  type: "button",
25972
- title: t("common.generate_suggestions") || "Generate Suggestions",
26158
+ title: "Generate Suggestions",
26159
+ onClick: generateSuggestions,
25973
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",
25974
26161
  children: /* @__PURE__ */ jsx(Plus, { className: "size-4" })
25975
26162
  }
25976
26163
  ),
25977
- /* @__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(
25978
26165
  "button",
25979
26166
  {
25980
26167
  type: "button",
@@ -25998,6 +26185,26 @@ function AgentTriggerPrompt({
25998
26185
  rows: 2
25999
26186
  }
26000
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
+ )) }),
26001
26208
  /* @__PURE__ */ jsxs("div", { className: "flex h-10 items-center justify-between px-2", children: [
26002
26209
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
26003
26210
  capabilities?.supportFiles && /* @__PURE__ */ jsx(
@@ -26005,6 +26212,7 @@ function AgentTriggerPrompt({
26005
26212
  {
26006
26213
  type: "button",
26007
26214
  title: t("tools.file_upload"),
26215
+ onClick: handleFileSelect,
26008
26216
  className: "flex size-7 items-center justify-center rounded text-muted-foreground transition-colors hover:text-foreground",
26009
26217
  children: /* @__PURE__ */ jsx(Plus, { className: "size-5" })
26010
26218
  }
@@ -26118,14 +26326,34 @@ function AgentTriggerPrompt({
26118
26326
  )) })
26119
26327
  ] })
26120
26328
  ] }),
26121
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsx(
26122
- "button",
26123
- {
26124
- type: "button",
26125
- className: "flex size-7 items-center justify-center rounded text-muted-foreground transition-colors hover:text-foreground",
26126
- children: /* @__PURE__ */ jsx(Mic, { className: "size-5" })
26127
- }
26128
- ) })
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
+ ] })
26129
26357
  ] })
26130
26358
  ] })
26131
26359
  ] });
@@ -26156,9 +26384,9 @@ function AgentTriggerWidget({
26156
26384
  [agents.length]
26157
26385
  );
26158
26386
  const handlePromptSubmit = useCallback(
26159
- (prompt, features, modelId) => {
26387
+ (prompt, features, modelId, files) => {
26160
26388
  if (!currentAgent) return;
26161
- onSubmit?.(currentAgent.id, prompt, features, modelId);
26389
+ onSubmit?.(currentAgent.id, prompt, features, modelId, files);
26162
26390
  },
26163
26391
  [currentAgent, onSubmit]
26164
26392
  );
@@ -26242,9 +26470,11 @@ function AgentTriggerWidget({
26242
26470
  /* @__PURE__ */ jsx("div", { className: "flex h-fit w-full grow items-end justify-center px-6 pb-6", children: /* @__PURE__ */ jsx(
26243
26471
  AgentTriggerPrompt,
26244
26472
  {
26473
+ agentId: currentAgent?.id ?? null,
26245
26474
  capabilities: currentAgent?.capabilities ?? null,
26246
26475
  models: currentAgent?.models ?? [],
26247
26476
  suggestions: currentAgent?.standardSuggestions ?? [],
26477
+ promptOptimizationChoice: currentAgent?.promptOptimizationChoice,
26248
26478
  placeholder,
26249
26479
  onSubmit: handlePromptSubmit
26250
26480
  }