@burdenoff/microfe-vibecontrols 2026.528.7 → 2026.528.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.
Files changed (37) hide show
  1. package/dist/VibeControlsRoot.js +1 -0
  2. package/dist/VibeControlsRoot.js.map +1 -1
  3. package/dist/components/agent-manager/AgentManagerInputArea.js +70 -64
  4. package/dist/components/agent-manager/AgentManagerInputArea.js.map +1 -1
  5. package/dist/components/audit/AuditLogFilters.js +71 -47
  6. package/dist/components/audit/AuditLogFilters.js.map +1 -1
  7. package/dist/components/shared/AgentSetupBanner.js +50 -45
  8. package/dist/components/shared/AgentSetupBanner.js.map +1 -1
  9. package/dist/components/shared/LinkToVibePanel.js +97 -0
  10. package/dist/components/shared/LinkToVibePanel.js.map +1 -0
  11. package/dist/components/shared/index.js +1 -0
  12. package/dist/components/vibe/VibeLinkedEntitiesPanel.js +60 -0
  13. package/dist/components/vibe/VibeLinkedEntitiesPanel.js.map +1 -0
  14. package/dist/components/vibedeck/VibeDeckButtonTile.js +25 -23
  15. package/dist/components/vibedeck/VibeDeckButtonTile.js.map +1 -1
  16. package/dist/components/vibedeck/VibeDeckGrid.js +2 -2
  17. package/dist/components/vibedeck/VibeDeckGrid.js.map +1 -1
  18. package/dist/microfe-vibecontrols.css +1 -1
  19. package/dist/pages/AgentDetailsPage.js +2 -2
  20. package/dist/pages/AgentDetailsPage.js.map +1 -1
  21. package/dist/pages/AnalyticsPage.js +255 -204
  22. package/dist/pages/AnalyticsPage.js.map +1 -1
  23. package/dist/pages/OverviewPage.js +1 -11
  24. package/dist/pages/OverviewPage.js.map +1 -1
  25. package/dist/pages/SessionsPage.js +825 -629
  26. package/dist/pages/SessionsPage.js.map +1 -1
  27. package/dist/pages/VibeAuditPage.js +184 -153
  28. package/dist/pages/VibeAuditPage.js.map +1 -1
  29. package/dist/pages/VibeDeckPage.js +416 -379
  30. package/dist/pages/VibeDeckPage.js.map +1 -1
  31. package/dist/pages/VibeDetailsPage.js +621 -557
  32. package/dist/pages/VibeDetailsPage.js.map +1 -1
  33. package/dist/pages/tunnels/TunnelsTab.js +115 -90
  34. package/dist/pages/tunnels/TunnelsTab.js.map +1 -1
  35. package/dist/services/schedulerApi.js +37 -15
  36. package/dist/services/schedulerApi.js.map +1 -1
  37. package/package.json +1 -1
@@ -2,6 +2,7 @@ import { VibeControlsProvider as e } from "./providers/VibeControlsProvider.js";
2
2
  import { VibeControlsRoutes as t } from "./VibeControlsRoutes.js";
3
3
  import n from "./components/shared/AgentEventsConnector.js";
4
4
  /* empty css */
5
+ /* empty css */
5
6
  import { useEffect as r } from "react";
6
7
  import { useI18n as i } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
7
8
  import { useRecordProductVisit as a } from "@burdenoff/fe-libs/shared/hooks";
