@burdenoff/microfe-vibecontrols 2026.527.8 → 2026.527.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.
@@ -11,7 +11,8 @@ import { schedulePrompt as te } from "../../services/schedulerApi.js";
11
11
  import { AutonomySelector as ne } from "./controls/AutonomySelector.js";
12
12
  import { McpServerSelector as re } from "./controls/McpServerSelector.js";
13
13
  import { VoiceToggle as ie } from "./controls/VoiceToggle.js";
14
- import { FileAttachButton as ae, createDropHandlers as oe } from "./controls/FileAttachButton.js";
14
+ import { FileAttachButton as ae } from "./controls/FileAttachButton.js";
15
+ import { createDropHandlers as oe } from "./controls/createDropHandlers.js";
15
16
  import { ContextLevelToggle as se } from "./controls/ContextLevelToggle.js";
16
17
  import { useCallback as c, useEffect as l, useMemo as u, useRef as d, useState as f } from "react";
17
18
  import { ArrowUp as ce, ChevronDown as le, Clock as ue, Square as de, X as fe } from "lucide-react";
@@ -1 +1 @@
1
- {"version":3,"file":"AgentManagerInputArea.js","names":[],"sources":["../../../src/components/agent-manager/AgentManagerInputArea.tsx"],"sourcesContent":["/**\n * Rich input area for the Agent Manager chat.\n *\n * Sits at the bottom of the chat pane. Contains a toolbar row with\n * control selectors and a resizable textarea with send/cancel buttons.\n * Supports file attachment preview, keyboard shortcuts, and slash\n * commands for quick actions.\n */\n\nimport { useState, useRef, useCallback, useEffect, useMemo, type KeyboardEvent } from 'react';\nimport { ArrowUp, Square, X, ChevronDown, Clock } from 'lucide-react';\nimport { useAgentManagerStore } from '@/store/agentManagerStore';\nimport { useVoiceMode } from '@/hooks/useVoiceMode';\nimport { useCachedInitialData } from '@/hooks/useCachedInitialData';\nimport { fetchProviders, type AIProvider } from '@/services/aiApi';\nimport { useActiveAgentProfile } from '@/hooks/useActiveAgentProfile';\nimport { schedulePrompt } from '@/services/schedulerApi';\nimport { ModelSelector } from './controls/ModelSelector';\nimport { SdkSelector } from './controls/SdkSelector';\nimport { AutonomySelector } from './controls/AutonomySelector';\nimport { McpServerSelector } from './controls/McpServerSelector';\nimport { VoiceToggle } from './controls/VoiceToggle';\nimport { FileAttachButton, createDropHandlers } from './controls/FileAttachButton';\nimport { ContextLevelToggle } from './controls/ContextLevelToggle';\nimport { GENERIC_MODEL_FALLBACK, resolveProviderDefaultModel } from './modelDefaults';\nimport type { AgentSdkType, McpServer, ProviderMode } from '@/types/agentManager';\nimport { useTr } from '../../shared/hooks/useTr';\n\n/* ────────────────────────────────────────────────────────────────────── */\n/* Slash commands */\n/* ────────────────────────────────────────────────────────────────────── */\n\ninterface SlashCommand {\n command: string;\n description: string;\n args?: string;\n}\n\nconst SLASH_COMMANDS: SlashCommand[] = [\n { command: '/new', description: 'Create new session' },\n { command: '/rename', description: 'Rename current session', args: '<name>' },\n { command: '/model', description: 'Switch model', args: '<model-name>' },\n {\n command: '/sdk',\n description: 'Switch SDK',\n args: '<claude|codex|gemini|opencode|openai-compat>',\n },\n { command: '/mode', description: 'Switch mode', args: '<sdk|cli>' },\n { command: '/export', description: 'Export conversation', args: '[json|md]' },\n { command: '/clear', description: 'Clear conversation' },\n { command: '/help', description: 'Show available commands' },\n];\n\nconst VALID_SDKS: AgentSdkType[] = [\n 'claude',\n 'codex',\n 'gemini',\n 'opencode',\n 'cursor',\n 'openrouter',\n 'minimax',\n 'ollama',\n 'openai-compat',\n 'goose',\n 'amp',\n 'copilot',\n 'crush',\n 'pi',\n 'aider',\n 'plandex',\n];\nconst VALID_MODES: ProviderMode[] = ['sdk', 'cli'];\n\n/* ────────────────────────────────────────────────────────────────────── */\n/* Component */\n/* ────────────────────────────────────────────────────────────────────── */\n\ninterface AgentManagerInputAreaProps {\n agentId: string;\n sessionId: string;\n onSend: (text: string, attachments?: File[]) => void;\n onCancel?: () => void;\n mcpServers?: McpServer[];\n agentTunnelUrl?: string;\n agentApiKey?: string;\n}\n\nexport function AgentManagerInputArea({\n agentId,\n sessionId,\n onSend,\n onCancel,\n mcpServers = [],\n agentTunnelUrl,\n agentApiKey,\n}: AgentManagerInputAreaProps) {\n const [text, setText] = useState('');\n const [pendingFiles, setPendingFiles] = useState<File[]>([]);\n const [showSlashMenu, setShowSlashMenu] = useState(false);\n const [slashFilter, setSlashFilter] = useState('');\n const [showScheduleMenu, setShowScheduleMenu] = useState(false);\n const [showSchedulePopup, setShowSchedulePopup] = useState(false);\n const [scheduleDateTime, setScheduleDateTime] = useState('');\n const [providers, setProviders] = useState<AIProvider[]>([]);\n const tr = useTr();\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const scheduleMenuRef = useRef<HTMLDivElement>(null);\n\n // Auto-focus textarea when session is opened or switched\n useEffect(() => {\n textareaRef.current?.focus({ preventScroll: true });\n }, []);\n\n const sessionState = useAgentManagerStore((s) => s.sessionStates[sessionId]);\n const setSessionModel = useAgentManagerStore((s) => s.setSessionModel);\n const setSessionSdk = useAgentManagerStore((s) => s.setSessionSdk);\n const setSessionMode = useAgentManagerStore((s) => s.setSessionMode);\n const setSessionPermissionMode = useAgentManagerStore((s) => s.setSessionPermissionMode);\n const toggleVoice = useAgentManagerStore((s) => s.toggleVoice);\n const toggleThinking = useAgentManagerStore((s) => s.toggleThinking);\n const setSessionContextLevel = useAgentManagerStore((s) => s.setSessionContextLevel);\n const setSessionVibe = useAgentManagerStore((s) => s.setSessionVibe);\n const setSessionRootPath = useAgentManagerStore((s) => s.setSessionRootPath);\n const openSession = useAgentManagerStore((s) => s.openSession);\n const addMessage = useAgentManagerStore((s) => s.addMessage);\n\n const { vibes, agents } = useCachedInitialData();\n const activeAgent = useMemo(\n () => agents.find((a) => a.id === agentId) ?? null,\n [agents, agentId]\n );\n const { active: activeProfile } = useActiveAgentProfile(activeAgent?.id ?? null);\n const agentRef = useMemo(\n () => ({ id: agentId, profile: activeProfile }),\n [agentId, activeProfile]\n );\n\n const { isListening, transcript, startListening, stopListening } = useVoiceMode();\n\n const isStreaming = sessionState?.status === 'streaming';\n const canSend = text.trim().length > 0 && !isStreaming;\n\n // Append voice transcript to textarea\n useEffect(() => {\n if (transcript && isListening) {\n setText((prev) => prev + (prev ? ' ' : '') + transcript);\n }\n }, [transcript, isListening]);\n\n useEffect(() => {\n let cancelled = false;\n void fetchProviders(agentRef)\n .then((items) => {\n if (!cancelled) setProviders(items);\n })\n .catch(() => {\n if (!cancelled) setProviders([]);\n });\n\n return () => {\n cancelled = true;\n };\n }, [agentRef]);\n\n // ── Slash command filtering ──\n useEffect(() => {\n if (text.startsWith('/') && !text.includes(' ')) {\n setShowSlashMenu(true);\n setSlashFilter(text.slice(1));\n } else {\n setShowSlashMenu(false);\n }\n }, [text]);\n\n const filteredCommands = useMemo(\n () =>\n SLASH_COMMANDS.filter((cmd) =>\n cmd.command.toLowerCase().includes(`/${slashFilter.toLowerCase()}`)\n ),\n [slashFilter]\n );\n\n // Auto-resize textarea\n useEffect(() => {\n const el = textareaRef.current;\n if (!el) return;\n el.style.height = 'auto';\n const maxRows = 10;\n const lineHeight = 20;\n const maxHeight = maxRows * lineHeight;\n el.style.height = `${Math.min(el.scrollHeight, maxHeight)}px`;\n }, [text]);\n\n // Close schedule menu on outside click\n useEffect(() => {\n if (!showScheduleMenu && !showSchedulePopup) return;\n const handler = (e: MouseEvent) => {\n if (scheduleMenuRef.current && !scheduleMenuRef.current.contains(e.target as Node)) {\n setShowScheduleMenu(false);\n setShowSchedulePopup(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [showScheduleMenu, showSchedulePopup]);\n\n const addSystemMessage = useCallback(\n (content: string) => {\n addMessage(sessionId, {\n id: `sys-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,\n role: 'system',\n content,\n timestamp: new Date().toISOString(),\n });\n },\n [addMessage, sessionId]\n );\n\n const handleScheduleSend = useCallback(async () => {\n if (!text.trim() || !scheduleDateTime || !agentTunnelUrl || !agentApiKey) return;\n try {\n const result = await schedulePrompt({\n sessionId,\n agentTunnelUrl,\n agentApiKey,\n prompt: text.trim(),\n scheduledAt: new Date(scheduleDateTime).toISOString(),\n });\n addSystemMessage(\n `Prompt scheduled for ${new Date(result.scheduledAt).toLocaleString()} (Job: ${result.jobId.slice(0, 8)})`\n );\n setText('');\n setScheduleDateTime('');\n setShowSchedulePopup(false);\n setShowScheduleMenu(false);\n } catch (err) {\n addSystemMessage(\n `Failed to schedule: ${err instanceof Error ? err.message : 'Unknown error'}`\n );\n }\n }, [text, scheduleDateTime, agentTunnelUrl, agentApiKey, sessionId, addSystemMessage]);\n\n const executeSlashCommand = useCallback(\n (input: string) => {\n const parts = input.trim().split(/\\s+/);\n const cmd = parts[0].toLowerCase();\n const arg = parts.slice(1).join(' ');\n\n switch (cmd) {\n case '/new': {\n const newId = `session-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n openSession(newId);\n break;\n }\n case '/rename':\n if (arg) {\n addSystemMessage(`Session renamed to \"${arg}\".`);\n } else {\n addSystemMessage('Usage: /rename <name>');\n }\n break;\n case '/model':\n if (arg) {\n setSessionModel(sessionId, arg);\n addSystemMessage(`Model switched to \"${arg}\".`);\n } else {\n addSystemMessage('Usage: /model <model-name>');\n }\n break;\n case '/sdk':\n if (arg && VALID_SDKS.includes(arg as AgentSdkType)) {\n const nextSdk = arg as AgentSdkType;\n setSessionSdk(sessionId, nextSdk);\n void resolveProviderDefaultModel(\n agentRef,\n nextSdk,\n sessionState?.model ?? GENERIC_MODEL_FALLBACK\n )\n .then((nextModel) => setSessionModel(sessionId, nextModel))\n .catch(() =>\n setSessionModel(sessionId, sessionState?.model ?? GENERIC_MODEL_FALLBACK)\n );\n addSystemMessage(`SDK switched to \"${arg}\".`);\n } else {\n addSystemMessage(`Usage: /sdk <${VALID_SDKS.join('|')}>`);\n }\n break;\n case '/mode':\n if (arg && VALID_MODES.includes(arg as ProviderMode)) {\n setSessionMode(sessionId, arg as ProviderMode);\n addSystemMessage(`Mode switched to \"${arg}\".`);\n } else {\n addSystemMessage(`Usage: /mode <${VALID_MODES.join('|')}>`);\n }\n break;\n case '/export': {\n const format = arg === 'md' ? 'md' : 'json';\n const messages = sessionState?.messages ?? [];\n const exported =\n format === 'json'\n ? JSON.stringify(messages, null, 2)\n : messages\n .map((m) => `**${m.role}** (${m.timestamp ?? ''}):\\n${m.content ?? ''}`)\n .join('\\n\\n---\\n\\n');\n const blob = new Blob([exported], {\n type: format === 'json' ? 'application/json' : 'text/markdown',\n });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `conversation-${sessionId}.${format}`;\n a.click();\n URL.revokeObjectURL(url);\n addSystemMessage(`Conversation exported as ${format}.`);\n break;\n }\n case '/clear':\n addSystemMessage('Conversation cleared.');\n break;\n case '/help': {\n const helpText = SLASH_COMMANDS.map(\n (c) => ` ${c.command}${c.args ? ' ' + c.args : ''} - ${c.description}`\n ).join('\\n');\n addSystemMessage(`Available commands:\\n${helpText}`);\n break;\n }\n default:\n addSystemMessage(`Unknown command: ${cmd}. Type /help for available commands.`);\n }\n },\n [\n sessionId,\n sessionState?.messages,\n sessionState?.model,\n openSession,\n setSessionModel,\n setSessionSdk,\n setSessionMode,\n addSystemMessage,\n agentRef,\n ]\n );\n\n const handleSlashSelect = useCallback(\n (cmd: SlashCommand) => {\n // If command takes args, fill the text and let user type args\n if (cmd.args) {\n setText(`${cmd.command} `);\n } else {\n executeSlashCommand(cmd.command);\n setText('');\n }\n setShowSlashMenu(false);\n textareaRef.current?.focus();\n },\n [executeSlashCommand]\n );\n\n const handleSend = useCallback(() => {\n if (!canSend) return;\n\n const trimmed = text.trim();\n\n // Handle slash commands locally\n if (trimmed.startsWith('/')) {\n executeSlashCommand(trimmed);\n setText('');\n setPendingFiles([]);\n return;\n }\n\n onSend(trimmed, pendingFiles.length > 0 ? pendingFiles : undefined);\n setText('');\n setPendingFiles([]);\n }, [canSend, text, pendingFiles, onSend, executeSlashCommand]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLTextAreaElement>) => {\n // Enter sends, Shift+Enter inserts newline\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n },\n [handleSend]\n );\n\n const handleCancel = useCallback(() => {\n onCancel?.();\n }, [onCancel]);\n\n const handleFileSelect = useCallback((files: File[]) => {\n setPendingFiles((prev) => [...prev, ...files]);\n }, []);\n\n const removeFile = useCallback((index: number) => {\n setPendingFiles((prev) => prev.filter((_, i) => i !== index));\n }, []);\n\n const dropHandlers = createDropHandlers(handleFileSelect);\n\n if (!sessionState) return null;\n\n return (\n <div className=\"relative z-30 border-t border-border-default bg-bg-surface\" {...dropHandlers}>\n {/* Slash command popup */}\n {showSlashMenu && filteredCommands.length > 0 && (\n <div className=\"absolute bottom-full left-0 right-0 mb-1 mx-3 bg-bg-elevated border border-border-default rounded-lg shadow-lg max-h-48 overflow-y-auto z-50\">\n {filteredCommands.map((cmd) => (\n <button\n key={cmd.command}\n type=\"button\"\n onClick={() => handleSlashSelect(cmd)}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-left hover:bg-bg-sunken transition-colors\"\n >\n <span className=\"font-mono text-xs text-text-primary\">{cmd.command}</span>\n {cmd.args && <span className=\"text-text-tertiary text-xs\">{cmd.args}</span>}\n <span className=\"text-text-secondary text-xs ml-auto\">{cmd.description}</span>\n </button>\n ))}\n </div>\n )}\n\n {/* File attachment preview row */}\n {pendingFiles.length > 0 && (\n <div className=\"flex items-center gap-2 px-3 pt-2 overflow-x-auto\">\n {pendingFiles.map((file, index) => (\n <div\n key={`${file.name}-${index}`}\n className=\"flex items-center gap-1.5 px-2 py-1 rounded-md bg-bg-elevated border border-border-default text-xs text-text-secondary\"\n >\n <span className=\"truncate max-w-[120px]\">{file.name}</span>\n <button\n type=\"button\"\n onClick={() => removeFile(index)}\n className=\"p-0.5 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\n >\n <X className=\"w-3 h-3\" />\n </button>\n </div>\n ))}\n </div>\n )}\n\n {/* Toolbar row */}\n <div className=\"flex flex-wrap items-center gap-1 px-3 pt-2 pb-1 overflow-x-auto\">\n <SdkSelector\n sdk={sessionState.sdk}\n mode={sessionState.mode}\n providers={providers}\n onSdkChange={(sdk) => {\n setSessionSdk(sessionId, sdk);\n void resolveProviderDefaultModel(\n agentRef,\n sdk,\n sessionState.model ?? GENERIC_MODEL_FALLBACK\n )\n .then((nextModel) => setSessionModel(sessionId, nextModel))\n .catch(() =>\n setSessionModel(sessionId, sessionState.model ?? GENERIC_MODEL_FALLBACK)\n );\n }}\n onModeChange={(mode) => setSessionMode(sessionId, mode)}\n />\n <ModelSelector\n value={sessionState.model}\n onChange={(model) => setSessionModel(sessionId, model)}\n provider={sessionState.sdk}\n agentId={agentId}\n />\n <AutonomySelector\n value={sessionState.permissionMode}\n mode={sessionState.mode}\n onChange={(permissionMode) => setSessionPermissionMode(sessionId, permissionMode)}\n />\n <McpServerSelector\n selected={sessionState.mcpServers}\n available={mcpServers}\n onChange={() => {\n // Update via store -- MCP servers are part of session state\n // For now we store them directly\n }}\n />\n <ContextLevelToggle\n agentId=\"\"\n sessionId={sessionId}\n contextLevel={sessionState.contextLevel}\n rootPath={sessionState.rootPath}\n onChange={(level, rootPath, vibeId) => {\n setSessionContextLevel(sessionId, level);\n setSessionRootPath(sessionId, rootPath ?? null);\n setSessionVibe(sessionId, vibeId ?? null, rootPath ?? null);\n }}\n vibes={vibes.map((v) => ({ id: v.id, name: v.name, path: v.path }))}\n />\n\n <div className=\"flex-1\" />\n\n {/* Show Thinking toggle */}\n <button\n type=\"button\"\n onClick={() => toggleThinking(sessionId)}\n className={`p-1.5 rounded text-xs font-medium transition-colors ${\n sessionState.showThinking\n ? 'bg-action-primary-bg/10 text-action-primary-text'\n : 'text-text-tertiary hover:text-text-secondary'\n }`}\n title={\n sessionState.showThinking\n ? tr('vibecontrols.agentManager.inputArea.hideThinking', 'Hide thinking')\n : tr('vibecontrols.agentManager.inputArea.showThinking', 'Show thinking')\n }\n >\n Think\n </button>\n {/* Context history limit */}\n <button\n type=\"button\"\n onClick={() => {\n const val = window.prompt(\n 'Context history limit (messages sent with each prompt):',\n String(sessionState.contextHistoryLimit)\n );\n if (val !== null) {\n const num = parseInt(val, 10);\n if (!isNaN(num) && num >= 0) {\n const store = useAgentManagerStore.getState();\n const s = store.sessionStates[sessionId];\n if (s) {\n useAgentManagerStore.setState((prev) => ({\n sessionStates: {\n ...prev.sessionStates,\n [sessionId]: { ...s, contextHistoryLimit: num },\n },\n }));\n }\n }\n }\n }}\n className=\"p-1.5 rounded text-[10px] font-mono text-text-tertiary hover:text-text-secondary transition-colors\"\n title={`Context history: last ${sessionState.contextHistoryLimit} messages sent with each prompt`}\n >\n H:{sessionState.contextHistoryLimit}\n </button>\n <VoiceToggle\n enabled={sessionState.voiceEnabled}\n onToggle={() => {\n toggleVoice(sessionId);\n if (!sessionState.voiceEnabled) startListening();\n else stopListening();\n }}\n isListening={isListening}\n />\n <FileAttachButton onFileSelect={handleFileSelect} />\n </div>\n\n {/* Textarea + send/cancel */}\n <div className=\"flex items-end gap-2 px-3 pb-3 pt-1\">\n <textarea\n ref={textareaRef}\n value={text}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={tr(\n 'vibecontrols.agentManager.inputArea.placeholder',\n 'Type a message or / for commands... (Enter to send)'\n )}\n rows={1}\n className=\"flex-1 resize-none rounded-lg border border-border-default bg-bg-primary px-3 py-2 text-sm text-text-primary placeholder:text-text-tertiary focus:outline-none focus:border-border-strong transition-colors\"\n disabled={isStreaming}\n />\n {isStreaming ? (\n <button\n type=\"button\"\n onClick={handleCancel}\n className=\"flex-shrink-0 p-2 rounded-lg bg-status-error-bg text-status-error-text hover:opacity-90 transition-opacity\"\n title={tr('vibecontrols.agentManager.inputArea.cancel', 'Cancel')}\n >\n <Square className=\"w-4 h-4\" />\n </button>\n ) : (\n <div className=\"flex items-end flex-shrink-0 relative\" ref={scheduleMenuRef}>\n <button\n type=\"button\"\n onClick={handleSend}\n disabled={!canSend}\n className=\"p-2 rounded-l-lg bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-40 disabled:cursor-not-allowed transition-colors\"\n title={tr('vibecontrols.agentManager.inputArea.send', 'Send (Enter)')}\n >\n <ArrowUp className=\"w-4 h-4\" />\n </button>\n <button\n type=\"button\"\n onClick={() => setShowScheduleMenu(!showScheduleMenu)}\n disabled={!canSend}\n className=\"ml-1 p-2 rounded-r-lg border-l border-action-primary-text/20 bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-40 disabled:cursor-not-allowed transition-colors\"\n title={tr('vibecontrols.agentManager.inputArea.scheduleSend', 'Schedule send')}\n >\n <ChevronDown className=\"w-3 h-3\" />\n </button>\n\n {/* Schedule dropdown */}\n {showScheduleMenu && (\n <div className=\"absolute bottom-full right-0 mb-1 w-56 bg-bg-surface border border-border-default rounded-md shadow-lg py-1 z-50\">\n {!showSchedulePopup ? (\n <button\n type=\"button\"\n onClick={() => setShowSchedulePopup(true)}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-left text-xs text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Clock className=\"w-3.5 h-3.5 text-text-secondary\" />\n {tr(\n 'vibecontrols.agentManager.inputArea.scheduleSendEllipsis',\n 'Schedule Send...'\n )}\n </button>\n ) : (\n <div className=\"px-3 py-2 space-y-2\">\n <label className=\"block text-[11px] font-medium text-text-secondary\">\n {tr('vibecontrols.agentManager.inputArea.sendAt', 'Send at:')}\n </label>\n <input\n type=\"datetime-local\"\n value={scheduleDateTime}\n onChange={(e) => setScheduleDateTime(e.target.value)}\n className=\"w-full px-2 py-1 text-xs rounded border border-border-default bg-bg-primary text-text-primary focus:outline-none focus:border-border-strong\"\n />\n <button\n type=\"button\"\n onClick={() => void handleScheduleSend()}\n disabled={!scheduleDateTime || !agentTunnelUrl || !agentApiKey}\n className=\"w-full px-2 py-1.5 text-xs font-medium rounded bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-40 disabled:cursor-not-allowed transition-colors\"\n >\n {tr('vibecontrols.agentManager.inputArea.schedule', 'Schedule')}\n </button>\n </div>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAsCA,IAAM,KAAiC;CACrC;EAAE,SAAS;EAAQ,aAAa;EAAsB;CACtD;EAAE,SAAS;EAAW,aAAa;EAA0B,MAAM;EAAU;CAC7E;EAAE,SAAS;EAAU,aAAa;EAAgB,MAAM;EAAgB;CACxE;EACE,SAAS;EACT,aAAa;EACb,MAAM;EACP;CACD;EAAE,SAAS;EAAS,aAAa;EAAe,MAAM;EAAa;CACnE;EAAE,SAAS;EAAW,aAAa;EAAuB,MAAM;EAAa;CAC7E;EAAE,SAAS;EAAU,aAAa;EAAsB;CACxD;EAAE,SAAS;EAAS,aAAa;EAA2B;CAC7D,EAEK,KAA6B;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,EACK,IAA8B,CAAC,OAAO,MAAM;AAgBlD,SAAgB,EAAsB,EACpC,YACA,cACA,WACA,cACA,iBAAa,EAAE,EACf,mBACA,kBAC6B;CAC7B,IAAM,CAAC,GAAM,KAAW,EAAS,GAAG,EAC9B,CAAC,GAAc,KAAmB,EAAiB,EAAE,CAAC,EACtD,CAAC,IAAe,KAAoB,EAAS,GAAM,EACnD,CAAC,GAAa,MAAkB,EAAS,GAAG,EAC5C,CAAC,GAAkB,KAAuB,EAAS,GAAM,EACzD,CAAC,GAAmB,KAAwB,EAAS,GAAM,EAC3D,CAAC,GAAkB,KAAuB,EAAS,GAAG,EACtD,CAAC,IAAW,KAAgB,EAAuB,EAAE,CAAC,EACtD,IAAK,GAAO,EACZ,IAAc,EAA4B,KAAK,EAC/C,IAAkB,EAAuB,KAAK;AAGpD,SAAgB;AACd,IAAY,SAAS,MAAM,EAAE,eAAe,IAAM,CAAC;IAClD,EAAE,CAAC;CAEN,IAAM,IAAe,GAAsB,MAAM,EAAE,cAAc,GAAW,EACtE,IAAkB,GAAsB,MAAM,EAAE,gBAAgB,EAChE,IAAgB,GAAsB,MAAM,EAAE,cAAc,EAC5D,IAAiB,GAAsB,MAAM,EAAE,eAAe,EAC9D,KAA2B,GAAsB,MAAM,EAAE,yBAAyB,EAClF,KAAc,GAAsB,MAAM,EAAE,YAAY,EACxD,KAAiB,GAAsB,MAAM,EAAE,eAAe,EAC9D,KAAyB,GAAsB,MAAM,EAAE,uBAAuB,EAC9E,KAAiB,GAAsB,MAAM,EAAE,eAAe,EAC9D,KAAqB,GAAsB,MAAM,EAAE,mBAAmB,EACtE,IAAc,GAAsB,MAAM,EAAE,YAAY,EACxD,IAAa,GAAsB,MAAM,EAAE,WAAW,EAEtD,EAAE,WAAO,cAAW,GAAsB,EAK1C,EAAE,QAAQ,MAAkB,EAJd,QACZ,EAAO,MAAM,MAAM,EAAE,OAAO,EAAQ,IAAI,MAC9C,CAAC,GAAQ,EAAQ,CAClB,EACoE,MAAM,KAAK,EAC1E,IAAW,SACR;EAAE,IAAI;EAAS,SAAS;EAAe,GAC9C,CAAC,GAAS,EAAc,CACzB,EAEK,EAAE,gBAAa,eAAY,oBAAgB,sBAAkB,IAAc,EAE3E,IAAc,GAAc,WAAW,aACvC,IAAU,EAAK,MAAM,CAAC,SAAS,KAAK,CAAC;AAyB3C,CAtBA,QAAgB;AACd,EAAI,KAAc,KAChB,GAAS,MAAS,KAAQ,IAAO,MAAM,MAAM,EAAW;IAEzD,CAAC,GAAY,EAAY,CAAC,EAE7B,QAAgB;EACd,IAAI,IAAY;AAShB,SARK,EAAe,EAAS,CAC1B,MAAM,MAAU;AACf,GAAK,KAAW,EAAa,EAAM;IACnC,CACD,YAAY;AACX,GAAK,KAAW,EAAa,EAAE,CAAC;IAChC,QAES;AACX,OAAY;;IAEb,CAAC,EAAS,CAAC,EAGd,QAAgB;AACd,EAAI,EAAK,WAAW,IAAI,IAAI,CAAC,EAAK,SAAS,IAAI,IAC7C,EAAiB,GAAK,EACtB,GAAe,EAAK,MAAM,EAAE,CAAC,IAE7B,EAAiB,GAAM;IAExB,CAAC,EAAK,CAAC;CAEV,IAAM,IAAmB,QAErB,GAAe,QAAQ,MACrB,EAAI,QAAQ,aAAa,CAAC,SAAS,IAAI,EAAY,aAAa,GAAG,CACpE,EACH,CAAC,EAAY,CACd;AAcD,CAXA,QAAgB;EACd,IAAM,IAAK,EAAY;AAClB,QACL,EAAG,MAAM,SAAS,QAIlB,EAAG,MAAM,SAAS,GAAG,KAAK,IAAI,EAAG,cAAc,IAAU,CAAC;IACzD,CAAC,EAAK,CAAC,EAGV,QAAgB;AACd,MAAI,CAAC,KAAoB,CAAC,EAAmB;EAC7C,IAAM,KAAW,MAAkB;AACjC,GAAI,EAAgB,WAAW,CAAC,EAAgB,QAAQ,SAAS,EAAE,OAAe,KAChF,EAAoB,GAAM,EAC1B,EAAqB,GAAM;;AAI/B,SADA,SAAS,iBAAiB,aAAa,EAAQ,QAClC,SAAS,oBAAoB,aAAa,EAAQ;IAC9D,CAAC,GAAkB,EAAkB,CAAC;CAEzC,IAAM,IAAmB,GACtB,MAAoB;AACnB,IAAW,GAAW;GACpB,IAAI,OAAO,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE;GAC/D,MAAM;GACN;GACA,4BAAW,IAAI,MAAM,EAAC,aAAa;GACpC,CAAC;IAEJ,CAAC,GAAY,EAAU,CACxB,EAEK,KAAqB,EAAY,YAAY;AAC7C,SAAC,EAAK,MAAM,IAAI,CAAC,KAAoB,CAAC,KAAkB,CAAC,GAC7D,KAAI;GACF,IAAM,IAAS,MAAM,GAAe;IAClC;IACA;IACA;IACA,QAAQ,EAAK,MAAM;IACnB,aAAa,IAAI,KAAK,EAAiB,CAAC,aAAa;IACtD,CAAC;AAOF,GANA,EACE,wBAAwB,IAAI,KAAK,EAAO,YAAY,CAAC,gBAAgB,CAAC,SAAS,EAAO,MAAM,MAAM,GAAG,EAAE,CAAC,GACzG,EACD,EAAQ,GAAG,EACX,EAAoB,GAAG,EACvB,EAAqB,GAAM,EAC3B,EAAoB,GAAM;WACnB,GAAK;AACZ,KACE,uBAAuB,aAAe,QAAQ,EAAI,UAAU,kBAC7D;;IAEF;EAAC;EAAM;EAAkB;EAAgB;EAAa;EAAW;EAAiB,CAAC,EAEhF,IAAsB,GACzB,MAAkB;EACjB,IAAM,IAAQ,EAAM,MAAM,CAAC,MAAM,MAAM,EACjC,IAAM,EAAM,GAAG,aAAa,EAC5B,IAAM,EAAM,MAAM,EAAE,CAAC,KAAK,IAAI;AAEpC,UAAQ,GAAR;GACE,KAAK;AAEH,MADc,WAAW,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE,GAC3D;AAClB;GAEF,KAAK;AACH,IACE,EADE,IACe,uBAAuB,EAAI,MAE3B,wBAAwB;AAE3C;GACF,KAAK;AACH,IAAI,KACF,EAAgB,GAAW,EAAI,EAC/B,EAAiB,sBAAsB,EAAI,IAAI,IAE/C,EAAiB,6BAA6B;AAEhD;GACF,KAAK;AACH,QAAI,KAAO,GAAW,SAAS,EAAoB,EAAE;KACnD,IAAM,IAAU;AAWhB,KAVA,EAAc,GAAW,EAAQ,EAC5B,EACH,GACA,GACA,GAAc,SAAA,UACf,CACE,MAAM,MAAc,EAAgB,GAAW,EAAU,CAAC,CAC1D,YACC,EAAgB,GAAW,GAAc,SAAA,UAAgC,CAC1E,EACH,EAAiB,oBAAoB,EAAI,IAAI;UAE7C,GAAiB,gBAAgB,GAAW,KAAK,IAAI,CAAC,GAAG;AAE3D;GACF,KAAK;AACH,IAAI,KAAO,EAAY,SAAS,EAAoB,IAClD,EAAe,GAAW,EAAoB,EAC9C,EAAiB,qBAAqB,EAAI,IAAI,IAE9C,EAAiB,iBAAiB,EAAY,KAAK,IAAI,CAAC,GAAG;AAE7D;GACF,KAAK,WAAW;IACd,IAAM,IAAS,MAAQ,OAAO,OAAO,QAC/B,IAAW,GAAc,YAAY,EAAE,EACvC,IACJ,MAAW,SACP,KAAK,UAAU,GAAU,MAAM,EAAE,GACjC,EACG,KAAK,MAAM,KAAK,EAAE,KAAK,MAAM,EAAE,aAAa,GAAG,MAAM,EAAE,WAAW,KAAK,CACvE,KAAK,cAAc,EACtB,IAAO,IAAI,KAAK,CAAC,EAAS,EAAE,EAChC,MAAM,MAAW,SAAS,qBAAqB,iBAChD,CAAC,EACI,IAAM,IAAI,gBAAgB,EAAK,EAC/B,IAAI,SAAS,cAAc,IAAI;AAKrC,IAJA,EAAE,OAAO,GACT,EAAE,WAAW,gBAAgB,EAAU,GAAG,KAC1C,EAAE,OAAO,EACT,IAAI,gBAAgB,EAAI,EACxB,EAAiB,4BAA4B,EAAO,GAAG;AACvD;;GAEF,KAAK;AACH,MAAiB,wBAAwB;AACzC;GACF,KAAK;AAIH,MAAiB,wBAHA,GAAe,KAC7B,MAAM,KAAK,EAAE,UAAU,EAAE,OAAO,MAAM,EAAE,OAAO,GAAG,KAAK,EAAE,cAC3D,CAAC,KAAK,KAAK,GACwC;AACpD;GAEF,QACE,GAAiB,oBAAoB,EAAI,sCAAsC;;IAGrF;EACE;EACA,GAAc;EACd,GAAc;EACd;EACA;EACA;EACA;EACA;EACA;EACD,CACF,EAEK,KAAoB,GACvB,MAAsB;AASrB,EAPI,EAAI,OACN,EAAQ,GAAG,EAAI,QAAQ,GAAG,IAE1B,EAAoB,EAAI,QAAQ,EAChC,EAAQ,GAAG,GAEb,EAAiB,GAAM,EACvB,EAAY,SAAS,OAAO;IAE9B,CAAC,EAAoB,CACtB,EAEK,IAAa,QAAkB;AACnC,MAAI,CAAC,EAAS;EAEd,IAAM,IAAU,EAAK,MAAM;AAG3B,MAAI,EAAQ,WAAW,IAAI,EAAE;AAG3B,GAFA,EAAoB,EAAQ,EAC5B,EAAQ,GAAG,EACX,EAAgB,EAAE,CAAC;AACnB;;AAKF,EAFA,EAAO,GAAS,EAAa,SAAS,IAAI,IAAe,KAAA,EAAU,EACnE,EAAQ,GAAG,EACX,EAAgB,EAAE,CAAC;IAClB;EAAC;EAAS;EAAM;EAAc;EAAQ;EAAoB,CAAC,EAExD,KAAgB,GACnB,MAA0C;AAEzC,EAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,aAC1B,EAAE,gBAAgB,EAClB,GAAY;IAGhB,CAAC,EAAW,CACb,EAEK,KAAe,QAAkB;AACrC,QAAY;IACX,CAAC,GAAS,CAAC,EAER,KAAmB,GAAa,MAAkB;AACtD,KAAiB,MAAS,CAAC,GAAG,GAAM,GAAG,EAAM,CAAC;IAC7C,EAAE,CAAC,EAEA,KAAa,GAAa,MAAkB;AAChD,KAAiB,MAAS,EAAK,QAAQ,GAAG,MAAM,MAAM,EAAM,CAAC;IAC5D,EAAE,CAAC,EAEA,KAAe,GAAmB,GAAiB;AAIzD,QAFK,IAGH,kBAAC,OAAD;EAAK,WAAU;EAA6D,GAAI;YAAhF;GAEG,MAAiB,EAAiB,SAAS,KAC1C,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAiB,KAAK,MACrB,kBAAC,UAAD;KAEE,MAAK;KACL,eAAe,GAAkB,EAAI;KACrC,WAAU;eAJZ;MAME,kBAAC,QAAD;OAAM,WAAU;iBAAuC,EAAI;OAAe,CAAA;MACzE,EAAI,QAAQ,kBAAC,QAAD;OAAM,WAAU;iBAA8B,EAAI;OAAY,CAAA;MAC3E,kBAAC,QAAD;OAAM,WAAU;iBAAuC,EAAI;OAAmB,CAAA;MACvE;OARF,EAAI,QAQF,CACT;IACE,CAAA;GAIP,EAAa,SAAS,KACrB,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAa,KAAK,GAAM,MACvB,kBAAC,OAAD;KAEE,WAAU;eAFZ,CAIE,kBAAC,QAAD;MAAM,WAAU;gBAA0B,EAAK;MAAY,CAAA,EAC3D,kBAAC,UAAD;MACE,MAAK;MACL,eAAe,GAAW,EAAM;MAChC,WAAU;gBAEV,kBAAC,IAAD,EAAG,WAAU,WAAY,CAAA;MAClB,CAAA,CACL;OAXC,GAAG,EAAK,KAAK,GAAG,IAWjB,CACN;IACE,CAAA;GAIR,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD;MACE,KAAK,EAAa;MAClB,MAAM,EAAa;MACR;MACX,cAAc,MAAQ;AAEf,OADL,EAAc,GAAW,EAAI,EACxB,EACH,GACA,GACA,EAAa,SAAA,UACd,CACE,MAAM,MAAc,EAAgB,GAAW,EAAU,CAAC,CAC1D,YACC,EAAgB,GAAW,EAAa,SAAA,UAAgC,CACzE;;MAEL,eAAe,MAAS,EAAe,GAAW,EAAK;MACvD,CAAA;KACF,kBAAC,GAAD;MACE,OAAO,EAAa;MACpB,WAAW,MAAU,EAAgB,GAAW,EAAM;MACtD,UAAU,EAAa;MACd;MACT,CAAA;KACF,kBAAC,IAAD;MACE,OAAO,EAAa;MACpB,MAAM,EAAa;MACnB,WAAW,MAAmB,GAAyB,GAAW,EAAe;MACjF,CAAA;KACF,kBAAC,IAAD;MACE,UAAU,EAAa;MACvB,WAAW;MACX,gBAAgB;MAIhB,CAAA;KACF,kBAAC,IAAD;MACE,SAAQ;MACG;MACX,cAAc,EAAa;MAC3B,UAAU,EAAa;MACvB,WAAW,GAAO,GAAU,MAAW;AAGrC,OAFA,GAAuB,GAAW,EAAM,EACxC,GAAmB,GAAW,KAAY,KAAK,EAC/C,GAAe,GAAW,KAAU,MAAM,KAAY,KAAK;;MAE7D,OAAO,GAAM,KAAK,OAAO;OAAE,IAAI,EAAE;OAAI,MAAM,EAAE;OAAM,MAAM,EAAE;OAAM,EAAE;MACnE,CAAA;KAEF,kBAAC,OAAD,EAAK,WAAU,UAAW,CAAA;KAG1B,kBAAC,UAAD;MACE,MAAK;MACL,eAAe,GAAe,EAAU;MACxC,WAAW,uDACT,EAAa,eACT,qDACA;MAEN,OACE,EAAa,eACT,EAAG,oDAAoD,gBAAgB,GACvE,EAAG,oDAAoD,gBAAgB;gBAE9E;MAEQ,CAAA;KAET,kBAAC,UAAD;MACE,MAAK;MACL,eAAe;OACb,IAAM,IAAM,OAAO,OACjB,2DACA,OAAO,EAAa,oBAAoB,CACzC;AACD,WAAI,MAAQ,MAAM;QAChB,IAAM,IAAM,SAAS,GAAK,GAAG;AAC7B,YAAI,CAAC,MAAM,EAAI,IAAI,KAAO,GAAG;SAE3B,IAAM,IADQ,EAAqB,UAAU,CAC7B,cAAc;AAC9B,SAAI,KACF,EAAqB,UAAU,OAAU,EACvC,eAAe;UACb,GAAG,EAAK;WACP,IAAY;WAAE,GAAG;WAAG,qBAAqB;WAAK;UAChD,EACF,EAAE;;;;MAKX,WAAU;MACV,OAAO,yBAAyB,EAAa,oBAAoB;gBAxBnE,CAyBC,MACI,EAAa,oBACT;;KACT,kBAAC,IAAD;MACE,SAAS,EAAa;MACtB,gBAAgB;AAEd,OADA,GAAY,EAAU,EACjB,EAAa,eACb,IAAe,GADY,IAAgB;;MAGrC;MACb,CAAA;KACF,kBAAC,IAAD,EAAkB,cAAc,IAAoB,CAAA;KAChD;;GAGN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,YAAD;KACE,KAAK;KACL,OAAO;KACP,WAAW,MAAM,EAAQ,EAAE,OAAO,MAAM;KACxC,WAAW;KACX,aAAa,EACX,mDACA,sDACD;KACD,MAAM;KACN,WAAU;KACV,UAAU;KACV,CAAA,EACD,IACC,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAU;KACV,OAAO,EAAG,8CAA8C,SAAS;eAEjE,kBAAC,IAAD,EAAQ,WAAU,WAAY,CAAA;KACvB,CAAA,GAET,kBAAC,OAAD;KAAK,WAAU;KAAwC,KAAK;eAA5D;MACE,kBAAC,UAAD;OACE,MAAK;OACL,SAAS;OACT,UAAU,CAAC;OACX,WAAU;OACV,OAAO,EAAG,4CAA4C,eAAe;iBAErE,kBAAC,IAAD,EAAS,WAAU,WAAY,CAAA;OACxB,CAAA;MACT,kBAAC,UAAD;OACE,MAAK;OACL,eAAe,EAAoB,CAAC,EAAiB;OACrD,UAAU,CAAC;OACX,WAAU;OACV,OAAO,EAAG,oDAAoD,gBAAgB;iBAE9E,kBAAC,IAAD,EAAa,WAAU,WAAY,CAAA;OAC5B,CAAA;MAGR,KACC,kBAAC,OAAD;OAAK,WAAU;iBACX,IAaA,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACE,kBAAC,SAAD;UAAO,WAAU;oBACd,EAAG,8CAA8C,WAAW;UACvD,CAAA;SACR,kBAAC,SAAD;UACE,MAAK;UACL,OAAO;UACP,WAAW,MAAM,EAAoB,EAAE,OAAO,MAAM;UACpD,WAAU;UACV,CAAA;SACF,kBAAC,UAAD;UACE,MAAK;UACL,eAAe,KAAK,IAAoB;UACxC,UAAU,CAAC,KAAoB,CAAC,KAAkB,CAAC;UACnD,WAAU;oBAET,EAAG,gDAAgD,WAAW;UACxD,CAAA;SACL;YA9BN,kBAAC,UAAD;QACE,MAAK;QACL,eAAe,EAAqB,GAAK;QACzC,WAAU;kBAHZ,CAKE,kBAAC,IAAD,EAAO,WAAU,mCAAoC,CAAA,EACpD,EACC,4DACA,mBACD,CACM;;OAsBP,CAAA;MAEJ;OAEJ;;GACF;MAjPkB"}
1
+ {"version":3,"file":"AgentManagerInputArea.js","names":[],"sources":["../../../src/components/agent-manager/AgentManagerInputArea.tsx"],"sourcesContent":["/**\n * Rich input area for the Agent Manager chat.\n *\n * Sits at the bottom of the chat pane. Contains a toolbar row with\n * control selectors and a resizable textarea with send/cancel buttons.\n * Supports file attachment preview, keyboard shortcuts, and slash\n * commands for quick actions.\n */\n\nimport { useState, useRef, useCallback, useEffect, useMemo, type KeyboardEvent } from 'react';\nimport { ArrowUp, Square, X, ChevronDown, Clock } from 'lucide-react';\nimport { useAgentManagerStore } from '@/store/agentManagerStore';\nimport { useVoiceMode } from '@/hooks/useVoiceMode';\nimport { useCachedInitialData } from '@/hooks/useCachedInitialData';\nimport { fetchProviders, type AIProvider } from '@/services/aiApi';\nimport { useActiveAgentProfile } from '@/hooks/useActiveAgentProfile';\nimport { schedulePrompt } from '@/services/schedulerApi';\nimport { ModelSelector } from './controls/ModelSelector';\nimport { SdkSelector } from './controls/SdkSelector';\nimport { AutonomySelector } from './controls/AutonomySelector';\nimport { McpServerSelector } from './controls/McpServerSelector';\nimport { VoiceToggle } from './controls/VoiceToggle';\nimport { FileAttachButton } from './controls/FileAttachButton';\nimport { createDropHandlers } from './controls/createDropHandlers';\nimport { ContextLevelToggle } from './controls/ContextLevelToggle';\nimport { GENERIC_MODEL_FALLBACK, resolveProviderDefaultModel } from './modelDefaults';\nimport type { AgentSdkType, McpServer, ProviderMode } from '@/types/agentManager';\nimport { useTr } from '../../shared/hooks/useTr';\n\n/* ────────────────────────────────────────────────────────────────────── */\n/* Slash commands */\n/* ────────────────────────────────────────────────────────────────────── */\n\ninterface SlashCommand {\n command: string;\n description: string;\n args?: string;\n}\n\nconst SLASH_COMMANDS: SlashCommand[] = [\n { command: '/new', description: 'Create new session' },\n { command: '/rename', description: 'Rename current session', args: '<name>' },\n { command: '/model', description: 'Switch model', args: '<model-name>' },\n {\n command: '/sdk',\n description: 'Switch SDK',\n args: '<claude|codex|gemini|opencode|openai-compat>',\n },\n { command: '/mode', description: 'Switch mode', args: '<sdk|cli>' },\n { command: '/export', description: 'Export conversation', args: '[json|md]' },\n { command: '/clear', description: 'Clear conversation' },\n { command: '/help', description: 'Show available commands' },\n];\n\nconst VALID_SDKS: AgentSdkType[] = [\n 'claude',\n 'codex',\n 'gemini',\n 'opencode',\n 'cursor',\n 'openrouter',\n 'minimax',\n 'ollama',\n 'openai-compat',\n 'goose',\n 'amp',\n 'copilot',\n 'crush',\n 'pi',\n 'aider',\n 'plandex',\n];\nconst VALID_MODES: ProviderMode[] = ['sdk', 'cli'];\n\n/* ────────────────────────────────────────────────────────────────────── */\n/* Component */\n/* ────────────────────────────────────────────────────────────────────── */\n\ninterface AgentManagerInputAreaProps {\n agentId: string;\n sessionId: string;\n onSend: (text: string, attachments?: File[]) => void;\n onCancel?: () => void;\n mcpServers?: McpServer[];\n agentTunnelUrl?: string;\n agentApiKey?: string;\n}\n\nexport function AgentManagerInputArea({\n agentId,\n sessionId,\n onSend,\n onCancel,\n mcpServers = [],\n agentTunnelUrl,\n agentApiKey,\n}: AgentManagerInputAreaProps) {\n const [text, setText] = useState('');\n const [pendingFiles, setPendingFiles] = useState<File[]>([]);\n const [showSlashMenu, setShowSlashMenu] = useState(false);\n const [slashFilter, setSlashFilter] = useState('');\n const [showScheduleMenu, setShowScheduleMenu] = useState(false);\n const [showSchedulePopup, setShowSchedulePopup] = useState(false);\n const [scheduleDateTime, setScheduleDateTime] = useState('');\n const [providers, setProviders] = useState<AIProvider[]>([]);\n const tr = useTr();\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const scheduleMenuRef = useRef<HTMLDivElement>(null);\n\n // Auto-focus textarea when session is opened or switched\n useEffect(() => {\n textareaRef.current?.focus({ preventScroll: true });\n }, []);\n\n const sessionState = useAgentManagerStore((s) => s.sessionStates[sessionId]);\n const setSessionModel = useAgentManagerStore((s) => s.setSessionModel);\n const setSessionSdk = useAgentManagerStore((s) => s.setSessionSdk);\n const setSessionMode = useAgentManagerStore((s) => s.setSessionMode);\n const setSessionPermissionMode = useAgentManagerStore((s) => s.setSessionPermissionMode);\n const toggleVoice = useAgentManagerStore((s) => s.toggleVoice);\n const toggleThinking = useAgentManagerStore((s) => s.toggleThinking);\n const setSessionContextLevel = useAgentManagerStore((s) => s.setSessionContextLevel);\n const setSessionVibe = useAgentManagerStore((s) => s.setSessionVibe);\n const setSessionRootPath = useAgentManagerStore((s) => s.setSessionRootPath);\n const openSession = useAgentManagerStore((s) => s.openSession);\n const addMessage = useAgentManagerStore((s) => s.addMessage);\n\n const { vibes, agents } = useCachedInitialData();\n const activeAgent = useMemo(\n () => agents.find((a) => a.id === agentId) ?? null,\n [agents, agentId]\n );\n const { active: activeProfile } = useActiveAgentProfile(activeAgent?.id ?? null);\n const agentRef = useMemo(\n () => ({ id: agentId, profile: activeProfile }),\n [agentId, activeProfile]\n );\n\n const { isListening, transcript, startListening, stopListening } = useVoiceMode();\n\n const isStreaming = sessionState?.status === 'streaming';\n const canSend = text.trim().length > 0 && !isStreaming;\n\n // Append voice transcript to textarea\n useEffect(() => {\n if (transcript && isListening) {\n setText((prev) => prev + (prev ? ' ' : '') + transcript);\n }\n }, [transcript, isListening]);\n\n useEffect(() => {\n let cancelled = false;\n void fetchProviders(agentRef)\n .then((items) => {\n if (!cancelled) setProviders(items);\n })\n .catch(() => {\n if (!cancelled) setProviders([]);\n });\n\n return () => {\n cancelled = true;\n };\n }, [agentRef]);\n\n // ── Slash command filtering ──\n useEffect(() => {\n if (text.startsWith('/') && !text.includes(' ')) {\n setShowSlashMenu(true);\n setSlashFilter(text.slice(1));\n } else {\n setShowSlashMenu(false);\n }\n }, [text]);\n\n const filteredCommands = useMemo(\n () =>\n SLASH_COMMANDS.filter((cmd) =>\n cmd.command.toLowerCase().includes(`/${slashFilter.toLowerCase()}`)\n ),\n [slashFilter]\n );\n\n // Auto-resize textarea\n useEffect(() => {\n const el = textareaRef.current;\n if (!el) return;\n el.style.height = 'auto';\n const maxRows = 10;\n const lineHeight = 20;\n const maxHeight = maxRows * lineHeight;\n el.style.height = `${Math.min(el.scrollHeight, maxHeight)}px`;\n }, [text]);\n\n // Close schedule menu on outside click\n useEffect(() => {\n if (!showScheduleMenu && !showSchedulePopup) return;\n const handler = (e: MouseEvent) => {\n if (scheduleMenuRef.current && !scheduleMenuRef.current.contains(e.target as Node)) {\n setShowScheduleMenu(false);\n setShowSchedulePopup(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [showScheduleMenu, showSchedulePopup]);\n\n const addSystemMessage = useCallback(\n (content: string) => {\n addMessage(sessionId, {\n id: `sys-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,\n role: 'system',\n content,\n timestamp: new Date().toISOString(),\n });\n },\n [addMessage, sessionId]\n );\n\n const handleScheduleSend = useCallback(async () => {\n if (!text.trim() || !scheduleDateTime || !agentTunnelUrl || !agentApiKey) return;\n try {\n const result = await schedulePrompt({\n sessionId,\n agentTunnelUrl,\n agentApiKey,\n prompt: text.trim(),\n scheduledAt: new Date(scheduleDateTime).toISOString(),\n });\n addSystemMessage(\n `Prompt scheduled for ${new Date(result.scheduledAt).toLocaleString()} (Job: ${result.jobId.slice(0, 8)})`\n );\n setText('');\n setScheduleDateTime('');\n setShowSchedulePopup(false);\n setShowScheduleMenu(false);\n } catch (err) {\n addSystemMessage(\n `Failed to schedule: ${err instanceof Error ? err.message : 'Unknown error'}`\n );\n }\n }, [text, scheduleDateTime, agentTunnelUrl, agentApiKey, sessionId, addSystemMessage]);\n\n const executeSlashCommand = useCallback(\n (input: string) => {\n const parts = input.trim().split(/\\s+/);\n const cmd = parts[0].toLowerCase();\n const arg = parts.slice(1).join(' ');\n\n switch (cmd) {\n case '/new': {\n const newId = `session-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n openSession(newId);\n break;\n }\n case '/rename':\n if (arg) {\n addSystemMessage(`Session renamed to \"${arg}\".`);\n } else {\n addSystemMessage('Usage: /rename <name>');\n }\n break;\n case '/model':\n if (arg) {\n setSessionModel(sessionId, arg);\n addSystemMessage(`Model switched to \"${arg}\".`);\n } else {\n addSystemMessage('Usage: /model <model-name>');\n }\n break;\n case '/sdk':\n if (arg && VALID_SDKS.includes(arg as AgentSdkType)) {\n const nextSdk = arg as AgentSdkType;\n setSessionSdk(sessionId, nextSdk);\n void resolveProviderDefaultModel(\n agentRef,\n nextSdk,\n sessionState?.model ?? GENERIC_MODEL_FALLBACK\n )\n .then((nextModel) => setSessionModel(sessionId, nextModel))\n .catch(() =>\n setSessionModel(sessionId, sessionState?.model ?? GENERIC_MODEL_FALLBACK)\n );\n addSystemMessage(`SDK switched to \"${arg}\".`);\n } else {\n addSystemMessage(`Usage: /sdk <${VALID_SDKS.join('|')}>`);\n }\n break;\n case '/mode':\n if (arg && VALID_MODES.includes(arg as ProviderMode)) {\n setSessionMode(sessionId, arg as ProviderMode);\n addSystemMessage(`Mode switched to \"${arg}\".`);\n } else {\n addSystemMessage(`Usage: /mode <${VALID_MODES.join('|')}>`);\n }\n break;\n case '/export': {\n const format = arg === 'md' ? 'md' : 'json';\n const messages = sessionState?.messages ?? [];\n const exported =\n format === 'json'\n ? JSON.stringify(messages, null, 2)\n : messages\n .map((m) => `**${m.role}** (${m.timestamp ?? ''}):\\n${m.content ?? ''}`)\n .join('\\n\\n---\\n\\n');\n const blob = new Blob([exported], {\n type: format === 'json' ? 'application/json' : 'text/markdown',\n });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `conversation-${sessionId}.${format}`;\n a.click();\n URL.revokeObjectURL(url);\n addSystemMessage(`Conversation exported as ${format}.`);\n break;\n }\n case '/clear':\n addSystemMessage('Conversation cleared.');\n break;\n case '/help': {\n const helpText = SLASH_COMMANDS.map(\n (c) => ` ${c.command}${c.args ? ' ' + c.args : ''} - ${c.description}`\n ).join('\\n');\n addSystemMessage(`Available commands:\\n${helpText}`);\n break;\n }\n default:\n addSystemMessage(`Unknown command: ${cmd}. Type /help for available commands.`);\n }\n },\n [\n sessionId,\n sessionState?.messages,\n sessionState?.model,\n openSession,\n setSessionModel,\n setSessionSdk,\n setSessionMode,\n addSystemMessage,\n agentRef,\n ]\n );\n\n const handleSlashSelect = useCallback(\n (cmd: SlashCommand) => {\n // If command takes args, fill the text and let user type args\n if (cmd.args) {\n setText(`${cmd.command} `);\n } else {\n executeSlashCommand(cmd.command);\n setText('');\n }\n setShowSlashMenu(false);\n textareaRef.current?.focus();\n },\n [executeSlashCommand]\n );\n\n const handleSend = useCallback(() => {\n if (!canSend) return;\n\n const trimmed = text.trim();\n\n // Handle slash commands locally\n if (trimmed.startsWith('/')) {\n executeSlashCommand(trimmed);\n setText('');\n setPendingFiles([]);\n return;\n }\n\n onSend(trimmed, pendingFiles.length > 0 ? pendingFiles : undefined);\n setText('');\n setPendingFiles([]);\n }, [canSend, text, pendingFiles, onSend, executeSlashCommand]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLTextAreaElement>) => {\n // Enter sends, Shift+Enter inserts newline\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n },\n [handleSend]\n );\n\n const handleCancel = useCallback(() => {\n onCancel?.();\n }, [onCancel]);\n\n const handleFileSelect = useCallback((files: File[]) => {\n setPendingFiles((prev) => [...prev, ...files]);\n }, []);\n\n const removeFile = useCallback((index: number) => {\n setPendingFiles((prev) => prev.filter((_, i) => i !== index));\n }, []);\n\n const dropHandlers = createDropHandlers(handleFileSelect);\n\n if (!sessionState) return null;\n\n return (\n <div className=\"relative z-30 border-t border-border-default bg-bg-surface\" {...dropHandlers}>\n {/* Slash command popup */}\n {showSlashMenu && filteredCommands.length > 0 && (\n <div className=\"absolute bottom-full left-0 right-0 mb-1 mx-3 bg-bg-elevated border border-border-default rounded-lg shadow-lg max-h-48 overflow-y-auto z-50\">\n {filteredCommands.map((cmd) => (\n <button\n key={cmd.command}\n type=\"button\"\n onClick={() => handleSlashSelect(cmd)}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-left hover:bg-bg-sunken transition-colors\"\n >\n <span className=\"font-mono text-xs text-text-primary\">{cmd.command}</span>\n {cmd.args && <span className=\"text-text-tertiary text-xs\">{cmd.args}</span>}\n <span className=\"text-text-secondary text-xs ml-auto\">{cmd.description}</span>\n </button>\n ))}\n </div>\n )}\n\n {/* File attachment preview row */}\n {pendingFiles.length > 0 && (\n <div className=\"flex items-center gap-2 px-3 pt-2 overflow-x-auto\">\n {pendingFiles.map((file, index) => (\n <div\n key={`${file.name}-${index}`}\n className=\"flex items-center gap-1.5 px-2 py-1 rounded-md bg-bg-elevated border border-border-default text-xs text-text-secondary\"\n >\n <span className=\"truncate max-w-[120px]\">{file.name}</span>\n <button\n type=\"button\"\n onClick={() => removeFile(index)}\n className=\"p-0.5 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\n >\n <X className=\"w-3 h-3\" />\n </button>\n </div>\n ))}\n </div>\n )}\n\n {/* Toolbar row */}\n <div className=\"flex flex-wrap items-center gap-1 px-3 pt-2 pb-1 overflow-x-auto\">\n <SdkSelector\n sdk={sessionState.sdk}\n mode={sessionState.mode}\n providers={providers}\n onSdkChange={(sdk) => {\n setSessionSdk(sessionId, sdk);\n void resolveProviderDefaultModel(\n agentRef,\n sdk,\n sessionState.model ?? GENERIC_MODEL_FALLBACK\n )\n .then((nextModel) => setSessionModel(sessionId, nextModel))\n .catch(() =>\n setSessionModel(sessionId, sessionState.model ?? GENERIC_MODEL_FALLBACK)\n );\n }}\n onModeChange={(mode) => setSessionMode(sessionId, mode)}\n />\n <ModelSelector\n value={sessionState.model}\n onChange={(model) => setSessionModel(sessionId, model)}\n provider={sessionState.sdk}\n agentId={agentId}\n />\n <AutonomySelector\n value={sessionState.permissionMode}\n mode={sessionState.mode}\n onChange={(permissionMode) => setSessionPermissionMode(sessionId, permissionMode)}\n />\n <McpServerSelector\n selected={sessionState.mcpServers}\n available={mcpServers}\n onChange={() => {\n // Update via store -- MCP servers are part of session state\n // For now we store them directly\n }}\n />\n <ContextLevelToggle\n agentId=\"\"\n sessionId={sessionId}\n contextLevel={sessionState.contextLevel}\n rootPath={sessionState.rootPath}\n onChange={(level, rootPath, vibeId) => {\n setSessionContextLevel(sessionId, level);\n setSessionRootPath(sessionId, rootPath ?? null);\n setSessionVibe(sessionId, vibeId ?? null, rootPath ?? null);\n }}\n vibes={vibes.map((v) => ({ id: v.id, name: v.name, path: v.path }))}\n />\n\n <div className=\"flex-1\" />\n\n {/* Show Thinking toggle */}\n <button\n type=\"button\"\n onClick={() => toggleThinking(sessionId)}\n className={`p-1.5 rounded text-xs font-medium transition-colors ${\n sessionState.showThinking\n ? 'bg-action-primary-bg/10 text-action-primary-text'\n : 'text-text-tertiary hover:text-text-secondary'\n }`}\n title={\n sessionState.showThinking\n ? tr('vibecontrols.agentManager.inputArea.hideThinking', 'Hide thinking')\n : tr('vibecontrols.agentManager.inputArea.showThinking', 'Show thinking')\n }\n >\n Think\n </button>\n {/* Context history limit */}\n <button\n type=\"button\"\n onClick={() => {\n const val = window.prompt(\n 'Context history limit (messages sent with each prompt):',\n String(sessionState.contextHistoryLimit)\n );\n if (val !== null) {\n const num = parseInt(val, 10);\n if (!isNaN(num) && num >= 0) {\n const store = useAgentManagerStore.getState();\n const s = store.sessionStates[sessionId];\n if (s) {\n useAgentManagerStore.setState((prev) => ({\n sessionStates: {\n ...prev.sessionStates,\n [sessionId]: { ...s, contextHistoryLimit: num },\n },\n }));\n }\n }\n }\n }}\n className=\"p-1.5 rounded text-[10px] font-mono text-text-tertiary hover:text-text-secondary transition-colors\"\n title={`Context history: last ${sessionState.contextHistoryLimit} messages sent with each prompt`}\n >\n H:{sessionState.contextHistoryLimit}\n </button>\n <VoiceToggle\n enabled={sessionState.voiceEnabled}\n onToggle={() => {\n toggleVoice(sessionId);\n if (!sessionState.voiceEnabled) startListening();\n else stopListening();\n }}\n isListening={isListening}\n />\n <FileAttachButton onFileSelect={handleFileSelect} />\n </div>\n\n {/* Textarea + send/cancel */}\n <div className=\"flex items-end gap-2 px-3 pb-3 pt-1\">\n <textarea\n ref={textareaRef}\n value={text}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={tr(\n 'vibecontrols.agentManager.inputArea.placeholder',\n 'Type a message or / for commands... (Enter to send)'\n )}\n rows={1}\n className=\"flex-1 resize-none rounded-lg border border-border-default bg-bg-primary px-3 py-2 text-sm text-text-primary placeholder:text-text-tertiary focus:outline-none focus:border-border-strong transition-colors\"\n disabled={isStreaming}\n />\n {isStreaming ? (\n <button\n type=\"button\"\n onClick={handleCancel}\n className=\"flex-shrink-0 p-2 rounded-lg bg-status-error-bg text-status-error-text hover:opacity-90 transition-opacity\"\n title={tr('vibecontrols.agentManager.inputArea.cancel', 'Cancel')}\n >\n <Square className=\"w-4 h-4\" />\n </button>\n ) : (\n <div className=\"flex items-end flex-shrink-0 relative\" ref={scheduleMenuRef}>\n <button\n type=\"button\"\n onClick={handleSend}\n disabled={!canSend}\n className=\"p-2 rounded-l-lg bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-40 disabled:cursor-not-allowed transition-colors\"\n title={tr('vibecontrols.agentManager.inputArea.send', 'Send (Enter)')}\n >\n <ArrowUp className=\"w-4 h-4\" />\n </button>\n <button\n type=\"button\"\n onClick={() => setShowScheduleMenu(!showScheduleMenu)}\n disabled={!canSend}\n className=\"ml-1 p-2 rounded-r-lg border-l border-action-primary-text/20 bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-40 disabled:cursor-not-allowed transition-colors\"\n title={tr('vibecontrols.agentManager.inputArea.scheduleSend', 'Schedule send')}\n >\n <ChevronDown className=\"w-3 h-3\" />\n </button>\n\n {/* Schedule dropdown */}\n {showScheduleMenu && (\n <div className=\"absolute bottom-full right-0 mb-1 w-56 bg-bg-surface border border-border-default rounded-md shadow-lg py-1 z-50\">\n {!showSchedulePopup ? (\n <button\n type=\"button\"\n onClick={() => setShowSchedulePopup(true)}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-left text-xs text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Clock className=\"w-3.5 h-3.5 text-text-secondary\" />\n {tr(\n 'vibecontrols.agentManager.inputArea.scheduleSendEllipsis',\n 'Schedule Send...'\n )}\n </button>\n ) : (\n <div className=\"px-3 py-2 space-y-2\">\n <label className=\"block text-[11px] font-medium text-text-secondary\">\n {tr('vibecontrols.agentManager.inputArea.sendAt', 'Send at:')}\n </label>\n <input\n type=\"datetime-local\"\n value={scheduleDateTime}\n onChange={(e) => setScheduleDateTime(e.target.value)}\n className=\"w-full px-2 py-1 text-xs rounded border border-border-default bg-bg-primary text-text-primary focus:outline-none focus:border-border-strong\"\n />\n <button\n type=\"button\"\n onClick={() => void handleScheduleSend()}\n disabled={!scheduleDateTime || !agentTunnelUrl || !agentApiKey}\n className=\"w-full px-2 py-1.5 text-xs font-medium rounded bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-40 disabled:cursor-not-allowed transition-colors\"\n >\n {tr('vibecontrols.agentManager.inputArea.schedule', 'Schedule')}\n </button>\n </div>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -24,21 +24,7 @@ function s({ onFileSelect: s }) {
24
24
  onChange: d
25
25
  })] });
