@burdenoff/microfe-vibecontrols 2026.529.16 → 2026.529.18

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.
Files changed (39) hide show
  1. package/dist/components/agent-manager/AgentManagerChatPane.js +1 -2
  2. package/dist/components/agent-manager/AgentManagerChatPane.js.map +1 -1
  3. package/dist/components/agent-manager/AgentManagerInputArea.js +114 -116
  4. package/dist/components/agent-manager/AgentManagerInputArea.js.map +1 -1
  5. package/dist/components/agents/OpenInBrowserEditorButton.js +109 -97
  6. package/dist/components/agents/OpenInBrowserEditorButton.js.map +1 -1
  7. package/dist/components/agents/OpenInEditorMenu.js +38 -43
  8. package/dist/components/agents/OpenInEditorMenu.js.map +1 -1
  9. package/dist/components/agents/PluginUIPanel.js +161 -149
  10. package/dist/components/agents/PluginUIPanel.js.map +1 -1
  11. package/dist/components/agents/backup/AgentBackupTab.js +124 -132
  12. package/dist/components/agents/backup/AgentBackupTab.js.map +1 -1
  13. package/dist/components/ai/AIPlanPanel.js +201 -188
  14. package/dist/components/ai/AIPlanPanel.js.map +1 -1
  15. package/dist/components/plugins/AddTabDialog.js +4 -4
  16. package/dist/components/sessions/TerminalPanel.js +332 -296
  17. package/dist/components/sessions/TerminalPanel.js.map +1 -1
  18. package/dist/generated/wspace-operations.js +1499 -1364
  19. package/dist/generated/wspace-operations.js.map +1 -1
  20. package/dist/generated/wspace-types.js.map +1 -1
  21. package/dist/hooks/useCachedInitialData.js +0 -1
  22. package/dist/hooks/useCachedInitialData.js.map +1 -1
  23. package/dist/index.js +10 -10
  24. package/dist/pages/AgentDetailsPage.js +837 -894
  25. package/dist/pages/AgentDetailsPage.js.map +1 -1
  26. package/dist/pages/AgentsPage.js +89 -109
  27. package/dist/pages/AgentsPage.js.map +1 -1
  28. package/dist/pages/VibeDetailsPage.js +210 -210
  29. package/dist/pages/VibeDetailsPage.js.map +1 -1
  30. package/dist/pages/ai/AIPage.js +1 -2
  31. package/dist/pages/ai/AIPage.js.map +1 -1
  32. package/dist/pages/ai/AISessionDetailPage.js +1 -1
  33. package/dist/pages/ai/AISessionDetailPage.js.map +1 -1
  34. package/dist/pages/ai/AgentManagerPage.js +1 -1
  35. package/dist/pages/ai/AgentManagerPage.js.map +1 -1
  36. package/dist/services/iframeToken.js +4 -4
  37. package/dist/services/schedulerApi.js +1 -1
  38. package/dist/services/schedulerApi.js.map +1 -1
  39. package/package.json +1 -1
@@ -166,8 +166,7 @@ var C = ({ sessionId: d, agentId: C }) => {
166
166
  sessionId: d,
167
167
  onSend: (e) => void J(e),
168
168
  onCancel: Y,
169
- agentTunnelUrl: H?.tunnelUrl ?? void 0,
170
- agentApiKey: H?.agentApiKey ?? void 0
169
+ agentTunnelUrl: H?.tunnelUrl ?? void 0
171
170
  }),