@@ -1 +1 @@
1
- {"version":3,"file":"VibeControlsRoot.js","names":[],"sources":["../src/VibeControlsRoot.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useEffect, useMemo } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useRecordProductVisit } from '@burdenoff/fe-libs/shared/hooks';\nimport {\n LayoutDashboard,\n Bot,\n Terminal,\n Zap,\n Globe,\n Settings,\n Activity,\n Rocket,\n LayoutGrid,\n CalendarClock,\n Shield,\n Server,\n GitBranch,\n Brain,\n Bookmark,\n PlayCircle,\n BarChart2,\n BookOpen,\n Box,\n FileCode,\n Plug,\n Puzzle,\n} from 'lucide-react';\nimport { VibeControlsProvider } from './providers/VibeControlsProvider';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport type { NavItem, VibeControlsRootProps } from './types';\nimport { VibeControlsRoutes } from './VibeControlsRoutes';\nimport { AgentEventsConnector } from './components/shared/AgentEventsConnector';\nimport './styles/vibecontrols.css';\n\n/**\n * Root component for the VibeControls microfrontend.\n *\n * This is the main entry point that host applications import and render.\n * It sets up the necessary providers and renders the internal routing.\n * Automatically registers navigation items with the shell if registration functions are provided.\n *\n * @example\n * ```tsx\n * import { VibeControlsRoot, type VibeControlsRootProps } from '@burdenoff/microfe-vibecontrols';\n *\n * function App() {\n * const props: VibeControlsRootProps = {\n * basePath: '/vibecontrols',\n * navigate: (path) => router.push(path),\n * currentUser: { id: '1', email: 'user@example.com', firstName: 'John', lastName: 'Doe' },\n * workspaceId: 'ws-123',\n * tenantId: 'tenant-123',\n * apiGatewayUrl: 'https://api.example.com',\n * authToken: 'token',\n * defaultView: 'agents',\n * onAgentSelect: (agent) => console.log('Agent selected:', agent),\n * onSessionStart: (session) => console.log('Session started:', session),\n * onVibeActivate: (vibe) => console.log('Vibe activated:', vibe),\n * registerNavItems: (items) => { return () => {}; },\n * };\n *\n * return <VibeControlsRoot {...props} />;\n * }\n * ```\n */\nexport const VibeControlsRoot: FC<VibeControlsRootProps> = (props) => {\n const { registerNavItems, registerFooterItems, basePath = '/', workspaceId } = props;\n const { t, locale } = useI18n();\n\n const isPublicLinkRoute =\n typeof window !== 'undefined' &&\n /^\\/vibecontrols\\/(share|deck)\\//.test(window.location.pathname);\n\n useRecordProductVisit({ productSlug: 'vibecontrols', enabled: !isPublicLinkRoute });\n\n // Helper to join paths correctly, avoiding double slashes\n const joinPath = (base: string, path: string): string => {\n const cleanBase = base.endsWith('/') ? base.slice(0, -1) : base;\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n return cleanBase + cleanPath;\n };\n\n // Register navigation items with the shell\n useEffect(() => {\n if (!registerNavItems || isPublicLinkRoute) return;\n\n const navItems: NavItem[] = [\n // Main navigation\n {\n id: 'vibecontrols-overview',\n label: t('nav.overview'),\n path: basePath === '/' ? '/' : basePath,\n icon: <LayoutDashboard size={20} />,\n order: 10,\n group: 'vibecontrols',\n },\n\n // Targets first — the primary entity\n {\n id: 'vibecontrols-targets',\n label: t('nav.targets'),\n path: joinPath(basePath, 'targets'),\n icon: <Server size={20} />,\n order: 12,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-agents',\n label: t('nav.agents'),\n path: joinPath(basePath, 'agents'),\n icon: <Bot size={20} />,\n order: 14,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-agent-graph',\n label: t('nav.agentGraph'),\n path: joinPath(basePath, 'agent-graph'),\n icon: <GitBranch size={20} />,\n order: 16,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-vibes',\n label: t('nav.vibes'),\n path: joinPath(basePath, 'vibes'),\n icon: <Zap size={20} />,\n order: 20,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-catalogs',\n label: t('nav.catalogs') === 'nav.catalogs' ? 'Catalogs' : t('nav.catalogs'),\n path: joinPath(basePath, 'catalogs'),\n icon: <BookOpen size={20} />,\n order: 21,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-components',\n label: t('nav.components') === 'nav.components' ? 'Components' : t('nav.components'),\n path: joinPath(basePath, 'components'),\n icon: <Box size={20} />,\n order: 22,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-templates',\n label: t('nav.templates') === 'nav.templates' ? 'Templates' : t('nav.templates'),\n path: joinPath(basePath, 'templates'),\n icon: <FileCode size={20} />,\n order: 23,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-plugins',\n label: t('nav.plugins') === 'nav.plugins' ? 'Plugins' : t('nav.plugins'),\n path: joinPath(basePath, 'plugins'),\n icon: <Puzzle size={20} />,\n order: 24,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-vibedeck',\n label: t('nav.vibeDeck'),\n path: joinPath(basePath, 'vibedeck'),\n icon: <LayoutGrid size={20} />,\n order: 25,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-sessions',\n label: t('nav.sessions'),\n path: joinPath(basePath, 'sessions'),\n icon: <Terminal size={20} />,\n order: 30,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-vibecalendar',\n label: t('nav.vibeCalendar'),\n path: joinPath(basePath, 'calendar'),\n icon: <CalendarClock size={20} />,\n order: 35,\n group: 'vibecontrols',\n },\n // AI Vibecoding\n {\n id: 'vibecontrols-ai',\n label: t('nav.ai'),\n path: joinPath(basePath, 'ai'),\n icon: <Brain size={20} />,\n order: 38,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-ai-bookmarks',\n label: t('nav.aiBookmarks'),\n path: joinPath(basePath, 'ai/bookmarks'),\n icon: <Bookmark size={20} />,\n order: 38.5,\n group: 'vibecontrols',\n },\n\n // Actions\n {\n id: 'vibecontrols-actions',\n label: t('nav.actions'),\n path: joinPath(basePath, 'actions'),\n icon: <PlayCircle size={20} />,\n order: 40,\n group: 'vibecontrols',\n },\n\n {\n id: 'vibecontrols-getting-started',\n label: t('nav.gettingStarted'),\n path: joinPath(basePath, 'getting-started'),\n icon: <Rocket size={20} />,\n order: 50,\n group: 'vibecontrols',\n },\n\n // Connection management\n {\n id: 'vibecontrols-tunnels',\n label: t('nav.tunnels'),\n path: joinPath(basePath, 'tunnels'),\n icon: <Globe size={20} />,\n order: 47,\n group: 'vibecontrols',\n },\n\n {\n id: 'vibecontrols-analytics',\n label: t('nav.analytics'),\n path: joinPath(basePath, 'analytics'),\n icon: <BarChart2 size={20} />,\n order: 55.5,\n group: 'vibecontrols-system',\n },\n {\n id: 'vibecontrols-audit',\n label: t('nav.vibeAudit'),\n path: joinPath(basePath, 'audit'),\n icon: <Shield size={20} />,\n order: 56,\n group: 'vibecontrols-system',\n },\n\n // Settings & System\n {\n id: 'vibecontrols-health',\n label: t('nav.health'),\n path: joinPath(basePath, 'health'),\n icon: <Activity size={20} />,\n order: 110,\n group: 'vibecontrols-system',\n },\n {\n id: 'vibecontrols-integrations',\n label:\n t('nav.integrations') === 'nav.integrations' ? 'Integrations' : t('nav.integrations'),\n // Absolute path — links out to the host shell's /integrations route\n // (microfe-integrations, mounted by vibecontrols-app). Keeps the\n // VibeControls MFE compliant with the no-cross-MFE-import rule.\n path: '/integrations',\n icon: <Plug size={20} />,\n order: 115,\n group: 'vibecontrols-system',\n },\n {\n id: 'vibecontrols-settings',\n label: t('nav.settings'),\n path: joinPath(basePath, 'settings'),\n icon: <Settings size={20} />,\n order: 120,\n group: 'vibecontrols-system',\n },\n ];\n\n // Register and get cleanup function\n const cleanup = registerNavItems(navItems);\n\n // Return cleanup function to unregister on unmount\n return cleanup;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [registerNavItems, basePath, t, locale, isPublicLinkRoute]);\n\n // Register footer items (example: status indicator in left section)\n useEffect(() => {\n if (!registerFooterItems || isPublicLinkRoute) return;\n\n const footerItems = [\n {\n id: 'vibecontrols-status',\n label: 'VibeControls Ready',\n type: 'status' as const,\n order: 10,\n section: 'left' as const,\n },\n ];\n\n const cleanup = registerFooterItems(footerItems);\n return cleanup;\n }, [registerFooterItems, isPublicLinkRoute]);\n\n return (\n <FeatureFlagProvider workspaceId={workspaceId ?? null} gateway=\"global\" defaultEnabled={true}>\n <VibeControlsProvider {...props}>\n {!isPublicLinkRoute ? (\n /* Agent events connector - syncs active agent to WebSocket */\n <AgentEventsConnector />\n ) : null}\n <VibeControlsRoutes />\n </VibeControlsProvider>\n </FeatureFlagProvider>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"VibeControlsRoot.js","names":[],"sources":["../src/VibeControlsRoot.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useEffect, useMemo } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useRecordProductVisit } from '@burdenoff/fe-libs/shared/hooks';\nimport {\n LayoutDashboard,\n Bot,\n Terminal,\n Zap,\n Globe,\n Settings,\n Activity,\n Rocket,\n LayoutGrid,\n CalendarClock,\n Shield,\n Server,\n GitBranch,\n Brain,\n Bookmark,\n PlayCircle,\n BarChart2,\n BookOpen,\n Box,\n FileCode,\n Plug,\n Puzzle,\n} from 'lucide-react';\nimport { VibeControlsProvider } from './providers/VibeControlsProvider';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport type { NavItem, VibeControlsRootProps } from './types';\nimport { VibeControlsRoutes } from './VibeControlsRoutes';\nimport { AgentEventsConnector } from './components/shared/AgentEventsConnector';\nimport './styles/vibecontrols.css';\nimport './styles/print.css';\n\n/**\n * Root component for the VibeControls microfrontend.\n *\n * This is the main entry point that host applications import and render.\n * It sets up the necessary providers and renders the internal routing.\n * Automatically registers navigation items with the shell if registration functions are provided.\n *\n * @example\n * ```tsx\n * import { VibeControlsRoot, type VibeControlsRootProps } from '@burdenoff/microfe-vibecontrols';\n *\n * function App() {\n * const props: VibeControlsRootProps = {\n * basePath: '/vibecontrols',\n * navigate: (path) => router.push(path),\n * currentUser: { id: '1', email: 'user@example.com', firstName: 'John', lastName: 'Doe' },\n * workspaceId: 'ws-123',\n * tenantId: 'tenant-123',\n * apiGatewayUrl: 'https://api.example.com',\n * authToken: 'token',\n * defaultView: 'agents',\n * onAgentSelect: (agent) => console.log('Agent selected:', agent),\n * onSessionStart: (session) => console.log('Session started:', session),\n * onVibeActivate: (vibe) => console.log('Vibe activated:', vibe),\n * registerNavItems: (items) => { return () => {}; },\n * };\n *\n * return <VibeControlsRoot {...props} />;\n * }\n * ```\n */\nexport const VibeControlsRoot: FC<VibeControlsRootProps> = (props) => {\n const { registerNavItems, registerFooterItems, basePath = '/', workspaceId } = props;\n const { t, locale } = useI18n();\n\n const isPublicLinkRoute =\n typeof window !== 'undefined' &&\n /^\\/vibecontrols\\/(share|deck)\\//.test(window.location.pathname);\n\n useRecordProductVisit({ productSlug: 'vibecontrols', enabled: !isPublicLinkRoute });\n\n // Helper to join paths correctly, avoiding double slashes\n const joinPath = (base: string, path: string): string => {\n const cleanBase = base.endsWith('/') ? base.slice(0, -1) : base;\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n return cleanBase + cleanPath;\n };\n\n // Register navigation items with the shell\n useEffect(() => {\n if (!registerNavItems || isPublicLinkRoute) return;\n\n const navItems: NavItem[] = [\n // Main navigation\n {\n id: 'vibecontrols-overview',\n label: t('nav.overview'),\n path: basePath === '/' ? '/' : basePath,\n icon: <LayoutDashboard size={20} />,\n order: 10,\n group: 'vibecontrols',\n },\n\n // Targets first — the primary entity\n {\n id: 'vibecontrols-targets',\n label: t('nav.targets'),\n path: joinPath(basePath, 'targets'),\n icon: <Server size={20} />,\n order: 12,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-agents',\n label: t('nav.agents'),\n path: joinPath(basePath, 'agents'),\n icon: <Bot size={20} />,\n order: 14,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-agent-graph',\n label: t('nav.agentGraph'),\n path: joinPath(basePath, 'agent-graph'),\n icon: <GitBranch size={20} />,\n order: 16,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-vibes',\n label: t('nav.vibes'),\n path: joinPath(basePath, 'vibes'),\n icon: <Zap size={20} />,\n order: 20,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-catalogs',\n label: t('nav.catalogs') === 'nav.catalogs' ? 'Catalogs' : t('nav.catalogs'),\n path: joinPath(basePath, 'catalogs'),\n icon: <BookOpen size={20} />,\n order: 21,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-components',\n label: t('nav.components') === 'nav.components' ? 'Components' : t('nav.components'),\n path: joinPath(basePath, 'components'),\n icon: <Box size={20} />,\n order: 22,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-templates',\n label: t('nav.templates') === 'nav.templates' ? 'Templates' : t('nav.templates'),\n path: joinPath(basePath, 'templates'),\n icon: <FileCode size={20} />,\n order: 23,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-plugins',\n label: t('nav.plugins') === 'nav.plugins' ? 'Plugins' : t('nav.plugins'),\n path: joinPath(basePath, 'plugins'),\n icon: <Puzzle size={20} />,\n order: 24,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-vibedeck',\n label: t('nav.vibeDeck'),\n path: joinPath(basePath, 'vibedeck'),\n icon: <LayoutGrid size={20} />,\n order: 25,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-sessions',\n label: t('nav.sessions'),\n path: joinPath(basePath, 'sessions'),\n icon: <Terminal size={20} />,\n order: 30,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-vibecalendar',\n label: t('nav.vibeCalendar'),\n path: joinPath(basePath, 'calendar'),\n icon: <CalendarClock size={20} />,\n order: 35,\n group: 'vibecontrols',\n },\n // AI Vibecoding\n {\n id: 'vibecontrols-ai',\n label: t('nav.ai'),\n path: joinPath(basePath, 'ai'),\n icon: <Brain size={20} />,\n order: 38,\n group: 'vibecontrols',\n },\n {\n id: 'vibecontrols-ai-bookmarks',\n label: t('nav.aiBookmarks'),\n path: joinPath(basePath, 'ai/bookmarks'),\n icon: <Bookmark size={20} />,\n order: 38.5,\n group: 'vibecontrols',\n },\n\n // Actions\n {\n id: 'vibecontrols-actions',\n label: t('nav.actions'),\n path: joinPath(basePath, 'actions'),\n icon: <PlayCircle size={20} />,\n order: 40,\n group: 'vibecontrols',\n },\n\n {\n id: 'vibecontrols-getting-started',\n label: t('nav.gettingStarted'),\n path: joinPath(basePath, 'getting-started'),\n icon: <Rocket size={20} />,\n order: 50,\n group: 'vibecontrols',\n },\n\n // Connection management\n {\n id: 'vibecontrols-tunnels',\n label: t('nav.tunnels'),\n path: joinPath(basePath, 'tunnels'),\n icon: <Globe size={20} />,\n order: 47,\n group: 'vibecontrols',\n },\n\n {\n id: 'vibecontrols-analytics',\n label: t('nav.analytics'),\n path: joinPath(basePath, 'analytics'),\n icon: <BarChart2 size={20} />,\n order: 55.5,\n group: 'vibecontrols-system',\n },\n {\n id: 'vibecontrols-audit',\n label: t('nav.vibeAudit'),\n path: joinPath(basePath, 'audit'),\n icon: <Shield size={20} />,\n order: 56,\n group: 'vibecontrols-system',\n },\n\n // Settings & System\n {\n id: 'vibecontrols-health',\n label: t('nav.health'),\n path: joinPath(basePath, 'health'),\n icon: <Activity size={20} />,\n order: 110,\n group: 'vibecontrols-system',\n },\n {\n id: 'vibecontrols-integrations',\n label:\n t('nav.integrations') === 'nav.integrations' ? 'Integrations' : t('nav.integrations'),\n // Absolute path — links out to the host shell's /integrations route\n // (microfe-integrations, mounted by vibecontrols-app). Keeps the\n // VibeControls MFE compliant with the no-cross-MFE-import rule.\n path: '/integrations',\n icon: <Plug size={20} />,\n order: 115,\n group: 'vibecontrols-system',\n },\n {\n id: 'vibecontrols-settings',\n label: t('nav.settings'),\n path: joinPath(basePath, 'settings'),\n icon: <Settings size={20} />,\n order: 120,\n group: 'vibecontrols-system',\n },\n ];\n\n // Register and get cleanup function\n const cleanup = registerNavItems(navItems);\n\n // Return cleanup function to unregister on unmount\n return cleanup;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [registerNavItems, basePath, t, locale, isPublicLinkRoute]);\n\n // Register footer items (example: status indicator in left section)\n useEffect(() => {\n if (!registerFooterItems || isPublicLinkRoute) return;\n\n const footerItems = [\n {\n id: 'vibecontrols-status',\n label: 'VibeControls Ready',\n type: 'status' as const,\n order: 10,\n section: 'left' as const,\n },\n ];\n\n const cleanup = registerFooterItems(footerItems);\n return cleanup;\n }, [registerFooterItems, isPublicLinkRoute]);\n\n return (\n <FeatureFlagProvider workspaceId={workspaceId ?? null} gateway=\"global\" defaultEnabled={true}>\n <VibeControlsProvider {...props}>\n {!isPublicLinkRoute ? (\n /* Agent events connector - syncs active agent to WebSocket */\n <AgentEventsConnector />\n ) : null}\n <VibeControlsRoutes />\n </VibeControlsProvider>\n </FeatureFlagProvider>\n );\n};\n"],"mappings":"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"}
@@ -56,7 +56,7 @@ var pe = [
56
56
  command: "/help",
57
57
  description: "Show available commands"
58
58
  }
59
- ], me = [
59
+ ], h = [
60
60
  "claude",
61
61
  "codex",
62
62
  "gemini",
@@ -73,18 +73,18 @@ var pe = [
73
73
  "pi",
74
74
  "aider",
75
75
  "plandex"
76
- ], h = ["sdk", "cli"];
77
- function g({ agentId: g, sessionId: _, onSend: v, onCancel: he, mcpServers: ge = [], agentTunnelUrl: y, agentApiKey: b }) {
78
- let [x, S] = f(""), [C, w] = f([]), [_e, T] = 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);
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
79
  l(() => {
80
80
  F.current?.focus({ preventScroll: !0 });
81
81
  }, []);
82
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(() => ({
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 = x.trim().length > 0 && !J;
85
+ }), [g, W]), { isListening: K, transcript: q, startListening: De, stopListening: Oe } = ee(), J = L?.status === "streaming", Y = S.trim().length > 0 && !J;
86
86
  l(() => {
87
- q && K && S((e) => e + (e ? " " : "") + q);
87
+ q && K && C((e) => e + (e ? " " : "") + q);
88
88
  }, [q, K]), l(() => {
89
89
  let e = !1;
90
90
  return r(G).then((t) => {
@@ -95,79 +95,85 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: he, mcpServers: ge =
95
95
  e = !0;
96
96
  };
97
97
  }, [G]), l(() => {
98
- x.startsWith("/") && !x.includes(" ") ? (T(!0), ve(x.slice(1))) : T(!1);
99
- }, [x]);
100
- let X = u(() => pe.filter((e) => e.command.toLowerCase().includes(`/${E.toLowerCase()}`)), [E]);
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
101
  l(() => {
102
102
  let e = F.current;
103
103
  e && (e.style.height = "auto", e.style.height = `${Math.min(e.scrollHeight, 200)}px`);
104
- }, [x]), l(() => {
104
+ }, [S]), l(() => {
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 Z = c((e) => {
111
+ let X = c((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, _]), ke = c(async () => {
119
- if (!(!x.trim() || !j || !y || !b)) try {
118
+ }, [H, _]), Ae = c(async () => {
119
+ if (!(!S.trim() || !j || !b || !x)) try {
120
120
  let e = await te({
121
121
  sessionId: _,
122
- agentTunnelUrl: y,
123
- agentApiKey: b,
124
- prompt: x.trim(),
122
+ agentTunnelUrl: b,
123
+ agentApiKey: x,
124
+ agentRef: W ? {
125
+ agentId: g,
126
+ profile: W
127
+ } : void 0,
128
+ prompt: S.trim(),
125
129
  scheduledAt: new Date(j).toISOString()
126
130
  });
127
- Z(`Prompt scheduled for ${new Date(e.scheduledAt).toLocaleString()} (Job: ${e.jobId.slice(0, 8)})`), S(""), M(""), A(!1), O(!1);
131
+ X(`Prompt scheduled for ${new Date(e.scheduledAt).toLocaleString()} (Job: ${e.jobId.slice(0, 8)})`), C(""), M(""), A(!1), O(!1);
128
132
  } catch (e) {
129
- Z(`Failed to schedule: ${e instanceof Error ? e.message : "Unknown error"}`);
133
+ X(`Failed to schedule: ${e instanceof Error ? e.message : "Unknown error"}`);
130
134
  }
131
135
  }, [
132
- x,
136
+ S,
133
137
  j,
134
- y,
135
138
  b,
139
+ x,
136
140
  _,
137
- Z
138
- ]), Q = c((e) => {
141
+ g,
142
+ W,
143
+ X
144
+ ]), Z = c((e) => {
139
145
  let t = e.trim().split(/\s+/), n = t[0].toLowerCase(), r = t.slice(1).join(" ");
140
146
  switch (n) {
141
147
  case "/new":
142
148
  V(`session-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`);
143
149
  break;
144
150
  case "/rename":
145
- Z(r ? `Session renamed to "${r}".` : "Usage: /rename <name>");
151
+ X(r ? `Session renamed to "${r}".` : "Usage: /rename <name>");
146
152
  break;
147
153
  case "/model":
148
- r ? (R(_, r), Z(`Model switched to "${r}".`)) : Z("Usage: /model <model-name>");
154
+ r ? (R(_, r), X(`Model switched to "${r}".`)) : X("Usage: /model <model-name>");
149
155
  break;
150
156
  case "/sdk":
151
- if (r && me.includes(r)) {
157
+ if (r && h.includes(r)) {
152
158
  let e = r;
153
- z(_, e), s(G, e, L?.model ?? "default").then((e) => R(_, e)).catch(() => R(_, L?.model ?? "default")), Z(`SDK switched to "${r}".`);
154
- } else Z(`Usage: /sdk <${me.join("|")}>`);
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("|")}>`);
155
161
  break;
156
162
  case "/mode":
157
- r && h.includes(r) ? (B(_, r), Z(`Mode switched to "${r}".`)) : Z(`Usage: /mode <${h.join("|")}>`);
163
+ r && me.includes(r) ? (B(_, r), X(`Mode switched to "${r}".`)) : X(`Usage: /mode <${me.join("|")}>`);
158
164
  break;
159
165
  case "/export": {
160
166
  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");
161
- o.href = a, o.download = `conversation-${_}.${e}`, o.click(), URL.revokeObjectURL(a), Z(`Conversation exported as ${e}.`);
167
+ o.href = a, o.download = `conversation-${_}.${e}`, o.click(), URL.revokeObjectURL(a), X(`Conversation exported as ${e}.`);
162
168
  break;
163
169
  }
164
170
  case "/clear":
165
- Z("Conversation cleared.");
171
+ X("Conversation cleared.");
166
172
  break;
167
173
  case "/help":
168
- Z(`Available commands:\n${pe.map((e) => ` ${e.command}${e.args ? " " + e.args : ""} - ${e.description}`).join("\n")}`);
174
+ X(`Available commands:\n${pe.map((e) => ` ${e.command}${e.args ? " " + e.args : ""} - ${e.description}`).join("\n")}`);
169
175
  break;
170
- default: Z(`Unknown command: ${n}. Type /help for available commands.`);
176
+ default: X(`Unknown command: ${n}. Type /help for available commands.`);
171
177
  }
172
178
  }, [
173
179
  _,
@@ -177,42 +183,42 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: he, mcpServers: ge =
177
183
  R,
178
184
  z,
179
185
  B,
180
- Z,
186
+ X,
181
187
  G
182
- ]), Ae = c((e) => {
183
- e.args ? S(`${e.command} `) : (Q(e.command), S("")), T(!1), F.current?.focus();
184
- }, [Q]), $ = c(() => {
188
+ ]), je = c((e) => {
189
+ e.args ? C(`${e.command} `) : (Z(e.command), C("")), E(!1), F.current?.focus();
190
+ }, [Z]), Q = c(() => {
185
191
  if (!Y) return;
186
- let e = x.trim();
192
+ let e = S.trim();
187
193
  if (e.startsWith("/")) {
188
- Q(e), S(""), w([]);
194
+ Z(e), C(""), T([]);
189
195
  return;
190
196
  }
191
- v(e, C.length > 0 ? C : void 0), S(""), w([]);
197
+ v(e, w.length > 0 ? w : void 0), C(""), T([]);
192
198
  }, [
193
199
  Y,
194
- x,
195
- C,
200
+ S,
201
+ w,
196
202
  v,
197
- Q
198
- ]), je = c((e) => {
199
- e.key === "Enter" && !e.shiftKey && (e.preventDefault(), $());
200
- }, [$]), Me = c(() => {
201
- he?.();
202
- }, [he]), Ne = c((e) => {
203
- w((t) => [...t, ...e]);
203
+ Z
204
+ ]), Me = c((e) => {
205
+ e.key === "Enter" && !e.shiftKey && (e.preventDefault(), Q());
206
+ }, [Q]), Ne = c(() => {
207
+ y?.();
208
+ }, [y]), $ = c((e) => {
209
+ T((t) => [...t, ...e]);
204
210
  }, []), Pe = c((e) => {
205
- w((t) => t.filter((t, n) => n !== e));
206
- }, []), Fe = oe(Ne);
211
+ T((t) => t.filter((t, n) => n !== e));
212
+ }, []), Fe = oe($);
207
213
  return L ? /* @__PURE__ */ m("div", {
208
214
  className: "relative z-30 border-t border-border-default bg-bg-surface",
209
215
  ...Fe,
210
216
  children: [
211
- _e && X.length > 0 && /* @__PURE__ */ p("div", {
217
+ ge && ke.length > 0 && /* @__PURE__ */ p("div", {
212
218
  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",
213
- children: X.map((e) => /* @__PURE__ */ m("button", {
219
+ children: ke.map((e) => /* @__PURE__ */ m("button", {
214
220
  type: "button",
215
- onClick: () => Ae(e),
221
+ onClick: () => je(e),
216
222
  className: "flex items-center gap-2 w-full px-3 py-2 text-left hover:bg-bg-sunken transition-colors",
217
223
  children: [
218
224
  /* @__PURE__ */ p("span", {
@@ -230,9 +236,9 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: he, mcpServers: ge =
230
236
  ]
231
237
  }, e.command))
232
238
  }),
233
- C.length > 0 && /* @__PURE__ */ p("div", {
239
+ w.length > 0 && /* @__PURE__ */ p("div", {
234
240
  className: "flex items-center gap-2 px-3 pt-2 overflow-x-auto",
235
- children: C.map((e, t) => /* @__PURE__ */ m("div", {
241
+ children: w.map((e, t) => /* @__PURE__ */ m("div", {
236
242
  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",
237
243
  children: [/* @__PURE__ */ p("span", {
238
244
  className: "truncate max-w-[120px]",
@@ -270,7 +276,7 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: he, mcpServers: ge =
270
276
  }),
271
277
  /* @__PURE__ */ p(re, {
272
278
  selected: L.mcpServers,
273
- available: ge,
279
+ available: he,
274
280
  onChange: () => {}
275
281
  }),
276
282
  /* @__PURE__ */ p(se, {
@@ -324,7 +330,7 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: he, mcpServers: ge =
324
330
  },
325
331
  isListening: K
326
332
  }),
327
- /* @__PURE__ */ p(ae, { onFileSelect: Ne })
333
+ /* @__PURE__ */ p(ae, { onFileSelect: $ })
328
334
  ]
329
335
  }),
330
336
  /* @__PURE__ */ m("div", {
@@ -332,16 +338,16 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: he, mcpServers: ge =
332
338
  children: [/* @__PURE__ */ p("textarea", {
333
339
  "aria-label": "control",
334
340
  ref: F,
335
- value: x,
336
- onChange: (e) => S(e.target.value),
337
- onKeyDown: je,
341
+ value: S,
342
+ onChange: (e) => C(e.target.value),
343
+ onKeyDown: Me,
338
344
  placeholder: P("vibecontrols.agentManager.inputArea.placeholder", "Type a message or / for commands... (Enter to send)"),
339
345
  rows: 1,
340
346
  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",
341
347
  disabled: J
342
348
  }), J ? /* @__PURE__ */ p("button", {
343
349
  type: "button",
344
- onClick: Me,
350
+ onClick: Ne,
345
351
  className: "flex-shrink-0 p-2 rounded-lg bg-status-error-bg text-status-error-text hover:opacity-90 transition-opacity",
346
352
  title: P("vibecontrols.agentManager.inputArea.cancel", "Cancel"),
347
353
  children: /* @__PURE__ */ p(de, { className: "size-4" })
@@ -351,7 +357,7 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: he, mcpServers: ge =
351
357
  children: [
352
358
  /* @__PURE__ */ p("button", {
353
359
  type: "button",
354
- onClick: $,
360
+ onClick: Q,
355
361
  disabled: !Y,
356
362
  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",
357
363
  title: P("vibecontrols.agentManager.inputArea.send", "Send (Enter)"),
@@ -383,8 +389,8 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: he, mcpServers: ge =
383
389
  }),
384
390
  /* @__PURE__ */ p("button", {
385
391
  type: "button",
386
- onClick: () => void ke(),
387
- disabled: !j || !y || !b,
392
+ onClick: () => void Ae(),
393
+ disabled: !j || !b || !x,
388
394
  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",
389
395
  children: P("vibecontrols.agentManager.inputArea.schedule", "Schedule")
390
396
  })
@@ -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 } 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=\"size-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 aria-label=\"control\"\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=\"size-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=\"size-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=\"size-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=\"size-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 aria-label=\"control\"\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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"}
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 // SECURITY-F12: pass both `agentRef` (preferred, secret-free) and\n // legacy `agentApiKey` (fallback). `schedulerApi.schedulePrompt`\n // picks the secret-free GRAPHQL executor when\n // `VITE_SCHEDULER_AGENT_REF_ENABLED=true` and `agentRef` is set;\n // otherwise it falls back to the legacy WEBHOOK payload. See\n // ~/products/dev/platform/context/scheduler/SECURITY_F12.md.\n const result = await schedulePrompt({\n sessionId,\n agentTunnelUrl,\n agentApiKey,\n agentRef: activeProfile ? { agentId, profile: activeProfile } : undefined,\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 }, [\n text,\n scheduleDateTime,\n agentTunnelUrl,\n agentApiKey,\n sessionId,\n agentId,\n activeProfile,\n addSystemMessage,\n ]);\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=\"size-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 aria-label=\"control\"\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=\"size-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=\"size-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=\"size-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=\"size-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 aria-label=\"control\"\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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"}