'use client' import * as React from 'react' import { createPortal } from 'react-dom' import { Command } from 'cmdk' import { Loader2, Send, Square } from 'lucide-react' import { cn } from '@open-mercato/shared/lib/utils' import { Button } from '@open-mercato/ui/primitives/button' import { Dialog, DialogContent, DialogTitle } from '@open-mercato/ui/primitives/dialog' import { VisuallyHidden } from '@radix-ui/react-visually-hidden' import { useCommandPaletteContext } from './CommandPaletteProvider' import { CommandInput } from './CommandInput' import { CommandHeader } from './CommandHeader' import { CommandFooter } from './CommandFooter' import { ToolChatPage } from './ToolChatPage' import { DebugPanel } from './DebugPanel' // Idle state - shown when palette is open but no query submitted function IdleState() { return (

Ask me anything or describe what you want to do.

Examples:

) } // Routing indicator - shown while fast model analyzes intent function RoutingIndicator() { return (
Analyzing request...
) } export function CommandPalette() { const { state, isThinking, agentStatus, isSessionAuthorized, messages, pendingToolCalls, selectedTool, close, setInputValue, handleSubmit, reset, sendAgenticMessage, stopExecution, approveToolCall, rejectToolCall, debugEvents, showDebug, setShowDebug, clearDebugEvents, pendingQuestion, answerQuestion, } = useCommandPaletteContext() const { isOpen, phase, inputValue, isLoading, isStreaming, connectionStatus, } = state const [localInput, setLocalInput] = React.useState('') const [chatInput, setChatInput] = React.useState('') const chatInputRef = React.useRef(null) // Reset local input when phase changes to idle React.useEffect(() => { if (phase === 'idle') { setLocalInput('') setChatInput('') } }, [phase]) // Focus chat input when entering chatting phase React.useEffect(() => { if (phase === 'chatting' || phase === 'confirming' || phase === 'executing') { // Small delay to ensure DOM is ready setTimeout(() => chatInputRef.current?.focus(), 50) } }, [phase]) const handleOpenChange = (open: boolean) => { if (!open) { close() } } const handleInputSubmit = async () => { const query = localInput.trim() if (!query) return setLocalInput('') await handleSubmit(query) } const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && phase === 'idle' && localInput.trim()) { e.preventDefault() handleInputSubmit() } } const handleChatSubmit = async (e: React.FormEvent) => { e.preventDefault() if (!chatInput.trim() || isStreaming) return const content = chatInput setChatInput('') await sendAgenticMessage(content) } const handleChatKeyDown = (e: React.KeyboardEvent) => { // Prevent escape from bubbling to close the palette if (e.key === 'Escape') { e.stopPropagation() } // Submit on Enter (not Shift+Enter for multiline) if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault() if (chatInput.trim() && !isStreaming) { const content = chatInput setChatInput('') sendAgenticMessage(content) } } } return ( <> {/* Custom blur overlay when debug mode is on (since modal=false removes it) */} {isOpen && showDebug && (
)} { // Prevent closing on outside click when debug mode is on if (showDebug) { e.preventDefault() } }} onInteractOutside={(e) => { // Prevent closing on outside interaction when debug mode is on if (showDebug) { e.preventDefault() } }} > {/* Visually hidden title for accessibility */} AI Command Palette {/* Header - shows phase/tool info */} {/* Input - shown in idle phase */} {phase === 'idle' && ( )} {/* Content area */}
{phase === 'idle' && !localInput && } {phase === 'routing' && } {(phase === 'chatting' || phase === 'confirming' || phase === 'executing') && ( )}
{/* Chat input - shown in chatting phases */} {(phase === 'chatting' || phase === 'confirming' || phase === 'executing') && (
setChatInput(e.target.value)} onKeyDown={handleChatKeyDown} placeholder="Describe what you want to do..." className={cn( 'flex-1 bg-muted rounded-lg px-4 py-2 text-sm outline-none', 'focus-visible:ring-2 focus-visible:ring-ring', 'disabled:opacity-50' )} disabled={isStreaming} />
)} {/* Footer with connection status and keyboard hints */} setShowDebug(!showDebug)} />
{/* Debug panel - rendered via portal outside the dialog DOM tree */} {isOpen && showDebug && typeof document !== 'undefined' && createPortal(
setShowDebug(false)} />
, document.body )} ) }