172
171
  /* @__PURE__ */ x(l, {
173
172
  open: te,
@@ -1 +1 @@
1
- {"version":3,"file":"AgentManagerChatPane.js","names":[],"sources":["../../../src/components/agent-manager/AgentManagerChatPane.tsx"],"sourcesContent":["/**\n * Main chat interface for a single Agent Manager session.\n *\n * Renders message list + input area, manages the send/receive flow,\n * fetches existing conversation logs on mount, and provides\n * auto-scroll, cancel, and in-session search support.\n */\n\nimport { useEffect, useRef, useState, useCallback, useMemo, type FC } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport { Bookmark, PackagePlus, Search, X } from 'lucide-react';\nimport { useAgentManagerStore } from '@/store/agentManagerStore';\nimport { useAgentManagerStreaming } from '@/hooks/useAgentManagerStreaming';\nimport { useCachedInitialData } from '@/hooks/useCachedInitialData';\nimport { fetchSessionLogs } from '@/services/aiApi';\nimport { useActiveAgentProfile } from '@/hooks/useActiveAgentProfile';\nimport { useToggleAgentBookmark } from '@/hooks/useToggleAgentBookmark';\nimport { AgentManagerMessageList } from './AgentManagerMessageList';\nimport { AgentManagerInputArea } from './AgentManagerInputArea';\nimport { AgentManagerBookmarksDrawer } from './AgentManagerBookmarksDrawer';\nimport { PluginInstallModal } from './PluginInstallModal';\nimport { AIProviderCredentialsCard } from '@/components/ai/AIProviderCredentialsCard';\nimport type { AgentManagerMessage } from '@/types/agentManager';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface AgentManagerChatPaneProps {\n sessionId: string;\n agentId: string;\n}\n\nexport const AgentManagerChatPane: FC<AgentManagerChatPaneProps> = ({ sessionId, agentId }) => {\n const [loadingLogs, setLoadingLogs] = useState(false);\n const [searchOpen, setSearchOpen] = useState(false);\n const [searchQuery, setSearchQuery] = useState('');\n // Provider-install modal triggered from the header. Lets users add a\n // claude/codex/gemini/opencode plugin without leaving the conversation.\n const [installModalOpen, setInstallModalOpen] = useState(false);\n const [bookmarksDrawerOpen, setBookmarksDrawerOpen] = useState(false);\n const [flashMessageId, setFlashMessageId] = useState<string | null>(null);\n const [searchParams, setSearchParams] = useSearchParams();\n const pendingScrollMessageId = searchParams.get('messageId');\n const consumedScrollTargetRef = useRef<string | null>(null);\n const tr = useTr();\n\n const { agents } = useCachedInitialData();\n const activeAgent = useMemo(\n () => agents.find((a) => a.id === agentId) ?? null,\n [agents, agentId]\n );\n\n const sessionState = useAgentManagerStore((s) => s.sessionStates[sessionId]);\n const addMessage = useAgentManagerStore((s) => s.addMessage);\n\n const messages = useMemo(() => sessionState?.messages ?? [], [sessionState?.messages]);\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 { sendMessage, cancelStream, isStreaming } = useAgentManagerStreaming({\n agent: agentRef,\n sessionId,\n });\n\n const { bookmarkedIds, toggle: toggleBookmark } = useToggleAgentBookmark(sessionId);\n\n const jumpToMessage = useCallback((messageId: string) => {\n const el = document.querySelector(`[data-message-id=\"${messageId}\"]`);\n if (!el) return;\n el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n setFlashMessageId(messageId);\n window.setTimeout(() => {\n setFlashMessageId((current) => (current === messageId ? null : current));\n }, 1500);\n }, []);\n\n const handleToggleBookmark = useCallback(\n (messageId: string) => {\n void toggleBookmark({ agentId, sessionId, messageId });\n },\n [toggleBookmark, agentId, sessionId]\n );\n\n const toggleSearch = useCallback(() => {\n setSearchOpen((prev) => {\n if (prev) setSearchQuery('');\n return !prev;\n });\n }, []);\n\n // Fetch existing conversation logs on mount\n useEffect(() => {\n let cancelled = false;\n\n const loadExistingLogs = async () => {\n // Only load if session has no messages yet\n if (messages.length > 0) return;\n\n setLoadingLogs(true);\n try {\n const logs = await fetchSessionLogs(agentRef, sessionId, {\n types: ['input', 'output'],\n });\n\n if (cancelled || logs.length === 0) return;\n\n const seenLogKeys = new Set<string>();\n\n // Convert session logs to AgentManagerMessage format. The core AI\n // route owns logging, but older provider builds also wrote the same\n // input/output records; collapse same-second duplicates on restore.\n for (const log of logs) {\n const content = log.message || log.content || '';\n const timestamp = log.timestamp || log.createdAt;\n const timestampSecond = timestamp ? Math.floor(new Date(timestamp).getTime() / 1000) : 0;\n const logKey = [log.type, content, log.model ?? '', timestampSecond].join('\\u0000');\n if (seenLogKeys.has(logKey)) continue;\n seenLogKeys.add(logKey);\n\n const msg: AgentManagerMessage = {\n id: log.id,\n role: log.type === 'input' ? 'user' : 'assistant',\n content,\n timestamp,\n tokens: log.tokenCount ? { input: 0, output: log.tokenCount } : undefined,\n model: log.model,\n };\n addMessage(sessionId, msg);\n }\n } catch {\n // Silent fail -- session may not have logs yet\n } finally {\n if (!cancelled) setLoadingLogs(false);\n }\n };\n\n void loadExistingLogs();\n\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- only run on mount\n }, [agentId, sessionId]);\n\n // Auto-scroll to a message linked via ?messageId=... (from drawer / cross-session page).\n // Waits for logs to finish loading and the target to be in the DOM before scrolling.\n useEffect(() => {\n if (!pendingScrollMessageId || loadingLogs) return;\n if (consumedScrollTargetRef.current === pendingScrollMessageId) return;\n\n const exists = messages.some((m) => m.id === pendingScrollMessageId);\n if (!exists) return;\n\n consumedScrollTargetRef.current = pendingScrollMessageId;\n jumpToMessage(pendingScrollMessageId);\n\n // Strip the query param so a manual refresh doesn't re-trigger the flash.\n const next = new URLSearchParams(searchParams);\n next.delete('messageId');\n setSearchParams(next, { replace: true });\n }, [pendingScrollMessageId, loadingLogs, messages, jumpToMessage, searchParams, setSearchParams]);\n\n return (\n <div className=\"flex flex-col h-full min-h-0\" data-testid=\"agent-manager-chat-pane\">\n {/* In-session search bar.\n Layout: [search controls (flex-1)] ... [Manage AI providers].\n The search input expands inside the LEFT cluster only, so the\n Manage button stays anchored on the right and never shifts. */}\n <div className=\"flex items-center gap-1 px-3 py-1 border-b border-border-default bg-bg-surface flex-shrink-0\">\n <div className=\"flex items-center gap-1.5 min-w-0 flex-1\">\n <button\n type=\"button\"\n onClick={toggleSearch}\n className={`p-1 rounded transition-colors shrink-0 ${\n searchOpen\n ? 'bg-action-primary-bg/10 text-action-primary-text'\n : 'text-text-tertiary hover:text-text-secondary hover:bg-bg-elevated'\n }`}\n title={tr(\n 'vibecontrols.agentManager.chatPane.searchInSession',\n 'Search in session (Ctrl+F)'\n )}\n aria-label={tr(\n 'vibecontrols.agentManager.chatPane.searchInSession',\n 'Search in session'\n )}\n >\n <Search className=\"size-3.5\" />\n </button>\n {searchOpen && (\n <div className=\"flex items-center gap-1.5 flex-1 min-w-0\">\n <input\n aria-label=\"control\"\n type=\"text\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n placeholder={tr(\n 'vibecontrols.agentManager.chatPane.searchPlaceholder',\n 'Search in conversation...'\n )}\n className=\"flex-1 min-w-0 bg-transparent text-xs text-text-primary placeholder:text-text-tertiary focus:outline-none\"\n />\n {searchQuery && (\n <button\n type=\"button\"\n onClick={() => setSearchQuery('')}\n className=\"p-0.5 rounded hover:bg-bg-elevated transition-colors\"\n >\n <X className=\"size-3 text-text-tertiary\" />\n </button>\n )}\n </div>\n )}\n </div>\n <button\n type=\"button\"\n onClick={() => setBookmarksDrawerOpen(true)}\n className=\"shrink-0 p-1 rounded transition-colors text-text-tertiary hover:text-text-secondary hover:bg-bg-elevated\"\n title={tr(\n 'vibecontrols.agentManager.chatPane.bookmarksTooltip',\n 'View bookmarked messages'\n )}\n aria-label={tr('vibecontrols.agentManager.chatPane.bookmarksLabel', 'Bookmarks')}\n data-testid=\"agent-manager-bookmarks-trigger\"\n >\n <Bookmark className=\"size-3.5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => setInstallModalOpen(true)}\n className=\"shrink-0 inline-flex items-center gap-1.5 rounded-md border border-border-default bg-bg-elevated px-2 py-1 text-xs font-medium text-text-primary transition-colors hover:bg-bg-sunken hover:border-action-primary-bg/40\"\n title={tr(\n 'vibecontrols.agentManager.chatPane.manageProvidersTooltip',\n 'Install or remove AI providers (Claude, Codex, Gemini, OpenCode)'\n )}\n aria-label={tr(\n 'vibecontrols.agentManager.chatPane.manageProviders',\n 'Manage AI providers'\n )}\n data-testid=\"agent-manager-manage-providers\"\n >\n <PackagePlus className=\"size-3.5\" />\n <span className=\"hidden sm:inline\">\n {tr('vibecontrols.agentManager.chatPane.manageProviders', 'Manage AI providers')}\n </span>\n </button>\n </div>\n\n {/* Message list */}\n {loadingLogs ? (\n <div className=\"flex-1 flex items-center justify-center\">\n <p className=\"text-sm text-text-secondary\">\n {tr(\n 'vibecontrols.agentManager.chatPane.loadingConversation',\n 'Loading conversation...'\n )}\n </p>\n </div>\n ) : (\n <AgentManagerMessageList\n messages={messages}\n isStreaming={isStreaming}\n onCancelStream={cancelStream}\n searchQuery={searchQuery}\n bookmarkedIds={bookmarkedIds}\n onToggleBookmark={handleToggleBookmark}\n flashMessageId={flashMessageId}\n />\n )}\n\n {/* Rich input area with controls */}\n <AgentManagerInputArea\n agentId={agentId}\n sessionId={sessionId}\n onSend={(text) => void sendMessage(text)}\n onCancel={cancelStream}\n agentTunnelUrl={activeAgent?.tunnelUrl ?? undefined}\n agentApiKey={activeAgent?.agentApiKey ?? undefined}\n />\n\n {/* Per-session bookmarks drawer */}\n <AgentManagerBookmarksDrawer\n open={bookmarksDrawerOpen}\n onClose={() => setBookmarksDrawerOpen(false)}\n sessionId={sessionId}\n messages={messages}\n onJump={jumpToMessage}\n />\n\n {/* Header-triggered provider install/remove. Sits below the chat\n tree so it can render full-screen without disturbing layout. */}\n <PluginInstallModal\n open={installModalOpen}\n agentId={agentId}\n onClose={() => setInstallModalOpen(false)}\n />\n\n {/* SDK auth prompt: opens when the streaming hook detects a missing\n ANTHROPIC_API_KEY / ANTHROPIC_AUTH_TOKEN, so the user can save the\n credential inline instead of being told to go look elsewhere.\n The session's currently-selected SDK is forwarded so the picker\n can preselect the right provider. */}\n <SdkAuthPromptModal\n agentId={agentId}\n agentRef={agentRef}\n initialProviderId={sessionState?.sdk ?? undefined}\n />\n </div>\n );\n};\n\ninterface SdkAuthPromptModalProps {\n agentId: string;\n agentRef: { id: string; profile: string };\n initialProviderId?: string;\n}\n\nconst SdkAuthPromptModal: FC<SdkAuthPromptModalProps> = ({\n agentId,\n agentRef,\n initialProviderId,\n}) => {\n const sdkAuthPrompt = useAgentManagerStore((s) => s.sdkAuthPrompt);\n const setSdkAuthPrompt = useAgentManagerStore((s) => s.setSdkAuthPrompt);\n // Track whether the inner card has at least one primary credential\n // saved on the agent. The Continue button is gated on this so the user\n // can't dismiss the modal without actually persisting a key — but the\n // moment they save *any* of the either-or options it lights up.\n const [authSatisfied, setAuthSatisfied] = useState(false);\n const tr = useTr();\n\n // Reset the satisfied flag whenever the modal re-opens for a fresh\n // prompt (different agent / different session). Without this, dismissing\n // and re-opening would leave the flag stuck at its previous value.\n useEffect(() => {\n if (sdkAuthPrompt && sdkAuthPrompt.agentId === agentId) {\n setAuthSatisfied(false);\n }\n }, [sdkAuthPrompt, agentId]);\n\n if (!sdkAuthPrompt || sdkAuthPrompt.agentId !== agentId) return null;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n <div\n className=\"absolute inset-0 bg-bg-overlay\"\n onClick={() => setSdkAuthPrompt(null)}\n aria-hidden\n />\n {/* Constrain height to the viewport and let the inner body scroll so the\n modal never escapes the screen no matter how many providers/fields\n render inside AIProviderCredentialsCard. The header + footer stay\n sticky so the close + Continue buttons are always reachable. */}\n <div className=\"relative w-full max-w-xl max-h-[85vh] flex flex-col rounded-lg border border-border-default bg-bg-surface shadow-xl overflow-hidden\">\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-border-default bg-bg-surface flex-shrink-0\">\n <h3 className=\"text-base font-semibold text-text-primary truncate pr-2\">\n {tr('vibecontrols.ai.sdkAuth.title', 'Configure AI provider credentials')}\n </h3>\n <button\n type=\"button\"\n onClick={() => setSdkAuthPrompt(null)}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\n aria-label={tr('vibecontrols.common.close', 'Close')}\n >\n <X className=\"size-5 text-text-secondary\" />\n </button>\n </div>\n <div className=\"flex-1 min-h-0 overflow-y-auto px-4 py-3 space-y-3\">\n <p className=\"text-sm text-text-secondary\">\n {tr(\n 'vibecontrols.ai.sdkAuth.body',\n \"The agent doesn't have a credential configured for this provider. Save any one of the listed keys (you don't need all of them) and click Continue to retry.\"\n )}\n </p>\n <AIProviderCredentialsCard\n agent={agentRef}\n initialProviderId={initialProviderId}\n onProviderAuthSatisfiedChange={setAuthSatisfied}\n />\n </div>\n <div className=\"flex items-center justify-end gap-2 px-4 py-3 border-t border-border-default bg-bg-surface flex-shrink-0\">\n <button\n type=\"button\"\n onClick={() => setSdkAuthPrompt(null)}\n className=\"px-3 py-1.5 rounded-md text-sm text-text-secondary hover:text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n {tr('vibecontrols.common.close', 'Close')}\n </button>\n <button\n type=\"button\"\n onClick={() => setSdkAuthPrompt(null)}\n disabled={!authSatisfied}\n title={\n authSatisfied\n ? undefined\n : tr(\n 'vibecontrols.ai.sdkAuth.saveOneFirst',\n 'Save at least one of the listed credentials to continue'\n )\n }\n className=\"px-3 py-1.5 rounded-md text-sm font-medium bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n {tr('vibecontrols.ai.sdkAuth.continue', 'Continue')}\n </button>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"AgentManagerChatPane.js","names":[],"sources":["../../../src/components/agent-manager/AgentManagerChatPane.tsx"],"sourcesContent":["/**\n * Main chat interface for a single Agent Manager session.\n *\n * Renders message list + input area, manages the send/receive flow,\n * fetches existing conversation logs on mount, and provides\n * auto-scroll, cancel, and in-session search support.\n */\n\nimport { useEffect, useRef, useState, useCallback, useMemo, type FC } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport { Bookmark, PackagePlus, Search, X } from 'lucide-react';\nimport { useAgentManagerStore } from '@/store/agentManagerStore';\nimport { useAgentManagerStreaming } from '@/hooks/useAgentManagerStreaming';\nimport { useCachedInitialData } from '@/hooks/useCachedInitialData';\nimport { fetchSessionLogs } from '@/services/aiApi';\nimport { useActiveAgentProfile } from '@/hooks/useActiveAgentProfile';\nimport { useToggleAgentBookmark } from '@/hooks/useToggleAgentBookmark';\nimport { AgentManagerMessageList } from './AgentManagerMessageList';\nimport { AgentManagerInputArea } from './AgentManagerInputArea';\nimport { AgentManagerBookmarksDrawer } from './AgentManagerBookmarksDrawer';\nimport { PluginInstallModal } from './PluginInstallModal';\nimport { AIProviderCredentialsCard } from '@/components/ai/AIProviderCredentialsCard';\nimport type { AgentManagerMessage } from '@/types/agentManager';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface AgentManagerChatPaneProps {\n sessionId: string;\n agentId: string;\n}\n\nexport const AgentManagerChatPane: FC<AgentManagerChatPaneProps> = ({ sessionId, agentId }) => {\n const [loadingLogs, setLoadingLogs] = useState(false);\n const [searchOpen, setSearchOpen] = useState(false);\n const [searchQuery, setSearchQuery] = useState('');\n // Provider-install modal triggered from the header. Lets users add a\n // claude/codex/gemini/opencode plugin without leaving the conversation.\n const [installModalOpen, setInstallModalOpen] = useState(false);\n const [bookmarksDrawerOpen, setBookmarksDrawerOpen] = useState(false);\n const [flashMessageId, setFlashMessageId] = useState<string | null>(null);\n const [searchParams, setSearchParams] = useSearchParams();\n const pendingScrollMessageId = searchParams.get('messageId');\n const consumedScrollTargetRef = useRef<string | null>(null);\n const tr = useTr();\n\n const { agents } = useCachedInitialData();\n const activeAgent = useMemo(\n () => agents.find((a) => a.id === agentId) ?? null,\n [agents, agentId]\n );\n\n const sessionState = useAgentManagerStore((s) => s.sessionStates[sessionId]);\n const addMessage = useAgentManagerStore((s) => s.addMessage);\n\n const messages = useMemo(() => sessionState?.messages ?? [], [sessionState?.messages]);\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 { sendMessage, cancelStream, isStreaming } = useAgentManagerStreaming({\n agent: agentRef,\n sessionId,\n });\n\n const { bookmarkedIds, toggle: toggleBookmark } = useToggleAgentBookmark(sessionId);\n\n const jumpToMessage = useCallback((messageId: string) => {\n const el = document.querySelector(`[data-message-id=\"${messageId}\"]`);\n if (!el) return;\n el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n setFlashMessageId(messageId);\n window.setTimeout(() => {\n setFlashMessageId((current) => (current === messageId ? null : current));\n }, 1500);\n }, []);\n\n const handleToggleBookmark = useCallback(\n (messageId: string) => {\n void toggleBookmark({ agentId, sessionId, messageId });\n },\n [toggleBookmark, agentId, sessionId]\n );\n\n const toggleSearch = useCallback(() => {\n setSearchOpen((prev) => {\n if (prev) setSearchQuery('');\n return !prev;\n });\n }, []);\n\n // Fetch existing conversation logs on mount\n useEffect(() => {\n let cancelled = false;\n\n const loadExistingLogs = async () => {\n // Only load if session has no messages yet\n if (messages.length > 0) return;\n\n setLoadingLogs(true);\n try {\n const logs = await fetchSessionLogs(agentRef, sessionId, {\n types: ['input', 'output'],\n });\n\n if (cancelled || logs.length === 0) return;\n\n const seenLogKeys = new Set<string>();\n\n // Convert session logs to AgentManagerMessage format. The core AI\n // route owns logging, but older provider builds also wrote the same\n // input/output records; collapse same-second duplicates on restore.\n for (const log of logs) {\n const content = log.message || log.content || '';\n const timestamp = log.timestamp || log.createdAt;\n const timestampSecond = timestamp ? Math.floor(new Date(timestamp).getTime() / 1000) : 0;\n const logKey = [log.type, content, log.model ?? '', timestampSecond].join('\\u0000');\n if (seenLogKeys.has(logKey)) continue;\n seenLogKeys.add(logKey);\n\n const msg: AgentManagerMessage = {\n id: log.id,\n role: log.type === 'input' ? 'user' : 'assistant',\n content,\n timestamp,\n tokens: log.tokenCount ? { input: 0, output: log.tokenCount } : undefined,\n model: log.model,\n };\n addMessage(sessionId, msg);\n }\n } catch {\n // Silent fail -- session may not have logs yet\n } finally {\n if (!cancelled) setLoadingLogs(false);\n }\n };\n\n void loadExistingLogs();\n\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- only run on mount\n }, [agentId, sessionId]);\n\n // Auto-scroll to a message linked via ?messageId=... (from drawer / cross-session page).\n // Waits for logs to finish loading and the target to be in the DOM before scrolling.\n useEffect(() => {\n if (!pendingScrollMessageId || loadingLogs) return;\n if (consumedScrollTargetRef.current === pendingScrollMessageId) return;\n\n const exists = messages.some((m) => m.id === pendingScrollMessageId);\n if (!exists) return;\n\n consumedScrollTargetRef.current = pendingScrollMessageId;\n jumpToMessage(pendingScrollMessageId);\n\n // Strip the query param so a manual refresh doesn't re-trigger the flash.\n const next = new URLSearchParams(searchParams);\n next.delete('messageId');\n setSearchParams(next, { replace: true });\n }, [pendingScrollMessageId, loadingLogs, messages, jumpToMessage, searchParams, setSearchParams]);\n\n return (\n <div className=\"flex flex-col h-full min-h-0\" data-testid=\"agent-manager-chat-pane\">\n {/* In-session search bar.\n Layout: [search controls (flex-1)] ... [Manage AI providers].\n The search input expands inside the LEFT cluster only, so the\n Manage button stays anchored on the right and never shifts. */}\n <div className=\"flex items-center gap-1 px-3 py-1 border-b border-border-default bg-bg-surface flex-shrink-0\">\n <div className=\"flex items-center gap-1.5 min-w-0 flex-1\">\n <button\n type=\"button\"\n onClick={toggleSearch}\n className={`p-1 rounded transition-colors shrink-0 ${\n searchOpen\n ? 'bg-action-primary-bg/10 text-action-primary-text'\n : 'text-text-tertiary hover:text-text-secondary hover:bg-bg-elevated'\n }`}\n title={tr(\n 'vibecontrols.agentManager.chatPane.searchInSession',\n 'Search in session (Ctrl+F)'\n )}\n aria-label={tr(\n 'vibecontrols.agentManager.chatPane.searchInSession',\n 'Search in session'\n )}\n >\n <Search className=\"size-3.5\" />\n </button>\n {searchOpen && (\n <div className=\"flex items-center gap-1.5 flex-1 min-w-0\">\n <input\n aria-label=\"control\"\n type=\"text\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n placeholder={tr(\n 'vibecontrols.agentManager.chatPane.searchPlaceholder',\n 'Search in conversation...'\n )}\n className=\"flex-1 min-w-0 bg-transparent text-xs text-text-primary placeholder:text-text-tertiary focus:outline-none\"\n />\n {searchQuery && (\n <button\n type=\"button\"\n onClick={() => setSearchQuery('')}\n className=\"p-0.5 rounded hover:bg-bg-elevated transition-colors\"\n >\n <X className=\"size-3 text-text-tertiary\" />\n </button>\n )}\n </div>\n )}\n </div>\n <button\n type=\"button\"\n onClick={() => setBookmarksDrawerOpen(true)}\n className=\"shrink-0 p-1 rounded transition-colors text-text-tertiary hover:text-text-secondary hover:bg-bg-elevated\"\n title={tr(\n 'vibecontrols.agentManager.chatPane.bookmarksTooltip',\n 'View bookmarked messages'\n )}\n aria-label={tr('vibecontrols.agentManager.chatPane.bookmarksLabel', 'Bookmarks')}\n data-testid=\"agent-manager-bookmarks-trigger\"\n >\n <Bookmark className=\"size-3.5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => setInstallModalOpen(true)}\n className=\"shrink-0 inline-flex items-center gap-1.5 rounded-md border border-border-default bg-bg-elevated px-2 py-1 text-xs font-medium text-text-primary transition-colors hover:bg-bg-sunken hover:border-action-primary-bg/40\"\n title={tr(\n 'vibecontrols.agentManager.chatPane.manageProvidersTooltip',\n 'Install or remove AI providers (Claude, Codex, Gemini, OpenCode)'\n )}\n aria-label={tr(\n 'vibecontrols.agentManager.chatPane.manageProviders',\n 'Manage AI providers'\n )}\n data-testid=\"agent-manager-manage-providers\"\n >\n <PackagePlus className=\"size-3.5\" />\n <span className=\"hidden sm:inline\">\n {tr('vibecontrols.agentManager.chatPane.manageProviders', 'Manage AI providers')}\n </span>\n </button>\n </div>\n\n {/* Message list */}\n {loadingLogs ? (\n <div className=\"flex-1 flex items-center justify-center\">\n <p className=\"text-sm text-text-secondary\">\n {tr(\n 'vibecontrols.agentManager.chatPane.loadingConversation',\n 'Loading conversation...'\n )}\n </p>\n </div>\n ) : (\n <AgentManagerMessageList\n messages={messages}\n isStreaming={isStreaming}\n onCancelStream={cancelStream}\n searchQuery={searchQuery}\n bookmarkedIds={bookmarkedIds}\n onToggleBookmark={handleToggleBookmark}\n flashMessageId={flashMessageId}\n />\n )}\n\n {/* Rich input area with controls */}\n <AgentManagerInputArea\n agentId={agentId}\n sessionId={sessionId}\n onSend={(text) => void sendMessage(text)}\n onCancel={cancelStream}\n agentTunnelUrl={activeAgent?.tunnelUrl ?? undefined}\n />\n\n {/* Per-session bookmarks drawer */}\n <AgentManagerBookmarksDrawer\n open={bookmarksDrawerOpen}\n onClose={() => setBookmarksDrawerOpen(false)}\n sessionId={sessionId}\n messages={messages}\n onJump={jumpToMessage}\n />\n\n {/* Header-triggered provider install/remove. Sits below the chat\n tree so it can render full-screen without disturbing layout. */}\n <PluginInstallModal\n open={installModalOpen}\n agentId={agentId}\n onClose={() => setInstallModalOpen(false)}\n />\n\n {/* SDK auth prompt: opens when the streaming hook detects a missing\n ANTHROPIC_API_KEY / ANTHROPIC_AUTH_TOKEN, so the user can save the\n credential inline instead of being told to go look elsewhere.\n The session's currently-selected SDK is forwarded so the picker\n can preselect the right provider. */}\n <SdkAuthPromptModal\n agentId={agentId}\n agentRef={agentRef}\n initialProviderId={sessionState?.sdk ?? undefined}\n />\n </div>\n );\n};\n\ninterface SdkAuthPromptModalProps {\n agentId: string;\n agentRef: { id: string; profile: string };\n initialProviderId?: string;\n}\n\nconst SdkAuthPromptModal: FC<SdkAuthPromptModalProps> = ({\n agentId,\n agentRef,\n initialProviderId,\n}) => {\n const sdkAuthPrompt = useAgentManagerStore((s) => s.sdkAuthPrompt);\n const setSdkAuthPrompt = useAgentManagerStore((s) => s.setSdkAuthPrompt);\n // Track whether the inner card has at least one primary credential\n // saved on the agent. The Continue button is gated on this so the user\n // can't dismiss the modal without actually persisting a key — but the\n // moment they save *any* of the either-or options it lights up.\n const [authSatisfied, setAuthSatisfied] = useState(false);\n const tr = useTr();\n\n // Reset the satisfied flag whenever the modal re-opens for a fresh\n // prompt (different agent / different session). Without this, dismissing\n // and re-opening would leave the flag stuck at its previous value.\n useEffect(() => {\n if (sdkAuthPrompt && sdkAuthPrompt.agentId === agentId) {\n setAuthSatisfied(false);\n }\n }, [sdkAuthPrompt, agentId]);\n\n if (!sdkAuthPrompt || sdkAuthPrompt.agentId !== agentId) return null;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n <div\n className=\"absolute inset-0 bg-bg-overlay\"\n onClick={() => setSdkAuthPrompt(null)}\n aria-hidden\n />\n {/* Constrain height to the viewport and let the inner body scroll so the\n modal never escapes the screen no matter how many providers/fields\n render inside AIProviderCredentialsCard. The header + footer stay\n sticky so the close + Continue buttons are always reachable. */}\n <div className=\"relative w-full max-w-xl max-h-[85vh] flex flex-col rounded-lg border border-border-default bg-bg-surface shadow-xl overflow-hidden\">\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-border-default bg-bg-surface flex-shrink-0\">\n <h3 className=\"text-base font-semibold text-text-primary truncate pr-2\">\n {tr('vibecontrols.ai.sdkAuth.title', 'Configure AI provider credentials')}\n </h3>\n <button\n type=\"button\"\n onClick={() => setSdkAuthPrompt(null)}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\n aria-label={tr('vibecontrols.common.close', 'Close')}\n >\n <X className=\"size-5 text-text-secondary\" />\n </button>\n </div>\n <div className=\"flex-1 min-h-0 overflow-y-auto px-4 py-3 space-y-3\">\n <p className=\"text-sm text-text-secondary\">\n {tr(\n 'vibecontrols.ai.sdkAuth.body',\n \"The agent doesn't have a credential configured for this provider. Save any one of the listed keys (you don't need all of them) and click Continue to retry.\"\n )}\n </p>\n <AIProviderCredentialsCard\n agent={agentRef}\n initialProviderId={initialProviderId}\n onProviderAuthSatisfiedChange={setAuthSatisfied}\n />\n </div>\n <div className=\"flex items-center justify-end gap-2 px-4 py-3 border-t border-border-default bg-bg-surface flex-shrink-0\">\n <button\n type=\"button\"\n onClick={() => setSdkAuthPrompt(null)}\n className=\"px-3 py-1.5 rounded-md text-sm text-text-secondary hover:text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n {tr('vibecontrols.common.close', 'Close')}\n </button>\n <button\n type=\"button\"\n onClick={() => setSdkAuthPrompt(null)}\n disabled={!authSatisfied}\n title={\n authSatisfied\n ? undefined\n : tr(\n 'vibecontrols.ai.sdkAuth.saveOneFirst',\n 'Save at least one of the listed credentials to continue'\n )\n }\n className=\"px-3 py-1.5 rounded-md text-sm font-medium bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n {tr('vibecontrols.ai.sdkAuth.continue', 'Continue')}\n </button>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -5,20 +5,20 @@ import { fetchProviders as r } from "../../services/aiApi.js";
5
5
  import { useAgentManagerStore as i } from "../../store/agentManagerStore.js";
6
6
  import { ModelSelector as a } from "./controls/ModelSelector.js";
7
7
  import { SdkSelector as o } from "./controls/SdkSelector.js";
8
- import { resolveProviderDefaultModel as s } from "./modelDefaults.js";
9
- import { useVoiceMode as ee } from "../../hooks/useVoiceMode.js";
10
- import { schedulePrompt as te } from "../../services/schedulerApi.js";
11
- import { AutonomySelector as ne } from "./controls/AutonomySelector.js";
12
- import { McpServerSelector as re } from "./controls/McpServerSelector.js";
13
- import { VoiceToggle as ie } from "./controls/VoiceToggle.js";
14
- import { FileAttachButton as ae } from "./controls/FileAttachButton.js";
15
- import { createDropHandlers as oe } from "./controls/createDropHandlers.js";
16
- import { ContextLevelToggle as se } from "./controls/ContextLevelToggle.js";
17
- import { useCallback as c, useEffect as l, useMemo as u, useRef as d, useState as f } from "react";
18
- import { ArrowUp as ce, ChevronDown as le, Clock as ue, Square as de, X as fe } from "lucide-react";
19
- import { jsx as p, jsxs as m } from "react/jsx-runtime";
8
+ import { resolveProviderDefaultModel as ee } from "./modelDefaults.js";
9
+ import { useVoiceMode as te } from "../../hooks/useVoiceMode.js";
10
+ import { schedulePrompt as ne } from "../../services/schedulerApi.js";
11
+ import { AutonomySelector as re } from "./controls/AutonomySelector.js";
12
+ import { McpServerSelector as ie } from "./controls/McpServerSelector.js";
13
+ import { VoiceToggle as ae } from "./controls/VoiceToggle.js";
14
+ import { FileAttachButton as oe } from "./controls/FileAttachButton.js";
15
+ import { createDropHandlers as se } from "./controls/createDropHandlers.js";
16
+ import { ContextLevelToggle as ce } from "./controls/ContextLevelToggle.js";
17
+ import { useCallback as s, useEffect as c, useMemo as l, useRef as le, useState as u } from "react";
18
+ import { ArrowUp as ue, ChevronDown as de, Clock as fe, Square as pe, X as me } from "lucide-react";
19
+ import { jsx as d, jsxs as f } from "react/jsx-runtime";
20
20
  //#region src/components/agent-manager/AgentManagerInputArea.tsx
21
- var pe = [
21
+ var p = [
22
22
  {
23
23
  command: "/new",
24
24
  description: "Create new session"
@@ -56,7 +56,7 @@ var pe = [
56
56
  command: "/help",
57
57
  description: "Show available commands"
58
58
  }
59
- ], h = [
59
+ ], m = [
60
60
  "claude",
61
61
  "codex",
62
62
  "gemini",
@@ -73,19 +73,19 @@ var pe = [
73
73
  "pi",
74
74
  "aider",
75
75
  "plandex"
76
- ], me = ["sdk", "cli"];
77
- function g({ agentId: g, sessionId: _, onSend: v, onCancel: y, mcpServers: he = [], agentTunnelUrl: b, agentApiKey: x }) {
78
- let [S, C] = f(""), [w, T] = f([]), [ge, E] = f(!1), [_e, ve] = f(""), [D, O] = f(!1), [k, A] = f(!1), [j, M] = f(""), [ye, N] = f([]), P = e(), F = d(null), I = d(null);
79
- l(() => {
76
+ ], h = ["sdk", "cli"];
77
+ function g({ agentId: g, sessionId: _, onSend: v, onCancel: y, mcpServers: he = [], agentTunnelUrl: b }) {
78
+ let [x, S] = u(""), [C, w] = u([]), [ge, T] = u(!1), [E, _e] = u(""), [D, O] = u(!1), [k, A] = u(!1), [j, M] = u(""), [ve, N] = u([]), P = e(), F = le(null), I = le(null);
79
+ c(() => {
80
80
  F.current?.focus({ preventScroll: !0 });
81
81
  }, []);
82
- let L = i((e) => e.sessionStates[_]), R = i((e) => e.setSessionModel), z = i((e) => e.setSessionSdk), B = i((e) => e.setSessionMode), be = i((e) => e.setSessionPermissionMode), xe = i((e) => e.toggleVoice), Se = i((e) => e.toggleThinking), Ce = i((e) => e.setSessionContextLevel), we = i((e) => e.setSessionVibe), Te = i((e) => e.setSessionRootPath), V = i((e) => e.openSession), H = i((e) => e.addMessage), { vibes: Ee, agents: U } = t(), { active: W } = n(u(() => U.find((e) => e.id === g) ?? null, [U, g])?.id ?? null), G = u(() => ({
82
+ let L = i((e) => e.sessionStates[_]), R = i((e) => e.setSessionModel), z = i((e) => e.setSessionSdk), B = i((e) => e.setSessionMode), ye = i((e) => e.setSessionPermissionMode), be = i((e) => e.toggleVoice), xe = i((e) => e.toggleThinking), Se = i((e) => e.setSessionContextLevel), Ce = i((e) => e.setSessionVibe), we = i((e) => e.setSessionRootPath), V = i((e) => e.openSession), H = i((e) => e.addMessage), { vibes: Te, agents: U } = t(), { active: W } = n(l(() => U.find((e) => e.id === g) ?? null, [U, g])?.id ?? null), G = l(() => ({
83
83
  id: g,
84
84
  profile: W
85
- }), [g, W]), { isListening: K, transcript: q, startListening: De, stopListening: Oe } = ee(), J = L?.status === "streaming", Y = S.trim().length > 0 && !J;
86
- l(() => {
87
- q && K && C((e) => e + (e ? " " : "") + q);
88
- }, [q, K]), l(() => {
85
+ }), [g, W]), { isListening: K, transcript: q, startListening: Ee, stopListening: De } = te(), J = L?.status === "streaming", Y = x.trim().length > 0 && !J;
86
+ c(() => {
87
+ q && K && S((e) => e + (e ? " " : "") + q);
88
+ }, [q, K]), c(() => {
89
89
  let e = !1;
90
90
  return r(G).then((t) => {
91
91
  e || N(t);
@@ -94,54 +94,52 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: y, mcpServers: he =
94
94
  }), () => {
95
95
  e = !0;
96
96
  };
97
- }, [G]), l(() => {
98
- S.startsWith("/") && !S.includes(" ") ? (E(!0), ve(S.slice(1))) : E(!1);
99
- }, [S]);
100
- let ke = u(() => pe.filter((e) => e.command.toLowerCase().includes(`/${_e.toLowerCase()}`)), [_e]);
101
- l(() => {
97
+ }, [G]), c(() => {
98
+ x.startsWith("/") && !x.includes(" ") ? (T(!0), _e(x.slice(1))) : T(!1);
99
+ }, [x]);
100
+ let Oe = l(() => p.filter((e) => e.command.toLowerCase().includes(`/${E.toLowerCase()}`)), [E]);
101
+ c(() => {
102
102
  let e = F.current;
103
103
  e && (e.style.height = "auto", e.style.height = `${Math.min(e.scrollHeight, 200)}px`);
104
- }, [S]), l(() => {
104
+ }, [x]), c(() => {
105
105
  if (!D && !k) return;
106
106
  let e = (e) => {
107
107
  I.current && !I.current.contains(e.target) && (O(!1), A(!1));
108
108
  };
109
109
  return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
110
110
  }, [D, k]);
111
- let X = c((e) => {
111
+ let X = s((e) => {
112
112
  H(_, {
113
113
  id: `sys-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
114
114
  role: "system",
115
115
  content: e,
116
116
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
117
117
  });
118
- }, [H, _]), Ae = c(async () => {
119
- if (!(!S.trim() || !j || !b || !x)) try {
120
- let e = await te({
118
+ }, [H, _]), ke = s(async () => {
119
+ if (!(!x.trim() || !j || !b || !g)) try {
120
+ let e = await ne({
121
121
  sessionId: _,
122
122
  agentTunnelUrl: b,
123
- agentApiKey: x,
124
- agentRef: W ? {
123
+ agentRef: {
125
124
  agentId: g,
126
- profile: W
127
- } : void 0,
128
- prompt: S.trim(),
125
+ profile: W ?? "default"
126
+ },
127
+ prompt: x.trim(),
129
128
  scheduledAt: new Date(j).toISOString()
130
129
  });
131
- X(`Prompt scheduled for ${new Date(e.scheduledAt).toLocaleString()} (Job: ${e.jobId.slice(0, 8)})`), C(""), M(""), A(!1), O(!1);
130
+ X(`Prompt scheduled for ${new Date(e.scheduledAt).toLocaleString()} (Job: ${e.jobId.slice(0, 8)})`), S(""), M(""), A(!1), O(!1);
132
131
  } catch (e) {
133
132
  X(`Failed to schedule: ${e instanceof Error ? e.message : "Unknown error"}`);
134
133
  }
135
134
  }, [
136
- S,
135
+ x,
137
136
  j,
138
137
  b,
139
- x,
140
138
  _,
141
139
  g,
142
140
  W,
143
141
  X
144
- ]), Z = c((e) => {
142
+ ]), Z = s((e) => {
145
143
  let t = e.trim().split(/\s+/), n = t[0].toLowerCase(), r = t.slice(1).join(" ");
146
144
  switch (n) {
147
145
  case "/new":
@@ -154,13 +152,13 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: y, mcpServers: he =
154
152
  r ? (R(_, r), X(`Model switched to "${r}".`)) : X("Usage: /model <model-name>");
155
153
  break;
156
154
  case "/sdk":
157
- if (r && h.includes(r)) {
155
+ if (r && m.includes(r)) {
158
156
  let e = r;
159
- z(_, e), s(G, e, L?.model ?? "default").then((e) => R(_, e)).catch(() => R(_, L?.model ?? "default")), X(`SDK switched to "${r}".`);
160
- } else X(`Usage: /sdk <${h.join("|")}>`);
157
+ z(_, e), ee(G, e, L?.model ?? "default").then((e) => R(_, e)).catch(() => R(_, L?.model ?? "default")), X(`SDK switched to "${r}".`);
158
+ } else X(`Usage: /sdk <${m.join("|")}>`);
161
159
  break;
162
160
  case "/mode":
163
- r && me.includes(r) ? (B(_, r), X(`Mode switched to "${r}".`)) : X(`Usage: /mode <${me.join("|")}>`);
161
+ r && h.includes(r) ? (B(_, r), X(`Mode switched to "${r}".`)) : X(`Usage: /mode <${h.join("|")}>`);
164
162
  break;
165
163
  case "/export": {
166
164
  let e = r === "md" ? "md" : "json", t = L?.messages ?? [], n = e === "json" ? JSON.stringify(t, null, 2) : t.map((e) => `**${e.role}** (${e.timestamp ?? ""}):\n${e.content ?? ""}`).join("\n\n---\n\n"), i = new Blob([n], { type: e === "json" ? "application/json" : "text/markdown" }), a = URL.createObjectURL(i), o = document.createElement("a");
@@ -171,7 +169,7 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: y, mcpServers: he =
171
169
  X("Conversation cleared.");
172
170
  break;
173
171
  case "/help":
174
- X(`Available commands:\n${pe.map((e) => ` ${e.command}${e.args ? " " + e.args : ""} - ${e.description}`).join("\n")}`);
172
+ X(`Available commands:\n${p.map((e) => ` ${e.command}${e.args ? " " + e.args : ""} - ${e.description}`).join("\n")}`);
175
173
  break;
176
174
  default: X(`Unknown command: ${n}. Type /help for available commands.`);
177
175
  }
@@ -185,123 +183,123 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: y, mcpServers: he =
185
183
  B,
186
184
  X,
187
185
  G
188
- ]), je = c((e) => {
189
- e.args ? C(`${e.command} `) : (Z(e.command), C("")), E(!1), F.current?.focus();
190
- }, [Z]), Q = c(() => {
186
+ ]), Ae = s((e) => {
187
+ e.args ? S(`${e.command} `) : (Z(e.command), S("")), T(!1), F.current?.focus();
188
+ }, [Z]), Q = s(() => {
191
189
  if (!Y) return;
192
- let e = S.trim();
190
+ let e = x.trim();
193
191
  if (e.startsWith("/")) {
194
- Z(e), C(""), T([]);
192
+ Z(e), S(""), w([]);
195
193
  return;
196
194
  }
197
- v(e, w.length > 0 ? w : void 0), C(""), T([]);
195
+ v(e, C.length > 0 ? C : void 0), S(""), w([]);
198
196
  }, [
199
197
  Y,
200
- S,
201
- w,
198
+ x,
199
+ C,
202
200
  v,
203
201
  Z
204
- ]), Me = c((e) => {
202
+ ]), je = s((e) => {
205
203
  e.key === "Enter" && !e.shiftKey && (e.preventDefault(), Q());
206
- }, [Q]), Ne = c(() => {
204
+ }, [Q]), Me = s(() => {
207
205
  y?.();
208
- }, [y]), $ = c((e) => {
209
- T((t) => [...t, ...e]);
210
- }, []), Pe = c((e) => {
211
- T((t) => t.filter((t, n) => n !== e));
212
- }, []), Fe = oe($);
213
- return L ? /* @__PURE__ */ m("div", {
206
+ }, [y]), $ = s((e) => {
207
+ w((t) => [...t, ...e]);
208
+ }, []), Ne = s((e) => {
209
+ w((t) => t.filter((t, n) => n !== e));
210
+ }, []), Pe = se($);
211
+ return L ? /* @__PURE__ */ f("div", {
214
212
  className: "relative z-30 border-t border-border-default bg-bg-surface",
215
- ...Fe,
213
+ ...Pe,
216
214
  children: [
217
- ge && ke.length > 0 && /* @__PURE__ */ p("div", {
215
+ ge && Oe.length > 0 && /* @__PURE__ */ d("div", {
218
216
  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",
219
- children: ke.map((e) => /* @__PURE__ */ m("button", {
217
+ children: Oe.map((e) => /* @__PURE__ */ f("button", {
220
218
  type: "button",
221
- onClick: () => je(e),
219
+ onClick: () => Ae(e),
222
220
  className: "flex items-center gap-2 w-full px-3 py-2 text-left hover:bg-bg-sunken transition-colors",
223
221
  children: [
224
- /* @__PURE__ */ p("span", {
222
+ /* @__PURE__ */ d("span", {
225
223
  className: "font-mono text-xs text-text-primary",
226
224
  children: e.command
227
225
  }),
228
- e.args && /* @__PURE__ */ p("span", {
226
+ e.args && /* @__PURE__ */ d("span", {
229
227
  className: "text-text-tertiary text-xs",
230
228
  children: e.args
231
229
  }),
232
- /* @__PURE__ */ p("span", {
230
+ /* @__PURE__ */ d("span", {
233
231
  className: "text-text-secondary text-xs ml-auto",
234
232
  children: e.description
235
233
  })
236
234
  ]
237
235
  }, e.command))
238
236
  }),
239
- w.length > 0 && /* @__PURE__ */ p("div", {
237
+ C.length > 0 && /* @__PURE__ */ d("div", {
240
238
  className: "flex items-center gap-2 px-3 pt-2 overflow-x-auto",
241
- children: w.map((e, t) => /* @__PURE__ */ m("div", {
239
+ children: C.map((e, t) => /* @__PURE__ */ f("div", {
242
240
  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",
243
- children: [/* @__PURE__ */ p("span", {
241
+ children: [/* @__PURE__ */ d("span", {
244
242
  className: "truncate max-w-[120px]",
245
243
  children: e.name
246
- }), /* @__PURE__ */ p("button", {
244
+ }), /* @__PURE__ */ d("button", {
247
245
  type: "button",
248
- onClick: () => Pe(t),
246
+ onClick: () => Ne(t),
249
247
  className: "p-0.5 rounded hover:bg-bg-sunken transition-colors flex-shrink-0",
250
- children: /* @__PURE__ */ p(fe, { className: "size-3" })
248
+ children: /* @__PURE__ */ d(me, { className: "size-3" })
251
249
  })]
252
250
  }, `${e.name}-${t}`))
253
251
  }),
254
- /* @__PURE__ */ m("div", {
252
+ /* @__PURE__ */ f("div", {
255
253
  className: "flex flex-wrap items-center gap-1 px-3 pt-2 pb-1 overflow-x-auto",
256
254
  children: [
257
- /* @__PURE__ */ p(o, {
255
+ /* @__PURE__ */ d(o, {
258
256
  sdk: L.sdk,
259
257
  mode: L.mode,
260
- providers: ye,
258
+ providers: ve,
261
259
  onSdkChange: (e) => {
262
- z(_, e), s(G, e, L.model ?? "default").then((e) => R(_, e)).catch(() => R(_, L.model ?? "default"));
260
+ z(_, e), ee(G, e, L.model ?? "default").then((e) => R(_, e)).catch(() => R(_, L.model ?? "default"));
263
261
  },
264
262
  onModeChange: (e) => B(_, e)
265
263
  }),
266
- /* @__PURE__ */ p(a, {
264
+ /* @__PURE__ */ d(a, {
267
265
  value: L.model,
268
266
  onChange: (e) => R(_, e),
269
267
  provider: L.sdk,
270
268
  agentId: g
271
269
  }),
272
- /* @__PURE__ */ p(ne, {
270
+ /* @__PURE__ */ d(re, {
273
271
  value: L.permissionMode,
274
272
  mode: L.mode,
275
- onChange: (e) => be(_, e)
273
+ onChange: (e) => ye(_, e)
276
274
  }),
277
- /* @__PURE__ */ p(re, {
275
+ /* @__PURE__ */ d(ie, {
278
276
  selected: L.mcpServers,
279
277
  available: he,
280
278
  onChange: () => {}
281
279
  }),
282
- /* @__PURE__ */ p(se, {
280
+ /* @__PURE__ */ d(ce, {
283
281
  agentId: "",
284
282
  sessionId: _,
285
283
  contextLevel: L.contextLevel,
286
284
  rootPath: L.rootPath,
287
285
  onChange: (e, t, n) => {
288
- Ce(_, e), Te(_, t ?? null), we(_, n ?? null, t ?? null);
286
+ Se(_, e), we(_, t ?? null), Ce(_, n ?? null, t ?? null);
289
287
  },
290
- vibes: Ee.map((e) => ({
288
+ vibes: Te.map((e) => ({
291
289
  id: e.id,
292
290
  name: e.name,
293
291
  path: e.path
294
292
  }))
295
293
  }),
296
- /* @__PURE__ */ p("div", { className: "flex-1" }),
297
- /* @__PURE__ */ p("button", {
294
+ /* @__PURE__ */ d("div", { className: "flex-1" }),
295
+ /* @__PURE__ */ d("button", {
298
296
  type: "button",
299
- onClick: () => Se(_),
297
+ onClick: () => xe(_),
300
298
  className: `p-1.5 rounded text-xs font-medium transition-colors ${L.showThinking ? "bg-action-primary-bg/10 text-action-primary-text" : "text-text-tertiary hover:text-text-secondary"}`,
301
299
  title: L.showThinking ? P("vibecontrols.agentManager.inputArea.hideThinking", "Hide thinking") : P("vibecontrols.agentManager.inputArea.showThinking", "Show thinking"),
302
300
  children: "Think"
303
301
  }),
304
- /* @__PURE__ */ m("button", {
302
+ /* @__PURE__ */ f("button", {
305
303
  type: "button",
306
304
  onClick: () => {
307
305
  let e = window.prompt("Context history limit (messages sent with each prompt):", String(L.contextHistoryLimit));
@@ -323,83 +321,83 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: y, mcpServers: he =
323
321
  title: `Context history: last ${L.contextHistoryLimit} messages sent with each prompt`,
324
322
  children: ["H:", L.contextHistoryLimit]
325
323
  }),
326
- /* @__PURE__ */ p(ie, {
324
+ /* @__PURE__ */ d(ae, {
327
325
  enabled: L.voiceEnabled,
328
326
  onToggle: () => {
329
- xe(_), L.voiceEnabled ? Oe() : De();
327
+ be(_), L.voiceEnabled ? De() : Ee();
330
328
  },
331
329
  isListening: K
332
330
  }),
333
- /* @__PURE__ */ p(ae, { onFileSelect: $ })
331
+ /* @__PURE__ */ d(oe, { onFileSelect: $ })
334
332
  ]
335
333
  }),
336
- /* @__PURE__ */ m("div", {
334
+ /* @__PURE__ */ f("div", {
337
335
  className: "flex items-end gap-2 px-3 pb-3 pt-1",
338
- children: [/* @__PURE__ */ p("textarea", {
336
+ children: [/* @__PURE__ */ d("textarea", {
339
337
  "aria-label": "control",
340
338
  ref: F,
341
- value: S,
342
- onChange: (e) => C(e.target.value),
343
- onKeyDown: Me,
339
+ value: x,
340
+ onChange: (e) => S(e.target.value),
341
+ onKeyDown: je,
344
342
  placeholder: P("vibecontrols.agentManager.inputArea.placeholder", "Type a message or / for commands... (Enter to send)"),
345
343
  rows: 1,
346
344
  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",
347
345
  disabled: J
348
- }), J ? /* @__PURE__ */ p("button", {
346
+ }), J ? /* @__PURE__ */ d("button", {
349
347
  type: "button",
350
- onClick: Ne,
348
+ onClick: Me,
351
349
  className: "flex-shrink-0 p-2 rounded-lg bg-status-error-bg text-status-error-text hover:opacity-90 transition-opacity",
352
350
  title: P("vibecontrols.agentManager.inputArea.cancel", "Cancel"),
353
- children: /* @__PURE__ */ p(de, { className: "size-4" })
354
- }) : /* @__PURE__ */ m("div", {
351
+ children: /* @__PURE__ */ d(pe, { className: "size-4" })
352
+ }) : /* @__PURE__ */ f("div", {
355
353
  className: "flex items-end flex-shrink-0 relative",
356
354
  ref: I,
357
355
  children: [
358
- /* @__PURE__ */ p("button", {
356
+ /* @__PURE__ */ d("button", {
359
357
  type: "button",
360
358
  onClick: Q,
361
359
  disabled: !Y,
362
360
  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",
363
361
  title: P("vibecontrols.agentManager.inputArea.send", "Send (Enter)"),
364
- children: /* @__PURE__ */ p(ce, { className: "size-4" })
362
+ children: /* @__PURE__ */ d(ue, { className: "size-4" })
365
363
  }),
366
- /* @__PURE__ */ p("button", {
364
+ /* @__PURE__ */ d("button", {
367
365
  type: "button",
368
366
  onClick: () => O(!D),
369
367
  disabled: !Y,
370
368
  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",
371
369
  title: P("vibecontrols.agentManager.inputArea.scheduleSend", "Schedule send"),
372
- children: /* @__PURE__ */ p(le, { className: "size-3" })
370
+ children: /* @__PURE__ */ d(de, { className: "size-3" })
373
371
  }),
374
- D && /* @__PURE__ */ p("div", {
372
+ D && /* @__PURE__ */ d("div", {
375
373
  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",
376
- children: k ? /* @__PURE__ */ m("div", {
374
+ children: k ? /* @__PURE__ */ f("div", {
377
375
  className: "px-3 py-2 space-y-2",
378
376
  children: [
379
- /* @__PURE__ */ p("label", {
377
+ /* @__PURE__ */ d("label", {
380
378
  className: "block text-[11px] font-medium text-text-secondary",
381
379
  children: P("vibecontrols.agentManager.inputArea.sendAt", "Send at:")
382
380
  }),
383
- /* @__PURE__ */ p("input", {
381
+ /* @__PURE__ */ d("input", {
384
382
  "aria-label": "control",
385
383
  type: "datetime-local",
386
384
  value: j,
387
385
  onChange: (e) => M(e.target.value),
388
386
  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"
389
387
  }),
390
- /* @__PURE__ */ p("button", {
388
+ /* @__PURE__ */ d("button", {
391
389
  type: "button",
392
- onClick: () => void Ae(),
393
- disabled: !j || !b || !x,
390
+ onClick: () => void ke(),
391
+ disabled: !j || !b || !g,
394
392
  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",
395
393
  children: P("vibecontrols.agentManager.inputArea.schedule", "Schedule")
396
394
  })
397
395
  ]
398
- }) : /* @__PURE__ */ m("button", {
396
+ }) : /* @__PURE__ */ f("button", {
399
397
  type: "button",
400
398
  onClick: () => A(!0),
401
399
  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",
402
- children: [/* @__PURE__ */ p(ue, { className: "size-3.5 text-text-secondary" }), P("vibecontrols.agentManager.inputArea.scheduleSendEllipsis", "Schedule Send...")]
400
+ children: [/* @__PURE__ */ d(fe, { className: "size-3.5 text-text-secondary" }), P("vibecontrols.agentManager.inputArea.scheduleSendEllipsis", "Schedule Send...")]
403
401
  })
404
402
  })
405
403
  ]