26
26
  }
27
- function c(e) {
28
- function t(e) {
29
- e.preventDefault(), e.stopPropagation();
30
- }
31
- function n(t) {
32
- t.preventDefault(), t.stopPropagation();
33
- let n = t.dataTransfer?.files;
34
- n && n.length > 0 && e(Array.from(n));
35
- }
36
- return {
37
- onDragOver: t,
38
- onDrop: n
39
- };
40
- }
41
27
  //#endregion
42
- export { s as FileAttachButton, c as createDropHandlers };
28
+ export { s as FileAttachButton };
43
29
 
44
30
  //# sourceMappingURL=FileAttachButton.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FileAttachButton.js","names":[],"sources":["../../../../src/components/agent-manager/controls/FileAttachButton.tsx"],"sourcesContent":["/**\n * File attachment button.\n *\n * Paperclip icon that opens the native file picker. Also exposes\n * drag-and-drop helpers for the parent to wire up.\n */\n\nimport { useRef, useCallback, type DragEvent } from 'react';\nimport { Paperclip } from 'lucide-react';\nimport { useTr } from '../../../shared/hooks/useTr';\n\ninterface FileAttachButtonProps {\n onFileSelect: (files: File[]) => void;\n}\n\nexport function FileAttachButton({ onFileSelect }: FileAttachButtonProps) {\n const tr = useTr();\n const inputRef = useRef<HTMLInputElement>(null);\n\n const handleClick = useCallback(() => {\n inputRef.current?.click();\n }, []);\n\n const handleInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const files = e.target.files;\n if (files && files.length > 0) {\n onFileSelect(Array.from(files));\n }\n // Reset so the same file can be re-selected\n if (inputRef.current) {\n inputRef.current.value = '';\n }\n },\n [onFileSelect]\n );\n\n return (\n <>\n <button\n type=\"button\"\n onClick={handleClick}\n className=\"p-1.5 rounded text-text-tertiary hover:text-text-secondary hover:bg-bg-elevated transition-colors\"\n title={tr('vibecontrols.agentManager.controls.attachFile', 'Attach file')}\n >\n <Paperclip className=\"w-4 h-4\" />\n </button>\n <input ref={inputRef} type=\"file\" multiple className=\"hidden\" onChange={handleInputChange} />\n </>\n );\n}\n\n/** Drag-and-drop handler helpers for use on the parent container. */\nexport function createDropHandlers(onFileSelect: (files: File[]) => void) {\n function handleDragOver(e: DragEvent) {\n e.preventDefault();\n e.stopPropagation();\n }\n\n function handleDrop(e: DragEvent) {\n e.preventDefault();\n e.stopPropagation();\n const files = e.dataTransfer?.files;\n if (files && files.length > 0) {\n onFileSelect(Array.from(files));\n }\n }\n\n return { onDragOver: handleDragOver, onDrop: handleDrop };\n}\n"],"mappings":";;;;;AAeA,SAAgB,EAAiB,EAAE,mBAAuC;CACxE,IAAM,IAAK,GAAO,EACZ,IAAW,EAAyB,KAAK,EAEzC,IAAc,QAAkB;AACpC,IAAS,SAAS,OAAO;IACxB,EAAE,CAAC,EAEA,IAAoB,GACvB,MAA2C;EAC1C,IAAM,IAAQ,EAAE,OAAO;AAKvB,EAJI,KAAS,EAAM,SAAS,KAC1B,EAAa,MAAM,KAAK,EAAM,CAAC,EAG7B,EAAS,YACX,EAAS,QAAQ,QAAQ;IAG7B,CAAC,EAAa,CACf;AAED,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,UAAD;EACE,MAAK;EACL,SAAS;EACT,WAAU;EACV,OAAO,EAAG,iDAAiD,cAAc;YAEzE,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA;EAC1B,CAAA,EACT,kBAAC,SAAD;EAAO,KAAK;EAAU,MAAK;EAAO,UAAA;EAAS,WAAU;EAAS,UAAU;EAAqB,CAAA,CAC5F,EAAA,CAAA;;AAKP,SAAgB,EAAmB,GAAuC;CACxE,SAAS,EAAe,GAAc;AAEpC,EADA,EAAE,gBAAgB,EAClB,EAAE,iBAAiB;;CAGrB,SAAS,EAAW,GAAc;AAEhC,EADA,EAAE,gBAAgB,EAClB,EAAE,iBAAiB;EACnB,IAAM,IAAQ,EAAE,cAAc;AAC9B,EAAI,KAAS,EAAM,SAAS,KAC1B,EAAa,MAAM,KAAK,EAAM,CAAC;;AAInC,QAAO;EAAE,YAAY;EAAgB,QAAQ;EAAY"}
1
+ {"version":3,"file":"FileAttachButton.js","names":[],"sources":["../../../../src/components/agent-manager/controls/FileAttachButton.tsx"],"sourcesContent":["/**\n * File attachment button.\n *\n * Paperclip icon that opens the native file picker. Also exposes\n * drag-and-drop helpers for the parent to wire up.\n */\n\nimport { useRef, useCallback } from 'react';\nimport { Paperclip } from 'lucide-react';\nimport { useTr } from '../../../shared/hooks/useTr';\n\ninterface FileAttachButtonProps {\n onFileSelect: (files: File[]) => void;\n}\n\nexport function FileAttachButton({ onFileSelect }: FileAttachButtonProps) {\n const tr = useTr();\n const inputRef = useRef<HTMLInputElement>(null);\n\n const handleClick = useCallback(() => {\n inputRef.current?.click();\n }, []);\n\n const handleInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const files = e.target.files;\n if (files && files.length > 0) {\n onFileSelect(Array.from(files));\n }\n // Reset so the same file can be re-selected\n if (inputRef.current) {\n inputRef.current.value = '';\n }\n },\n [onFileSelect]\n );\n\n return (\n <>\n <button\n type=\"button\"\n onClick={handleClick}\n className=\"p-1.5 rounded text-text-tertiary hover:text-text-secondary hover:bg-bg-elevated transition-colors\"\n title={tr('vibecontrols.agentManager.controls.attachFile', 'Attach file')}\n >\n <Paperclip className=\"w-4 h-4\" />\n </button>\n <input ref={inputRef} type=\"file\" multiple className=\"hidden\" onChange={handleInputChange} />\n </>\n );\n}\n\n"],"mappings":";;;;;AAeA,SAAgB,EAAiB,EAAE,mBAAuC;CACxE,IAAM,IAAK,GAAO,EACZ,IAAW,EAAyB,KAAK,EAEzC,IAAc,QAAkB;AACpC,IAAS,SAAS,OAAO;IACxB,EAAE,CAAC,EAEA,IAAoB,GACvB,MAA2C;EAC1C,IAAM,IAAQ,EAAE,OAAO;AAKvB,EAJI,KAAS,EAAM,SAAS,KAC1B,EAAa,MAAM,KAAK,EAAM,CAAC,EAG7B,EAAS,YACX,EAAS,QAAQ,QAAQ;IAG7B,CAAC,EAAa,CACf;AAED,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,UAAD;EACE,MAAK;EACL,SAAS;EACT,WAAU;EACV,OAAO,EAAG,iDAAiD,cAAc;YAEzE,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA;EAC1B,CAAA,EACT,kBAAC,SAAD;EAAO,KAAK;EAAU,MAAK;EAAO,UAAA;EAAS,WAAU;EAAS,UAAU;EAAqB,CAAA,CAC5F,EAAA,CAAA"}
@@ -0,0 +1,19 @@
1
+ //#region src/components/agent-manager/controls/createDropHandlers.ts
2
+ function e(e) {
3
+ function t(e) {
4
+ e.preventDefault(), e.stopPropagation();
5
+ }
6
+ function n(t) {
7
+ t.preventDefault(), t.stopPropagation();
8
+ let n = t.dataTransfer?.files;
9
+ n && n.length > 0 && e(Array.from(n));
10
+ }
11
+ return {
12
+ onDragOver: t,
13
+ onDrop: n
14
+ };
15
+ }
16
+ //#endregion
17
+ export { e as createDropHandlers };
18
+
19
+ //# sourceMappingURL=createDropHandlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createDropHandlers.js","names":[],"sources":["../../../../src/components/agent-manager/controls/createDropHandlers.ts"],"sourcesContent":["import type { DragEvent } from 'react';\n\n/** Drag-and-drop handler helpers for use on the parent container. */\nexport function createDropHandlers(onFileSelect: (files: File[]) => void) {\n function handleDragOver(e: DragEvent) {\n e.preventDefault();\n e.stopPropagation();\n }\n\n function handleDrop(e: DragEvent) {\n e.preventDefault();\n e.stopPropagation();\n const files = e.dataTransfer?.files;\n if (files && files.length > 0) {\n onFileSelect(Array.from(files));\n }\n }\n\n return { onDragOver: handleDragOver, onDrop: handleDrop };\n}\n"],"mappings":";AAGA,SAAgB,EAAmB,GAAuC;CACxE,SAAS,EAAe,GAAc;AAEpC,EADA,EAAE,gBAAgB,EAClB,EAAE,iBAAiB;;CAGrB,SAAS,EAAW,GAAc;AAEhC,EADA,EAAE,gBAAgB,EAClB,EAAE,iBAAiB;EACnB,IAAM,IAAQ,EAAE,cAAc;AAC9B,EAAI,KAAS,EAAM,SAAS,KAC1B,EAAa,MAAM,KAAK,EAAM,CAAC;;AAInC,QAAO;EAAE,YAAY;EAAgB,QAAQ;EAAY"}
@@ -9,7 +9,11 @@ import { jsx as p, jsxs as m } from "react/jsx-runtime";
9
9
  function h({ isOpen: h, agent: g, onClose: _ }) {
10
10
  let [v, y] = o(""), [b, x] = o([]), [S, C] = o(!1), w = e(), T = a(null), E = a(null), D = f(), O = n((e) => e.openSession);
11
11
  i(() => {
12
- h && (y(""), x([]), setTimeout(() => T.current?.focus(), 50));
12
+ if (h) {
13
+ y(""), x([]);
14
+ let e = setTimeout(() => T.current?.focus(), 50);
15
+ return () => clearTimeout(e);
16
+ }
13
17
  }, [h]), i(() => {
14
18
  if (!v.trim()) {
15
19
  x([]), C(!1);
@@ -1 +1 @@
1
- {"version":3,"file":"SessionSearchDialog.js","names":[],"sources":["../../../../src/components/agent-manager/dialogs/SessionSearchDialog.tsx"],"sourcesContent":["/**\n * Cmd+K style session search dialog.\n *\n * Full-screen overlay with a prominent search input. Results appear\n * in real-time (debounced) and clicking a result opens the session tab\n * and scrolls to the matched message.\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react';\nimport { Search, X, MessageSquare } from 'lucide-react';\nimport { motion, AnimatePresence, useReducedMotion } from 'framer-motion';\nimport { searchSessions, type SearchResult, type AgentRef } from '@/services/aiApi';\nimport { useAgentManagerStore } from '@/store/agentManagerStore';\nimport { useTr } from '../../../shared/hooks/useTr';\n\ninterface SessionSearchDialogProps {\n isOpen: boolean;\n agent: AgentRef;\n onClose: () => void;\n}\n\nexport function SessionSearchDialog({ isOpen, agent, onClose }: SessionSearchDialogProps) {\n const [query, setQuery] = useState('');\n const [results, setResults] = useState<SearchResult[]>([]);\n const [searching, setSearching] = useState(false);\n const tr = useTr();\n const inputRef = useRef<HTMLInputElement>(null);\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const shouldReduceMotion = useReducedMotion();\n\n const openSession = useAgentManagerStore((s) => s.openSession);\n\n // Focus input when opened\n useEffect(() => {\n if (isOpen) {\n setQuery('');\n setResults([]);\n setTimeout(() => inputRef.current?.focus(), 50);\n }\n }, [isOpen]);\n\n // Debounced search\n useEffect(() => {\n if (!query.trim()) {\n setResults([]);\n setSearching(false);\n return;\n }\n\n setSearching(true);\n\n if (debounceRef.current) {\n clearTimeout(debounceRef.current);\n }\n\n debounceRef.current = setTimeout(async () => {\n try {\n const data = await searchSessions(agent, query.trim());\n setResults(data);\n } catch {\n setResults([]);\n } finally {\n setSearching(false);\n }\n }, 300);\n\n return () => {\n if (debounceRef.current) {\n clearTimeout(debounceRef.current);\n }\n };\n }, [query, agent]);\n\n const handleSelect = useCallback(\n (result: SearchResult) => {\n openSession(result.sessionId, result.sessionName);\n onClose();\n },\n [openSession, onClose]\n );\n\n // Close on Escape\n useEffect(() => {\n if (!isOpen) return;\n function handleKeyDown(e: KeyboardEvent) {\n if (e.key === 'Escape') {\n onClose();\n }\n }\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [isOpen, onClose]);\n\n if (!isOpen) return null;\n\n return (\n <AnimatePresence>\n {isOpen && (\n <div className=\"fixed inset-0 z-50 flex items-start justify-center pt-[15vh]\">\n <motion.div\n className=\"absolute inset-0 bg-bg-overlay\"\n initial={shouldReduceMotion ? undefined : { opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.15 }}\n onClick={onClose}\n />\n <motion.div\n className=\"relative w-full max-w-xl mx-4 rounded-lg border border-border-default bg-bg-surface shadow-xl overflow-hidden\"\n initial={shouldReduceMotion ? undefined : { opacity: 0, y: -8, scale: 0.98 }}\n animate={{ opacity: 1, y: 0, scale: 1 }}\n exit={{ opacity: 0, y: -8, scale: 0.98 }}\n transition={{ duration: 0.15, ease: [0.2, 0, 0, 1] }}\n >\n {/* Search input */}\n <div className=\"flex items-center gap-3 px-4 py-3 border-b border-border-default\">\n <Search className=\"w-5 h-5 text-text-tertiary flex-shrink-0\" />\n <input\n ref={inputRef}\n type=\"text\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder={tr(\n 'vibecontrols.agentManager.dialogs.searchPlaceholder',\n 'Search sessions and messages...'\n )}\n className=\"flex-1 bg-transparent text-sm text-text-primary placeholder:text-text-tertiary focus:outline-none\"\n />\n {query && (\n <button\n type=\"button\"\n onClick={() => setQuery('')}\n className=\"p-0.5 rounded hover:bg-bg-elevated transition-colors\"\n >\n <X className=\"w-4 h-4 text-text-tertiary\" />\n </button>\n )}\n </div>\n\n {/* Results */}\n <div className=\"max-h-[50vh] overflow-y-auto\">\n {searching && (\n <div className=\"px-4 py-6 text-center text-sm text-text-tertiary\">\n {tr('vibecontrols.agentManager.dialogs.searching', 'Searching...')}\n </div>\n )}\n\n {!searching && query.trim() && results.length === 0 && (\n <div className=\"px-4 py-6 text-center text-sm text-text-tertiary\">\n {tr('vibecontrols.agentManager.dialogs.noResultsFound', 'No results found')}\n </div>\n )}\n\n {!searching && results.length > 0 && (\n <div className=\"py-1\">\n {results.map((result, index) => (\n <button\n key={`${result.sessionId}-${result.messageId ?? index}`}\n type=\"button\"\n onClick={() => handleSelect(result)}\n className=\"w-full text-left px-4 py-3 hover:bg-bg-elevated transition-colors\"\n >\n <div className=\"flex items-center gap-2 mb-1\">\n <MessageSquare className=\"w-3.5 h-3.5 text-text-tertiary flex-shrink-0\" />\n <span className=\"text-sm font-medium text-text-primary truncate\">\n {result.sessionName}\n </span>\n <span className=\"text-[10px] text-text-tertiary ml-auto flex-shrink-0\">\n {new Date(result.timestamp).toLocaleDateString()}\n </span>\n </div>\n <p className=\"text-xs text-text-secondary line-clamp-2 pl-5.5\">\n {result.content}\n </p>\n </button>\n ))}\n </div>\n )}\n\n {!query.trim() && (\n <div className=\"px-4 py-6 text-center text-sm text-text-tertiary\">\n {tr(\n 'vibecontrols.agentManager.dialogs.typeToSearch',\n 'Type to search across all sessions'\n )}\n </div>\n )}\n </div>\n\n {/* Footer hint */}\n <div className=\"flex items-center gap-4 px-4 py-2 border-t border-border-default bg-bg-sunken text-[10px] text-text-tertiary\">\n <span>\n <kbd className=\"px-1 py-0.5 rounded bg-bg-elevated border border-border-default font-mono\">\n Esc\n </kbd>{' '}\n to close\n </span>\n <span>\n <kbd className=\"px-1 py-0.5 rounded bg-bg-elevated border border-border-default font-mono\">\n Enter\n </kbd>{' '}\n to select\n </span>\n </div>\n </motion.div>\n </div>\n )}\n </AnimatePresence>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"SessionSearchDialog.js","names":[],"sources":["../../../../src/components/agent-manager/dialogs/SessionSearchDialog.tsx"],"sourcesContent":["/**\n * Cmd+K style session search dialog.\n *\n * Full-screen overlay with a prominent search input. Results appear\n * in real-time (debounced) and clicking a result opens the session tab\n * and scrolls to the matched message.\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react';\nimport { Search, X, MessageSquare } from 'lucide-react';\nimport { motion, AnimatePresence, useReducedMotion } from 'framer-motion';\nimport { searchSessions, type SearchResult, type AgentRef } from '@/services/aiApi';\nimport { useAgentManagerStore } from '@/store/agentManagerStore';\nimport { useTr } from '../../../shared/hooks/useTr';\n\ninterface SessionSearchDialogProps {\n isOpen: boolean;\n agent: AgentRef;\n onClose: () => void;\n}\n\nexport function SessionSearchDialog({ isOpen, agent, onClose }: SessionSearchDialogProps) {\n const [query, setQuery] = useState('');\n const [results, setResults] = useState<SearchResult[]>([]);\n const [searching, setSearching] = useState(false);\n const tr = useTr();\n const inputRef = useRef<HTMLInputElement>(null);\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const shouldReduceMotion = useReducedMotion();\n\n const openSession = useAgentManagerStore((s) => s.openSession);\n\n // Focus input when opened\n useEffect(() => {\n if (isOpen) {\n setQuery('');\n setResults([]);\n const id = setTimeout(() => inputRef.current?.focus(), 50);\n return () => clearTimeout(id);\n }\n return undefined;\n }, [isOpen]);\n\n // Debounced search\n useEffect(() => {\n if (!query.trim()) {\n setResults([]);\n setSearching(false);\n return;\n }\n\n setSearching(true);\n\n if (debounceRef.current) {\n clearTimeout(debounceRef.current);\n }\n\n debounceRef.current = setTimeout(async () => {\n try {\n const data = await searchSessions(agent, query.trim());\n setResults(data);\n } catch {\n setResults([]);\n } finally {\n setSearching(false);\n }\n }, 300);\n\n return () => {\n if (debounceRef.current) {\n clearTimeout(debounceRef.current);\n }\n };\n }, [query, agent]);\n\n const handleSelect = useCallback(\n (result: SearchResult) => {\n openSession(result.sessionId, result.sessionName);\n onClose();\n },\n [openSession, onClose]\n );\n\n // Close on Escape\n useEffect(() => {\n if (!isOpen) return;\n function handleKeyDown(e: KeyboardEvent) {\n if (e.key === 'Escape') {\n onClose();\n }\n }\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [isOpen, onClose]);\n\n if (!isOpen) return null;\n\n return (\n <AnimatePresence>\n {isOpen && (\n <div className=\"fixed inset-0 z-50 flex items-start justify-center pt-[15vh]\">\n <motion.div\n className=\"absolute inset-0 bg-bg-overlay\"\n initial={shouldReduceMotion ? undefined : { opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.15 }}\n onClick={onClose}\n />\n <motion.div\n className=\"relative w-full max-w-xl mx-4 rounded-lg border border-border-default bg-bg-surface shadow-xl overflow-hidden\"\n initial={shouldReduceMotion ? undefined : { opacity: 0, y: -8, scale: 0.98 }}\n animate={{ opacity: 1, y: 0, scale: 1 }}\n exit={{ opacity: 0, y: -8, scale: 0.98 }}\n transition={{ duration: 0.15, ease: [0.2, 0, 0, 1] }}\n >\n {/* Search input */}\n <div className=\"flex items-center gap-3 px-4 py-3 border-b border-border-default\">\n <Search className=\"w-5 h-5 text-text-tertiary flex-shrink-0\" />\n <input\n ref={inputRef}\n type=\"text\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder={tr(\n 'vibecontrols.agentManager.dialogs.searchPlaceholder',\n 'Search sessions and messages...'\n )}\n className=\"flex-1 bg-transparent text-sm text-text-primary placeholder:text-text-tertiary focus:outline-none\"\n />\n {query && (\n <button\n type=\"button\"\n onClick={() => setQuery('')}\n className=\"p-0.5 rounded hover:bg-bg-elevated transition-colors\"\n >\n <X className=\"w-4 h-4 text-text-tertiary\" />\n </button>\n )}\n </div>\n\n {/* Results */}\n <div className=\"max-h-[50vh] overflow-y-auto\">\n {searching && (\n <div className=\"px-4 py-6 text-center text-sm text-text-tertiary\">\n {tr('vibecontrols.agentManager.dialogs.searching', 'Searching...')}\n </div>\n )}\n\n {!searching && query.trim() && results.length === 0 && (\n <div className=\"px-4 py-6 text-center text-sm text-text-tertiary\">\n {tr('vibecontrols.agentManager.dialogs.noResultsFound', 'No results found')}\n </div>\n )}\n\n {!searching && results.length > 0 && (\n <div className=\"py-1\">\n {results.map((result, index) => (\n <button\n key={`${result.sessionId}-${result.messageId ?? index}`}\n type=\"button\"\n onClick={() => handleSelect(result)}\n className=\"w-full text-left px-4 py-3 hover:bg-bg-elevated transition-colors\"\n >\n <div className=\"flex items-center gap-2 mb-1\">\n <MessageSquare className=\"w-3.5 h-3.5 text-text-tertiary flex-shrink-0\" />\n <span className=\"text-sm font-medium text-text-primary truncate\">\n {result.sessionName}\n </span>\n <span className=\"text-[10px] text-text-tertiary ml-auto flex-shrink-0\">\n {new Date(result.timestamp).toLocaleDateString()}\n </span>\n </div>\n <p className=\"text-xs text-text-secondary line-clamp-2 pl-5.5\">\n {result.content}\n </p>\n </button>\n ))}\n </div>\n )}\n\n {!query.trim() && (\n <div className=\"px-4 py-6 text-center text-sm text-text-tertiary\">\n {tr(\n 'vibecontrols.agentManager.dialogs.typeToSearch',\n 'Type to search across all sessions'\n )}\n </div>\n )}\n </div>\n\n {/* Footer hint */}\n <div className=\"flex items-center gap-4 px-4 py-2 border-t border-border-default bg-bg-sunken text-[10px] text-text-tertiary\">\n <span>\n <kbd className=\"px-1 py-0.5 rounded bg-bg-elevated border border-border-default font-mono\">\n Esc\n </kbd>{' '}\n to close\n </span>\n <span>\n <kbd className=\"px-1 py-0.5 rounded bg-bg-elevated border border-border-default font-mono\">\n Enter\n </kbd>{' '}\n to select\n </span>\n </div>\n </motion.div>\n </div>\n )}\n </AnimatePresence>\n );\n}\n"],"mappings":"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"}
@@ -112,7 +112,7 @@ function h({ onSubmit: h, onCancel: g, isLoading: _, onNavigate: v, targets: y,
112
112
  x,
113
113
  L,
114
114
  S
115
- ]), Pe = ({ text: e, id: t }) => /* @__PURE__ */ p("button", {
115
+ ]), Pe = (e, t) => /* @__PURE__ */ p("button", {
116
116
  type: "button",
117
117
  onClick: () => Ee(e, t),
118
118
  className: "p-1 rounded hover:bg-bg-elevated transition-colors",
@@ -208,10 +208,7 @@ function h({ onSubmit: h, onCancel: g, isLoading: _, onNavigate: v, targets: y,
208
208
  className: "flex-1",
209
209
  children: e.cmd
210
210
  }),
211
- /* @__PURE__ */ p(Pe, {
212
- text: e.cmd,
213
- id: e.cmd
214
- })
211
+ Pe(e.cmd, e.cmd)
215
212
  ]
216
213
  })] }, e.cmd))
217
214
  })