centaurus-cli 3.1.3 → 3.1.4
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.
- package/dist/cli-adapter.js +685 -153
- package/dist/cli-adapter.js.map +1 -1
- package/dist/config/defaultConfig.js +1 -4
- package/dist/config/defaultConfig.js.map +1 -1
- package/dist/config/models.js +4 -0
- package/dist/config/models.js.map +1 -1
- package/dist/config/slash-commands.js +66 -2
- package/dist/config/slash-commands.js.map +1 -1
- package/dist/config/types.js +4 -4
- package/dist/config/types.js.map +1 -1
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -1
- package/dist/services/ai-context-injector.js +109 -0
- package/dist/services/ai-context-injector.js.map +1 -1
- package/dist/services/api-client.js.map +1 -1
- package/dist/services/background-task-manager.js +59 -0
- package/dist/services/background-task-manager.js.map +1 -1
- package/dist/services/local-chat-storage.js +2 -0
- package/dist/services/local-chat-storage.js.map +1 -1
- package/dist/services/skill-storage.js +141 -0
- package/dist/services/skill-storage.js.map +1 -0
- package/dist/services/sub-agent-manager.js +49 -8
- package/dist/services/sub-agent-manager.js.map +1 -1
- package/dist/services/warpify-detector.js +17 -5
- package/dist/services/warpify-detector.js.map +1 -1
- package/dist/tools/background-command.js +5 -2
- package/dist/tools/background-command.js.map +1 -1
- package/dist/tools/command.js +367 -109
- package/dist/tools/command.js.map +1 -1
- package/dist/tools/file-ops.js +23 -6
- package/dist/tools/file-ops.js.map +1 -1
- package/dist/tools/plan-mode.js +184 -336
- package/dist/tools/plan-mode.js.map +1 -1
- package/dist/tools/sub-agent.js +24 -5
- package/dist/tools/sub-agent.js.map +1 -1
- package/dist/tools/todo-list.js +157 -0
- package/dist/tools/todo-list.js.map +1 -0
- package/dist/types/skill.js +30 -0
- package/dist/types/skill.js.map +1 -0
- package/dist/ui/components/App.js +956 -162
- package/dist/ui/components/App.js.map +1 -1
- package/dist/ui/components/AuthScreen.js +3 -1
- package/dist/ui/components/AuthScreen.js.map +1 -1
- package/dist/ui/components/AuthWelcomeScreen.js +3 -1
- package/dist/ui/components/AuthWelcomeScreen.js.map +1 -1
- package/dist/ui/components/CodeBlock.js +3 -1
- package/dist/ui/components/CodeBlock.js.map +1 -1
- package/dist/ui/components/CompactShellPreview.js +44 -0
- package/dist/ui/components/CompactShellPreview.js.map +1 -0
- package/dist/ui/components/ConfigViewer.js +3 -1
- package/dist/ui/components/ConfigViewer.js.map +1 -1
- package/dist/ui/components/ConfirmPrompt.js +3 -1
- package/dist/ui/components/ConfirmPrompt.js.map +1 -1
- package/dist/ui/components/ConnectionStatusMessage.js +3 -1
- package/dist/ui/components/ConnectionStatusMessage.js.map +1 -1
- package/dist/ui/components/DetailedPlanReviewScreen.js +84 -74
- package/dist/ui/components/DetailedPlanReviewScreen.js.map +1 -1
- package/dist/ui/components/DiffViewer.js +6 -3
- package/dist/ui/components/DiffViewer.js.map +1 -1
- package/dist/ui/components/FileCreationPreview.js.map +1 -1
- package/dist/ui/components/FileTagAutocomplete.js +4 -2
- package/dist/ui/components/FileTagAutocomplete.js.map +1 -1
- package/dist/ui/components/InputBox.js +243 -40
- package/dist/ui/components/InputBox.js.map +1 -1
- package/dist/ui/components/InteractiveShell.js +5 -3
- package/dist/ui/components/InteractiveShell.js.map +1 -1
- package/dist/ui/components/KeyboardHelp.js +4 -1
- package/dist/ui/components/KeyboardHelp.js.map +1 -1
- package/dist/ui/components/LoadingIndicator.js +3 -1
- package/dist/ui/components/LoadingIndicator.js.map +1 -1
- package/dist/ui/components/MCPAddScreen.js +63 -13
- package/dist/ui/components/MCPAddScreen.js.map +1 -1
- package/dist/ui/components/MarkdownRenderer.js +3 -1
- package/dist/ui/components/MarkdownRenderer.js.map +1 -1
- package/dist/ui/components/MessageDisplay.js +9 -7
- package/dist/ui/components/MessageDisplay.js.map +1 -1
- package/dist/ui/components/ModelPicker.js +170 -0
- package/dist/ui/components/ModelPicker.js.map +1 -0
- package/dist/ui/components/MonitorModeAIPanel.js +3 -1
- package/dist/ui/components/MonitorModeAIPanel.js.map +1 -1
- package/dist/ui/components/PlanAcceptedMessage.js +12 -6
- package/dist/ui/components/PlanAcceptedMessage.js.map +1 -1
- package/dist/ui/components/PlanQuestionMessage.js +37 -0
- package/dist/ui/components/PlanQuestionMessage.js.map +1 -0
- package/dist/ui/components/PlanQuestionScreen.js +138 -0
- package/dist/ui/components/PlanQuestionScreen.js.map +1 -0
- package/dist/ui/components/PlanReviewScreen.js +7 -9
- package/dist/ui/components/PlanReviewScreen.js.map +1 -1
- package/dist/ui/components/RulesEditorScreen.js +65 -28
- package/dist/ui/components/RulesEditorScreen.js.map +1 -1
- package/dist/ui/components/SelectPrompt.js +3 -1
- package/dist/ui/components/SelectPrompt.js.map +1 -1
- package/dist/ui/components/SkillCreatorScreen.js +217 -0
- package/dist/ui/components/SkillCreatorScreen.js.map +1 -0
- package/dist/ui/components/SlashCommandAutocomplete.js +4 -2
- package/dist/ui/components/SlashCommandAutocomplete.js.map +1 -1
- package/dist/ui/components/StatusBar.js +4 -2
- package/dist/ui/components/StatusBar.js.map +1 -1
- package/dist/ui/components/StreamingMessageDisplay.js +5 -3
- package/dist/ui/components/StreamingMessageDisplay.js.map +1 -1
- package/dist/ui/components/SubAgentListScreen.js +65 -0
- package/dist/ui/components/SubAgentListScreen.js.map +1 -0
- package/dist/ui/components/SubAgentViewScreen.js +123 -0
- package/dist/ui/components/SubAgentViewScreen.js.map +1 -0
- package/dist/ui/components/TaskCompletedMessage.js +40 -8
- package/dist/ui/components/TaskCompletedMessage.js.map +1 -1
- package/dist/ui/components/TaskProgressIndicator.js +6 -4
- package/dist/ui/components/TaskProgressIndicator.js.map +1 -1
- package/dist/ui/components/TextEditor.js +297 -0
- package/dist/ui/components/TextEditor.js.map +1 -0
- package/dist/ui/components/TodoListMessage.js +59 -0
- package/dist/ui/components/TodoListMessage.js.map +1 -0
- package/dist/ui/components/ToolExecutionMessage.js +134 -84
- package/dist/ui/components/ToolExecutionMessage.js.map +1 -1
- package/dist/ui/components/ToolExecutionStatus.js +3 -1
- package/dist/ui/components/ToolExecutionStatus.js.map +1 -1
- package/dist/ui/components/WelcomeBanner.js +33 -33
- package/dist/ui/components/WelcomeBanner.js.map +1 -1
- package/dist/ui/components/WorkflowCreatorScreen.js +5 -3
- package/dist/ui/components/WorkflowCreatorScreen.js.map +1 -1
- package/dist/ui/theme.js +97 -0
- package/dist/ui/theme.js.map +1 -0
- package/dist/ui/utils/chat-history-limit.js +247 -0
- package/dist/ui/utils/chat-history-limit.js.map +1 -0
- package/dist/utils/chat-formatter.js +22 -9
- package/dist/utils/chat-formatter.js.map +1 -1
- package/dist/utils/input-classifier.js +11 -1
- package/dist/utils/input-classifier.js.map +1 -1
- package/dist/utils/output-truncation.js +175 -0
- package/dist/utils/output-truncation.js.map +1 -0
- package/dist/utils/rule-reference-resolver.js +3 -3
- package/dist/utils/rule-reference-resolver.js.map +1 -1
- package/dist/utils/tunnel-commands-manager.js +134 -0
- package/dist/utils/tunnel-commands-manager.js.map +1 -0
- package/package.json +91 -90
- package/postinstall.js +4 -11
- package/dist/ui/components/MultiLineInput.js +0 -255
- package/dist/ui/components/MultiLineInput.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/ui/components/InputBox.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useMemo } from 'react';\r\nimport { Box, Text, useInput } from 'ink';\r\nimport * as fs from 'fs';\r\nimport * as path from 'path';\r\nimport { SubshellContext } from '../../context/types.js';\r\nimport { useConnectivity } from '../../hooks/useConnectivity.js';\r\nimport { Breadcrumbs } from './Breadcrumbs.js';\r\nimport { GitDiffBreadcrumb } from './GitDiffBreadcrumb.js';\r\nimport { ContextWindowIndicator } from './ContextWindowIndicator.js';\r\nimport { logDebug } from '../../utils/logger.js';\r\nimport { apiClient } from '../../services/api-client.js';\r\nimport { detectIntent } from '../../utils/input-classifier.js';\r\nimport { CommandHistoryManager } from '../../utils/command-history.js';\r\nimport { SlashCommandAutocomplete } from './SlashCommandAutocomplete.js';\r\nimport { FileTagAutocomplete } from './FileTagAutocomplete.js';\r\nimport { filterCommands, SlashCommand } from '../../config/slash-commands.js';\r\nimport { hasClipboardFile, getClipboardFiles, ClipboardFile } from '../../services/clipboard-service.js';\r\nimport { useTerminalDimensions, TERMINAL_HEIGHT_CONSTANTS } from '../../hooks/useTerminalDimensions.js';\r\nimport { AIAutocompleteAgent, AI_AUTOCOMPLETE_DEBOUNCE_MS, AutocompleteContext } from '../../services/ai-autocomplete-agent.js';\r\nimport { quickLog } from '../../utils/conversation-logger.js';\r\nimport { workflowStorage } from '../../services/workflow-storage.js';\r\nimport { rulesStorage } from '../../services/rules-storage.js';\r\n\r\ninterface InputBoxProps {\r\n onSubmit: (value: string, clipboardFiles?: ClipboardFile[]) => void;\r\n placeholder?: string;\r\n autoAcceptMode: boolean;\r\n model?: string;\r\n planMode?: boolean;\r\n commandMode?: boolean;\r\n backgroundMode?: boolean; // Background shell mode for running commands in background\r\n currentWorkingDirectory?: string;\r\n commandHistory?: string[];\r\n onToggleAutoAccept: () => void;\r\n onToggleCommandMode?: () => void;\r\n onToggleBackgroundMode?: () => void; // Callback to toggle background mode\r\n isActive?: boolean;\r\n subshellContext?: SubshellContext;\r\n subshellContextStack?: SubshellContext[];\r\n currentTokens?: number;\r\n maxTokens?: number;\r\n contextLimitReached?: boolean; // True when context window is ≥80% full\r\n isShellRunning?: boolean; // Block input submission while shell command is running\r\n backgroundTaskCount?: number; // Number of running background tasks\r\n initialValue?: string; // Initial value to restore when component mounts (for preserving text across screen transitions)\r\n onValueChange?: (value: string) => void; // Callback when value changes (for preserving text across screen transitions)\r\n onSetAutoModeSetup?: (callback: (enabled: boolean) => void) => void; // Setup callback to control Auto mode from outside\r\n sessionQuotaExhausted?: boolean;\r\n sessionQuotaTimeRemaining?: string;\r\n subAgentCount?: number; // Number of running sub-agents\r\n aiAutoSuggestEnabled?: boolean; // Enable AI-powered command auto-suggestions\r\n sessionCommands?: string[]; // Commands executed in this chat session (for AI context)\r\n getCheckpoints?: () => Array<{ id: string; prompt: string; timestamp: Date }>; // Get checkpoints for revert autocomplete\r\n onSetInputSetup?: (callback: (value: string) => void) => void; // Setup callback to set input value from outside\r\n gitDiffStats?: { additions: number; deletions: number } | null; // Git diff stats for display in breadcrumb\r\n}\r\n\r\ntype MentionSuggestionKind = 'file' | 'directory' | 'rule-namespace' | 'rule';\r\n\r\ninterface MentionSuggestion {\r\n name: string;\r\n insertText: string;\r\n kind: MentionSuggestionKind;\r\n description?: string;\r\n}\r\n\r\nconst getVisualLines = (text: string, width: number) => {\r\n const logicalLines = text.split('\\n');\r\n const visualLines: Array<{ start: number; end: number; isHardEnd: boolean }> = [];\r\n let currentOffset = 0;\r\n\r\n logicalLines.forEach((line, i) => {\r\n if (line.length === 0) {\r\n visualLines.push({ start: currentOffset, end: currentOffset, isHardEnd: true });\r\n currentOffset += 1;\r\n return;\r\n }\r\n\r\n let remaining = line;\r\n let lineStartOffset = currentOffset;\r\n\r\n while (remaining.length > 0) {\r\n let splitIndex = remaining.length;\r\n let isHardEnd = false;\r\n\r\n if (remaining.length > width) {\r\n splitIndex = width;\r\n const lastSpace = remaining.lastIndexOf(' ', width);\r\n if (lastSpace > 0) {\r\n splitIndex = lastSpace + 1;\r\n }\r\n } else {\r\n isHardEnd = true;\r\n }\r\n\r\n visualLines.push({\r\n start: lineStartOffset,\r\n end: lineStartOffset + splitIndex,\r\n isHardEnd: isHardEnd\r\n });\r\n\r\n lineStartOffset += splitIndex;\r\n remaining = remaining.slice(splitIndex);\r\n }\r\n\r\n currentOffset += line.length + (i < logicalLines.length - 1 ? 1 : 0);\r\n });\r\n\r\n return visualLines;\r\n};\r\n\r\nexport const InputBox: React.FC<InputBoxProps> = React.memo(({\r\n onSubmit,\r\n placeholder = 'Ask anything ...',\r\n autoAcceptMode,\r\n model,\r\n planMode = false,\r\n commandMode = false,\r\n backgroundMode = false,\r\n currentWorkingDirectory,\r\n commandHistory = [],\r\n onToggleAutoAccept,\r\n onToggleCommandMode,\r\n onToggleBackgroundMode,\r\n isActive = true,\r\n subshellContext,\r\n subshellContextStack,\r\n currentTokens = 0,\r\n maxTokens = 1000000,\r\n contextLimitReached = false,\r\n isShellRunning = false,\r\n backgroundTaskCount = 0,\r\n initialValue = '',\r\n onValueChange,\r\n onSetAutoModeSetup,\r\n sessionQuotaExhausted = false,\r\n sessionQuotaTimeRemaining = '',\r\n subAgentCount = 0,\r\n aiAutoSuggestEnabled = false,\r\n sessionCommands = [],\r\n getCheckpoints,\r\n onSetInputSetup,\r\n gitDiffStats\r\n}) => {\r\n\r\n // Use initialValue for first mount, but manage state internally after that\r\n const [value, setValueInternal] = useState(initialValue);\r\n const [cursorOffset, setCursorOffset] = useState(0);\r\n const [completions, setCompletions] = useState<string[]>([]);\r\n const [completionIndex, setCompletionIndex] = useState(0);\r\n const [historyIndex, setHistoryIndex] = useState(-1);\r\n const [tempValue, setTempValue] = useState('');\r\n const ignoreNextChangeRef = useRef(false);\r\n\r\n // Refs to track current value and cursor for paste handling\r\n // This prevents stale closure issues when Ink calls useInput multiple times during paste\r\n const valueRef = useRef(initialValue);\r\n const cursorOffsetRef = useRef(0);\r\n\r\n // Auto Mode State\r\n const [isAutoMode, setIsAutoMode] = useState(true);\r\n const [detectedIntent, setDetectedIntent] = useState<'command' | 'ai'>('ai');\r\n\r\n // Autocomplete State\r\n const [autocompleteSuggestion, setAutocompleteSuggestion] = useState<string | null>(null);\r\n\r\n // AI Autocomplete State\r\n const [aiAutocompleteSuggestion, setAiAutocompleteSuggestion] = useState<string | null>(null);\r\n const [isAiAutocompleteLoading, setIsAiAutocompleteLoading] = useState(false);\r\n const aiAutocompleteDebounceRef = useRef<NodeJS.Timeout | null>(null);\r\n const aiAutocompleteAbortRef = useRef<AbortController | null>(null);\r\n\r\n // Undo/Redo State\r\n const [undoStack, setUndoStack] = useState<Array<{ value: string; cursorOffset: number }>>([]);\r\n const [redoStack, setRedoStack] = useState<Array<{ value: string; cursorOffset: number }>>([]);\r\n\r\n // Selection State\r\n const [selection, setSelection] = useState<{ start: number; end: number } | null>(null);\r\n\r\n // Platform Detection\r\n const isMac = process.platform === 'darwin';\r\n\r\n // Reject Flash State (turns border red when submission is blocked)\r\n const [rejectFlash, setRejectFlash] = useState(false);\r\n\r\n // Session Quota Message State (shows quota exhausted message)\r\n const [showQuotaMessage, setShowQuotaMessage] = useState(false);\r\n\r\n // Slash Command Autocomplete State\r\n const [slashAutocompleteVisible, setSlashAutocompleteVisible] = useState(false);\r\n const [slashAutocompleteCommands, setSlashAutocompleteCommands] = useState<SlashCommand[]>([]);\r\n const [slashAutocompleteSelectedIndex, setSlashAutocompleteSelectedIndex] = useState(0);\r\n const [slashAutocompleteScrollOffset, setSlashAutocompleteScrollOffset] = useState(0);\r\n\r\n // Connectivity State\r\n const isConnected = useConnectivity();\r\n\r\n // Terminal dimensions for height-aware autocomplete\r\n const dimensions = useTerminalDimensions();\r\n // Max 5 items, min 0 for very small terminals (use MIN_ROWS_FOR_STREAMING as threshold)\r\n const slashMaxVisibleItems = dimensions.rows < TERMINAL_HEIGHT_CONSTANTS.MIN_ROWS_FOR_STREAMING\r\n ? 0\r\n : Math.min(5, Math.max(1, Math.floor((dimensions.rows - 20) / 3)));\r\n\r\n // Responsive visibility thresholds based on terminal width\r\n const showBottomHints = dimensions.columns >= 90;\r\n const showModeIndicator = dimensions.columns >= 70;\r\n\r\n // File Tag Autocomplete State (@ symbol)\r\n const [fileTagAutocompleteVisible, setFileTagAutocompleteVisible] = useState(false);\r\n const [fileTagSuggestions, setFileTagSuggestions] = useState<MentionSuggestion[]>([]);\r\n const [fileTagSelectedIndex, setFileTagSelectedIndex] = useState(0);\r\n const [activeFileTagStart, setActiveFileTagStart] = useState<number | null>(null);\r\n const [confirmedFileTags, setConfirmedFileTags] = useState<Array<{ start: number, end: number, fileName: string }>>([]);\r\n\r\n // Clipboard File State (Alt+V paste)\r\n const [confirmedClipboardFiles, setConfirmedClipboardFiles] = useState<ClipboardFile[]>([]);\r\n\r\n // Track visual line count to force re-renders when text wraps\r\n // This is necessary because Ink doesn't automatically update layout when text wraps\r\n const [visualLineCount, setVisualLineCount] = useState(1);\r\n\r\n // Configuration for scrolling\r\n const MAX_VISIBLE_LINES = 9;\r\n\r\n // Wrapper for setValue that also notifies parent of changes and updates ref\r\n const setValue = React.useCallback((newValue: string | ((prev: string) => string)) => {\r\n setValueInternal(prev => {\r\n const resolvedValue = typeof newValue === 'function' ? newValue(prev) : newValue;\r\n // Update ref synchronously for paste handling\r\n valueRef.current = resolvedValue;\r\n // Notify parent of value change for preservation across screen transitions\r\n if (onValueChange) {\r\n onValueChange(resolvedValue);\r\n }\r\n return resolvedValue;\r\n });\r\n }, [onValueChange]);\r\n\r\n // Wrapper for setCursorOffset that also updates ref\r\n const setCursorOffsetWithRef = React.useCallback((newOffset: number | ((prev: number) => number)) => {\r\n setCursorOffset(prev => {\r\n const resolvedOffset = typeof newOffset === 'function' ? newOffset(prev) : newOffset;\r\n // Update ref synchronously for paste handling\r\n cursorOffsetRef.current = resolvedOffset;\r\n return resolvedOffset;\r\n });\r\n }, []);\r\n\r\n // Initialize cursor position when initialValue is provided\r\n useEffect(() => {\r\n if (initialValue && initialValue.length > 0) {\r\n setCursorOffset(initialValue.length);\r\n cursorOffsetRef.current = initialValue.length;\r\n }\r\n }, []); // Only run on mount\r\n\r\n // Keep refs in sync with state (for cases where state is updated directly)\r\n useEffect(() => {\r\n valueRef.current = value;\r\n }, [value]);\r\n\r\n useEffect(() => {\r\n cursorOffsetRef.current = cursorOffset;\r\n }, [cursorOffset]);\r\n\r\n // Load history on mount\r\n useEffect(() => {\r\n CommandHistoryManager.getInstance().load();\r\n }, []);\r\n\r\n // Register setInput callback for external control (e.g., for revert functionality)\r\n useEffect(() => {\r\n if (onSetInputSetup) {\r\n onSetInputSetup((newValue: string) => {\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n });\r\n }\r\n }, [onSetInputSetup, setValue, setCursorOffset]);\r\n\r\n // Register setIsAutoMode callback for external control (e.g., after background task starts)\r\n useEffect(() => {\r\n if (onSetInputSetup) {\r\n onSetInputSetup((newValue: string) => {\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n });\r\n }\r\n }, [onSetInputSetup, setValue, setCursorOffset]);\r\n\r\n useEffect(() => {\r\n if (onSetAutoModeSetup) {\r\n onSetAutoModeSetup((enabled: boolean) => {\r\n setIsAutoMode(enabled);\r\n if (enabled) {\r\n // When enabling Auto mode, also update detected intent based on current value\r\n const intent = detectIntent(value);\r\n setDetectedIntent(intent);\r\n // Set command mode based on intent\r\n if (intent === 'command' && !commandMode && onToggleCommandMode) {\r\n onToggleCommandMode();\r\n } else if (intent === 'ai' && commandMode && onToggleCommandMode) {\r\n onToggleCommandMode();\r\n }\r\n }\r\n });\r\n }\r\n }, [onSetAutoModeSetup, value, commandMode, onToggleCommandMode]);\r\n\r\n // Force clear value if it becomes empty or whitespace-only after external changes\r\n useEffect(() => {\r\n if (value && value.trim() === '' && cursorOffset > 0) {\r\n setValue('');\r\n setCursorOffset(0);\r\n }\r\n }, [value, cursorOffset]);\r\n\r\n // Track visual line count changes to force re-renders when text wraps\r\n // This is crucial for the input box height to update correctly\r\n useEffect(() => {\r\n const termWidth = (process.stdout.columns || 80) - 6;\r\n const visualLines = getVisualLines(value, termWidth);\r\n const newLineCount = Math.max(1, visualLines.length);\r\n if (newLineCount !== visualLineCount) {\r\n setVisualLineCount(newLineCount);\r\n }\r\n }, [value, visualLineCount]);\r\n\r\n // Determine current working directory — progressively shrinks as terminal narrows.\r\n // Segments shown: 3 (≥120), 2 (100–119), 1 / current dir only (<100).\r\n // The Ctrl+T and Mode hiding thresholds (90 and 70) are deliberately below 100\r\n // so the CWD is always fully reduced before other elements start disappearing.\r\n const currentDir = useMemo(() => {\r\n const cwd = currentWorkingDirectory || process.cwd();\r\n const sep = cwd.includes('/') ? '/' : '\\\\';\r\n const parts = cwd.split(/[\\\\/]/).filter(Boolean);\r\n\r\n const maxSegments = dimensions.columns >= 120 ? 3 : dimensions.columns >= 100 ? 2 : 1;\r\n\r\n if (parts.length > maxSegments) {\r\n return '...' + sep + parts.slice(-maxSegments).join(sep);\r\n }\r\n return cwd;\r\n }, [currentWorkingDirectory, dimensions.columns]);\r\n\r\n // Determine current environment for command history isolation\r\n // Format: 'local', 'ssh:user@host', or 'wsl:distroName'\r\n const currentEnvironment = useMemo(() => {\r\n if (!subshellContext) return 'local';\r\n if (subshellContext.type === 'ssh') {\r\n const user = subshellContext.metadata?.username || 'user';\r\n const host = subshellContext.metadata?.hostname || 'host';\r\n return `ssh:${user}@${host}`;\r\n }\r\n if (subshellContext.type === 'wsl') {\r\n const distro = subshellContext.metadata?.distroName || 'Ubuntu';\r\n return `wsl:${distro}`;\r\n }\r\n if (subshellContext.type === 'docker') {\r\n const container = subshellContext.metadata?.containerId || 'container';\r\n return `docker:${container}`;\r\n }\r\n return 'local';\r\n }, [subshellContext]);\r\n\r\n // Autocomplete Logic\r\n useEffect(() => {\r\n if (!value || value.trim() === '') {\r\n setAutocompleteSuggestion(null);\r\n return;\r\n }\r\n\r\n // Only show suggestions if we are in command mode (manual or auto-detected)\r\n // OR if we are in Auto mode and it looks like a command\r\n const shouldSuggest = commandMode || (isAutoMode && detectedIntent === 'command');\r\n\r\n if (shouldSuggest) {\r\n const matches = CommandHistoryManager.getInstance().getMatches(value, currentDir, currentEnvironment);\r\n if (matches.length > 0) {\r\n setAutocompleteSuggestion(matches[0]);\r\n } else {\r\n setAutocompleteSuggestion(null);\r\n }\r\n } else {\r\n setAutocompleteSuggestion(null);\r\n }\r\n }, [value, commandMode, isAutoMode, detectedIntent, aiAutoSuggestEnabled, currentDir, currentEnvironment]);\r\n\r\n // AI Autocomplete Logic (5-second debounce)\r\n\r\n useEffect(() => {\r\n // Clear AI suggestion when value changes\r\n setAiAutocompleteSuggestion(null);\r\n\r\n // Clear any existing debounce timer\r\n if (aiAutocompleteDebounceRef.current) {\r\n clearTimeout(aiAutocompleteDebounceRef.current);\r\n aiAutocompleteDebounceRef.current = null;\r\n }\r\n\r\n // Abort any pending AI request\r\n if (aiAutocompleteAbortRef.current) {\r\n aiAutocompleteAbortRef.current.abort();\r\n aiAutocompleteAbortRef.current = null;\r\n }\r\n\r\n // Debug logging for trigger ref\r\n /*\r\n try {\r\n if (detectedIntent !== 'ai' || value.length > 5) {\r\n quickLog(`[InputBox] AI Effect: val=\"${value}\", enabled=${aiAutoSuggestEnabled}, mode=${commandMode}, auto=${isAutoMode}, intent=${detectedIntent}`);\r\n }\r\n } catch (e) {}\r\n */\r\n\r\n // Don't trigger AI autocomplete if disabled or not in command mode\r\n if (!aiAutoSuggestEnabled) {\r\n // quickLog('[InputBox] AI skipped: disabled');\r\n return;\r\n }\r\n\r\n const shouldSuggest = commandMode || (isAutoMode && detectedIntent === 'command');\r\n if (!shouldSuggest) {\r\n // if (value.length > 3) quickLog(`[InputBox] AI skipped: !shouldSuggest (cmd=${commandMode}, auto=${isAutoMode}, intent=${detectedIntent})`);\r\n return;\r\n }\r\n\r\n // Don't suggest for empty, very short, or slash commands\r\n if (!value || value.trim().length < 2 || value.startsWith('/')) {\r\n // quickLog('[InputBox] AI skipped: too short or slash');\r\n return;\r\n }\r\n\r\n // quickLog('[InputBox] AI Triggering debounce...');\r\n\r\n // Set up 5-second debounce timer\r\n aiAutocompleteDebounceRef.current = setTimeout(async () => {\r\n setIsAiAutocompleteLoading(true);\r\n\r\n // Create abort controller for this request\r\n const abortController = new AbortController();\r\n aiAutocompleteAbortRef.current = abortController;\r\n\r\n try {\r\n if (!aiAutoSuggestEnabled) return; // double check inside timeout\r\n\r\n // Get directory history using the correct method\r\n const directoryHistory = CommandHistoryManager.getInstance().getDirectoryHistory(currentDir, currentEnvironment);\r\n\r\n // Get files in current directory (local or remote)\r\n let files: string[] = [];\r\n try {\r\n if (subshellContext && subshellContext.type !== 'local' && subshellContext.handler) {\r\n // Remote/Subshell environment\r\n // Check if we can list files\r\n try {\r\n const dirEntries = await subshellContext.handler.listDirectory(currentDir);\r\n files = dirEntries\r\n .slice(0, 50)\r\n .map((e: any) => e.name + (e.type === 'directory' ? '/' : ''));\r\n } catch (remoteErr) {\r\n // quickLog('Remote list error: ' + remoteErr);\r\n }\r\n } else {\r\n // Local environment\r\n const dir = currentDir || process.cwd();\r\n if (fs.existsSync(dir)) {\r\n const entries = fs.readdirSync(dir, { withFileTypes: true });\r\n files = entries\r\n .slice(0, 50)\r\n .map(e => e.name + (e.isDirectory() ? '/' : ''));\r\n }\r\n }\r\n } catch (e) {\r\n // Ignore file access errors\r\n }\r\n\r\n // Determine OS and Platform from subshell context if available\r\n let osContext = process.platform;\r\n let platformContext = process.platform;\r\n\r\n if (subshellContext && subshellContext.type !== 'local' && subshellContext.metadata) {\r\n const metaOs = subshellContext.metadata.os;\r\n if (metaOs === 'windows') {\r\n osContext = 'win32';\r\n platformContext = 'win32';\r\n } else if (metaOs === 'macos') {\r\n osContext = 'darwin';\r\n platformContext = 'darwin';\r\n } else if (metaOs === 'linux') {\r\n osContext = 'linux';\r\n platformContext = 'linux';\r\n }\r\n }\r\n\r\n const context: AutocompleteContext = {\r\n os: osContext,\r\n platform: platformContext,\r\n cwd: currentDir || process.cwd(),\r\n directoryHistory: directoryHistory.slice(0, 10),\r\n sessionCommands: sessionCommands.slice(-10),\r\n files: files,\r\n currentInput: value\r\n };\r\n\r\n const prediction = await AIAutocompleteAgent.predictCommand(context, abortController.signal);\r\n\r\n if (prediction && !abortController.signal.aborted) {\r\n setAiAutocompleteSuggestion(prediction);\r\n }\r\n } catch (error) {\r\n // Ignore errors (likely aborted)\r\n } finally {\r\n setIsAiAutocompleteLoading(false);\r\n if (aiAutocompleteAbortRef.current === abortController) {\r\n aiAutocompleteAbortRef.current = null;\r\n }\r\n }\r\n }, AI_AUTOCOMPLETE_DEBOUNCE_MS);\r\n\r\n return () => {\r\n if (aiAutocompleteDebounceRef.current) {\r\n clearTimeout(aiAutocompleteDebounceRef.current);\r\n }\r\n if (aiAutocompleteAbortRef.current) {\r\n aiAutocompleteAbortRef.current.abort();\r\n }\r\n };\r\n }, [value, commandMode, isAutoMode, detectedIntent, aiAutoSuggestEnabled, currentDir, currentEnvironment, sessionCommands]);\r\n\r\n // Auto-classification effect (Synchronous Heuristics Only)\r\n useEffect(() => {\r\n // Only run classification if in Auto Mode\r\n if (!isAutoMode) {\r\n return;\r\n }\r\n\r\n // Only classify if value is non-empty and not just whitespace\r\n const trimmedValue = value.trim();\r\n if (!trimmedValue || !onToggleCommandMode) {\r\n // Default to AI if empty\r\n setDetectedIntent('ai');\r\n if (commandMode) onToggleCommandMode();\r\n return;\r\n }\r\n\r\n // Run local heuristic detection immediately\r\n const intent = detectIntent(trimmedValue);\r\n setDetectedIntent(intent);\r\n\r\n // Switch mode based on intent\r\n if (intent === 'command') {\r\n if (!commandMode) onToggleCommandMode();\r\n } else {\r\n // intent === 'ai'\r\n if (commandMode) onToggleCommandMode();\r\n }\r\n }, [value, commandMode, onToggleCommandMode, isAutoMode]);\r\n\r\n const showSlashAutocomplete = React.useCallback((commands: SlashCommand[]) => {\r\n if (commands.length > 0) {\r\n setSlashAutocompleteCommands(commands);\r\n setSlashAutocompleteVisible(true);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n }, []);\r\n\r\n const getRuleNameAutocompleteEntries = React.useCallback((partialName: string): SlashCommand[] => {\r\n const normalized = partialName.toLowerCase();\r\n const rules = rulesStorage.list();\r\n\r\n if (rules.length === 0) {\r\n return [{\r\n name: '(no rules)',\r\n description: 'Create one with /rules add'\r\n }];\r\n }\r\n\r\n const matches = rules\r\n .filter(rule => rule.name.toLowerCase().includes(normalized))\r\n .slice(0, 10)\r\n .map(rule => ({\r\n name: rule.name,\r\n description: rule.preview || 'Saved rule'\r\n }));\r\n\r\n if (matches.length === 0) {\r\n return [{\r\n name: '(no matches)',\r\n description: 'No saved rules match that name'\r\n }];\r\n }\r\n\r\n return matches;\r\n }, []);\r\n\r\n const updateSlashAutocomplete = React.useCallback((nextValue: string) => {\r\n if (!nextValue.startsWith('/')) {\r\n setSlashAutocompleteVisible(false);\r\n return;\r\n }\r\n\r\n if (!nextValue.includes(' ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/mcp ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/chat ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/add-command ') || nextValue.startsWith('/add-command-auto-detect ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/background-task ') || nextValue.startsWith('/bkg ') || nextValue.startsWith('/bg-task ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/sync ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/models ') || nextValue.startsWith('/model ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/settings auto-suggest ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/settings ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/revert ')) {\r\n const partialId = nextValue.slice(8).toLowerCase();\r\n const checkpoints = getCheckpoints ? getCheckpoints() : [];\r\n\r\n if (checkpoints.length === 0) {\r\n showSlashAutocomplete([{\r\n name: '(no checkpoints)',\r\n description: 'Ask AI a question first to create a checkpoint'\r\n }]);\r\n return;\r\n }\r\n\r\n const checkpointCommands: SlashCommand[] = checkpoints\r\n .filter(cp => cp.id.toLowerCase().includes(partialId) || cp.prompt.toLowerCase().includes(partialId))\r\n .slice(0, 10)\r\n .map(cp => ({\r\n name: cp.id,\r\n description: cp.prompt.length > 50 ? cp.prompt.slice(0, 50) + '...' : cp.prompt\r\n }));\r\n\r\n showSlashAutocomplete(checkpointCommands);\r\n return;\r\n }\r\n\r\n if (nextValue.match(/^\\/rules\\s+(edit|delete)\\s+/)) {\r\n const match = nextValue.match(/^\\/rules\\s+(?:edit|delete)\\s+(.*)$/);\r\n const partialName = match ? match[1] : '';\r\n showSlashAutocomplete(getRuleNameAutocompleteEntries(partialName));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/rules ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (\r\n nextValue.match(/^\\/workflow\\s+(run|view|delete)\\s+/) ||\r\n nextValue.match(/^\\/wf\\s+(run|view|delete)\\s+/)\r\n ) {\r\n const match = nextValue.match(/^\\/(?:workflow|wf)\\s+(?:run|view|delete)\\s+(.*)$/);\r\n const partialName = match ? match[1].toLowerCase() : '';\r\n const workflows = workflowStorage.list();\r\n const matchingWorkflows: SlashCommand[] = workflows\r\n .filter(wf => wf.name.toLowerCase().includes(partialName))\r\n .slice(0, 10)\r\n .map(wf => ({\r\n name: wf.name,\r\n description: wf.description || `${wf.stepCount} step${wf.stepCount !== 1 ? 's' : ''}`\r\n }));\r\n\r\n showSlashAutocomplete(matchingWorkflows);\r\n return;\r\n }\r\n\r\n if (\r\n nextValue.match(/^\\/workflow\\s+new\\s+/) ||\r\n nextValue.match(/^\\/wf\\s+new\\s+/)\r\n ) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/workflow ') || nextValue.startsWith('/wf ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n setSlashAutocompleteVisible(false);\r\n }, [getCheckpoints, getRuleNameAutocompleteEntries, showSlashAutocomplete]);\r\n\r\n const getMatchingFiles = React.useCallback((query: string): MentionSuggestion[] => {\r\n try {\r\n const cwd = currentWorkingDirectory || process.cwd();\r\n if (!fs.existsSync(cwd)) return [];\r\n\r\n const lowerQuery = query.toLowerCase();\r\n const results: MentionSuggestion[] = [];\r\n\r\n // Directories to skip when recursing\r\n const SKIP_DIRS = new Set([\r\n '.git', 'node_modules', 'dist', 'build', '.next', '__pycache__',\r\n '.cache', 'coverage', '.nyc_output', '.turbo', 'out', '.svelte-kit'\r\n ]);\r\n\r\n // When query is empty, show only top-level entries for a clean initial view\r\n if (lowerQuery === '') {\r\n let entries: fs.Dirent[];\r\n try { entries = fs.readdirSync(cwd, { withFileTypes: true }); } catch { return []; }\r\n for (const entry of entries) {\r\n if (entry.name.startsWith('.')) continue;\r\n results.push({\r\n name: entry.name,\r\n insertText: entry.isDirectory() ? `${entry.name}/` : entry.name,\r\n kind: entry.isDirectory() ? 'directory' as const : 'file' as const\r\n });\r\n }\r\n results.sort((a, b) => a.name.localeCompare(b.name));\r\n return results.slice(0, 15);\r\n }\r\n\r\n // For a non-empty query, recursively walk the entire CWD and return\r\n // all matching relative paths (e.g. \"src/components/App.tsx\")\r\n const walk = (dir: string, relativePath: string, depth: number) => {\r\n if (depth > 6 || results.length >= 60) return;\r\n let entries: fs.Dirent[];\r\n try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }\r\n\r\n for (const entry of entries) {\r\n if (entry.name.startsWith('.')) continue;\r\n const entryRelPath = relativePath ? `${relativePath}/${entry.name}` : entry.name;\r\n const lowerRelPath = entryRelPath.toLowerCase();\r\n const lowerBasename = entry.name.toLowerCase();\r\n\r\n if (entry.isDirectory()) {\r\n if (SKIP_DIRS.has(entry.name)) continue;\r\n // Include directory if any part of its relative path matches the query\r\n if (lowerRelPath.includes(lowerQuery) || lowerBasename.includes(lowerQuery)) {\r\n results.push({\r\n name: entryRelPath,\r\n insertText: `${entryRelPath}/`,\r\n kind: 'directory' as const\r\n });\r\n }\r\n walk(path.join(dir, entry.name), entryRelPath, depth + 1);\r\n } else {\r\n if (lowerRelPath.includes(lowerQuery) || lowerBasename.includes(lowerQuery)) {\r\n results.push({\r\n name: entryRelPath,\r\n insertText: entryRelPath,\r\n kind: 'file' as const\r\n });\r\n }\r\n }\r\n }\r\n };\r\n\r\n walk(cwd, '', 0);\r\n\r\n // Sort: exact basename prefix match first, then shallower paths, then alphabetical\r\n results.sort((a, b) => {\r\n const aBasename = a.name.split('/').pop()!.toLowerCase();\r\n const bBasename = b.name.split('/').pop()!.toLowerCase();\r\n const aStartsBasename = aBasename.startsWith(lowerQuery);\r\n const bStartsBasename = bBasename.startsWith(lowerQuery);\r\n const aStartsFull = a.name.toLowerCase().startsWith(lowerQuery);\r\n const bStartsFull = b.name.toLowerCase().startsWith(lowerQuery);\r\n\r\n if ((aStartsFull || aStartsBasename) && !(bStartsFull || bStartsBasename)) return -1;\r\n if (!(aStartsFull || aStartsBasename) && (bStartsFull || bStartsBasename)) return 1;\r\n\r\n // Shallower paths first\r\n const aDepth = a.name.split('/').length;\r\n const bDepth = b.name.split('/').length;\r\n if (aDepth !== bDepth) return aDepth - bDepth;\r\n\r\n return a.name.localeCompare(b.name);\r\n });\r\n\r\n return results.slice(0, 15);\r\n } catch (error) {\r\n return [];\r\n }\r\n }, [currentWorkingDirectory]);\r\n\r\n const getMatchingMentionSuggestions = React.useCallback((query: string): MentionSuggestion[] => {\r\n const normalized = query.toLowerCase();\r\n\r\n if (normalized.startsWith('rules:')) {\r\n const ruleQuery = query.slice('rules:'.length).toLowerCase();\r\n return rulesStorage.list()\r\n .filter(rule => rule.name.toLowerCase().includes(ruleQuery))\r\n .slice(0, 10)\r\n .map(rule => ({\r\n name: `rules:${rule.name}`,\r\n insertText: `rules:${rule.name}`,\r\n kind: 'rule' as const,\r\n description: rule.preview || 'Saved rule'\r\n }));\r\n }\r\n\r\n const suggestions: MentionSuggestion[] = [];\r\n if ('rules:'.startsWith(normalized) || normalized.startsWith('rules')) {\r\n suggestions.push({\r\n name: 'rules:',\r\n insertText: 'rules:',\r\n kind: 'rule-namespace',\r\n description: 'Insert a saved reusable rule'\r\n });\r\n }\r\n\r\n return [...suggestions, ...getMatchingFiles(query)].slice(0, 15);\r\n }, [getMatchingFiles]);\r\n\r\n // File tag (@) detection effect\r\n useEffect(() => {\r\n // Don't show file tag autocomplete in command mode\r\n if (commandMode) {\r\n setFileTagAutocompleteVisible(false);\r\n return;\r\n }\r\n\r\n // Find if cursor is within a potential file tag\r\n // Look backwards from cursor to find @\r\n let atPosition = -1;\r\n for (let i = cursorOffset - 1; i >= 0; i--) {\r\n const char = value[i];\r\n // Stop if we hit whitespace or another special char\r\n if (/[\\s\\n]/.test(char)) break;\r\n if (char === '@') {\r\n atPosition = i;\r\n break;\r\n }\r\n }\r\n\r\n // Only treat @ as file tag if it's at start of input OR preceded by whitespace\r\n // This prevents triggering on things like \"rohan@localhost\" or \"email@domain.com\"\r\n if (atPosition === -1 || (atPosition > 0 && !/[\\s\\n]/.test(value[atPosition - 1]))) {\r\n setFileTagAutocompleteVisible(false);\r\n setActiveFileTagStart(null);\r\n return;\r\n }\r\n\r\n // Extract the query after @\r\n const query = value.slice(atPosition + 1, cursorOffset);\r\n\r\n const matches = getMatchingMentionSuggestions(query);\r\n\r\n if (matches.length > 0) {\r\n setFileTagSuggestions(matches);\r\n setFileTagAutocompleteVisible(true);\r\n setActiveFileTagStart(atPosition);\r\n setFileTagSelectedIndex(0);\r\n } else {\r\n setFileTagAutocompleteVisible(false);\r\n setActiveFileTagStart(null);\r\n }\r\n }, [value, cursorOffset, commandMode, currentWorkingDirectory, getMatchingMentionSuggestions]);\r\n\r\n const pushToUndoStack = () => {\r\n setUndoStack(prev => [...prev, { value, cursorOffset }]);\r\n setRedoStack([]); // Clear redo stack on new action\r\n };\r\n\r\n const handleUndo = () => {\r\n if (undoStack.length === 0) return;\r\n const previousState = undoStack[undoStack.length - 1];\r\n setRedoStack(prev => [...prev, { value, cursorOffset }]);\r\n setUndoStack(prev => prev.slice(0, -1));\r\n setValue(previousState.value);\r\n setCursorOffset(previousState.cursorOffset);\r\n setSelection(null);\r\n };\r\n\r\n const applyMentionSuggestion = (selected: MentionSuggestion, viaTab: boolean) => {\r\n if (activeFileTagStart === null) {\r\n return;\r\n }\r\n\r\n pushToUndoStack();\r\n\r\n const beforeTag = value.slice(0, activeFileTagStart);\r\n const afterCursor = value.slice(cursorOffset);\r\n const baseValue = beforeTag + '@' + selected.insertText;\r\n\r\n if (selected.kind === 'rule-namespace') {\r\n const newValue = baseValue + afterCursor;\r\n const newCursorPos = activeFileTagStart + 1 + selected.insertText.length;\r\n setValue(newValue);\r\n setCursorOffset(newCursorPos);\r\n return;\r\n }\r\n\r\n if (viaTab && selected.kind === 'directory') {\r\n const newValue = baseValue + afterCursor;\r\n const newCursorPos = activeFileTagStart + 1 + selected.insertText.length;\r\n setValue(newValue);\r\n setCursorOffset(newCursorPos);\r\n return;\r\n }\r\n\r\n const trailingSuffix = viaTab ? '' : ' ';\r\n const newValue = baseValue + trailingSuffix + afterCursor;\r\n const newCursorPos = activeFileTagStart + 1 + selected.insertText.length + trailingSuffix.length;\r\n\r\n setValue(newValue);\r\n setCursorOffset(newCursorPos);\r\n\r\n setConfirmedFileTags(prev => [\r\n ...prev.filter(tag =>\r\n !(tag.start >= activeFileTagStart && tag.start <= cursorOffset)\r\n ),\r\n {\r\n start: activeFileTagStart,\r\n end: activeFileTagStart + 1 + selected.insertText.length,\r\n fileName: selected.name\r\n }\r\n ]);\r\n\r\n setFileTagAutocompleteVisible(false);\r\n setActiveFileTagStart(null);\r\n };\r\n\r\n useInput((input, key) => {\r\n if (!isActive) return;\r\n\r\n // Detect OS for platform-specific key handling\r\n const isWindows = process.platform === 'win32';\r\n const inputCharCode = input ? input.charCodeAt(0) : null;\r\n const normalizedInput = input ? input.toLowerCase() : '';\r\n\r\n // Shift+Enter may arrive as terminal remap sequences instead of key.shift.\r\n // Handle common variants used by iTerm/Kitty/VS Code keybinding remaps.\r\n const isTerminalShiftEnterSequence =\r\n input === '\\u001b\\r' ||\r\n input === '\\u001b\\n' ||\r\n normalizedInput === '\\u001b[13;2u' ||\r\n normalizedInput === '\\u001b[13;2~' ||\r\n normalizedInput === '\\u001b[27;2;13~';\r\n const isEnterEvent = key.return || isTerminalShiftEnterSequence;\r\n\r\n // macOS Option+Arrow often arrives as ESC-prefixed sequences.\r\n // Handle these explicitly without changing any existing backspace/delete behavior.\r\n const isMacOptionWordBackwardSequence = isMac && (\r\n normalizedInput === '\\u001bb' ||\r\n normalizedInput === '\\u001b[1;3d' ||\r\n normalizedInput === '\\u001b[1;9d' ||\r\n (key.meta && normalizedInput === 'b') ||\r\n (key.escape && key.leftArrow)\r\n );\r\n const isMacOptionWordForwardSequence = isMac && (\r\n normalizedInput === '\\u001bf' ||\r\n normalizedInput === '\\u001b[1;3c' ||\r\n normalizedInput === '\\u001b[1;9c' ||\r\n (key.meta && normalizedInput === 'f') ||\r\n (key.escape && key.rightArrow)\r\n );\r\n\r\n // Handle slash command autocomplete navigation\r\n if (slashAutocompleteVisible) {\r\n if (key.downArrow) {\r\n const newIndex = Math.min(slashAutocompleteSelectedIndex + 1, slashAutocompleteCommands.length - 1);\r\n setSlashAutocompleteSelectedIndex(newIndex);\r\n // Scroll down if selected is below visible window\r\n if (newIndex >= slashAutocompleteScrollOffset + slashMaxVisibleItems) {\r\n setSlashAutocompleteScrollOffset(newIndex - slashMaxVisibleItems + 1);\r\n }\r\n return;\r\n }\r\n\r\n if (key.upArrow) {\r\n const newIndex = Math.max(slashAutocompleteSelectedIndex - 1, 0);\r\n setSlashAutocompleteSelectedIndex(newIndex);\r\n // Scroll up if selected is above visible window\r\n if (newIndex < slashAutocompleteScrollOffset) {\r\n setSlashAutocompleteScrollOffset(newIndex);\r\n }\r\n return;\r\n }\r\n\r\n if (key.return && input.length <= 1 && !key.shift && !key.ctrl && !key.meta) {\r\n // Select the highlighted command\r\n const selected = slashAutocompleteCommands[slashAutocompleteSelectedIndex];\r\n if (!selected || selected.name.startsWith('(no ')) {\r\n setSlashAutocompleteVisible(false);\r\n return;\r\n }\r\n\r\n // Check if we're in MCP subcommand mode\r\n if (value.startsWith('/mcp ')) {\r\n // We're selecting an MCP subcommand, keep \"/mcp \" and append the subcommand\r\n const newValue = `/mcp ${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/chat ')) {\r\n // We're selecting a chat subcommand, keep \"/chat \" and append the subcommand\r\n const newValue = `/chat ${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/add-command ') || value.startsWith('/add-command-auto-detect ')) {\r\n // We're selecting an add-command subcommand\r\n const prefix = value.startsWith('/add-command-auto-detect ') ? '/add-command-auto-detect ' : '/add-command ';\r\n const newValue = `${prefix}${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/background-task ') || value.startsWith('/bkg ') || value.startsWith('/bg-task ')) {\r\n // We're selecting a background-task subcommand\r\n const prefix = value.startsWith('/bkg ') ? '/bkg ' : (value.startsWith('/bg-task ') ? '/bg-task ' : '/background-task ');\r\n const newValue = `${prefix}${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/sync ')) {\r\n // We're selecting a sync subcommand\r\n const newValue = `/sync ${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/revert ')) {\r\n // We're selecting a checkpoint from /revert dropdown\r\n const newValue = `/revert ${selected.name}`;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/models ') || value.startsWith('/model ')) {\r\n // We're selecting a models subcommand\r\n const prefix = value.startsWith('/models ') ? '/models ' : '/model ';\r\n const newValue = `${prefix}${selected.name}`;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/rules ')) {\r\n const ruleNameMatch = value.match(/^\\/rules\\s+(edit|delete)\\s+/);\r\n if (ruleNameMatch) {\r\n const prefix = value.match(/^\\/rules\\s+(?:edit|delete)\\s+/)?.[0] || '';\r\n const newValue = `${prefix}${selected.name}`;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else {\r\n const newValue = `/rules ${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n\r\n if (selected.name === 'edit' || selected.name === 'delete') {\r\n const ruleMatches = getRuleNameAutocompleteEntries('');\r\n if (ruleMatches.length > 0) {\r\n setSlashAutocompleteCommands(ruleMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n }\r\n } else if (value.startsWith('/workflow new ') || value.startsWith('/wf new ')) {\r\n // We're in workflow new subcommand mode (manual or learn-workflow)\r\n const prefix = value.startsWith('/workflow new ') ? '/workflow new ' : '/wf new ';\r\n const newValue = `${prefix}${selected.name}`;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/workflow ') || value.startsWith('/wf ')) {\r\n // Check if we're in workflow name selection mode (after run/view/delete)\r\n const workflowNameMatch = value.match(/^\\/(?:workflow|wf)\\s+(run|view|delete)\\s+/);\r\n if (workflowNameMatch) {\r\n // We're selecting a workflow name\r\n const prefix = value.match(/^\\/(?:workflow|wf)\\s+(?:run|view|delete)\\s+/)?.[0] || '';\r\n const newValue = `${prefix}${selected.name}`;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else {\r\n // We're selecting a workflow subcommand\r\n const prefix = value.startsWith('/workflow ') ? '/workflow ' : '/wf ';\r\n const newValue = `${prefix}${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n\r\n // For run/view/delete, show workflow names immediately\r\n if (selected.name === 'run' || selected.name === 'view' || selected.name === 'delete') {\r\n const workflows = workflowStorage.list();\r\n const matchingWorkflows: SlashCommand[] = workflows\r\n .slice(0, 10)\r\n .map(wf => ({\r\n name: wf.name,\r\n description: wf.description || `${wf.stepCount} step${wf.stepCount !== 1 ? 's' : ''}`\r\n }));\r\n\r\n if (matchingWorkflows.length > 0) {\r\n setSlashAutocompleteCommands(matchingWorkflows);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'new') {\r\n // For 'new' subcommand, show manual/learn-workflow options\r\n const subcommandMatches = filterCommands('workflow new ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible for next level\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n }\r\n } else if (value.startsWith('/settings auto-suggest ')) {\r\n // We're selecting an auto-suggest option (on/off)\r\n const newValue = `/settings auto-suggest ${selected.name}`;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/settings ')) {\r\n // We're selecting a settings subcommand (e.g., auto-suggest)\r\n const newValue = `/settings ${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n // Show the next level options (on/off for auto-suggest)\r\n if (selected.name === 'auto-suggest') {\r\n const optionMatches = filterCommands('settings auto-suggest ');\r\n if (optionMatches.length > 0) {\r\n setSlashAutocompleteCommands(optionMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else {\r\n // Regular slash command, replace everything\r\n const newValue = `/${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n\r\n // Check if this command has subcommands (e.g., /mcp, /chat, /add-command)\r\n // If so, immediately show the subcommand list\r\n if (selected.name === 'mcp') {\r\n const subcommandMatches = filterCommands('mcp ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible for subcommands\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'chat') {\r\n const subcommandMatches = filterCommands('chat ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible for subcommands\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'add-command' || selected.name === 'add-command-auto-detect') {\r\n const subcommandMatches = filterCommands('add-command ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible for subcommands\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'background-task' || selected.name === 'bkg' || selected.name === 'bg-task') {\r\n const subcommandMatches = filterCommands('background-task ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible for subcommands\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'sync') {\r\n const subcommandMatches = filterCommands('sync ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible for subcommands\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'models' || selected.name === 'model') {\r\n const subcommandMatches = filterCommands('models ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible for subcommands\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'settings') {\r\n const subcommandMatches = filterCommands('settings ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible for subcommands\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'workflow' || selected.name === 'wf') {\r\n const subcommandMatches = filterCommands('workflow ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible for subcommands\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'rules') {\r\n const subcommandMatches = filterCommands('rules ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'revert') {\r\n // For revert, show checkpoints immediately\r\n const checkpoints = getCheckpoints ? getCheckpoints() : [];\r\n if (checkpoints.length === 0) {\r\n setSlashAutocompleteCommands([{\r\n name: '(no checkpoints)',\r\n description: 'Ask AI a question first to create a checkpoint'\r\n }]);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible\r\n } else {\r\n const checkpointCommands: SlashCommand[] = checkpoints\r\n .slice(0, 10)\r\n .map(cp => {\r\n const truncatedPrompt = cp.prompt.length > 50 ? cp.prompt.slice(0, 50) + '...' : cp.prompt;\r\n return {\r\n name: cp.id,\r\n description: truncatedPrompt\r\n };\r\n });\r\n setSlashAutocompleteCommands(checkpointCommands);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible\r\n }\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n }\r\n return;\r\n }\r\n\r\n if (key.escape) {\r\n setSlashAutocompleteVisible(false);\r\n return;\r\n }\r\n }\r\n\r\n // Handle file tag (@) autocomplete navigation\r\n if (fileTagAutocompleteVisible) {\r\n if (key.downArrow) {\r\n setFileTagSelectedIndex(prev =>\r\n Math.min(prev + 1, fileTagSuggestions.length - 1)\r\n );\r\n return;\r\n }\r\n\r\n if (key.upArrow) {\r\n setFileTagSelectedIndex(prev => Math.max(prev - 1, 0));\r\n return;\r\n }\r\n\r\n if (key.return && input.length <= 1 && !key.shift && !key.ctrl && !key.meta) {\r\n // Select the highlighted file\r\n const selected = fileTagSuggestions[fileTagSelectedIndex];\r\n if (selected && activeFileTagStart !== null) {\r\n applyMentionSuggestion(selected, false);\r\n }\r\n return;\r\n }\r\n\r\n if (key.escape) {\r\n setFileTagAutocompleteVisible(false);\r\n setActiveFileTagStart(null);\r\n return;\r\n }\r\n\r\n // If Tab is pressed, also select the current file\r\n if (key.tab && !key.shift) {\r\n const selected = fileTagSuggestions[fileTagSelectedIndex];\r\n if (selected && activeFileTagStart !== null) {\r\n applyMentionSuggestion(selected, true);\r\n }\r\n return;\r\n }\r\n }\r\n\r\n // Alt+V: Paste image from clipboard\r\n // Detect Alt+V on Windows/Linux (key.meta is often Alt on Windows in Ink)\r\n // On Mac, we want to support Cmd+V explicitly as requested (\"make alt key combinations work with cmd key\")\r\n // Note: Cmd+V is often captured by the terminal for text paste, but if it gets through, we handle it.\r\n // Option+V on Mac often sends '√', which we also support.\r\n const isAltV = (key.meta && input === 'v') || (input === '√');\r\n\r\n if (isAltV && !commandMode) {\r\n // Check clipboard for files asynchronously\r\n (async () => {\r\n try {\r\n const files = await getClipboardFiles();\r\n if (files.length > 0) {\r\n // Check limits (max 5 files allowed)\r\n const currentCount = confirmedClipboardFiles.length;\r\n const newCount = files.length;\r\n\r\n if (currentCount + newCount > 5) {\r\n logDebug(`Alt+V: Rejected file paste, limit exceeded (${currentCount} + ${newCount} > 5)`);\r\n setRejectFlash(true);\r\n setTimeout(() => setRejectFlash(false), 1000);\r\n return;\r\n }\r\n\r\n logDebug(`Alt+V: Found ${files.length} file(s) in clipboard, adding to input`);\r\n\r\n // Add files to confirmed list with unique ID\r\n const newFilesWithIds = files.map(file => ({\r\n ...file,\r\n id: `${file.id}_${Date.now()}_${Math.random().toString(36).substring(7)}`\r\n }));\r\n\r\n setConfirmedClipboardFiles(prev => [...prev, ...newFilesWithIds]);\r\n } else {\r\n logDebug('Alt+V: No file in clipboard');\r\n }\r\n } catch (error) {\r\n logDebug(`Alt+V: Failed to check clipboard: ${error instanceof Error ? error.message : 'Unknown error'}`);\r\n }\r\n })();\r\n return;\r\n }\r\n\r\n // Alt+X / Cmd+X: Remove the last attached file/image\r\n // Detect Alt+X on Windows/Linux or Cmd+X on Mac.\r\n // Option+X on Mac often produces '≈'\r\n const isAltX = (key.meta && input === 'x') || (input === '≈');\r\n\r\n if (isAltX && !commandMode) {\r\n if (confirmedClipboardFiles.length > 0) {\r\n logDebug(`Alt+X: Removing last attached file`);\r\n setConfirmedClipboardFiles(prev => prev.slice(0, -1));\r\n } else {\r\n logDebug(`Alt+X: No files to remove`);\r\n }\r\n return;\r\n }\r\n\r\n // macOS Option+Left / Option+Right word navigation.\r\n if (isMacOptionWordBackwardSequence) {\r\n if (cursorOffset > 0) {\r\n let newOffset = cursorOffset;\r\n while (newOffset > 0 && /\\s/.test(value[newOffset - 1])) {\r\n newOffset--;\r\n }\r\n while (newOffset > 0 && !/\\s/.test(value[newOffset - 1])) {\r\n newOffset--;\r\n }\r\n setCursorOffset(newOffset);\r\n }\r\n return;\r\n }\r\n\r\n if (isMacOptionWordForwardSequence) {\r\n if (cursorOffset < value.length) {\r\n let newOffset = cursorOffset;\r\n while (newOffset < value.length && /\\s/.test(value[newOffset])) {\r\n newOffset++;\r\n }\r\n while (newOffset < value.length && !/\\s/.test(value[newOffset])) {\r\n newOffset++;\r\n }\r\n setCursorOffset(newOffset);\r\n }\r\n return;\r\n }\r\n\r\n\r\n // DELETE WORD BACKWARDS\r\n // 1. Ctrl+W\r\n // 2. Cmd+Backspace (Mac) - often mapped to delete line, but here we treat key.meta as modifier\r\n // 3. Alt+Backspace (Windows/Linux)\r\n const isDeleteWord =\r\n inputCharCode === 23 || // Ctrl+W\r\n (key.meta && (key.backspace || key.delete)) || // Cmd+Backspace (Mac) or Alt+Backspace (Win)\r\n (key.ctrl && key.delete) || // Ctrl+Delete\r\n (isWindows && inputCharCode === 127); // Windows: Ctrl+Del sends char 127\r\n\r\n if (isDeleteWord) {\r\n pushToUndoStack();\r\n if (cursorOffset > 0) {\r\n let newOffset = cursorOffset;\r\n // Skip whitespace backwards\r\n while (newOffset > 0 && /\\s/.test(value[newOffset - 1])) {\r\n newOffset--;\r\n }\r\n // Skip non-whitespace backwards\r\n while (newOffset > 0 && !/\\s/.test(value[newOffset - 1])) {\r\n newOffset--;\r\n }\r\n const newValue = value.slice(0, newOffset) + value.slice(cursorOffset);\r\n setValue(newValue);\r\n setCursorOffset(newOffset);\r\n updateSlashAutocomplete(newValue);\r\n }\r\n setHistoryIndex(-1);\r\n setCompletions([]);\r\n return;\r\n }\r\n\r\n // Ctrl+T: Toggle auto-accept\r\n if (key.ctrl && input.toLowerCase() === 't') {\r\n ignoreNextChangeRef.current = true;\r\n onToggleAutoAccept();\r\n setTimeout(() => { ignoreNextChangeRef.current = false; }, 100);\r\n return;\r\n }\r\n\r\n // Ctrl+D: Cycle modes (Agent -> Terminal -> Background -> Auto -> Agent)\r\n if (key.ctrl && input.toLowerCase() === 'd') {\r\n if (onToggleCommandMode) {\r\n ignoreNextChangeRef.current = true;\r\n\r\n // Cycle Logic: Agent -> Terminal -> Background -> Auto -> Agent\r\n if (!isAutoMode && !commandMode && !backgroundMode) {\r\n // Agent -> Terminal\r\n onToggleCommandMode();\r\n } else if (!isAutoMode && commandMode && !backgroundMode) {\r\n // Terminal -> Background\r\n onToggleCommandMode(); // Exit terminal mode\r\n if (onToggleBackgroundMode) onToggleBackgroundMode(); // Enter background mode\r\n } else if (!isAutoMode && !commandMode && backgroundMode) {\r\n // Background -> Auto\r\n if (onToggleBackgroundMode) onToggleBackgroundMode(); // Exit background mode\r\n setIsAutoMode(true);\r\n // Trigger initial detection for Auto mode\r\n const intent = detectIntent(value);\r\n setDetectedIntent(intent);\r\n // Set command mode based on intent\r\n if (intent === 'command') onToggleCommandMode();\r\n } else if (isAutoMode) {\r\n // Auto -> Agent\r\n setIsAutoMode(false);\r\n // Ensure we go back to Agent mode (commandMode = false, backgroundMode = false)\r\n if (commandMode) onToggleCommandMode();\r\n if (backgroundMode && onToggleBackgroundMode) onToggleBackgroundMode();\r\n }\r\n\r\n setTimeout(() => { ignoreNextChangeRef.current = false; }, 100);\r\n }\r\n return;\r\n }\r\n\r\n // Ctrl+Z / Cmd+Z: Undo\r\n if ((key.ctrl && input.toLowerCase() === 'z') || (key.meta && input.toLowerCase() === 'z')) {\r\n handleUndo();\r\n return;\r\n }\r\n\r\n // Ctrl+A / Cmd+A: Select All\r\n if ((key.ctrl && input.toLowerCase() === 'a') || (key.meta && input.toLowerCase() === 'a')) {\r\n setSelection({ start: 0, end: value.length });\r\n setCursorOffset(value.length);\r\n return;\r\n }\r\n\r\n // Home: Start of Line\r\n // Note: In single-line inputs, this goes to start of text. \r\n // In multi-line wrapped view, we ideally want start of logical line or start of text? \r\n // Standard terminal Home = Start of command. Editor Home = Start of line.\r\n // Let's stick to Start of Text for now as it's a single \"input box\".\r\n // Home: Start of Line\r\n // @ts-ignore\r\n if (key.home) {\r\n const width = (process.stdout.columns || 80) - 6;\r\n const visualLines = getVisualLines(value, width);\r\n\r\n const currentLine = visualLines.find(line =>\r\n (cursorOffset >= line.start && cursorOffset < line.end) ||\r\n (cursorOffset === line.end && line.isHardEnd)\r\n );\r\n\r\n if (currentLine) {\r\n setCursorOffset(currentLine.start);\r\n } else {\r\n setCursorOffset(0);\r\n }\r\n return;\r\n }\r\n\r\n // End: End of Line\r\n // @ts-ignore\r\n if (key.end) {\r\n const width = (process.stdout.columns || 80) - 6;\r\n const visualLines = getVisualLines(value, width);\r\n\r\n const currentLine = visualLines.find(line =>\r\n (cursorOffset >= line.start && cursorOffset < line.end) ||\r\n (cursorOffset === line.end && line.isHardEnd)\r\n );\r\n\r\n if (currentLine) {\r\n setCursorOffset(currentLine.end);\r\n } else {\r\n setCursorOffset(value.length);\r\n }\r\n return;\r\n }\r\n\r\n\r\n // Note: Clipboard images are handled via Alt+V keyboard shortcut\r\n\r\n // DELETE CHAR - Only runs if Delete Word did NOT trigger\r\n // Triggers on:\r\n // 1. Backspace or Delete key flag is present\r\n // 2. OR char code 8 (standard backspace)\r\n // 3. OR char code 127 (DEL) on non-Windows (Mac/Linux treat 127 as normal backspace)\r\n // NOTE: On Windows/Ink, Backspace often reports as 'delete: true', so we treat key.delete as Backspace to ensure the Backspace key works correctly.\r\n const isDeleteChar =\r\n key.backspace ||\r\n key.delete ||\r\n inputCharCode === 8 ||\r\n (!isWindows && inputCharCode === 127);\r\n\r\n if (isDeleteChar) {\r\n pushToUndoStack();\r\n\r\n let newValue = value;\r\n\r\n if (selection) {\r\n // Delete selection\r\n const start = Math.min(selection.start, selection.end);\r\n const end = Math.max(selection.start, selection.end);\r\n newValue = value.slice(0, start) + value.slice(end);\r\n setValue(newValue);\r\n setCursorOffset(start);\r\n setSelection(null);\r\n } else if (cursorOffset > 0) {\r\n // Backspace (or Delete acting as Backspace): Delete character before cursor\r\n newValue = value.slice(0, cursorOffset - 1) + value.slice(cursorOffset);\r\n setValue(newValue);\r\n setCursorOffset(cursorOffset - 1);\r\n }\r\n\r\n // Reset history/completions on edit\r\n setHistoryIndex(-1);\r\n setCompletions([]);\r\n updateSlashAutocomplete(newValue);\r\n\r\n return;\r\n }\r\n\r\n // Handle Enter\r\n // Check input length to distinguish single key press from paste\r\n if (isEnterEvent && (input.length <= 1 || isTerminalShiftEnterSequence)) {\r\n // Newline insertion triggers:\r\n // 1) Shift/Ctrl/Meta + Enter\r\n // 2) Remapped Shift+Enter terminal sequences (ESC+CR / CSI variants)\r\n // 3) Universal fallback: \"\\\" immediately before Enter\r\n const isBackslashEnterFallback =\r\n !key.shift &&\r\n !key.ctrl &&\r\n !key.meta &&\r\n !isTerminalShiftEnterSequence &&\r\n !selection &&\r\n cursorOffset > 0 &&\r\n value[cursorOffset - 1] === '\\\\';\r\n\r\n if (key.shift || key.ctrl || key.meta || input === '\\n' || isTerminalShiftEnterSequence || isBackslashEnterFallback) {\r\n pushToUndoStack();\r\n // Insert newline, optionally replacing trailing backslash fallback marker.\r\n // If selection exists, replace it\r\n let newValue = value;\r\n let newOffset = cursorOffset;\r\n\r\n if (selection) {\r\n const start = Math.min(selection.start, selection.end);\r\n const end = Math.max(selection.start, selection.end);\r\n newValue = value.slice(0, start) + '\\n' + value.slice(end);\r\n newOffset = start + 1;\r\n setSelection(null);\r\n } else if (isBackslashEnterFallback) {\r\n newValue = value.slice(0, cursorOffset - 1) + '\\n' + value.slice(cursorOffset);\r\n newOffset = cursorOffset;\r\n } else {\r\n newValue = value.slice(0, cursorOffset) + '\\n' + value.slice(cursorOffset);\r\n newOffset = cursorOffset + 1;\r\n }\r\n\r\n setValue(newValue);\r\n setCursorOffset(newOffset);\r\n } else {\r\n // Enter: Submit\r\n // Check if submission is allowed when disconnected\r\n // Allowed: /exit command, OR Command Mode is active, OR detected intent is 'command'\r\n const isExitCommand = value.trim() === '/exit';\r\n const isCommandIntent = detectedIntent === 'command';\r\n const isAllowedOffline = isConnected || isExitCommand || commandMode || isCommandIntent;\r\n\r\n if (!isAllowedOffline) {\r\n setRejectFlash(true);\r\n setTimeout(() => setRejectFlash(false), 1000);\r\n return;\r\n }\r\n\r\n const isSlashCommand = value.trim().startsWith('/');\r\n\r\n // Check session quota (only for AI mode, not command mode or slash commands)\r\n // Slash commands and terminal commands should always be allowed\r\n if (!commandMode && !isCommandIntent && !isSlashCommand && sessionQuotaExhausted) {\r\n setRejectFlash(true);\r\n setShowQuotaMessage(true);\r\n setTimeout(() => {\r\n setRejectFlash(false);\r\n setShowQuotaMessage(false);\r\n }, 3000); // Show quota message for 3 seconds\r\n return;\r\n }\r\n\r\n handleSubmit();\r\n }\r\n return;\r\n }\r\n\r\n // Handle Arrows\r\n if (key.upArrow || key.downArrow || key.leftArrow || key.rightArrow) {\r\n // Clear selection on arrow keys\r\n if (selection) {\r\n setSelection(null);\r\n // If left/right, maybe move cursor to start/end of selection?\r\n // For now, just clear selection and let default logic run (or reset cursor to one end)\r\n if (key.leftArrow) setCursorOffset(Math.min(selection.start, selection.end));\r\n if (key.rightArrow) setCursorOffset(Math.max(selection.start, selection.end));\r\n if (key.upArrow || key.downArrow) {\r\n // Keep cursor where it is (at the end usually) or move it?\r\n // Let's just fall through to normal arrow logic from current cursorOffset\r\n }\r\n if (key.leftArrow || key.rightArrow) return; // We handled the move\r\n }\r\n }\r\n\r\n if (key.upArrow) {\r\n const width = (process.stdout.columns || 80) - 6;\r\n const visualLines = getVisualLines(value, width);\r\n\r\n let currentVisualLineIndex = visualLines.findIndex(line => {\r\n if (cursorOffset >= line.start && cursorOffset < line.end) return true;\r\n if (cursorOffset === line.end && line.isHardEnd) return true;\r\n return false;\r\n });\r\n\r\n // If cursor is at the very end of the last line\r\n if (currentVisualLineIndex === -1 && cursorOffset === value.length) {\r\n currentVisualLineIndex = visualLines.length - 1;\r\n }\r\n\r\n if (currentVisualLineIndex <= 0) {\r\n // Top line: History navigation\r\n if (commandHistory.length > 0) {\r\n if (historyIndex === -1) {\r\n setTempValue(value);\r\n const newIndex = commandHistory.length - 1;\r\n setHistoryIndex(newIndex);\r\n const newValue = commandHistory[newIndex];\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n } else if (historyIndex > 0) {\r\n const newIndex = historyIndex - 1;\r\n setHistoryIndex(newIndex);\r\n const newValue = commandHistory[newIndex];\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n }\r\n }\r\n } else {\r\n // Move cursor up one visual line\r\n const currentLine = visualLines[currentVisualLineIndex];\r\n const targetLine = visualLines[currentVisualLineIndex - 1];\r\n const offsetInLine = cursorOffset - currentLine.start;\r\n\r\n const newOffset = targetLine.start + Math.min(offsetInLine, targetLine.end - targetLine.start);\r\n setCursorOffset(newOffset);\r\n }\r\n return;\r\n }\r\n\r\n if (key.downArrow) {\r\n const width = (process.stdout.columns || 80) - 6;\r\n const visualLines = getVisualLines(value, width);\r\n\r\n let currentVisualLineIndex = visualLines.findIndex(line => {\r\n if (cursorOffset >= line.start && cursorOffset < line.end) return true;\r\n if (cursorOffset === line.end && line.isHardEnd) return true;\r\n return false;\r\n });\r\n\r\n // If cursor is at the very end of the last line\r\n if (currentVisualLineIndex === -1 && cursorOffset === value.length) {\r\n currentVisualLineIndex = visualLines.length - 1;\r\n }\r\n\r\n if (currentVisualLineIndex === visualLines.length - 1) {\r\n // Bottom line: History navigation\r\n if (historyIndex !== -1) {\r\n if (historyIndex < commandHistory.length - 1) {\r\n const newIndex = historyIndex + 1;\r\n setHistoryIndex(newIndex);\r\n const newValue = commandHistory[newIndex];\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n } else {\r\n setHistoryIndex(-1);\r\n setValue(tempValue);\r\n setCursorOffset(tempValue.length);\r\n }\r\n }\r\n } else {\r\n // Move cursor down one visual line\r\n const currentLine = visualLines[currentVisualLineIndex];\r\n const targetLine = visualLines[currentVisualLineIndex + 1];\r\n const offsetInLine = cursorOffset - currentLine.start;\r\n\r\n const newOffset = targetLine.start + Math.min(offsetInLine, targetLine.end - targetLine.start);\r\n setCursorOffset(newOffset);\r\n }\r\n return;\r\n }\r\n\r\n if (key.leftArrow) {\r\n if (isMac && key.meta) {\r\n // macOS fallback: many terminals map Option+Left to meta+left.\r\n // Treat as word-backward navigation.\r\n let newOffset = cursorOffset;\r\n if (newOffset > 0) {\r\n while (newOffset > 0 && /\\s/.test(value[newOffset - 1])) {\r\n newOffset--;\r\n }\r\n while (newOffset > 0 && !/\\s/.test(value[newOffset - 1])) {\r\n newOffset--;\r\n }\r\n setCursorOffset(newOffset);\r\n }\r\n return;\r\n }\r\n\r\n if (key.ctrl || (!isMac && key.meta)) {\r\n // Ctrl+Left (All) or Alt+Left (Win/Linux): Move word backwards\r\n // Note: On Mac, Option+Left is the standard for word back, but Ink doesn't expose 'alt'.\r\n // Users can use Ctrl+Left or rely on terminal mapping Option to Meta which effectively makes it key.meta\r\n // BUT if key.meta is Cmd on Mac, we map that to Home.\r\n // So standard Mac \"Option+Left\" might not work unless it sends Esc sequence or mapped to Ctrl.\r\n // We allow Ctrl+Left for Mac users.\r\n let newOffset = cursorOffset;\r\n if (newOffset > 0) {\r\n // Skip whitespace backwards\r\n while (newOffset > 0 && /\\s/.test(value[newOffset - 1])) {\r\n newOffset--;\r\n }\r\n // Skip non-whitespace backwards\r\n while (newOffset > 0 && !/\\s/.test(value[newOffset - 1])) {\r\n newOffset--;\r\n }\r\n setCursorOffset(newOffset);\r\n }\r\n return;\r\n }\r\n\r\n // Standard Left Arrow\r\n if (cursorOffset > 0) {\r\n setCursorOffset(cursorOffset - 1);\r\n }\r\n return;\r\n }\r\n\r\n if (key.rightArrow) {\r\n // Autocomplete Logic (Only at end of line)\r\n // AI suggestion takes priority over passive suggestion\r\n // Autocomplete Logic\r\n const effectiveSuggestion = aiAutocompleteSuggestion || autocompleteSuggestion;\r\n if (effectiveSuggestion && cursorOffset === value.length) {\r\n if (key.ctrl || (!isMac && key.meta)) {\r\n // Ctrl+Right (or Alt+Right on non-macOS): Accept FULL suggestion\r\n // (Wait, Cmd+Right is usually End of Line on Mac. We should prioritize Navigation over Autocomplete?\r\n // Actually, if we are at end of line, End of Line does nothing. So we can use it for accept full?)\r\n // Convention: Right Arrow accepts word. Ctrl+Right accepts full?\r\n // On Mac, Cmd+Right is End. If at End, it's a no-op for nav.\r\n // Let's allow Cmd+Right to accept full IF at end.\r\n setValue(effectiveSuggestion);\r\n setCursorOffset(effectiveSuggestion.length);\r\n setAutocompleteSuggestion(null);\r\n setAiAutocompleteSuggestion(null);\r\n return;\r\n } else {\r\n // Right: Accept NEXT WORD\r\n const remaining = effectiveSuggestion.slice(value.length);\r\n // Match next chunk of non-whitespace\r\n const match = remaining.match(/^(\\s*\\S+)/);\r\n\r\n if (match) {\r\n const toAdd = match[0];\r\n const newValue = value + toAdd;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n return; // Done\r\n } else if (remaining.length > 0) {\r\n const newValue = value + remaining;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // Navigation Logic\r\n if (isMac && key.meta) {\r\n // macOS fallback: many terminals map Option+Right to meta+right.\r\n // Treat as word-forward navigation.\r\n let newOffset = cursorOffset;\r\n if (newOffset < value.length) {\r\n while (newOffset < value.length && /\\s/.test(value[newOffset])) {\r\n newOffset++;\r\n }\r\n while (newOffset < value.length && !/\\s/.test(value[newOffset])) {\r\n newOffset++;\r\n }\r\n setCursorOffset(newOffset);\r\n }\r\n return;\r\n }\r\n\r\n if ((!isMac && key.meta) || key.ctrl) {\r\n // Alt+Right (Win) or Ctrl+Right: Word Forward\r\n // (Note: Ink uses key.meta for Alt on Windows)\r\n let newOffset = cursorOffset;\r\n if (newOffset < value.length) {\r\n // Skip whitespace forwards\r\n while (newOffset < value.length && /\\s/.test(value[newOffset])) {\r\n newOffset++;\r\n }\r\n // Skip non-whitespace forwards\r\n while (newOffset < value.length && !/\\s/.test(value[newOffset])) {\r\n newOffset++;\r\n }\r\n setCursorOffset(newOffset);\r\n }\r\n return;\r\n }\r\n\r\n // Navigation Logic (if not completing)\r\n if (key.ctrl || key.meta) {\r\n // Ctrl+Right / Meta+Right (Option+Right): Move word forwards\r\n let newOffset = cursorOffset;\r\n if (newOffset < value.length) {\r\n // Skip non-whitespace forwards\r\n while (newOffset < value.length && !/\\s/.test(value[newOffset])) {\r\n newOffset++;\r\n }\r\n // Skip whitespace forwards\r\n while (newOffset < value.length && /\\s/.test(value[newOffset])) {\r\n newOffset++;\r\n }\r\n setCursorOffset(newOffset);\r\n }\r\n } else if (cursorOffset < value.length) {\r\n setCursorOffset(cursorOffset + 1);\r\n }\r\n return;\r\n }\r\n\r\n // Tab Completion\r\n if (key.tab && !key.shift) {\r\n // Only file completion (only in command mode)\r\n if (commandMode) {\r\n handleTabCompletion();\r\n return;\r\n }\r\n }\r\n\r\n // Regular Input\r\n // Ignore control keys to prevent printing garbage (like 'v' for Ctrl+V)\r\n if (input && !key.ctrl && !key.meta) {\r\n pushToUndoStack();\r\n // Handle paste with newlines\r\n const cleanedInput = input.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\r\n\r\n // Use refs to get the latest value and cursor position\r\n // This prevents stale closure issues when Ink calls useInput multiple times during paste\r\n const currentValue = valueRef.current;\r\n const currentCursorOffset = cursorOffsetRef.current;\r\n\r\n let newValue = currentValue;\r\n let newOffset = currentCursorOffset;\r\n\r\n if (selection) {\r\n const start = Math.min(selection.start, selection.end);\r\n const end = Math.max(selection.start, selection.end);\r\n newValue = currentValue.slice(0, start) + cleanedInput + currentValue.slice(end);\r\n newOffset = start + cleanedInput.length;\r\n setSelection(null);\r\n } else {\r\n newValue = currentValue.slice(0, currentCursorOffset) + cleanedInput + currentValue.slice(currentCursorOffset);\r\n newOffset = currentCursorOffset + cleanedInput.length;\r\n }\r\n\r\n // Update refs immediately for subsequent paste chunks\r\n valueRef.current = newValue;\r\n cursorOffsetRef.current = newOffset;\r\n\r\n setValue(newValue);\r\n setCursorOffsetWithRef(newOffset);\r\n\r\n // Reset history/completions\r\n setHistoryIndex(-1);\r\n setCompletions([]);\r\n updateSlashAutocomplete(newValue);\r\n }\r\n }, { isActive });\r\n\r\n const handleTabCompletion = async () => {\r\n if (!value) return;\r\n\r\n const words = value.split(' ');\r\n const lastWord = words[words.length - 1];\r\n\r\n if (completions.length > 0) {\r\n const nextIndex = (completionIndex + 1) % completions.length;\r\n setCompletionIndex(nextIndex);\r\n words[words.length - 1] = completions[nextIndex];\r\n const newValue = words.join(' ');\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n return;\r\n }\r\n\r\n try {\r\n const cwd = currentWorkingDirectory || process.cwd();\r\n let searchDir = cwd;\r\n let searchPattern = lastWord;\r\n let dirPart = '';\r\n\r\n if (lastWord.includes('/') || lastWord.includes('\\\\')) {\r\n const lastSep = Math.max(lastWord.lastIndexOf('/'), lastWord.lastIndexOf('\\\\'));\r\n dirPart = lastWord.substring(0, lastSep + 1);\r\n searchPattern = lastWord.substring(lastSep + 1);\r\n\r\n if (subshellContext && subshellContext.type !== 'local') {\r\n searchDir = dirPart.startsWith('/') ? dirPart.slice(0, -1) : cwd + '/' + dirPart.slice(0, -1);\r\n } else {\r\n searchDir = path.resolve(cwd, dirPart);\r\n }\r\n }\r\n\r\n let entries: Array<{ name: string; type: 'file' | 'directory' }>;\r\n\r\n if (subshellContext && subshellContext.type !== 'local' && subshellContext.handler) {\r\n const dirEntries = await subshellContext.handler.listDirectory(searchDir);\r\n entries = dirEntries.map(entry => ({ name: entry.name, type: entry.type }));\r\n } else {\r\n if (!fs.existsSync(searchDir)) return;\r\n const fsEntries = fs.readdirSync(searchDir, { withFileTypes: true });\r\n entries = fsEntries.map(entry => ({\r\n name: entry.name,\r\n type: entry.isDirectory() ? 'directory' : 'file'\r\n }));\r\n }\r\n\r\n const matches = entries\r\n .filter(entry => entry.name.toLowerCase().startsWith(searchPattern.toLowerCase()))\r\n .map(entry => {\r\n const separator = (subshellContext && subshellContext.type !== 'local') ? '/' : path.sep;\r\n const fullPath = dirPart ? dirPart + entry.name : entry.name;\r\n return entry.type === 'directory' ? fullPath + separator : fullPath;\r\n })\r\n .sort();\r\n\r\n if (matches.length > 0) {\r\n if (matches.length > 1) {\r\n setCompletions(matches);\r\n setCompletionIndex(0);\r\n }\r\n words[words.length - 1] = matches[0];\r\n const newValue = words.join(' ');\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n }\r\n } catch (error) {\r\n // Ignore errors\r\n }\r\n };\r\n\r\n const handleSubmit = () => {\r\n if (!isActive) return;\r\n\r\n // Block submission while shell command is running - flash red\r\n if (isShellRunning) {\r\n setRejectFlash(true);\r\n setTimeout(() => setRejectFlash(false), 1000); // Flash for 1.0 seconds\r\n return;\r\n }\r\n\r\n const trimmedValue = value.trim();\r\n if (trimmedValue) {\r\n // Save to history if it was a command\r\n if (commandMode) {\r\n CommandHistoryManager.getInstance().addCommand(trimmedValue, currentDir, currentEnvironment);\r\n }\r\n\r\n // File tags (@relative/path) are kept as-is in the message content and\r\n // resolved to absolute paths in cli-adapter before being sent to the AI.\r\n // This preserves the short @tag display in the chat UI.\r\n onSubmit(trimmedValue, confirmedClipboardFiles.length > 0 ? confirmedClipboardFiles : undefined);\r\n setValue('');\r\n setCursorOffset(0);\r\n setCompletions([]);\r\n setCompletionIndex(0);\r\n setHistoryIndex(-1);\r\n setTempValue('');\r\n setUndoStack([]);\r\n setRedoStack([]);\r\n setSelection(null);\r\n setAutocompleteSuggestion(null);\r\n setConfirmedFileTags([]); // Clear confirmed tags on submit\r\n setConfirmedClipboardFiles([]); // Clear confirmed clipboard files on submit\r\n }\r\n };\r\n // Rendering Logic with Scrolling\r\n const renderInput = () => {\r\n const effectivePlaceholder = backgroundMode\r\n ? 'Run commands in the background'\r\n : commandMode\r\n ? 'Run a command'\r\n : placeholder;\r\n\r\n // Get terminal width for visual line calculation\r\n // Account for borders (2) + padding (2) + prompt \"> \" (2) = 6 chars\r\n const termWidth = (process.stdout.columns || 80) - 6;\r\n\r\n // Use getVisualLines to properly calculate wrapped lines\r\n const visualLines = getVisualLines(value, termWidth);\r\n const logicalLines = value.split('\\n');\r\n\r\n // If empty, show placeholder\r\n if (logicalLines.length === 1 && logicalLines[0] === '') {\r\n return <Text color=\"gray\">{effectivePlaceholder}</Text>;\r\n }\r\n\r\n // For rendering, we still use logical lines (split by \\n) since we render character-by-character\r\n // But for height calculation, we use visualLines.length\r\n const lines = logicalLines;\r\n\r\n // Calculate cursor line and column (based on logical lines)\r\n let currentPos = 0;\r\n let cursorLine = 0;\r\n let cursorCol = 0;\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n if (currentPos + lines[i].length >= cursorOffset) {\r\n cursorLine = i;\r\n cursorCol = cursorOffset - currentPos;\r\n break;\r\n }\r\n currentPos += lines[i].length + 1; // +1 for newline\r\n }\r\n // Edge case: cursor at very end of content\r\n if (cursorOffset === value.length && lines.length > 0) {\r\n cursorLine = lines.length - 1;\r\n cursorCol = lines[lines.length - 1].length;\r\n }\r\n\r\n // For scrolling, calculate which VISUAL line the cursor is on\r\n let cursorVisualLine = 0;\r\n for (let i = 0; i < visualLines.length; i++) {\r\n if (cursorOffset >= visualLines[i].start && cursorOffset <= visualLines[i].end) {\r\n cursorVisualLine = i;\r\n break;\r\n }\r\n }\r\n // Handle cursor at very end\r\n if (cursorOffset === value.length && visualLines.length > 0) {\r\n cursorVisualLine = visualLines.length - 1;\r\n }\r\n\r\n // Calculate visible range using VISUAL lines count for proper scrolling\r\n const totalVisualLines = visualLines.length;\r\n let startLine = 0;\r\n if (totalVisualLines > MAX_VISIBLE_LINES) {\r\n // Use visual line position for scrolling calculation\r\n if (cursorVisualLine < MAX_VISIBLE_LINES) {\r\n startLine = 0;\r\n } else {\r\n startLine = cursorVisualLine - MAX_VISIBLE_LINES + 1;\r\n }\r\n }\r\n const endLine = Math.min(startLine + MAX_VISIBLE_LINES, totalVisualLines);\r\n\r\n // Get the text content for each visual line\r\n const visibleVisualLines = visualLines.slice(startLine, endLine);\r\n\r\n return (\r\n <Box flexDirection=\"column\" flexGrow={1}>\r\n {startLine > 0 && <Text color=\"gray\">↑ ...</Text>}\r\n {visibleVisualLines.map((vLine, idx) => {\r\n const actualVisualLineIndex = startLine + idx;\r\n\r\n // Extract the text content for this visual line\r\n const lineText = value.slice(vLine.start, vLine.end);\r\n const lineStartPos = vLine.start;\r\n\r\n // Determine if cursor is on this visual line\r\n const isCursorLine = cursorOffset >= vLine.start && cursorOffset <= vLine.end;\r\n const cursorCol = isCursorLine ? cursorOffset - vLine.start : -1;\r\n\r\n // Is this the last visual line?\r\n const isLastLine = actualVisualLineIndex === totalVisualLines - 1;\r\n\r\n if (!isActive) {\r\n if (lineText.length === 0) {\r\n return <Text key={idx}> </Text>;\r\n }\r\n return <Text key={idx}>{lineText}</Text>;\r\n }\r\n\r\n // Render with selection and cursor\r\n const chars = lineText.split('');\r\n const renderedChars = chars.map((char, charIdx) => {\r\n const absPos = lineStartPos + charIdx;\r\n const isSelected = selection &&\r\n absPos >= Math.min(selection.start, selection.end) &&\r\n absPos < Math.max(selection.start, selection.end);\r\n\r\n // Check if this character is part of an active file tag (being typed after @)\r\n let activeFileTagEnd = activeFileTagStart !== null ? activeFileTagStart : 0;\r\n if (activeFileTagStart !== null) {\r\n for (let j = activeFileTagStart; j < value.length && j < cursorOffset; j++) {\r\n if (/[\\s\\n]/.test(value[j])) {\r\n break;\r\n }\r\n activeFileTagEnd = j + 1;\r\n }\r\n }\r\n const isInActiveFileTag = activeFileTagStart !== null &&\r\n absPos >= activeFileTagStart &&\r\n absPos < activeFileTagEnd;\r\n\r\n // Check if this character is part of a confirmed file tag\r\n let isInConfirmedFileTag = false;\r\n if (!commandMode) {\r\n const fileTagRegex = /(?:^|[\\s\\n])(@[^\\s@]+)/g;\r\n let match;\r\n while ((match = fileTagRegex.exec(value)) !== null) {\r\n const fullMatch = match[0];\r\n const tagContent = match[1];\r\n const tagStart = match.index + (fullMatch.length - tagContent.length);\r\n const tagEnd = tagStart + tagContent.length;\r\n if (activeFileTagStart !== null && tagStart === activeFileTagStart) {\r\n continue;\r\n }\r\n if (absPos >= tagStart && absPos < tagEnd) {\r\n isInConfirmedFileTag = true;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n const isCursor = isCursorLine && charIdx === cursorCol;\r\n\r\n if (isCursor) {\r\n return <Text key={charIdx} inverse color={isSelected ? \"yellow\" : undefined}>{char}</Text>;\r\n }\r\n if (isSelected) {\r\n return <Text key={charIdx} backgroundColor=\"white\" color=\"black\">{char}</Text>;\r\n }\r\n // Highlight file tags with cyan color\r\n if (isInConfirmedFileTag || isInActiveFileTag) {\r\n return <Text key={charIdx} color=\"#00ccff\" bold>{char}</Text>;\r\n }\r\n\r\n return <Text key={charIdx}>{char}</Text>;\r\n });\r\n\r\n // Handle cursor at end of line\r\n if (isCursorLine && cursorCol === lineText.length) {\r\n renderedChars.push(<Text key=\"cursor\" inverse> </Text>);\r\n }\r\n\r\n // Render Autocomplete Ghost Text\r\n // Only on the last line, if suggestion exists and matches start\r\n // AI suggestion takes priority over passive suggestion\r\n const effectiveSuggestion = aiAutocompleteSuggestion || autocompleteSuggestion;\r\n if (isLastLine && effectiveSuggestion && effectiveSuggestion.startsWith(value)) {\r\n const suffix = effectiveSuggestion.slice(value.length);\r\n if (suffix) {\r\n // Use slightly different color for AI suggestion to differentiate\r\n const ghostColor = aiAutocompleteSuggestion ? '#888888' : 'gray';\r\n renderedChars.push(<Text key=\"ghost\" color={ghostColor}>{suffix}</Text>);\r\n }\r\n }\r\n\r\n if (renderedChars.length === 0) {\r\n return <Text key={idx}> </Text>;\r\n }\r\n\r\n return <Text key={idx}>{renderedChars}</Text>;\r\n })}\r\n {endLine < totalVisualLines && <Text color=\"gray\">↓ ...</Text>}\r\n </Box>\r\n );\r\n };\r\n\r\n return (\r\n <Box\r\n flexDirection=\"column\"\r\n borderStyle=\"round\"\r\n borderColor={\r\n rejectFlash ? \"#ff3366\" :\r\n sessionQuotaExhausted ? \"#ff3366\" : // Red when quota exhausted\r\n backgroundMode ? \"#9966ff\" :\r\n commandMode ? \"#00cc66\" :\r\n \"#257aa5ff\"\r\n }\r\n paddingX={1}\r\n paddingY={0}\r\n width=\"100%\"\r\n >\r\n <Box marginY={1} justifyContent=\"space-between\" width=\"100%\">\r\n <Box flexShrink={1} minWidth={0} flexDirection=\"row\">\r\n {subshellContext && subshellContext.type !== 'local' && (\r\n <Breadcrumbs context={subshellContext} stack={subshellContextStack} />\r\n )}\r\n <Text color=\"#666666\">CWD: </Text>\r\n <Text color=\"#00ccff\" bold wrap=\"truncate-start\">{currentDir}</Text>\r\n {gitDiffStats && (gitDiffStats.additions > 0 || gitDiffStats.deletions > 0) && (\r\n <GitDiffBreadcrumb\r\n additions={gitDiffStats.additions}\r\n deletions={gitDiffStats.deletions}\r\n />\r\n )}\r\n </Box>\r\n <Box flexShrink={0}>\r\n\r\n {model && !commandMode && !backgroundMode && (\r\n <Box marginRight={1}>\r\n <Text color=\"#666666\">Model: </Text>\r\n <Text color=\"#00ccff\">{model}</Text>\r\n </Box>\r\n )}\r\n <Box>\r\n {showModeIndicator && (\r\n <>\r\n <Text color=\"#666666\">Mode: </Text>\r\n {isAutoMode ? (\r\n <Text>\r\n <Text color=\"#00ccff\" bold>Auto [</Text>\r\n {detectedIntent === 'command' ? (\r\n <Text color=\"#00cc66\" bold>Terminal</Text>\r\n ) : (\r\n <Text color=\"#00ccff\">Agent</Text>\r\n )}\r\n <Text color=\"#00ccff\" bold>]</Text>\r\n </Text>\r\n ) : backgroundMode ? (\r\n <Text color=\"#9966ff\" bold>Background</Text>\r\n ) : commandMode ? (\r\n <Text color=\"#00cc66\" bold>Terminal</Text>\r\n ) : planMode ? (\r\n <Text color=\"#ffaa00\" bold>Plan</Text>\r\n ) : (\r\n <Text color=\"#00ccff\">Agent</Text>\r\n )}\r\n </>\r\n )}\r\n </Box>\r\n </Box>\r\n </Box>\r\n\r\n {/* File Breadcrumbs - Show attached files from Alt+V */}\r\n {confirmedClipboardFiles.length > 0 && (\r\n <Box marginBottom={1} flexDirection=\"row\" flexWrap=\"wrap\" gap={1}>\r\n {confirmedClipboardFiles.map((file, index) => (\r\n <Box\r\n key={file.id}\r\n borderStyle=\"round\"\r\n borderColor=\"#ff69b4\"\r\n paddingX={1}\r\n >\r\n <Text color=\"#ff69b4\" bold>file_{index + 1}</Text>\r\n </Box>\r\n ))}\r\n </Box>\r\n )}\r\n\r\n\r\n {/* Session Quota Exhausted Message */}\r\n {showQuotaMessage && (\r\n <Box justifyContent=\"flex-end\" marginBottom={1}>\r\n <Text color=\"#ff3366\" bold>\r\n Session quota reached. Try again in {sessionQuotaTimeRemaining}\r\n </Text>\r\n </Box>\r\n )}\r\n\r\n\r\n <Box flexDirection=\"row\" width=\"100%\">\r\n <Text color=\"#666666\">> </Text>\r\n {renderInput()}\r\n </Box>\r\n\r\n <Box marginY={1} justifyContent=\"space-between\" width=\"100%\">\r\n <Text color=\"#666666\" dimColor>\r\n {isAutoMode ? (\r\n showBottomHints ? 'Ctrl+D to switch modes • Ctrl+T to auto-approve' : 'Ctrl+D to switch modes'\r\n ) : backgroundMode ? (\r\n 'Ctrl+D to switch modes • Commands run in background'\r\n ) : commandMode ? (\r\n 'Ctrl+D to switch modes • Tab for autocomplete'\r\n ) : (\r\n showBottomHints ? 'Ctrl+D to switch modes • Ctrl+T to auto-approve' : 'Ctrl+D to switch modes'\r\n )}\r\n </Text>\r\n <Box gap={1}>\r\n {subAgentCount > 0 && (\r\n <Text color=\"#00ccff\" bold>[sub-agent: {subAgentCount}]</Text>\r\n )}\r\n {backgroundTaskCount > 0 && (\r\n <Text color=\"#9966ff\" bold>[bkg tasks: {backgroundTaskCount}]</Text>\r\n )}\r\n {!commandMode && !backgroundMode && planMode && (\r\n <Text color=\"#ffaa00\" bold>[PLANNING]</Text>\r\n )}\r\n {!commandMode && !backgroundMode && autoAcceptMode ? (\r\n <Text color=\"#00cc66\" bold>[AUTO-ACCEPT: ON]</Text>\r\n ) : !commandMode && !backgroundMode ? (\r\n <Text color=\"#666666\" dimColor>[AUTO-ACCEPT: OFF]</Text>\r\n ) : null}\r\n {!commandMode && !backgroundMode && (\r\n <Box marginLeft={1}>\r\n <ContextWindowIndicator\r\n currentTokens={currentTokens}\r\n maxTokens={maxTokens}\r\n />\r\n </Box>\r\n )}\r\n </Box>\r\n </Box>\r\n\r\n {/* Slash Command Autocomplete Dropdown */}\r\n {\r\n slashAutocompleteVisible && slashMaxVisibleItems > 0 && (\r\n <SlashCommandAutocomplete\r\n commands={slashAutocompleteCommands}\r\n selectedIndex={slashAutocompleteSelectedIndex}\r\n maxVisibleItems={slashMaxVisibleItems}\r\n scrollOffset={slashAutocompleteScrollOffset}\r\n />\r\n )\r\n }\r\n\r\n {/* File Tag (@) Autocomplete Dropdown */}\r\n {\r\n fileTagAutocompleteVisible && (\r\n <FileTagAutocomplete\r\n files={fileTagSuggestions}\r\n selectedIndex={fileTagSelectedIndex}\r\n />\r\n )\r\n }\r\n\r\n\r\n </Box>\r\n );\r\n});\r\n"],"mappings":"AAAA,OAAO,SAAS,UAAU,WAAW,QAAQ,eAAe;AAC5D,SAAS,KAAK,MAAM,gBAAgB;AACpC,YAAY,QAAQ;AACpB,YAAY,UAAU;AAEtB,SAAS,uBAAuB;AAChC,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAClC,SAAS,8BAA8B;AACvC,SAAS,gBAAgB;AAEzB,SAAS,oBAAoB;AAC7B,SAAS,6BAA6B;AACtC,SAAS,gCAAgC;AACzC,SAAS,2BAA2B;AACpC,SAAS,sBAAoC;AAC7C,SAA2B,yBAAwC;AACnE,SAAS,uBAAuB,iCAAiC;AACjE,SAAS,qBAAqB,mCAAwD;AAEtF,SAAS,uBAAuB;AAChC,SAAS,oBAAoB;AA6C7B,MAAM,iBAAiB,CAAC,MAAc,UAAkB;AACtD,QAAM,eAAe,KAAK,MAAM,IAAI;AACpC,QAAM,cAAyE,CAAC;AAChF,MAAI,gBAAgB;AAEpB,eAAa,QAAQ,CAAC,MAAM,MAAM;AAChC,QAAI,KAAK,WAAW,GAAG;AACrB,kBAAY,KAAK,EAAE,OAAO,eAAe,KAAK,eAAe,WAAW,KAAK,CAAC;AAC9E,uBAAiB;AACjB;AAAA,IACF;AAEA,QAAI,YAAY;AAChB,QAAI,kBAAkB;AAEtB,WAAO,UAAU,SAAS,GAAG;AAC3B,UAAI,aAAa,UAAU;AAC3B,UAAI,YAAY;AAEhB,UAAI,UAAU,SAAS,OAAO;AAC5B,qBAAa;AACb,cAAM,YAAY,UAAU,YAAY,KAAK,KAAK;AAClD,YAAI,YAAY,GAAG;AACjB,uBAAa,YAAY;AAAA,QAC3B;AAAA,MACF,OAAO;AACL,oBAAY;AAAA,MACd;AAEA,kBAAY,KAAK;AAAA,QACf,OAAO;AAAA,QACP,KAAK,kBAAkB;AAAA,QACvB;AAAA,MACF,CAAC;AAED,yBAAmB;AACnB,kBAAY,UAAU,MAAM,UAAU;AAAA,IACxC;AAEA,qBAAiB,KAAK,UAAU,IAAI,aAAa,SAAS,IAAI,IAAI;AAAA,EACpE,CAAC;AAED,SAAO;AACT;AAEO,MAAM,WAAoC,MAAM,KAAK,CAAC;AAAA,EAC3D;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB;AAAA,EACA,iBAAiB,CAAC;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,sBAAsB;AAAA,EACtB,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA,wBAAwB;AAAA,EACxB,4BAA4B;AAAA,EAC5B,gBAAgB;AAAA,EAChB,uBAAuB;AAAA,EACvB,kBAAkB,CAAC;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AACF,MAAM;AAGJ,QAAM,CAAC,OAAO,gBAAgB,IAAI,SAAS,YAAY;AACvD,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,CAAC;AAClD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAmB,CAAC,CAAC;AAC3D,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAS,CAAC;AACxD,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,EAAE;AACnD,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,EAAE;AAC7C,QAAM,sBAAsB,OAAO,KAAK;AAIxC,QAAM,WAAW,OAAO,YAAY;AACpC,QAAM,kBAAkB,OAAO,CAAC;AAGhC,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,IAAI;AACjD,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAA2B,IAAI;AAG3E,QAAM,CAAC,wBAAwB,yBAAyB,IAAI,SAAwB,IAAI;AAGxF,QAAM,CAAC,0BAA0B,2BAA2B,IAAI,SAAwB,IAAI;AAC5F,QAAM,CAAC,yBAAyB,0BAA0B,IAAI,SAAS,KAAK;AAC5E,QAAM,4BAA4B,OAA8B,IAAI;AACpE,QAAM,yBAAyB,OAA+B,IAAI;AAGlE,QAAM,CAAC,WAAW,YAAY,IAAI,SAAyD,CAAC,CAAC;AAC7F,QAAM,CAAC,WAAW,YAAY,IAAI,SAAyD,CAAC,CAAC;AAG7F,QAAM,CAAC,WAAW,YAAY,IAAI,SAAgD,IAAI;AAGtF,QAAM,QAAQ,QAAQ,aAAa;AAGnC,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AAGpD,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,SAAS,KAAK;AAG9D,QAAM,CAAC,0BAA0B,2BAA2B,IAAI,SAAS,KAAK;AAC9E,QAAM,CAAC,2BAA2B,4BAA4B,IAAI,SAAyB,CAAC,CAAC;AAC7F,QAAM,CAAC,gCAAgC,iCAAiC,IAAI,SAAS,CAAC;AACtF,QAAM,CAAC,+BAA+B,gCAAgC,IAAI,SAAS,CAAC;AAGpF,QAAM,cAAc,gBAAgB;AAGpC,QAAM,aAAa,sBAAsB;AAEzC,QAAM,uBAAuB,WAAW,OAAO,0BAA0B,yBACrE,IACA,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,OAAO,WAAW,OAAO,MAAM,CAAC,CAAC,CAAC;AAGnE,QAAM,kBAAkB,WAAW,WAAW;AAC9C,QAAM,oBAAoB,WAAW,WAAW;AAGhD,QAAM,CAAC,4BAA4B,6BAA6B,IAAI,SAAS,KAAK;AAClF,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,SAA8B,CAAC,CAAC;AACpF,QAAM,CAAC,sBAAsB,uBAAuB,IAAI,SAAS,CAAC;AAClE,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,SAAwB,IAAI;AAChF,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,SAAkE,CAAC,CAAC;AAGtH,QAAM,CAAC,yBAAyB,0BAA0B,IAAI,SAA0B,CAAC,CAAC;AAI1F,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAS,CAAC;AAGxD,QAAM,oBAAoB;AAG1B,QAAM,WAAW,MAAM,YAAY,CAAC,aAAkD;AACpF,qBAAiB,UAAQ;AACvB,YAAM,gBAAgB,OAAO,aAAa,aAAa,SAAS,IAAI,IAAI;AAExE,eAAS,UAAU;AAEnB,UAAI,eAAe;AACjB,sBAAc,aAAa;AAAA,MAC7B;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,aAAa,CAAC;AAGlB,QAAM,yBAAyB,MAAM,YAAY,CAAC,cAAmD;AACnG,oBAAgB,UAAQ;AACtB,YAAM,iBAAiB,OAAO,cAAc,aAAa,UAAU,IAAI,IAAI;AAE3E,sBAAgB,UAAU;AAC1B,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAGL,YAAU,MAAM;AACd,QAAI,gBAAgB,aAAa,SAAS,GAAG;AAC3C,sBAAgB,aAAa,MAAM;AACnC,sBAAgB,UAAU,aAAa;AAAA,IACzC;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,YAAU,MAAM;AACd,aAAS,UAAU;AAAA,EACrB,GAAG,CAAC,KAAK,CAAC;AAEV,YAAU,MAAM;AACd,oBAAgB,UAAU;AAAA,EAC5B,GAAG,CAAC,YAAY,CAAC;AAGjB,YAAU,MAAM;AACd,0BAAsB,YAAY,EAAE,KAAK;AAAA,EAC3C,GAAG,CAAC,CAAC;AAGL,YAAU,MAAM;AACd,QAAI,iBAAiB;AACnB,sBAAgB,CAAC,aAAqB;AACpC,iBAAS,QAAQ;AACjB,wBAAgB,SAAS,MAAM;AAAA,MACjC,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,iBAAiB,UAAU,eAAe,CAAC;AAG/C,YAAU,MAAM;AACd,QAAI,iBAAiB;AACnB,sBAAgB,CAAC,aAAqB;AACpC,iBAAS,QAAQ;AACjB,wBAAgB,SAAS,MAAM;AAAA,MACjC,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,iBAAiB,UAAU,eAAe,CAAC;AAE/C,YAAU,MAAM;AACd,QAAI,oBAAoB;AACtB,yBAAmB,CAAC,YAAqB;AACvC,sBAAc,OAAO;AACrB,YAAI,SAAS;AAEX,gBAAM,SAAS,aAAa,KAAK;AACjC,4BAAkB,MAAM;AAExB,cAAI,WAAW,aAAa,CAAC,eAAe,qBAAqB;AAC/D,gCAAoB;AAAA,UACtB,WAAW,WAAW,QAAQ,eAAe,qBAAqB;AAChE,gCAAoB;AAAA,UACtB;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,oBAAoB,OAAO,aAAa,mBAAmB,CAAC;AAGhE,YAAU,MAAM;AACd,QAAI,SAAS,MAAM,KAAK,MAAM,MAAM,eAAe,GAAG;AACpD,eAAS,EAAE;AACX,sBAAgB,CAAC;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,OAAO,YAAY,CAAC;AAIxB,YAAU,MAAM;AACd,UAAM,aAAa,QAAQ,OAAO,WAAW,MAAM;AACnD,UAAM,cAAc,eAAe,OAAO,SAAS;AACnD,UAAM,eAAe,KAAK,IAAI,GAAG,YAAY,MAAM;AACnD,QAAI,iBAAiB,iBAAiB;AACpC,yBAAmB,YAAY;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,OAAO,eAAe,CAAC;AAM3B,QAAM,aAAa,QAAQ,MAAM;AAC/B,UAAM,MAAM,2BAA2B,QAAQ,IAAI;AACnD,UAAM,MAAM,IAAI,SAAS,GAAG,IAAI,MAAM;AACtC,UAAM,QAAQ,IAAI,MAAM,OAAO,EAAE,OAAO,OAAO;AAE/C,UAAM,cAAc,WAAW,WAAW,MAAM,IAAI,WAAW,WAAW,MAAM,IAAI;AAEpF,QAAI,MAAM,SAAS,aAAa;AAC9B,aAAO,QAAQ,MAAM,MAAM,MAAM,CAAC,WAAW,EAAE,KAAK,GAAG;AAAA,IACzD;AACA,WAAO;AAAA,EACT,GAAG,CAAC,yBAAyB,WAAW,OAAO,CAAC;AAIhD,QAAM,qBAAqB,QAAQ,MAAM;AACvC,QAAI,CAAC,gBAAiB,QAAO;AAC7B,QAAI,gBAAgB,SAAS,OAAO;AAClC,YAAM,OAAO,gBAAgB,UAAU,YAAY;AACnD,YAAM,OAAO,gBAAgB,UAAU,YAAY;AACnD,aAAO,OAAO,IAAI,IAAI,IAAI;AAAA,IAC5B;AACA,QAAI,gBAAgB,SAAS,OAAO;AAClC,YAAM,SAAS,gBAAgB,UAAU,cAAc;AACvD,aAAO,OAAO,MAAM;AAAA,IACtB;AACA,QAAI,gBAAgB,SAAS,UAAU;AACrC,YAAM,YAAY,gBAAgB,UAAU,eAAe;AAC3D,aAAO,UAAU,SAAS;AAAA,IAC5B;AACA,WAAO;AAAA,EACT,GAAG,CAAC,eAAe,CAAC;AAGpB,YAAU,MAAM;AACd,QAAI,CAAC,SAAS,MAAM,KAAK,MAAM,IAAI;AACjC,gCAA0B,IAAI;AAC9B;AAAA,IACF;AAIA,UAAM,gBAAgB,eAAgB,cAAc,mBAAmB;AAEvE,QAAI,eAAe;AACjB,YAAM,UAAU,sBAAsB,YAAY,EAAE,WAAW,OAAO,YAAY,kBAAkB;AACpG,UAAI,QAAQ,SAAS,GAAG;AACtB,kCAA0B,QAAQ,CAAC,CAAC;AAAA,MACtC,OAAO;AACL,kCAA0B,IAAI;AAAA,MAChC;AAAA,IACF,OAAO;AACL,gCAA0B,IAAI;AAAA,IAChC;AAAA,EACF,GAAG,CAAC,OAAO,aAAa,YAAY,gBAAgB,sBAAsB,YAAY,kBAAkB,CAAC;AAIzG,YAAU,MAAM;AAEd,gCAA4B,IAAI;AAGhC,QAAI,0BAA0B,SAAS;AACrC,mBAAa,0BAA0B,OAAO;AAC9C,gCAA0B,UAAU;AAAA,IACtC;AAGA,QAAI,uBAAuB,SAAS;AAClC,6BAAuB,QAAQ,MAAM;AACrC,6BAAuB,UAAU;AAAA,IACnC;AAYA,QAAI,CAAC,sBAAsB;AAEzB;AAAA,IACF;AAEA,UAAM,gBAAgB,eAAgB,cAAc,mBAAmB;AACvE,QAAI,CAAC,eAAe;AAElB;AAAA,IACF;AAGA,QAAI,CAAC,SAAS,MAAM,KAAK,EAAE,SAAS,KAAK,MAAM,WAAW,GAAG,GAAG;AAE9D;AAAA,IACF;AAKA,8BAA0B,UAAU,WAAW,YAAY;AACzD,iCAA2B,IAAI;AAG/B,YAAM,kBAAkB,IAAI,gBAAgB;AAC5C,6BAAuB,UAAU;AAEjC,UAAI;AACF,YAAI,CAAC,qBAAsB;AAG3B,cAAM,mBAAmB,sBAAsB,YAAY,EAAE,oBAAoB,YAAY,kBAAkB;AAG/G,YAAI,QAAkB,CAAC;AACvB,YAAI;AACF,cAAI,mBAAmB,gBAAgB,SAAS,WAAW,gBAAgB,SAAS;AAGlF,gBAAI;AACF,oBAAM,aAAa,MAAM,gBAAgB,QAAQ,cAAc,UAAU;AACzE,sBAAQ,WACL,MAAM,GAAG,EAAE,EACX,IAAI,CAAC,MAAW,EAAE,QAAQ,EAAE,SAAS,cAAc,MAAM,GAAG;AAAA,YACjE,SAAS,WAAW;AAAA,YAEpB;AAAA,UACF,OAAO;AAEL,kBAAM,MAAM,cAAc,QAAQ,IAAI;AACtC,gBAAI,GAAG,WAAW,GAAG,GAAG;AACtB,oBAAM,UAAU,GAAG,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAC3D,sBAAQ,QACL,MAAM,GAAG,EAAE,EACX,IAAI,OAAK,EAAE,QAAQ,EAAE,YAAY,IAAI,MAAM,GAAG;AAAA,YACnD;AAAA,UACF;AAAA,QACF,SAAS,GAAG;AAAA,QAEZ;AAGA,YAAI,YAAY,QAAQ;AACxB,YAAI,kBAAkB,QAAQ;AAE9B,YAAI,mBAAmB,gBAAgB,SAAS,WAAW,gBAAgB,UAAU;AACnF,gBAAM,SAAS,gBAAgB,SAAS;AACxC,cAAI,WAAW,WAAW;AACxB,wBAAY;AACZ,8BAAkB;AAAA,UACpB,WAAW,WAAW,SAAS;AAC7B,wBAAY;AACZ,8BAAkB;AAAA,UACpB,WAAW,WAAW,SAAS;AAC7B,wBAAY;AACZ,8BAAkB;AAAA,UACpB;AAAA,QACF;AAEA,cAAM,UAA+B;AAAA,UACnC,IAAI;AAAA,UACJ,UAAU;AAAA,UACV,KAAK,cAAc,QAAQ,IAAI;AAAA,UAC/B,kBAAkB,iBAAiB,MAAM,GAAG,EAAE;AAAA,UAC9C,iBAAiB,gBAAgB,MAAM,GAAG;AAAA,UAC1C;AAAA,UACA,cAAc;AAAA,QAChB;AAEA,cAAM,aAAa,MAAM,oBAAoB,eAAe,SAAS,gBAAgB,MAAM;AAE3F,YAAI,cAAc,CAAC,gBAAgB,OAAO,SAAS;AACjD,sCAA4B,UAAU;AAAA,QACxC;AAAA,MACF,SAAS,OAAO;AAAA,MAEhB,UAAE;AACA,mCAA2B,KAAK;AAChC,YAAI,uBAAuB,YAAY,iBAAiB;AACtD,iCAAuB,UAAU;AAAA,QACnC;AAAA,MACF;AAAA,IACF,GAAG,2BAA2B;AAE9B,WAAO,MAAM;AACX,UAAI,0BAA0B,SAAS;AACrC,qBAAa,0BAA0B,OAAO;AAAA,MAChD;AACA,UAAI,uBAAuB,SAAS;AAClC,+BAAuB,QAAQ,MAAM;AAAA,MACvC;AAAA,IACF;AAAA,EACF,GAAG,CAAC,OAAO,aAAa,YAAY,gBAAgB,sBAAsB,YAAY,oBAAoB,eAAe,CAAC;AAG1H,YAAU,MAAM;AAEd,QAAI,CAAC,YAAY;AACf;AAAA,IACF;AAGA,UAAM,eAAe,MAAM,KAAK;AAChC,QAAI,CAAC,gBAAgB,CAAC,qBAAqB;AAEzC,wBAAkB,IAAI;AACtB,UAAI,YAAa,qBAAoB;AACrC;AAAA,IACF;AAGA,UAAM,SAAS,aAAa,YAAY;AACxC,sBAAkB,MAAM;AAGxB,QAAI,WAAW,WAAW;AACxB,UAAI,CAAC,YAAa,qBAAoB;AAAA,IACxC,OAAO;AAEL,UAAI,YAAa,qBAAoB;AAAA,IACvC;AAAA,EACF,GAAG,CAAC,OAAO,aAAa,qBAAqB,UAAU,CAAC;AAExD,QAAM,wBAAwB,MAAM,YAAY,CAAC,aAA6B;AAC5E,QAAI,SAAS,SAAS,GAAG;AACvB,mCAA6B,QAAQ;AACrC,kCAA4B,IAAI;AAChC,wCAAkC,CAAC;AACnC,uCAAiC,CAAC;AAAA,IACpC,OAAO;AACL,kCAA4B,KAAK;AAAA,IACnC;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,iCAAiC,MAAM,YAAY,CAAC,gBAAwC;AAChG,UAAM,aAAa,YAAY,YAAY;AAC3C,UAAM,QAAQ,aAAa,KAAK;AAEhC,QAAI,MAAM,WAAW,GAAG;AACtB,aAAO,CAAC;AAAA,QACN,MAAM;AAAA,QACN,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAEA,UAAM,UAAU,MACb,OAAO,UAAQ,KAAK,KAAK,YAAY,EAAE,SAAS,UAAU,CAAC,EAC3D,MAAM,GAAG,EAAE,EACX,IAAI,WAAS;AAAA,MACZ,MAAM,KAAK;AAAA,MACX,aAAa,KAAK,WAAW;AAAA,IAC/B,EAAE;AAEJ,QAAI,QAAQ,WAAW,GAAG;AACxB,aAAO,CAAC;AAAA,QACN,MAAM;AAAA,QACN,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,QAAM,0BAA0B,MAAM,YAAY,CAAC,cAAsB;AACvE,QAAI,CAAC,UAAU,WAAW,GAAG,GAAG;AAC9B,kCAA4B,KAAK;AACjC;AAAA,IACF;AAEA,QAAI,CAAC,UAAU,SAAS,GAAG,GAAG;AAC5B,4BAAsB,eAAe,UAAU,MAAM,CAAC,CAAC,CAAC;AACxD;AAAA,IACF;AAEA,QAAI,UAAU,WAAW,OAAO,GAAG;AACjC,4BAAsB,eAAe,UAAU,MAAM,CAAC,CAAC,CAAC;AACxD;AAAA,IACF;AAEA,QAAI,UAAU,WAAW,QAAQ,GAAG;AAClC,4BAAsB,eAAe,UAAU,MAAM,CAAC,CAAC,CAAC;AACxD;AAAA,IACF;AAEA,QAAI,UAAU,WAAW,eAAe,KAAK,UAAU,WAAW,2BAA2B,GAAG;AAC9F,4BAAsB,eAAe,UAAU,MAAM,CAAC,CAAC,CAAC;AACxD;AAAA,IACF;AAEA,QAAI,UAAU,WAAW,mBAAmB,KAAK,UAAU,WAAW,OAAO,KAAK,UAAU,WAAW,WAAW,GAAG;AACnH,4BAAsB,eAAe,UAAU,MAAM,CAAC,CAAC,CAAC;AACxD;AAAA,IACF;AAEA,QAAI,UAAU,WAAW,QAAQ,GAAG;AAClC,4BAAsB,eAAe,UAAU,MAAM,CAAC,CAAC,CAAC;AACxD;AAAA,IACF;AAEA,QAAI,UAAU,WAAW,UAAU,KAAK,UAAU,WAAW,SAAS,GAAG;AACvE,4BAAsB,eAAe,UAAU,MAAM,CAAC,CAAC,CAAC;AACxD;AAAA,IACF;AAEA,QAAI,UAAU,WAAW,yBAAyB,GAAG;AACnD,4BAAsB,eAAe,UAAU,MAAM,CAAC,CAAC,CAAC;AACxD;AAAA,IACF;AAEA,QAAI,UAAU,WAAW,YAAY,GAAG;AACtC,4BAAsB,eAAe,UAAU,MAAM,CAAC,CAAC,CAAC;AACxD;AAAA,IACF;AAEA,QAAI,UAAU,WAAW,UAAU,GAAG;AACpC,YAAM,YAAY,UAAU,MAAM,CAAC,EAAE,YAAY;AACjD,YAAM,cAAc,iBAAiB,eAAe,IAAI,CAAC;AAEzD,UAAI,YAAY,WAAW,GAAG;AAC5B,8BAAsB,CAAC;AAAA,UACrB,MAAM;AAAA,UACN,aAAa;AAAA,QACf,CAAC,CAAC;AACF;AAAA,MACF;AAEA,YAAM,qBAAqC,YACxC,OAAO,QAAM,GAAG,GAAG,YAAY,EAAE,SAAS,SAAS,KAAK,GAAG,OAAO,YAAY,EAAE,SAAS,SAAS,CAAC,EACnG,MAAM,GAAG,EAAE,EACX,IAAI,SAAO;AAAA,QACV,MAAM,GAAG;AAAA,QACT,aAAa,GAAG,OAAO,SAAS,KAAK,GAAG,OAAO,MAAM,GAAG,EAAE,IAAI,QAAQ,GAAG;AAAA,MAC3E,EAAE;AAEJ,4BAAsB,kBAAkB;AACxC;AAAA,IACF;AAEA,QAAI,UAAU,MAAM,6BAA6B,GAAG;AAClD,YAAM,QAAQ,UAAU,MAAM,oCAAoC;AAClE,YAAM,cAAc,QAAQ,MAAM,CAAC,IAAI;AACvC,4BAAsB,+BAA+B,WAAW,CAAC;AACjE;AAAA,IACF;AAEA,QAAI,UAAU,WAAW,SAAS,GAAG;AACnC,4BAAsB,eAAe,UAAU,MAAM,CAAC,CAAC,CAAC;AACxD;AAAA,IACF;AAEA,QACE,UAAU,MAAM,oCAAoC,KACpD,UAAU,MAAM,8BAA8B,GAC9C;AACA,YAAM,QAAQ,UAAU,MAAM,kDAAkD;AAChF,YAAM,cAAc,QAAQ,MAAM,CAAC,EAAE,YAAY,IAAI;AACrD,YAAM,YAAY,gBAAgB,KAAK;AACvC,YAAM,oBAAoC,UACvC,OAAO,QAAM,GAAG,KAAK,YAAY,EAAE,SAAS,WAAW,CAAC,EACxD,MAAM,GAAG,EAAE,EACX,IAAI,SAAO;AAAA,QACV,MAAM,GAAG;AAAA,QACT,aAAa,GAAG,eAAe,GAAG,GAAG,SAAS,QAAQ,GAAG,cAAc,IAAI,MAAM,EAAE;AAAA,MACrF,EAAE;AAEJ,4BAAsB,iBAAiB;AACvC;AAAA,IACF;AAEA,QACE,UAAU,MAAM,sBAAsB,KACtC,UAAU,MAAM,gBAAgB,GAChC;AACA,4BAAsB,eAAe,UAAU,MAAM,CAAC,CAAC,CAAC;AACxD;AAAA,IACF;AAEA,QAAI,UAAU,WAAW,YAAY,KAAK,UAAU,WAAW,MAAM,GAAG;AACtE,4BAAsB,eAAe,UAAU,MAAM,CAAC,CAAC,CAAC;AACxD;AAAA,IACF;AAEA,gCAA4B,KAAK;AAAA,EACnC,GAAG,CAAC,gBAAgB,gCAAgC,qBAAqB,CAAC;AAE1E,QAAM,mBAAmB,MAAM,YAAY,CAAC,UAAuC;AACjF,QAAI;AACF,YAAM,MAAM,2BAA2B,QAAQ,IAAI;AACnD,UAAI,CAAC,GAAG,WAAW,GAAG,EAAG,QAAO,CAAC;AAEjC,YAAM,aAAa,MAAM,YAAY;AACrC,YAAM,UAA+B,CAAC;AAGtC,YAAM,YAAY,oBAAI,IAAI;AAAA,QACxB;AAAA,QAAQ;AAAA,QAAgB;AAAA,QAAQ;AAAA,QAAS;AAAA,QAAS;AAAA,QAClD;AAAA,QAAU;AAAA,QAAY;AAAA,QAAe;AAAA,QAAU;AAAA,QAAO;AAAA,MACxD,CAAC;AAGD,UAAI,eAAe,IAAI;AACrB,YAAI;AACJ,YAAI;AAAE,oBAAU,GAAG,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAAA,QAAG,QAAQ;AAAE,iBAAO,CAAC;AAAA,QAAG;AACnF,mBAAW,SAAS,SAAS;AAC3B,cAAI,MAAM,KAAK,WAAW,GAAG,EAAG;AAChC,kBAAQ,KAAK;AAAA,YACX,MAAM,MAAM;AAAA,YACZ,YAAY,MAAM,YAAY,IAAI,GAAG,MAAM,IAAI,MAAM,MAAM;AAAA,YAC3D,MAAM,MAAM,YAAY,IAAI,cAAuB;AAAA,UACrD,CAAC;AAAA,QACH;AACA,gBAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AACnD,eAAO,QAAQ,MAAM,GAAG,EAAE;AAAA,MAC5B;AAIA,YAAM,OAAO,CAAC,KAAa,cAAsB,UAAkB;AACjE,YAAI,QAAQ,KAAK,QAAQ,UAAU,GAAI;AACvC,YAAI;AACJ,YAAI;AAAE,oBAAU,GAAG,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAAA,QAAG,QAAQ;AAAE;AAAA,QAAQ;AAEhF,mBAAW,SAAS,SAAS;AAC3B,cAAI,MAAM,KAAK,WAAW,GAAG,EAAG;AAChC,gBAAM,eAAe,eAAe,GAAG,YAAY,IAAI,MAAM,IAAI,KAAK,MAAM;AAC5E,gBAAM,eAAe,aAAa,YAAY;AAC9C,gBAAM,gBAAgB,MAAM,KAAK,YAAY;AAE7C,cAAI,MAAM,YAAY,GAAG;AACvB,gBAAI,UAAU,IAAI,MAAM,IAAI,EAAG;AAE/B,gBAAI,aAAa,SAAS,UAAU,KAAK,cAAc,SAAS,UAAU,GAAG;AAC3E,sBAAQ,KAAK;AAAA,gBACX,MAAM;AAAA,gBACN,YAAY,GAAG,YAAY;AAAA,gBAC3B,MAAM;AAAA,cACR,CAAC;AAAA,YACH;AACA,iBAAK,KAAK,KAAK,KAAK,MAAM,IAAI,GAAG,cAAc,QAAQ,CAAC;AAAA,UAC1D,OAAO;AACL,gBAAI,aAAa,SAAS,UAAU,KAAK,cAAc,SAAS,UAAU,GAAG;AAC3E,sBAAQ,KAAK;AAAA,gBACX,MAAM;AAAA,gBACN,YAAY;AAAA,gBACZ,MAAM;AAAA,cACR,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,WAAK,KAAK,IAAI,CAAC;AAGf,cAAQ,KAAK,CAAC,GAAG,MAAM;AACrB,cAAM,YAAY,EAAE,KAAK,MAAM,GAAG,EAAE,IAAI,EAAG,YAAY;AACvD,cAAM,YAAY,EAAE,KAAK,MAAM,GAAG,EAAE,IAAI,EAAG,YAAY;AACvD,cAAM,kBAAkB,UAAU,WAAW,UAAU;AACvD,cAAM,kBAAkB,UAAU,WAAW,UAAU;AACvD,cAAM,cAAc,EAAE,KAAK,YAAY,EAAE,WAAW,UAAU;AAC9D,cAAM,cAAc,EAAE,KAAK,YAAY,EAAE,WAAW,UAAU;AAE9D,aAAK,eAAe,oBAAoB,EAAE,eAAe,iBAAkB,QAAO;AAClF,YAAI,EAAE,eAAe,qBAAqB,eAAe,iBAAkB,QAAO;AAGlF,cAAM,SAAS,EAAE,KAAK,MAAM,GAAG,EAAE;AACjC,cAAM,SAAS,EAAE,KAAK,MAAM,GAAG,EAAE;AACjC,YAAI,WAAW,OAAQ,QAAO,SAAS;AAEvC,eAAO,EAAE,KAAK,cAAc,EAAE,IAAI;AAAA,MACpC,CAAC;AAED,aAAO,QAAQ,MAAM,GAAG,EAAE;AAAA,IAC5B,SAAS,OAAO;AACd,aAAO,CAAC;AAAA,IACV;AAAA,EACF,GAAG,CAAC,uBAAuB,CAAC;AAE5B,QAAM,gCAAgC,MAAM,YAAY,CAAC,UAAuC;AAC9F,UAAM,aAAa,MAAM,YAAY;AAErC,QAAI,WAAW,WAAW,QAAQ,GAAG;AACnC,YAAM,YAAY,MAAM,MAAM,SAAS,MAAM,EAAE,YAAY;AAC3D,aAAO,aAAa,KAAK,EACtB,OAAO,UAAQ,KAAK,KAAK,YAAY,EAAE,SAAS,SAAS,CAAC,EAC1D,MAAM,GAAG,EAAE,EACX,IAAI,WAAS;AAAA,QACZ,MAAM,SAAS,KAAK,IAAI;AAAA,QACxB,YAAY,SAAS,KAAK,IAAI;AAAA,QAC9B,MAAM;AAAA,QACN,aAAa,KAAK,WAAW;AAAA,MAC/B,EAAE;AAAA,IACN;AAEA,UAAM,cAAmC,CAAC;AAC1C,QAAI,SAAS,WAAW,UAAU,KAAK,WAAW,WAAW,OAAO,GAAG;AACrE,kBAAY,KAAK;AAAA,QACf,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,MAAM;AAAA,QACN,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAEA,WAAO,CAAC,GAAG,aAAa,GAAG,iBAAiB,KAAK,CAAC,EAAE,MAAM,GAAG,EAAE;AAAA,EACjE,GAAG,CAAC,gBAAgB,CAAC;AAGrB,YAAU,MAAM;AAEd,QAAI,aAAa;AACf,oCAA8B,KAAK;AACnC;AAAA,IACF;AAIA,QAAI,aAAa;AACjB,aAAS,IAAI,eAAe,GAAG,KAAK,GAAG,KAAK;AAC1C,YAAM,OAAO,MAAM,CAAC;AAEpB,UAAI,SAAS,KAAK,IAAI,EAAG;AACzB,UAAI,SAAS,KAAK;AAChB,qBAAa;AACb;AAAA,MACF;AAAA,IACF;AAIA,QAAI,eAAe,MAAO,aAAa,KAAK,CAAC,SAAS,KAAK,MAAM,aAAa,CAAC,CAAC,GAAI;AAClF,oCAA8B,KAAK;AACnC,4BAAsB,IAAI;AAC1B;AAAA,IACF;AAGA,UAAM,QAAQ,MAAM,MAAM,aAAa,GAAG,YAAY;AAEtD,UAAM,UAAU,8BAA8B,KAAK;AAEnD,QAAI,QAAQ,SAAS,GAAG;AACtB,4BAAsB,OAAO;AAC7B,oCAA8B,IAAI;AAClC,4BAAsB,UAAU;AAChC,8BAAwB,CAAC;AAAA,IAC3B,OAAO;AACL,oCAA8B,KAAK;AACnC,4BAAsB,IAAI;AAAA,IAC5B;AAAA,EACF,GAAG,CAAC,OAAO,cAAc,aAAa,yBAAyB,6BAA6B,CAAC;AAE7F,QAAM,kBAAkB,MAAM;AAC5B,iBAAa,UAAQ,CAAC,GAAG,MAAM,EAAE,OAAO,aAAa,CAAC,CAAC;AACvD,iBAAa,CAAC,CAAC;AAAA,EACjB;AAEA,QAAM,aAAa,MAAM;AACvB,QAAI,UAAU,WAAW,EAAG;AAC5B,UAAM,gBAAgB,UAAU,UAAU,SAAS,CAAC;AACpD,iBAAa,UAAQ,CAAC,GAAG,MAAM,EAAE,OAAO,aAAa,CAAC,CAAC;AACvD,iBAAa,UAAQ,KAAK,MAAM,GAAG,EAAE,CAAC;AACtC,aAAS,cAAc,KAAK;AAC5B,oBAAgB,cAAc,YAAY;AAC1C,iBAAa,IAAI;AAAA,EACnB;AAEA,QAAM,yBAAyB,CAAC,UAA6B,WAAoB;AAC/E,QAAI,uBAAuB,MAAM;AAC/B;AAAA,IACF;AAEA,oBAAgB;AAEhB,UAAM,YAAY,MAAM,MAAM,GAAG,kBAAkB;AACnD,UAAM,cAAc,MAAM,MAAM,YAAY;AAC5C,UAAM,YAAY,YAAY,MAAM,SAAS;AAE7C,QAAI,SAAS,SAAS,kBAAkB;AACtC,YAAMA,YAAW,YAAY;AAC7B,YAAMC,gBAAe,qBAAqB,IAAI,SAAS,WAAW;AAClE,eAASD,SAAQ;AACjB,sBAAgBC,aAAY;AAC5B;AAAA,IACF;AAEA,QAAI,UAAU,SAAS,SAAS,aAAa;AAC3C,YAAMD,YAAW,YAAY;AAC7B,YAAMC,gBAAe,qBAAqB,IAAI,SAAS,WAAW;AAClE,eAASD,SAAQ;AACjB,sBAAgBC,aAAY;AAC5B;AAAA,IACF;AAEA,UAAM,iBAAiB,SAAS,KAAK;AACrC,UAAM,WAAW,YAAY,iBAAiB;AAC9C,UAAM,eAAe,qBAAqB,IAAI,SAAS,WAAW,SAAS,eAAe;AAE1F,aAAS,QAAQ;AACjB,oBAAgB,YAAY;AAE5B,yBAAqB,UAAQ;AAAA,MAC3B,GAAG,KAAK;AAAA,QAAO,SACb,EAAE,IAAI,SAAS,sBAAsB,IAAI,SAAS;AAAA,MACpD;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,KAAK,qBAAqB,IAAI,SAAS,WAAW;AAAA,QAClD,UAAU,SAAS;AAAA,MACrB;AAAA,IACF,CAAC;AAED,kCAA8B,KAAK;AACnC,0BAAsB,IAAI;AAAA,EAC5B;AAEA,WAAS,CAAC,OAAO,QAAQ;AACvB,QAAI,CAAC,SAAU;AAGf,UAAM,YAAY,QAAQ,aAAa;AACvC,UAAM,gBAAgB,QAAQ,MAAM,WAAW,CAAC,IAAI;AACpD,UAAM,kBAAkB,QAAQ,MAAM,YAAY,IAAI;AAItD,UAAM,+BACJ,UAAU,YACV,UAAU,YACV,oBAAoB,gBACpB,oBAAoB,gBACpB,oBAAoB;AACtB,UAAM,eAAe,IAAI,UAAU;AAInC,UAAM,kCAAkC,UACtC,oBAAoB,WACpB,oBAAoB,eACpB,oBAAoB,eACnB,IAAI,QAAQ,oBAAoB,OAChC,IAAI,UAAU,IAAI;AAErB,UAAM,iCAAiC,UACrC,oBAAoB,WACpB,oBAAoB,eACpB,oBAAoB,eACnB,IAAI,QAAQ,oBAAoB,OAChC,IAAI,UAAU,IAAI;AAIrB,QAAI,0BAA0B;AAC5B,UAAI,IAAI,WAAW;AACjB,cAAM,WAAW,KAAK,IAAI,iCAAiC,GAAG,0BAA0B,SAAS,CAAC;AAClG,0CAAkC,QAAQ;AAE1C,YAAI,YAAY,gCAAgC,sBAAsB;AACpE,2CAAiC,WAAW,uBAAuB,CAAC;AAAA,QACtE;AACA;AAAA,MACF;AAEA,UAAI,IAAI,SAAS;AACf,cAAM,WAAW,KAAK,IAAI,iCAAiC,GAAG,CAAC;AAC/D,0CAAkC,QAAQ;AAE1C,YAAI,WAAW,+BAA+B;AAC5C,2CAAiC,QAAQ;AAAA,QAC3C;AACA;AAAA,MACF;AAEA,UAAI,IAAI,UAAU,MAAM,UAAU,KAAK,CAAC,IAAI,SAAS,CAAC,IAAI,QAAQ,CAAC,IAAI,MAAM;AAE3E,cAAM,WAAW,0BAA0B,8BAA8B;AACzE,YAAI,CAAC,YAAY,SAAS,KAAK,WAAW,MAAM,GAAG;AACjD,sCAA4B,KAAK;AACjC;AAAA,QACF;AAGA,YAAI,MAAM,WAAW,OAAO,GAAG;AAE7B,gBAAM,WAAW,QAAQ,SAAS,IAAI;AACtC,mBAAS,QAAQ;AACjB,0BAAgB,SAAS,MAAM;AAC/B,sCAA4B,KAAK;AAAA,QACnC,WAAW,MAAM,WAAW,QAAQ,GAAG;AAErC,gBAAM,WAAW,SAAS,SAAS,IAAI;AACvC,mBAAS,QAAQ;AACjB,0BAAgB,SAAS,MAAM;AAC/B,sCAA4B,KAAK;AAAA,QACnC,WAAW,MAAM,WAAW,eAAe,KAAK,MAAM,WAAW,2BAA2B,GAAG;AAE7F,gBAAM,SAAS,MAAM,WAAW,2BAA2B,IAAI,8BAA8B;AAC7F,gBAAM,WAAW,GAAG,MAAM,GAAG,SAAS,IAAI;AAC1C,mBAAS,QAAQ;AACjB,0BAAgB,SAAS,MAAM;AAC/B,sCAA4B,KAAK;AAAA,QACnC,WAAW,MAAM,WAAW,mBAAmB,KAAK,MAAM,WAAW,OAAO,KAAK,MAAM,WAAW,WAAW,GAAG;AAE9G,gBAAM,SAAS,MAAM,WAAW,OAAO,IAAI,UAAW,MAAM,WAAW,WAAW,IAAI,cAAc;AACpG,gBAAM,WAAW,GAAG,MAAM,GAAG,SAAS,IAAI;AAC1C,mBAAS,QAAQ;AACjB,0BAAgB,SAAS,MAAM;AAC/B,sCAA4B,KAAK;AAAA,QACnC,WAAW,MAAM,WAAW,QAAQ,GAAG;AAErC,gBAAM,WAAW,SAAS,SAAS,IAAI;AACvC,mBAAS,QAAQ;AACjB,0BAAgB,SAAS,MAAM;AAC/B,sCAA4B,KAAK;AAAA,QACnC,WAAW,MAAM,WAAW,UAAU,GAAG;AAEvC,gBAAM,WAAW,WAAW,SAAS,IAAI;AACzC,mBAAS,QAAQ;AACjB,0BAAgB,SAAS,MAAM;AAC/B,sCAA4B,KAAK;AAAA,QACnC,WAAW,MAAM,WAAW,UAAU,KAAK,MAAM,WAAW,SAAS,GAAG;AAEtE,gBAAM,SAAS,MAAM,WAAW,UAAU,IAAI,aAAa;AAC3D,gBAAM,WAAW,GAAG,MAAM,GAAG,SAAS,IAAI;AAC1C,mBAAS,QAAQ;AACjB,0BAAgB,SAAS,MAAM;AAC/B,sCAA4B,KAAK;AAAA,QACnC,WAAW,MAAM,WAAW,SAAS,GAAG;AACtC,gBAAM,gBAAgB,MAAM,MAAM,6BAA6B;AAC/D,cAAI,eAAe;AACjB,kBAAM,SAAS,MAAM,MAAM,+BAA+B,IAAI,CAAC,KAAK;AACpE,kBAAM,WAAW,GAAG,MAAM,GAAG,SAAS,IAAI;AAC1C,qBAAS,QAAQ;AACjB,4BAAgB,SAAS,MAAM;AAC/B,wCAA4B,KAAK;AAAA,UACnC,OAAO;AACL,kBAAM,WAAW,UAAU,SAAS,IAAI;AACxC,qBAAS,QAAQ;AACjB,4BAAgB,SAAS,MAAM;AAE/B,gBAAI,SAAS,SAAS,UAAU,SAAS,SAAS,UAAU;AAC1D,oBAAM,cAAc,+BAA+B,EAAE;AACrD,kBAAI,YAAY,SAAS,GAAG;AAC1B,6CAA6B,WAAW;AACxC,kDAAkC,CAAC;AACnC,iDAAiC,CAAC;AAAA,cACpC,OAAO;AACL,4CAA4B,KAAK;AAAA,cACnC;AAAA,YACF,OAAO;AACL,0CAA4B,KAAK;AAAA,YACnC;AAAA,UACF;AAAA,QACF,WAAW,MAAM,WAAW,gBAAgB,KAAK,MAAM,WAAW,UAAU,GAAG;AAE7E,gBAAM,SAAS,MAAM,WAAW,gBAAgB,IAAI,mBAAmB;AACvE,gBAAM,WAAW,GAAG,MAAM,GAAG,SAAS,IAAI;AAC1C,mBAAS,QAAQ;AACjB,0BAAgB,SAAS,MAAM;AAC/B,sCAA4B,KAAK;AAAA,QACnC,WAAW,MAAM,WAAW,YAAY,KAAK,MAAM,WAAW,MAAM,GAAG;AAErE,gBAAM,oBAAoB,MAAM,MAAM,2CAA2C;AACjF,cAAI,mBAAmB;AAErB,kBAAM,SAAS,MAAM,MAAM,6CAA6C,IAAI,CAAC,KAAK;AAClF,kBAAM,WAAW,GAAG,MAAM,GAAG,SAAS,IAAI;AAC1C,qBAAS,QAAQ;AACjB,4BAAgB,SAAS,MAAM;AAC/B,wCAA4B,KAAK;AAAA,UACnC,OAAO;AAEL,kBAAM,SAAS,MAAM,WAAW,YAAY,IAAI,eAAe;AAC/D,kBAAM,WAAW,GAAG,MAAM,GAAG,SAAS,IAAI;AAC1C,qBAAS,QAAQ;AACjB,4BAAgB,SAAS,MAAM;AAG/B,gBAAI,SAAS,SAAS,SAAS,SAAS,SAAS,UAAU,SAAS,SAAS,UAAU;AACrF,oBAAM,YAAY,gBAAgB,KAAK;AACvC,oBAAM,oBAAoC,UACvC,MAAM,GAAG,EAAE,EACX,IAAI,SAAO;AAAA,gBACV,MAAM,GAAG;AAAA,gBACT,aAAa,GAAG,eAAe,GAAG,GAAG,SAAS,QAAQ,GAAG,cAAc,IAAI,MAAM,EAAE;AAAA,cACrF,EAAE;AAEJ,kBAAI,kBAAkB,SAAS,GAAG;AAChC,6CAA6B,iBAAiB;AAC9C,kDAAkC,CAAC;AACnC,iDAAiC,CAAC;AAAA,cAEpC,OAAO;AACL,4CAA4B,KAAK;AAAA,cACnC;AAAA,YACF,WAAW,SAAS,SAAS,OAAO;AAElC,oBAAM,oBAAoB,eAAe,eAAe;AACxD,kBAAI,kBAAkB,SAAS,GAAG;AAChC,6CAA6B,iBAAiB;AAC9C,kDAAkC,CAAC;AACnC,iDAAiC,CAAC;AAAA,cAEpC,OAAO;AACL,4CAA4B,KAAK;AAAA,cACnC;AAAA,YACF,OAAO;AACL,0CAA4B,KAAK;AAAA,YACnC;AAAA,UACF;AAAA,QACF,WAAW,MAAM,WAAW,yBAAyB,GAAG;AAEtD,gBAAM,WAAW,0BAA0B,SAAS,IAAI;AACxD,mBAAS,QAAQ;AACjB,0BAAgB,SAAS,MAAM;AAC/B,sCAA4B,KAAK;AAAA,QACnC,WAAW,MAAM,WAAW,YAAY,GAAG;AAEzC,gBAAM,WAAW,aAAa,SAAS,IAAI;AAC3C,mBAAS,QAAQ;AACjB,0BAAgB,SAAS,MAAM;AAE/B,cAAI,SAAS,SAAS,gBAAgB;AACpC,kBAAM,gBAAgB,eAAe,wBAAwB;AAC7D,gBAAI,cAAc,SAAS,GAAG;AAC5B,2CAA6B,aAAa;AAC1C,gDAAkC,CAAC;AACnC,+CAAiC,CAAC;AAAA,YACpC,OAAO;AACL,0CAA4B,KAAK;AAAA,YACnC;AAAA,UACF,OAAO;AACL,wCAA4B,KAAK;AAAA,UACnC;AAAA,QACF,OAAO;AAEL,gBAAM,WAAW,IAAI,SAAS,IAAI;AAClC,mBAAS,QAAQ;AACjB,0BAAgB,SAAS,MAAM;AAI/B,cAAI,SAAS,SAAS,OAAO;AAC3B,kBAAM,oBAAoB,eAAe,MAAM;AAC/C,gBAAI,kBAAkB,SAAS,GAAG;AAChC,2CAA6B,iBAAiB;AAC9C,gDAAkC,CAAC;AACnC,+CAAiC,CAAC;AAAA,YAEpC,OAAO;AACL,0CAA4B,KAAK;AAAA,YACnC;AAAA,UACF,WAAW,SAAS,SAAS,QAAQ;AACnC,kBAAM,oBAAoB,eAAe,OAAO;AAChD,gBAAI,kBAAkB,SAAS,GAAG;AAChC,2CAA6B,iBAAiB;AAC9C,gDAAkC,CAAC;AACnC,+CAAiC,CAAC;AAAA,YAEpC,OAAO;AACL,0CAA4B,KAAK;AAAA,YACnC;AAAA,UACF,WAAW,SAAS,SAAS,iBAAiB,SAAS,SAAS,2BAA2B;AACzF,kBAAM,oBAAoB,eAAe,cAAc;AACvD,gBAAI,kBAAkB,SAAS,GAAG;AAChC,2CAA6B,iBAAiB;AAC9C,gDAAkC,CAAC;AACnC,+CAAiC,CAAC;AAAA,YAEpC,OAAO;AACL,0CAA4B,KAAK;AAAA,YACnC;AAAA,UACF,WAAW,SAAS,SAAS,qBAAqB,SAAS,SAAS,SAAS,SAAS,SAAS,WAAW;AACxG,kBAAM,oBAAoB,eAAe,kBAAkB;AAC3D,gBAAI,kBAAkB,SAAS,GAAG;AAChC,2CAA6B,iBAAiB;AAC9C,gDAAkC,CAAC;AACnC,+CAAiC,CAAC;AAAA,YAEpC,OAAO;AACL,0CAA4B,KAAK;AAAA,YACnC;AAAA,UACF,WAAW,SAAS,SAAS,QAAQ;AACnC,kBAAM,oBAAoB,eAAe,OAAO;AAChD,gBAAI,kBAAkB,SAAS,GAAG;AAChC,2CAA6B,iBAAiB;AAC9C,gDAAkC,CAAC;AACnC,+CAAiC,CAAC;AAAA,YAEpC,OAAO;AACL,0CAA4B,KAAK;AAAA,YACnC;AAAA,UACF,WAAW,SAAS,SAAS,YAAY,SAAS,SAAS,SAAS;AAClE,kBAAM,oBAAoB,eAAe,SAAS;AAClD,gBAAI,kBAAkB,SAAS,GAAG;AAChC,2CAA6B,iBAAiB;AAC9C,gDAAkC,CAAC;AACnC,+CAAiC,CAAC;AAAA,YAEpC,OAAO;AACL,0CAA4B,KAAK;AAAA,YACnC;AAAA,UACF,WAAW,SAAS,SAAS,YAAY;AACvC,kBAAM,oBAAoB,eAAe,WAAW;AACpD,gBAAI,kBAAkB,SAAS,GAAG;AAChC,2CAA6B,iBAAiB;AAC9C,gDAAkC,CAAC;AACnC,+CAAiC,CAAC;AAAA,YAEpC,OAAO;AACL,0CAA4B,KAAK;AAAA,YACnC;AAAA,UACF,WAAW,SAAS,SAAS,cAAc,SAAS,SAAS,MAAM;AACjE,kBAAM,oBAAoB,eAAe,WAAW;AACpD,gBAAI,kBAAkB,SAAS,GAAG;AAChC,2CAA6B,iBAAiB;AAC9C,gDAAkC,CAAC;AACnC,+CAAiC,CAAC;AAAA,YAEpC,OAAO;AACL,0CAA4B,KAAK;AAAA,YACnC;AAAA,UACF,WAAW,SAAS,SAAS,SAAS;AACpC,kBAAM,oBAAoB,eAAe,QAAQ;AACjD,gBAAI,kBAAkB,SAAS,GAAG;AAChC,2CAA6B,iBAAiB;AAC9C,gDAAkC,CAAC;AACnC,+CAAiC,CAAC;AAAA,YACpC,OAAO;AACL,0CAA4B,KAAK;AAAA,YACnC;AAAA,UACF,WAAW,SAAS,SAAS,UAAU;AAErC,kBAAM,cAAc,iBAAiB,eAAe,IAAI,CAAC;AACzD,gBAAI,YAAY,WAAW,GAAG;AAC5B,2CAA6B,CAAC;AAAA,gBAC5B,MAAM;AAAA,gBACN,aAAa;AAAA,cACf,CAAC,CAAC;AACF,gDAAkC,CAAC;AACnC,+CAAiC,CAAC;AAAA,YAEpC,OAAO;AACL,oBAAM,qBAAqC,YACxC,MAAM,GAAG,EAAE,EACX,IAAI,QAAM;AACT,sBAAM,kBAAkB,GAAG,OAAO,SAAS,KAAK,GAAG,OAAO,MAAM,GAAG,EAAE,IAAI,QAAQ,GAAG;AACpF,uBAAO;AAAA,kBACL,MAAM,GAAG;AAAA,kBACT,aAAa;AAAA,gBACf;AAAA,cACF,CAAC;AACH,2CAA6B,kBAAkB;AAC/C,gDAAkC,CAAC;AACnC,+CAAiC,CAAC;AAAA,YAEpC;AAAA,UACF,OAAO;AACL,wCAA4B,KAAK;AAAA,UACnC;AAAA,QACF;AACA;AAAA,MACF;AAEA,UAAI,IAAI,QAAQ;AACd,oCAA4B,KAAK;AACjC;AAAA,MACF;AAAA,IACF;AAGA,QAAI,4BAA4B;AAC9B,UAAI,IAAI,WAAW;AACjB;AAAA,UAAwB,UACtB,KAAK,IAAI,OAAO,GAAG,mBAAmB,SAAS,CAAC;AAAA,QAClD;AACA;AAAA,MACF;AAEA,UAAI,IAAI,SAAS;AACf,gCAAwB,UAAQ,KAAK,IAAI,OAAO,GAAG,CAAC,CAAC;AACrD;AAAA,MACF;AAEA,UAAI,IAAI,UAAU,MAAM,UAAU,KAAK,CAAC,IAAI,SAAS,CAAC,IAAI,QAAQ,CAAC,IAAI,MAAM;AAE3E,cAAM,WAAW,mBAAmB,oBAAoB;AACxD,YAAI,YAAY,uBAAuB,MAAM;AAC3C,iCAAuB,UAAU,KAAK;AAAA,QACxC;AACA;AAAA,MACF;AAEA,UAAI,IAAI,QAAQ;AACd,sCAA8B,KAAK;AACnC,8BAAsB,IAAI;AAC1B;AAAA,MACF;AAGA,UAAI,IAAI,OAAO,CAAC,IAAI,OAAO;AACzB,cAAM,WAAW,mBAAmB,oBAAoB;AACxD,YAAI,YAAY,uBAAuB,MAAM;AAC3C,iCAAuB,UAAU,IAAI;AAAA,QACvC;AACA;AAAA,MACF;AAAA,IACF;AAOA,UAAM,SAAU,IAAI,QAAQ,UAAU,OAAS,UAAU;AAEzD,QAAI,UAAU,CAAC,aAAa;AAE1B,OAAC,YAAY;AACX,YAAI;AACF,gBAAM,QAAQ,MAAM,kBAAkB;AACtC,cAAI,MAAM,SAAS,GAAG;AAEpB,kBAAM,eAAe,wBAAwB;AAC7C,kBAAM,WAAW,MAAM;AAEvB,gBAAI,eAAe,WAAW,GAAG;AAC/B,uBAAS,+CAA+C,YAAY,MAAM,QAAQ,OAAO;AACzF,6BAAe,IAAI;AACnB,yBAAW,MAAM,eAAe,KAAK,GAAG,GAAI;AAC5C;AAAA,YACF;AAEA,qBAAS,gBAAgB,MAAM,MAAM,wCAAwC;AAG7E,kBAAM,kBAAkB,MAAM,IAAI,WAAS;AAAA,cACzC,GAAG;AAAA,cACH,IAAI,GAAG,KAAK,EAAE,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC,CAAC;AAAA,YACzE,EAAE;AAEF,uCAA2B,UAAQ,CAAC,GAAG,MAAM,GAAG,eAAe,CAAC;AAAA,UAClE,OAAO;AACL,qBAAS,6BAA6B;AAAA,UACxC;AAAA,QACF,SAAS,OAAO;AACd,mBAAS,qCAAqC,iBAAiB,QAAQ,MAAM,UAAU,eAAe,EAAE;AAAA,QAC1G;AAAA,MACF,GAAG;AACH;AAAA,IACF;AAKA,UAAM,SAAU,IAAI,QAAQ,UAAU,OAAS,UAAU;AAEzD,QAAI,UAAU,CAAC,aAAa;AAC1B,UAAI,wBAAwB,SAAS,GAAG;AACtC,iBAAS,oCAAoC;AAC7C,mCAA2B,UAAQ,KAAK,MAAM,GAAG,EAAE,CAAC;AAAA,MACtD,OAAO;AACL,iBAAS,2BAA2B;AAAA,MACtC;AACA;AAAA,IACF;AAGA,QAAI,iCAAiC;AACnC,UAAI,eAAe,GAAG;AACpB,YAAI,YAAY;AAChB,eAAO,YAAY,KAAK,KAAK,KAAK,MAAM,YAAY,CAAC,CAAC,GAAG;AACvD;AAAA,QACF;AACA,eAAO,YAAY,KAAK,CAAC,KAAK,KAAK,MAAM,YAAY,CAAC,CAAC,GAAG;AACxD;AAAA,QACF;AACA,wBAAgB,SAAS;AAAA,MAC3B;AACA;AAAA,IACF;AAEA,QAAI,gCAAgC;AAClC,UAAI,eAAe,MAAM,QAAQ;AAC/B,YAAI,YAAY;AAChB,eAAO,YAAY,MAAM,UAAU,KAAK,KAAK,MAAM,SAAS,CAAC,GAAG;AAC9D;AAAA,QACF;AACA,eAAO,YAAY,MAAM,UAAU,CAAC,KAAK,KAAK,MAAM,SAAS,CAAC,GAAG;AAC/D;AAAA,QACF;AACA,wBAAgB,SAAS;AAAA,MAC3B;AACA;AAAA,IACF;AAOA,UAAM,eACJ,kBAAkB;AAAA,IACjB,IAAI,SAAS,IAAI,aAAa,IAAI;AAAA,IAClC,IAAI,QAAQ,IAAI;AAAA,IAChB,aAAa,kBAAkB;AAElC,QAAI,cAAc;AAChB,sBAAgB;AAChB,UAAI,eAAe,GAAG;AACpB,YAAI,YAAY;AAEhB,eAAO,YAAY,KAAK,KAAK,KAAK,MAAM,YAAY,CAAC,CAAC,GAAG;AACvD;AAAA,QACF;AAEA,eAAO,YAAY,KAAK,CAAC,KAAK,KAAK,MAAM,YAAY,CAAC,CAAC,GAAG;AACxD;AAAA,QACF;AACA,cAAM,WAAW,MAAM,MAAM,GAAG,SAAS,IAAI,MAAM,MAAM,YAAY;AACrE,iBAAS,QAAQ;AACjB,wBAAgB,SAAS;AACzB,gCAAwB,QAAQ;AAAA,MAClC;AACA,sBAAgB,EAAE;AAClB,qBAAe,CAAC,CAAC;AACjB;AAAA,IACF;AAGA,QAAI,IAAI,QAAQ,MAAM,YAAY,MAAM,KAAK;AAC3C,0BAAoB,UAAU;AAC9B,yBAAmB;AACnB,iBAAW,MAAM;AAAE,4BAAoB,UAAU;AAAA,MAAO,GAAG,GAAG;AAC9D;AAAA,IACF;AAGA,QAAI,IAAI,QAAQ,MAAM,YAAY,MAAM,KAAK;AAC3C,UAAI,qBAAqB;AACvB,4BAAoB,UAAU;AAG9B,YAAI,CAAC,cAAc,CAAC,eAAe,CAAC,gBAAgB;AAElD,8BAAoB;AAAA,QACtB,WAAW,CAAC,cAAc,eAAe,CAAC,gBAAgB;AAExD,8BAAoB;AACpB,cAAI,uBAAwB,wBAAuB;AAAA,QACrD,WAAW,CAAC,cAAc,CAAC,eAAe,gBAAgB;AAExD,cAAI,uBAAwB,wBAAuB;AACnD,wBAAc,IAAI;AAElB,gBAAM,SAAS,aAAa,KAAK;AACjC,4BAAkB,MAAM;AAExB,cAAI,WAAW,UAAW,qBAAoB;AAAA,QAChD,WAAW,YAAY;AAErB,wBAAc,KAAK;AAEnB,cAAI,YAAa,qBAAoB;AACrC,cAAI,kBAAkB,uBAAwB,wBAAuB;AAAA,QACvE;AAEA,mBAAW,MAAM;AAAE,8BAAoB,UAAU;AAAA,QAAO,GAAG,GAAG;AAAA,MAChE;AACA;AAAA,IACF;AAGA,QAAK,IAAI,QAAQ,MAAM,YAAY,MAAM,OAAS,IAAI,QAAQ,MAAM,YAAY,MAAM,KAAM;AAC1F,iBAAW;AACX;AAAA,IACF;AAGA,QAAK,IAAI,QAAQ,MAAM,YAAY,MAAM,OAAS,IAAI,QAAQ,MAAM,YAAY,MAAM,KAAM;AAC1F,mBAAa,EAAE,OAAO,GAAG,KAAK,MAAM,OAAO,CAAC;AAC5C,sBAAgB,MAAM,MAAM;AAC5B;AAAA,IACF;AASA,QAAI,IAAI,MAAM;AACZ,YAAM,SAAS,QAAQ,OAAO,WAAW,MAAM;AAC/C,YAAM,cAAc,eAAe,OAAO,KAAK;AAE/C,YAAM,cAAc,YAAY;AAAA,QAAK,UAClC,gBAAgB,KAAK,SAAS,eAAe,KAAK,OAClD,iBAAiB,KAAK,OAAO,KAAK;AAAA,MACrC;AAEA,UAAI,aAAa;AACf,wBAAgB,YAAY,KAAK;AAAA,MACnC,OAAO;AACL,wBAAgB,CAAC;AAAA,MACnB;AACA;AAAA,IACF;AAIA,QAAI,IAAI,KAAK;AACX,YAAM,SAAS,QAAQ,OAAO,WAAW,MAAM;AAC/C,YAAM,cAAc,eAAe,OAAO,KAAK;AAE/C,YAAM,cAAc,YAAY;AAAA,QAAK,UAClC,gBAAgB,KAAK,SAAS,eAAe,KAAK,OAClD,iBAAiB,KAAK,OAAO,KAAK;AAAA,MACrC;AAEA,UAAI,aAAa;AACf,wBAAgB,YAAY,GAAG;AAAA,MACjC,OAAO;AACL,wBAAgB,MAAM,MAAM;AAAA,MAC9B;AACA;AAAA,IACF;AAWA,UAAM,eACJ,IAAI,aACJ,IAAI,UACJ,kBAAkB,KACjB,CAAC,aAAa,kBAAkB;AAEnC,QAAI,cAAc;AAChB,sBAAgB;AAEhB,UAAI,WAAW;AAEf,UAAI,WAAW;AAEb,cAAM,QAAQ,KAAK,IAAI,UAAU,OAAO,UAAU,GAAG;AACrD,cAAM,MAAM,KAAK,IAAI,UAAU,OAAO,UAAU,GAAG;AACnD,mBAAW,MAAM,MAAM,GAAG,KAAK,IAAI,MAAM,MAAM,GAAG;AAClD,iBAAS,QAAQ;AACjB,wBAAgB,KAAK;AACrB,qBAAa,IAAI;AAAA,MACnB,WAAW,eAAe,GAAG;AAE3B,mBAAW,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,MAAM,MAAM,YAAY;AACtE,iBAAS,QAAQ;AACjB,wBAAgB,eAAe,CAAC;AAAA,MAClC;AAGA,sBAAgB,EAAE;AAClB,qBAAe,CAAC,CAAC;AACjB,8BAAwB,QAAQ;AAEhC;AAAA,IACF;AAIA,QAAI,iBAAiB,MAAM,UAAU,KAAK,+BAA+B;AAKvE,YAAM,2BACJ,CAAC,IAAI,SACL,CAAC,IAAI,QACL,CAAC,IAAI,QACL,CAAC,gCACD,CAAC,aACD,eAAe,KACf,MAAM,eAAe,CAAC,MAAM;AAE9B,UAAI,IAAI,SAAS,IAAI,QAAQ,IAAI,QAAQ,UAAU,QAAQ,gCAAgC,0BAA0B;AACnH,wBAAgB;AAGhB,YAAI,WAAW;AACf,YAAI,YAAY;AAEhB,YAAI,WAAW;AACb,gBAAM,QAAQ,KAAK,IAAI,UAAU,OAAO,UAAU,GAAG;AACrD,gBAAM,MAAM,KAAK,IAAI,UAAU,OAAO,UAAU,GAAG;AACnD,qBAAW,MAAM,MAAM,GAAG,KAAK,IAAI,OAAO,MAAM,MAAM,GAAG;AACzD,sBAAY,QAAQ;AACpB,uBAAa,IAAI;AAAA,QACnB,WAAW,0BAA0B;AACnC,qBAAW,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,OAAO,MAAM,MAAM,YAAY;AAC7E,sBAAY;AAAA,QACd,OAAO;AACL,qBAAW,MAAM,MAAM,GAAG,YAAY,IAAI,OAAO,MAAM,MAAM,YAAY;AACzE,sBAAY,eAAe;AAAA,QAC7B;AAEA,iBAAS,QAAQ;AACjB,wBAAgB,SAAS;AAAA,MAC3B,OAAO;AAIL,cAAM,gBAAgB,MAAM,KAAK,MAAM;AACvC,cAAM,kBAAkB,mBAAmB;AAC3C,cAAM,mBAAmB,eAAe,iBAAiB,eAAe;AAExE,YAAI,CAAC,kBAAkB;AACrB,yBAAe,IAAI;AACnB,qBAAW,MAAM,eAAe,KAAK,GAAG,GAAI;AAC5C;AAAA,QACF;AAEA,cAAM,iBAAiB,MAAM,KAAK,EAAE,WAAW,GAAG;AAIlD,YAAI,CAAC,eAAe,CAAC,mBAAmB,CAAC,kBAAkB,uBAAuB;AAChF,yBAAe,IAAI;AACnB,8BAAoB,IAAI;AACxB,qBAAW,MAAM;AACf,2BAAe,KAAK;AACpB,gCAAoB,KAAK;AAAA,UAC3B,GAAG,GAAI;AACP;AAAA,QACF;AAEA,qBAAa;AAAA,MACf;AACA;AAAA,IACF;AAGA,QAAI,IAAI,WAAW,IAAI,aAAa,IAAI,aAAa,IAAI,YAAY;AAEnE,UAAI,WAAW;AACb,qBAAa,IAAI;AAGjB,YAAI,IAAI,UAAW,iBAAgB,KAAK,IAAI,UAAU,OAAO,UAAU,GAAG,CAAC;AAC3E,YAAI,IAAI,WAAY,iBAAgB,KAAK,IAAI,UAAU,OAAO,UAAU,GAAG,CAAC;AAC5E,YAAI,IAAI,WAAW,IAAI,WAAW;AAAA,QAGlC;AACA,YAAI,IAAI,aAAa,IAAI,WAAY;AAAA,MACvC;AAAA,IACF;AAEA,QAAI,IAAI,SAAS;AACf,YAAM,SAAS,QAAQ,OAAO,WAAW,MAAM;AAC/C,YAAM,cAAc,eAAe,OAAO,KAAK;AAE/C,UAAI,yBAAyB,YAAY,UAAU,UAAQ;AACzD,YAAI,gBAAgB,KAAK,SAAS,eAAe,KAAK,IAAK,QAAO;AAClE,YAAI,iBAAiB,KAAK,OAAO,KAAK,UAAW,QAAO;AACxD,eAAO;AAAA,MACT,CAAC;AAGD,UAAI,2BAA2B,MAAM,iBAAiB,MAAM,QAAQ;AAClE,iCAAyB,YAAY,SAAS;AAAA,MAChD;AAEA,UAAI,0BAA0B,GAAG;AAE/B,YAAI,eAAe,SAAS,GAAG;AAC7B,cAAI,iBAAiB,IAAI;AACvB,yBAAa,KAAK;AAClB,kBAAM,WAAW,eAAe,SAAS;AACzC,4BAAgB,QAAQ;AACxB,kBAAM,WAAW,eAAe,QAAQ;AACxC,qBAAS,QAAQ;AACjB,4BAAgB,SAAS,MAAM;AAAA,UACjC,WAAW,eAAe,GAAG;AAC3B,kBAAM,WAAW,eAAe;AAChC,4BAAgB,QAAQ;AACxB,kBAAM,WAAW,eAAe,QAAQ;AACxC,qBAAS,QAAQ;AACjB,4BAAgB,SAAS,MAAM;AAAA,UACjC;AAAA,QACF;AAAA,MACF,OAAO;AAEL,cAAM,cAAc,YAAY,sBAAsB;AACtD,cAAM,aAAa,YAAY,yBAAyB,CAAC;AACzD,cAAM,eAAe,eAAe,YAAY;AAEhD,cAAM,YAAY,WAAW,QAAQ,KAAK,IAAI,cAAc,WAAW,MAAM,WAAW,KAAK;AAC7F,wBAAgB,SAAS;AAAA,MAC3B;AACA;AAAA,IACF;AAEA,QAAI,IAAI,WAAW;AACjB,YAAM,SAAS,QAAQ,OAAO,WAAW,MAAM;AAC/C,YAAM,cAAc,eAAe,OAAO,KAAK;AAE/C,UAAI,yBAAyB,YAAY,UAAU,UAAQ;AACzD,YAAI,gBAAgB,KAAK,SAAS,eAAe,KAAK,IAAK,QAAO;AAClE,YAAI,iBAAiB,KAAK,OAAO,KAAK,UAAW,QAAO;AACxD,eAAO;AAAA,MACT,CAAC;AAGD,UAAI,2BAA2B,MAAM,iBAAiB,MAAM,QAAQ;AAClE,iCAAyB,YAAY,SAAS;AAAA,MAChD;AAEA,UAAI,2BAA2B,YAAY,SAAS,GAAG;AAErD,YAAI,iBAAiB,IAAI;AACvB,cAAI,eAAe,eAAe,SAAS,GAAG;AAC5C,kBAAM,WAAW,eAAe;AAChC,4BAAgB,QAAQ;AACxB,kBAAM,WAAW,eAAe,QAAQ;AACxC,qBAAS,QAAQ;AACjB,4BAAgB,SAAS,MAAM;AAAA,UACjC,OAAO;AACL,4BAAgB,EAAE;AAClB,qBAAS,SAAS;AAClB,4BAAgB,UAAU,MAAM;AAAA,UAClC;AAAA,QACF;AAAA,MACF,OAAO;AAEL,cAAM,cAAc,YAAY,sBAAsB;AACtD,cAAM,aAAa,YAAY,yBAAyB,CAAC;AACzD,cAAM,eAAe,eAAe,YAAY;AAEhD,cAAM,YAAY,WAAW,QAAQ,KAAK,IAAI,cAAc,WAAW,MAAM,WAAW,KAAK;AAC7F,wBAAgB,SAAS;AAAA,MAC3B;AACA;AAAA,IACF;AAEA,QAAI,IAAI,WAAW;AACjB,UAAI,SAAS,IAAI,MAAM;AAGrB,YAAI,YAAY;AAChB,YAAI,YAAY,GAAG;AACjB,iBAAO,YAAY,KAAK,KAAK,KAAK,MAAM,YAAY,CAAC,CAAC,GAAG;AACvD;AAAA,UACF;AACA,iBAAO,YAAY,KAAK,CAAC,KAAK,KAAK,MAAM,YAAY,CAAC,CAAC,GAAG;AACxD;AAAA,UACF;AACA,0BAAgB,SAAS;AAAA,QAC3B;AACA;AAAA,MACF;AAEA,UAAI,IAAI,QAAS,CAAC,SAAS,IAAI,MAAO;AAOpC,YAAI,YAAY;AAChB,YAAI,YAAY,GAAG;AAEjB,iBAAO,YAAY,KAAK,KAAK,KAAK,MAAM,YAAY,CAAC,CAAC,GAAG;AACvD;AAAA,UACF;AAEA,iBAAO,YAAY,KAAK,CAAC,KAAK,KAAK,MAAM,YAAY,CAAC,CAAC,GAAG;AACxD;AAAA,UACF;AACA,0BAAgB,SAAS;AAAA,QAC3B;AACA;AAAA,MACF;AAGA,UAAI,eAAe,GAAG;AACpB,wBAAgB,eAAe,CAAC;AAAA,MAClC;AACA;AAAA,IACF;AAEA,QAAI,IAAI,YAAY;AAIlB,YAAM,sBAAsB,4BAA4B;AACxD,UAAI,uBAAuB,iBAAiB,MAAM,QAAQ;AACxD,YAAI,IAAI,QAAS,CAAC,SAAS,IAAI,MAAO;AAOpC,mBAAS,mBAAmB;AAC5B,0BAAgB,oBAAoB,MAAM;AAC1C,oCAA0B,IAAI;AAC9B,sCAA4B,IAAI;AAChC;AAAA,QACF,OAAO;AAEL,gBAAM,YAAY,oBAAoB,MAAM,MAAM,MAAM;AAExD,gBAAM,QAAQ,UAAU,MAAM,WAAW;AAEzC,cAAI,OAAO;AACT,kBAAM,QAAQ,MAAM,CAAC;AACrB,kBAAM,WAAW,QAAQ;AACzB,qBAAS,QAAQ;AACjB,4BAAgB,SAAS,MAAM;AAC/B;AAAA,UACF,WAAW,UAAU,SAAS,GAAG;AAC/B,kBAAM,WAAW,QAAQ;AACzB,qBAAS,QAAQ;AACjB,4BAAgB,SAAS,MAAM;AAC/B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,UAAI,SAAS,IAAI,MAAM;AAGrB,YAAI,YAAY;AAChB,YAAI,YAAY,MAAM,QAAQ;AAC5B,iBAAO,YAAY,MAAM,UAAU,KAAK,KAAK,MAAM,SAAS,CAAC,GAAG;AAC9D;AAAA,UACF;AACA,iBAAO,YAAY,MAAM,UAAU,CAAC,KAAK,KAAK,MAAM,SAAS,CAAC,GAAG;AAC/D;AAAA,UACF;AACA,0BAAgB,SAAS;AAAA,QAC3B;AACA;AAAA,MACF;AAEA,UAAK,CAAC,SAAS,IAAI,QAAS,IAAI,MAAM;AAGpC,YAAI,YAAY;AAChB,YAAI,YAAY,MAAM,QAAQ;AAE5B,iBAAO,YAAY,MAAM,UAAU,KAAK,KAAK,MAAM,SAAS,CAAC,GAAG;AAC9D;AAAA,UACF;AAEA,iBAAO,YAAY,MAAM,UAAU,CAAC,KAAK,KAAK,MAAM,SAAS,CAAC,GAAG;AAC/D;AAAA,UACF;AACA,0BAAgB,SAAS;AAAA,QAC3B;AACA;AAAA,MACF;AAGA,UAAI,IAAI,QAAQ,IAAI,MAAM;AAExB,YAAI,YAAY;AAChB,YAAI,YAAY,MAAM,QAAQ;AAE5B,iBAAO,YAAY,MAAM,UAAU,CAAC,KAAK,KAAK,MAAM,SAAS,CAAC,GAAG;AAC/D;AAAA,UACF;AAEA,iBAAO,YAAY,MAAM,UAAU,KAAK,KAAK,MAAM,SAAS,CAAC,GAAG;AAC9D;AAAA,UACF;AACA,0BAAgB,SAAS;AAAA,QAC3B;AAAA,MACF,WAAW,eAAe,MAAM,QAAQ;AACtC,wBAAgB,eAAe,CAAC;AAAA,MAClC;AACA;AAAA,IACF;AAGA,QAAI,IAAI,OAAO,CAAC,IAAI,OAAO;AAEzB,UAAI,aAAa;AACf,4BAAoB;AACpB;AAAA,MACF;AAAA,IACF;AAIA,QAAI,SAAS,CAAC,IAAI,QAAQ,CAAC,IAAI,MAAM;AACnC,sBAAgB;AAEhB,YAAM,eAAe,MAAM,QAAQ,SAAS,IAAI,EAAE,QAAQ,OAAO,IAAI;AAIrE,YAAM,eAAe,SAAS;AAC9B,YAAM,sBAAsB,gBAAgB;AAE5C,UAAI,WAAW;AACf,UAAI,YAAY;AAEhB,UAAI,WAAW;AACb,cAAM,QAAQ,KAAK,IAAI,UAAU,OAAO,UAAU,GAAG;AACrD,cAAM,MAAM,KAAK,IAAI,UAAU,OAAO,UAAU,GAAG;AACnD,mBAAW,aAAa,MAAM,GAAG,KAAK,IAAI,eAAe,aAAa,MAAM,GAAG;AAC/E,oBAAY,QAAQ,aAAa;AACjC,qBAAa,IAAI;AAAA,MACnB,OAAO;AACL,mBAAW,aAAa,MAAM,GAAG,mBAAmB,IAAI,eAAe,aAAa,MAAM,mBAAmB;AAC7G,oBAAY,sBAAsB,aAAa;AAAA,MACjD;AAGA,eAAS,UAAU;AACnB,sBAAgB,UAAU;AAE1B,eAAS,QAAQ;AACjB,6BAAuB,SAAS;AAGhC,sBAAgB,EAAE;AAClB,qBAAe,CAAC,CAAC;AACjB,8BAAwB,QAAQ;AAAA,IAClC;AAAA,EACF,GAAG,EAAE,SAAS,CAAC;AAEf,QAAM,sBAAsB,YAAY;AACtC,QAAI,CAAC,MAAO;AAEZ,UAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,UAAM,WAAW,MAAM,MAAM,SAAS,CAAC;AAEvC,QAAI,YAAY,SAAS,GAAG;AAC1B,YAAM,aAAa,kBAAkB,KAAK,YAAY;AACtD,yBAAmB,SAAS;AAC5B,YAAM,MAAM,SAAS,CAAC,IAAI,YAAY,SAAS;AAC/C,YAAM,WAAW,MAAM,KAAK,GAAG;AAC/B,eAAS,QAAQ;AACjB,sBAAgB,SAAS,MAAM;AAC/B;AAAA,IACF;AAEA,QAAI;AACF,YAAM,MAAM,2BAA2B,QAAQ,IAAI;AACnD,UAAI,YAAY;AAChB,UAAI,gBAAgB;AACpB,UAAI,UAAU;AAEd,UAAI,SAAS,SAAS,GAAG,KAAK,SAAS,SAAS,IAAI,GAAG;AACrD,cAAM,UAAU,KAAK,IAAI,SAAS,YAAY,GAAG,GAAG,SAAS,YAAY,IAAI,CAAC;AAC9E,kBAAU,SAAS,UAAU,GAAG,UAAU,CAAC;AAC3C,wBAAgB,SAAS,UAAU,UAAU,CAAC;AAE9C,YAAI,mBAAmB,gBAAgB,SAAS,SAAS;AACvD,sBAAY,QAAQ,WAAW,GAAG,IAAI,QAAQ,MAAM,GAAG,EAAE,IAAI,MAAM,MAAM,QAAQ,MAAM,GAAG,EAAE;AAAA,QAC9F,OAAO;AACL,sBAAY,KAAK,QAAQ,KAAK,OAAO;AAAA,QACvC;AAAA,MACF;AAEA,UAAI;AAEJ,UAAI,mBAAmB,gBAAgB,SAAS,WAAW,gBAAgB,SAAS;AAClF,cAAM,aAAa,MAAM,gBAAgB,QAAQ,cAAc,SAAS;AACxE,kBAAU,WAAW,IAAI,YAAU,EAAE,MAAM,MAAM,MAAM,MAAM,MAAM,KAAK,EAAE;AAAA,MAC5E,OAAO;AACL,YAAI,CAAC,GAAG,WAAW,SAAS,EAAG;AAC/B,cAAM,YAAY,GAAG,YAAY,WAAW,EAAE,eAAe,KAAK,CAAC;AACnE,kBAAU,UAAU,IAAI,YAAU;AAAA,UAChC,MAAM,MAAM;AAAA,UACZ,MAAM,MAAM,YAAY,IAAI,cAAc;AAAA,QAC5C,EAAE;AAAA,MACJ;AAEA,YAAM,UAAU,QACb,OAAO,WAAS,MAAM,KAAK,YAAY,EAAE,WAAW,cAAc,YAAY,CAAC,CAAC,EAChF,IAAI,WAAS;AACZ,cAAM,YAAa,mBAAmB,gBAAgB,SAAS,UAAW,MAAM,KAAK;AACrF,cAAM,WAAW,UAAU,UAAU,MAAM,OAAO,MAAM;AACxD,eAAO,MAAM,SAAS,cAAc,WAAW,YAAY;AAAA,MAC7D,CAAC,EACA,KAAK;AAER,UAAI,QAAQ,SAAS,GAAG;AACtB,YAAI,QAAQ,SAAS,GAAG;AACtB,yBAAe,OAAO;AACtB,6BAAmB,CAAC;AAAA,QACtB;AACA,cAAM,MAAM,SAAS,CAAC,IAAI,QAAQ,CAAC;AACnC,cAAM,WAAW,MAAM,KAAK,GAAG;AAC/B,iBAAS,QAAQ;AACjB,wBAAgB,SAAS,MAAM;AAAA,MACjC;AAAA,IACF,SAAS,OAAO;AAAA,IAEhB;AAAA,EACF;AAEA,QAAM,eAAe,MAAM;AACzB,QAAI,CAAC,SAAU;AAGf,QAAI,gBAAgB;AAClB,qBAAe,IAAI;AACnB,iBAAW,MAAM,eAAe,KAAK,GAAG,GAAI;AAC5C;AAAA,IACF;AAEA,UAAM,eAAe,MAAM,KAAK;AAChC,QAAI,cAAc;AAEhB,UAAI,aAAa;AACf,8BAAsB,YAAY,EAAE,WAAW,cAAc,YAAY,kBAAkB;AAAA,MAC7F;AAKA,eAAS,cAAc,wBAAwB,SAAS,IAAI,0BAA0B,MAAS;AAC/F,eAAS,EAAE;AACX,sBAAgB,CAAC;AACjB,qBAAe,CAAC,CAAC;AACjB,yBAAmB,CAAC;AACpB,sBAAgB,EAAE;AAClB,mBAAa,EAAE;AACf,mBAAa,CAAC,CAAC;AACf,mBAAa,CAAC,CAAC;AACf,mBAAa,IAAI;AACjB,gCAA0B,IAAI;AAC9B,2BAAqB,CAAC,CAAC;AACvB,iCAA2B,CAAC,CAAC;AAAA,IAC/B;AAAA,EACF;AAEA,QAAM,cAAc,MAAM;AACxB,UAAM,uBAAuB,iBACzB,mCACA,cACE,kBACA;AAIN,UAAM,aAAa,QAAQ,OAAO,WAAW,MAAM;AAGnD,UAAM,cAAc,eAAe,OAAO,SAAS;AACnD,UAAM,eAAe,MAAM,MAAM,IAAI;AAGrC,QAAI,aAAa,WAAW,KAAK,aAAa,CAAC,MAAM,IAAI;AACvD,aAAO,oCAAC,QAAK,OAAM,UAAQ,oBAAqB;AAAA,IAClD;AAIA,UAAM,QAAQ;AAGd,QAAI,aAAa;AACjB,QAAI,aAAa;AACjB,QAAI,YAAY;AAEhB,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAI,aAAa,MAAM,CAAC,EAAE,UAAU,cAAc;AAChD,qBAAa;AACb,oBAAY,eAAe;AAC3B;AAAA,MACF;AACA,oBAAc,MAAM,CAAC,EAAE,SAAS;AAAA,IAClC;AAEA,QAAI,iBAAiB,MAAM,UAAU,MAAM,SAAS,GAAG;AACrD,mBAAa,MAAM,SAAS;AAC5B,kBAAY,MAAM,MAAM,SAAS,CAAC,EAAE;AAAA,IACtC;AAGA,QAAI,mBAAmB;AACvB,aAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,UAAI,gBAAgB,YAAY,CAAC,EAAE,SAAS,gBAAgB,YAAY,CAAC,EAAE,KAAK;AAC9E,2BAAmB;AACnB;AAAA,MACF;AAAA,IACF;AAEA,QAAI,iBAAiB,MAAM,UAAU,YAAY,SAAS,GAAG;AAC3D,yBAAmB,YAAY,SAAS;AAAA,IAC1C;AAGA,UAAM,mBAAmB,YAAY;AACrC,QAAI,YAAY;AAChB,QAAI,mBAAmB,mBAAmB;AAExC,UAAI,mBAAmB,mBAAmB;AACxC,oBAAY;AAAA,MACd,OAAO;AACL,oBAAY,mBAAmB,oBAAoB;AAAA,MACrD;AAAA,IACF;AACA,UAAM,UAAU,KAAK,IAAI,YAAY,mBAAmB,gBAAgB;AAGxE,UAAM,qBAAqB,YAAY,MAAM,WAAW,OAAO;AAE/D,WACE,oCAAC,OAAI,eAAc,UAAS,UAAU,KACnC,YAAY,KAAK,oCAAC,QAAK,OAAM,UAAO,YAAK,GACzC,mBAAmB,IAAI,CAAC,OAAO,QAAQ;AACtC,YAAM,wBAAwB,YAAY;AAG1C,YAAM,WAAW,MAAM,MAAM,MAAM,OAAO,MAAM,GAAG;AACnD,YAAM,eAAe,MAAM;AAG3B,YAAM,eAAe,gBAAgB,MAAM,SAAS,gBAAgB,MAAM;AAC1E,YAAMC,aAAY,eAAe,eAAe,MAAM,QAAQ;AAG9D,YAAM,aAAa,0BAA0B,mBAAmB;AAEhE,UAAI,CAAC,UAAU;AACb,YAAI,SAAS,WAAW,GAAG;AACzB,iBAAO,oCAAC,QAAK,KAAK,OAAK,GAAC;AAAA,QAC1B;AACA,eAAO,oCAAC,QAAK,KAAK,OAAM,QAAS;AAAA,MACnC;AAGA,YAAM,QAAQ,SAAS,MAAM,EAAE;AAC/B,YAAM,gBAAgB,MAAM,IAAI,CAAC,MAAM,YAAY;AACjD,cAAM,SAAS,eAAe;AAC9B,cAAM,aAAa,aACjB,UAAU,KAAK,IAAI,UAAU,OAAO,UAAU,GAAG,KACjD,SAAS,KAAK,IAAI,UAAU,OAAO,UAAU,GAAG;AAGlD,YAAI,mBAAmB,uBAAuB,OAAO,qBAAqB;AAC1E,YAAI,uBAAuB,MAAM;AAC/B,mBAAS,IAAI,oBAAoB,IAAI,MAAM,UAAU,IAAI,cAAc,KAAK;AAC1E,gBAAI,SAAS,KAAK,MAAM,CAAC,CAAC,GAAG;AAC3B;AAAA,YACF;AACA,+BAAmB,IAAI;AAAA,UACzB;AAAA,QACF;AACA,cAAM,oBAAoB,uBAAuB,QAC/C,UAAU,sBACV,SAAS;AAGX,YAAI,uBAAuB;AAC3B,YAAI,CAAC,aAAa;AAChB,gBAAM,eAAe;AACrB,cAAI;AACJ,kBAAQ,QAAQ,aAAa,KAAK,KAAK,OAAO,MAAM;AAClD,kBAAM,YAAY,MAAM,CAAC;AACzB,kBAAM,aAAa,MAAM,CAAC;AAC1B,kBAAM,WAAW,MAAM,SAAS,UAAU,SAAS,WAAW;AAC9D,kBAAM,SAAS,WAAW,WAAW;AACrC,gBAAI,uBAAuB,QAAQ,aAAa,oBAAoB;AAClE;AAAA,YACF;AACA,gBAAI,UAAU,YAAY,SAAS,QAAQ;AACzC,qCAAuB;AACvB;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,cAAM,WAAW,gBAAgB,YAAYA;AAE7C,YAAI,UAAU;AACZ,iBAAO,oCAAC,QAAK,KAAK,SAAS,SAAO,MAAC,OAAO,aAAa,WAAW,UAAY,IAAK;AAAA,QACrF;AACA,YAAI,YAAY;AACd,iBAAO,oCAAC,QAAK,KAAK,SAAS,iBAAgB,SAAQ,OAAM,WAAS,IAAK;AAAA,QACzE;AAEA,YAAI,wBAAwB,mBAAmB;AAC7C,iBAAO,oCAAC,QAAK,KAAK,SAAS,OAAM,WAAU,MAAI,QAAE,IAAK;AAAA,QACxD;AAEA,eAAO,oCAAC,QAAK,KAAK,WAAU,IAAK;AAAA,MACnC,CAAC;AAGD,UAAI,gBAAgBA,eAAc,SAAS,QAAQ;AACjD,sBAAc,KAAK,oCAAC,QAAK,KAAI,UAAS,SAAO,QAAC,GAAC,CAAO;AAAA,MACxD;AAKA,YAAM,sBAAsB,4BAA4B;AACxD,UAAI,cAAc,uBAAuB,oBAAoB,WAAW,KAAK,GAAG;AAC9E,cAAM,SAAS,oBAAoB,MAAM,MAAM,MAAM;AACrD,YAAI,QAAQ;AAEV,gBAAM,aAAa,2BAA2B,YAAY;AAC1D,wBAAc,KAAK,oCAAC,QAAK,KAAI,SAAQ,OAAO,cAAa,MAAO,CAAO;AAAA,QACzE;AAAA,MACF;AAEA,UAAI,cAAc,WAAW,GAAG;AAC9B,eAAO,oCAAC,QAAK,KAAK,OAAK,GAAC;AAAA,MAC1B;AAEA,aAAO,oCAAC,QAAK,KAAK,OAAM,aAAc;AAAA,IACxC,CAAC,GACA,UAAU,oBAAoB,oCAAC,QAAK,OAAM,UAAO,YAAK,CACzD;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAc;AAAA,MACd,aAAY;AAAA,MACZ,aACE,cAAc,YACZ,wBAAwB;AAAA;AAAA,QACtB,iBAAiB,YACf,cAAc,YACZ;AAAA;AAAA,MAEV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,OAAM;AAAA;AAAA,IAEN,oCAAC,OAAI,SAAS,GAAG,gBAAe,iBAAgB,OAAM,UACpD,oCAAC,OAAI,YAAY,GAAG,UAAU,GAAG,eAAc,SAC5C,mBAAmB,gBAAgB,SAAS,WAC3C,oCAAC,eAAY,SAAS,iBAAiB,OAAO,sBAAsB,GAEtE,oCAAC,QAAK,OAAM,aAAU,OAAK,GAC3B,oCAAC,QAAK,OAAM,WAAU,MAAI,MAAC,MAAK,oBAAkB,UAAW,GAC5D,iBAAiB,aAAa,YAAY,KAAK,aAAa,YAAY,MACvE;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,aAAa;AAAA,QACxB,WAAW,aAAa;AAAA;AAAA,IAC1B,CAEJ,GACA,oCAAC,OAAI,YAAY,KAEd,SAAS,CAAC,eAAe,CAAC,kBACzB,oCAAC,OAAI,aAAa,KAChB,oCAAC,QAAK,OAAM,aAAU,SAAO,GAC7B,oCAAC,QAAK,OAAM,aAAW,KAAM,CAC/B,GAEF,oCAAC,WACE,qBACC,0DACE,oCAAC,QAAK,OAAM,aAAU,QAAM,GAC3B,aACC,oCAAC,YACC,oCAAC,QAAK,OAAM,WAAU,MAAI,QAAC,QAAM,GAChC,mBAAmB,YAClB,oCAAC,QAAK,OAAM,WAAU,MAAI,QAAC,UAAQ,IAEnC,oCAAC,QAAK,OAAM,aAAU,OAAK,GAE7B,oCAAC,QAAK,OAAM,WAAU,MAAI,QAAC,GAAC,CAC9B,IACE,iBACF,oCAAC,QAAK,OAAM,WAAU,MAAI,QAAC,YAAU,IACnC,cACF,oCAAC,QAAK,OAAM,WAAU,MAAI,QAAC,UAAQ,IACjC,WACF,oCAAC,QAAK,OAAM,WAAU,MAAI,QAAC,MAAI,IAE/B,oCAAC,QAAK,OAAM,aAAU,OAAK,CAE/B,CAEJ,CACF,CACF;AAAA,IAGC,wBAAwB,SAAS,KAChC,oCAAC,OAAI,cAAc,GAAG,eAAc,OAAM,UAAS,QAAO,KAAK,KAC5D,wBAAwB,IAAI,CAAC,MAAM,UAClC;AAAA,MAAC;AAAA;AAAA,QACC,KAAK,KAAK;AAAA,QACV,aAAY;AAAA,QACZ,aAAY;AAAA,QACZ,UAAU;AAAA;AAAA,MAEV,oCAAC,QAAK,OAAM,WAAU,MAAI,QAAC,SAAM,QAAQ,CAAE;AAAA,IAC7C,CACD,CACH;AAAA,IAKD,oBACC,oCAAC,OAAI,gBAAe,YAAW,cAAc,KAC3C,oCAAC,QAAK,OAAM,WAAU,MAAI,QAAC,wCACY,yBACvC,CACF;AAAA,IAIF,oCAAC,OAAI,eAAc,OAAM,OAAM,UAC7B,oCAAC,QAAK,OAAM,aAAU,IAAK,GAC1B,YAAY,CACf;AAAA,IAEA,oCAAC,OAAI,SAAS,GAAG,gBAAe,iBAAgB,OAAM,UACpD,oCAAC,QAAK,OAAM,WAAU,UAAQ,QAC3B,aACC,kBAAkB,yDAAoD,2BACpE,iBACF,6DACE,cACF,uDAEA,kBAAkB,yDAAoD,wBAE1E,GACA,oCAAC,OAAI,KAAK,KACP,gBAAgB,KACf,oCAAC,QAAK,OAAM,WAAU,MAAI,QAAC,gBAAa,eAAc,GAAC,GAExD,sBAAsB,KACrB,oCAAC,QAAK,OAAM,WAAU,MAAI,QAAC,gBAAa,qBAAoB,GAAC,GAE9D,CAAC,eAAe,CAAC,kBAAkB,YAClC,oCAAC,QAAK,OAAM,WAAU,MAAI,QAAC,YAAU,GAEtC,CAAC,eAAe,CAAC,kBAAkB,iBAClC,oCAAC,QAAK,OAAM,WAAU,MAAI,QAAC,mBAAiB,IAC1C,CAAC,eAAe,CAAC,iBACnB,oCAAC,QAAK,OAAM,WAAU,UAAQ,QAAC,oBAAkB,IAC/C,MACH,CAAC,eAAe,CAAC,kBAChB,oCAAC,OAAI,YAAY,KACf;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA;AAAA,IACF,CACF,CAEJ,CACF;AAAA,IAIE,4BAA4B,uBAAuB,KACjD;AAAA,MAAC;AAAA;AAAA,QACC,UAAU;AAAA,QACV,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,cAAc;AAAA;AAAA,IAChB;AAAA,IAMF,8BACE;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,QACP,eAAe;AAAA;AAAA,IACjB;AAAA,EAKN;AAEJ,CAAC;","names":["newValue","newCursorPos","cursorCol"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/ui/components/InputBox.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useMemo } from 'react';\r\nimport { Box, Text, useInput } from 'ink';\r\nimport * as fs from 'fs';\r\nimport * as path from 'path';\r\nimport { SubshellContext } from '../../context/types.js';\r\nimport { useConnectivity } from '../../hooks/useConnectivity.js';\r\nimport { Breadcrumbs } from './Breadcrumbs.js';\r\nimport { GitDiffBreadcrumb } from './GitDiffBreadcrumb.js';\r\nimport { ContextWindowIndicator } from './ContextWindowIndicator.js';\r\nimport { LoadingIndicator } from './LoadingIndicator.js';\r\nimport { AgentTimer } from './AgentTimer.js';\r\nimport { logDebug } from '../../utils/logger.js';\r\nimport { apiClient } from '../../services/api-client.js';\r\nimport { detectIntent } from '../../utils/input-classifier.js';\r\nimport { CommandHistoryManager } from '../../utils/command-history.js';\r\nimport { SlashCommandAutocomplete } from './SlashCommandAutocomplete.js';\r\nimport { FileTagAutocomplete } from './FileTagAutocomplete.js';\r\nimport { filterCommands, SlashCommand } from '../../config/slash-commands.js';\r\nimport { hasClipboardFile, getClipboardFiles, ClipboardFile } from '../../services/clipboard-service.js';\r\nimport { useTerminalDimensions, TERMINAL_HEIGHT_CONSTANTS } from '../../hooks/useTerminalDimensions.js';\r\nimport { AIAutocompleteAgent, AI_AUTOCOMPLETE_DEBOUNCE_MS, AutocompleteContext } from '../../services/ai-autocomplete-agent.js';\r\nimport { quickLog } from '../../utils/conversation-logger.js';\r\nimport { workflowStorage } from '../../services/workflow-storage.js';\r\nimport { rulesStorage } from '../../services/rules-storage.js';\r\nimport { skillStorage } from '../../services/skill-storage.js';\r\nimport { useTheme } from '../theme.js';\r\n\r\ninterface InputBoxProps {\r\n onSubmit: (value: string, clipboardFiles?: ClipboardFile[]) => void;\r\n placeholder?: string;\r\n autoAcceptMode: boolean;\r\n model?: string;\r\n planMode?: boolean;\r\n commandMode?: boolean;\r\n backgroundMode?: boolean; // Background shell mode for running commands in background\r\n currentWorkingDirectory?: string;\r\n commandHistory?: string[];\r\n onToggleAutoAccept: () => void;\r\n onToggleCommandMode?: () => void;\r\n onTogglePlanMode?: () => void; // Callback to toggle plan mode (Ctrl+P)\r\n onToggleBackgroundMode?: () => void; // Callback to toggle background mode\r\n isActive?: boolean;\r\n subshellContext?: SubshellContext;\r\n subshellContextStack?: SubshellContext[];\r\n currentTokens?: number;\r\n maxTokens?: number;\r\n contextLimitReached?: boolean; // True when context window is ≥80% full\r\n isShellRunning?: boolean; // Block input submission while shell command is running\r\n allowSubmitWhileShellRunning?: boolean;\r\n customTunnelCommand?: string; // Active custom tunnel command name (shown as breadcrumb)\r\n backgroundTaskCount?: number; // Number of running background tasks\r\n initialValue?: string; // Initial value to restore when component mounts (for preserving text across screen transitions)\r\n onValueChange?: (value: string) => void; // Callback when value changes (for preserving text across screen transitions)\r\n onSetAutoModeSetup?: (callback: (enabled: boolean) => void) => void; // Setup callback to control Auto mode from outside\r\n sessionQuotaExhausted?: boolean;\r\n sessionQuotaTimeRemaining?: string;\r\n subAgentCount?: number; // Number of running sub-agents\r\n aiAutoSuggestEnabled?: boolean; // Enable AI-powered command auto-suggestions\r\n sessionCommands?: string[]; // Commands executed in this chat session (for AI context)\r\n getCheckpoints?: () => Array<{ id: string; prompt: string; timestamp: Date }>; // Get checkpoints for revert autocomplete\r\n onSetInputSetup?: (callback: (value: string) => void) => void; // Setup callback to set input value from outside\r\n gitDiffStats?: { additions: number; deletions: number } | null; // Git diff stats for display in breadcrumb\r\n isAiWorking?: boolean; // Whether the AI agent is currently generating a response\r\n lastFileChangeSummary?: { filesChanged: number; insertions: number; deletions: number } | null; // File changes from last task_complete\r\n}\r\n\r\ntype MentionSuggestionKind = 'file' | 'directory' | 'rule-namespace' | 'rule';\r\n\r\ninterface MentionSuggestion {\r\n name: string;\r\n insertText: string;\r\n kind: MentionSuggestionKind;\r\n description?: string;\r\n}\r\n\r\nconst getVisualLines = (text: string, width: number) => {\r\n const logicalLines = text.split('\\n');\r\n const visualLines: Array<{ start: number; end: number; isHardEnd: boolean }> = [];\r\n let currentOffset = 0;\r\n\r\n logicalLines.forEach((line, i) => {\r\n if (line.length === 0) {\r\n visualLines.push({ start: currentOffset, end: currentOffset, isHardEnd: true });\r\n currentOffset += 1;\r\n return;\r\n }\r\n\r\n let remaining = line;\r\n let lineStartOffset = currentOffset;\r\n\r\n while (remaining.length > 0) {\r\n let splitIndex = remaining.length;\r\n let isHardEnd = false;\r\n\r\n if (remaining.length > width) {\r\n splitIndex = width;\r\n const lastSpace = remaining.lastIndexOf(' ', width);\r\n if (lastSpace > 0) {\r\n splitIndex = lastSpace + 1;\r\n }\r\n } else {\r\n isHardEnd = true;\r\n }\r\n\r\n visualLines.push({\r\n start: lineStartOffset,\r\n end: lineStartOffset + splitIndex,\r\n isHardEnd: isHardEnd\r\n });\r\n\r\n lineStartOffset += splitIndex;\r\n remaining = remaining.slice(splitIndex);\r\n }\r\n\r\n currentOffset += line.length + (i < logicalLines.length - 1 ? 1 : 0);\r\n });\r\n\r\n return visualLines;\r\n};\r\n\r\nexport const InputBox: React.FC<InputBoxProps> = React.memo(({\r\n onSubmit,\r\n placeholder = 'Ask anything ...',\r\n autoAcceptMode,\r\n model,\r\n planMode = false,\r\n commandMode = false,\r\n backgroundMode = false,\r\n currentWorkingDirectory,\r\n commandHistory = [],\r\n onToggleAutoAccept,\r\n onToggleCommandMode,\r\n onTogglePlanMode,\r\n onToggleBackgroundMode,\r\n isActive = true,\r\n subshellContext,\r\n subshellContextStack,\r\n currentTokens = 0,\r\n maxTokens = 1000000,\r\n contextLimitReached = false,\r\n isShellRunning = false,\r\n allowSubmitWhileShellRunning = false,\r\n customTunnelCommand,\r\n backgroundTaskCount = 0,\r\n initialValue = '',\r\n onValueChange,\r\n onSetAutoModeSetup,\r\n sessionQuotaExhausted = false,\r\n sessionQuotaTimeRemaining = '',\r\n subAgentCount = 0,\r\n aiAutoSuggestEnabled = false,\r\n sessionCommands = [],\r\n getCheckpoints,\r\n onSetInputSetup,\r\n gitDiffStats,\r\n isAiWorking = false,\r\n lastFileChangeSummary\r\n}) => {\r\n const theme = useTheme();\r\n\r\n // Use initialValue for first mount, but manage state internally after that\r\n const [value, setValueInternal] = useState(initialValue);\r\n const [cursorOffset, setCursorOffset] = useState(0);\r\n const [completions, setCompletions] = useState<string[]>([]);\r\n const [completionIndex, setCompletionIndex] = useState(0);\r\n const [historyIndex, setHistoryIndex] = useState(-1);\r\n const [tempValue, setTempValue] = useState('');\r\n const ignoreNextChangeRef = useRef(false);\r\n\r\n // Refs to track current value and cursor for paste handling\r\n // This prevents stale closure issues when Ink calls useInput multiple times during paste\r\n const valueRef = useRef(initialValue);\r\n const cursorOffsetRef = useRef(0);\r\n\r\n // Auto Mode State\r\n const [isAutoMode, setIsAutoMode] = useState(true);\r\n const [detectedIntent, setDetectedIntent] = useState<'command' | 'ai'>('ai');\r\n\r\n // Autocomplete State\r\n const [autocompleteSuggestion, setAutocompleteSuggestion] = useState<string | null>(null);\r\n\r\n // AI Autocomplete State\r\n const [aiAutocompleteSuggestion, setAiAutocompleteSuggestion] = useState<string | null>(null);\r\n const [isAiAutocompleteLoading, setIsAiAutocompleteLoading] = useState(false);\r\n const aiAutocompleteDebounceRef = useRef<NodeJS.Timeout | null>(null);\r\n const aiAutocompleteAbortRef = useRef<AbortController | null>(null);\r\n\r\n // Undo/Redo State\r\n const [undoStack, setUndoStack] = useState<Array<{ value: string; cursorOffset: number }>>([]);\r\n const [redoStack, setRedoStack] = useState<Array<{ value: string; cursorOffset: number }>>([]);\r\n\r\n // Selection State\r\n const [selection, setSelection] = useState<{ start: number; end: number } | null>(null);\r\n\r\n // Platform Detection\r\n const isMac = process.platform === 'darwin';\r\n\r\n // Reject Flash State (turns border red when submission is blocked)\r\n const [rejectFlash, setRejectFlash] = useState(false);\r\n\r\n // Session Quota Message State (shows quota exhausted message)\r\n const [showQuotaMessage, setShowQuotaMessage] = useState(false);\r\n\r\n // Slash Command Autocomplete State\r\n const [slashAutocompleteVisible, setSlashAutocompleteVisible] = useState(false);\r\n const [slashAutocompleteCommands, setSlashAutocompleteCommands] = useState<SlashCommand[]>([]);\r\n const [slashAutocompleteSelectedIndex, setSlashAutocompleteSelectedIndex] = useState(0);\r\n const [slashAutocompleteScrollOffset, setSlashAutocompleteScrollOffset] = useState(0);\r\n\r\n // Connectivity State\r\n const isConnected = useConnectivity();\r\n\r\n // Terminal dimensions for height-aware autocomplete\r\n const dimensions = useTerminalDimensions();\r\n // Max 5 items, min 0 for very small terminals (use MIN_ROWS_FOR_STREAMING as threshold)\r\n const slashMaxVisibleItems = dimensions.rows < TERMINAL_HEIGHT_CONSTANTS.MIN_ROWS_FOR_STREAMING\r\n ? 0\r\n : Math.min(5, Math.max(1, Math.floor((dimensions.rows - 20) / 3)));\r\n\r\n // Compact mode: when terminal height is too small for streaming, shrink\r\n // the input bar to a minimal single-line layout (no box border, just\r\n // horizontal rules with status info displayed outside the rules).\r\n const isCompactMode = !dimensions.shouldEnableStreaming;\r\n\r\n // Responsive visibility thresholds based on terminal width\r\n const showBottomHints = dimensions.columns >= 90;\r\n const showModeIndicator = dimensions.columns >= 70;\r\n\r\n // File Tag Autocomplete State (@ symbol)\r\n const [fileTagAutocompleteVisible, setFileTagAutocompleteVisible] = useState(false);\r\n const [fileTagSuggestions, setFileTagSuggestions] = useState<MentionSuggestion[]>([]);\r\n const [fileTagSelectedIndex, setFileTagSelectedIndex] = useState(0);\r\n const [activeFileTagStart, setActiveFileTagStart] = useState<number | null>(null);\r\n const [confirmedFileTags, setConfirmedFileTags] = useState<Array<{ start: number, end: number, fileName: string }>>([]);\r\n\r\n // Clipboard File State (Ctrl+V paste)\r\n const [confirmedClipboardFiles, setConfirmedClipboardFiles] = useState<ClipboardFile[]>([]);\r\n // File selection mode: -1 = not selecting, 0..n = index of selected file\r\n const [fileSelectionIndex, setFileSelectionIndex] = useState<number>(-1);\r\n\r\n // Track visual line count to force re-renders when text wraps\r\n // This is necessary because Ink doesn't automatically update layout when text wraps\r\n const [visualLineCount, setVisualLineCount] = useState(1);\r\n\r\n // Configuration for scrolling\r\n const MAX_VISIBLE_LINES = 9;\r\n\r\n // Wrapper for setValue that also notifies parent of changes and updates ref\r\n const setValue = React.useCallback((newValue: string | ((prev: string) => string)) => {\r\n setValueInternal(prev => {\r\n const resolvedValue = typeof newValue === 'function' ? newValue(prev) : newValue;\r\n // Update ref synchronously for paste handling\r\n valueRef.current = resolvedValue;\r\n // Notify parent of value change for preservation across screen transitions\r\n if (onValueChange) {\r\n onValueChange(resolvedValue);\r\n }\r\n return resolvedValue;\r\n });\r\n }, [onValueChange]);\r\n\r\n // Wrapper for setCursorOffset that also updates ref\r\n const setCursorOffsetWithRef = React.useCallback((newOffset: number | ((prev: number) => number)) => {\r\n setCursorOffset(prev => {\r\n const resolvedOffset = typeof newOffset === 'function' ? newOffset(prev) : newOffset;\r\n // Update ref synchronously for paste handling\r\n cursorOffsetRef.current = resolvedOffset;\r\n return resolvedOffset;\r\n });\r\n }, []);\r\n\r\n // Initialize cursor position when initialValue is provided\r\n useEffect(() => {\r\n if (initialValue && initialValue.length > 0) {\r\n setCursorOffset(initialValue.length);\r\n cursorOffsetRef.current = initialValue.length;\r\n }\r\n }, []); // Only run on mount\r\n\r\n // Keep refs in sync with state (for cases where state is updated directly)\r\n useEffect(() => {\r\n valueRef.current = value;\r\n }, [value]);\r\n\r\n useEffect(() => {\r\n cursorOffsetRef.current = cursorOffset;\r\n }, [cursorOffset]);\r\n\r\n // Load history on mount\r\n useEffect(() => {\r\n CommandHistoryManager.getInstance().load();\r\n }, []);\r\n\r\n // Register setInput callback for external control (e.g., for revert functionality)\r\n useEffect(() => {\r\n if (onSetInputSetup) {\r\n onSetInputSetup((newValue: string) => {\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n });\r\n }\r\n }, [onSetInputSetup, setValue, setCursorOffset]);\r\n\r\n // Register setIsAutoMode callback for external control (e.g., after background task starts)\r\n useEffect(() => {\r\n if (onSetInputSetup) {\r\n onSetInputSetup((newValue: string) => {\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n });\r\n }\r\n }, [onSetInputSetup, setValue, setCursorOffset]);\r\n\r\n useEffect(() => {\r\n if (onSetAutoModeSetup) {\r\n onSetAutoModeSetup((enabled: boolean) => {\r\n setIsAutoMode(enabled);\r\n if (enabled) {\r\n // When enabling Auto mode, also update detected intent based on current value\r\n const intent = detectIntent(value);\r\n setDetectedIntent(intent);\r\n // Set command mode based on intent\r\n if (intent === 'command' && !commandMode && onToggleCommandMode) {\r\n onToggleCommandMode();\r\n } else if (intent === 'ai' && commandMode && onToggleCommandMode) {\r\n onToggleCommandMode();\r\n }\r\n }\r\n });\r\n }\r\n }, [onSetAutoModeSetup, value, commandMode, onToggleCommandMode]);\r\n\r\n // Force clear value if it becomes empty or whitespace-only after external changes\r\n useEffect(() => {\r\n if (value && value.trim() === '' && cursorOffset > 0) {\r\n setValue('');\r\n setCursorOffset(0);\r\n }\r\n }, [value, cursorOffset]);\r\n\r\n // Track visual line count changes to force re-renders when text wraps\r\n // This is crucial for the input box height to update correctly\r\n useEffect(() => {\r\n const termWidth = (process.stdout.columns || 80) - 6;\r\n const visualLines = getVisualLines(value, termWidth);\r\n const newLineCount = Math.max(1, visualLines.length);\r\n if (newLineCount !== visualLineCount) {\r\n setVisualLineCount(newLineCount);\r\n }\r\n }, [value, visualLineCount]);\r\n\r\n // Determine current working directory — progressively shrinks as terminal narrows.\r\n // Segments shown: 3 (≥120), 2 (100–119), 1 / current dir only (<100).\r\n // The Ctrl+T and Mode hiding thresholds (90 and 70) are deliberately below 100\r\n // so the CWD is always fully reduced before other elements start disappearing.\r\n const currentDir = useMemo(() => {\r\n const cwd = currentWorkingDirectory || process.cwd();\r\n const sep = cwd.includes('/') ? '/' : '\\\\';\r\n const parts = cwd.split(/[\\\\/]/).filter(Boolean);\r\n\r\n const maxSegments = dimensions.columns >= 120 ? 3 : dimensions.columns >= 100 ? 2 : 1;\r\n\r\n if (parts.length > maxSegments) {\r\n return '...' + sep + parts.slice(-maxSegments).join(sep);\r\n }\r\n return cwd;\r\n }, [currentWorkingDirectory, dimensions.columns]);\r\n\r\n // Determine current environment for command history isolation\r\n // Format: 'local', 'ssh:user@host', or 'wsl:distroName'\r\n const currentEnvironment = useMemo(() => {\r\n if (!subshellContext) return 'local';\r\n if (subshellContext.type === 'ssh') {\r\n const user = subshellContext.metadata?.username || 'user';\r\n const host = subshellContext.metadata?.hostname || 'host';\r\n return `ssh:${user}@${host}`;\r\n }\r\n if (subshellContext.type === 'wsl') {\r\n const distro = subshellContext.metadata?.distroName || 'Ubuntu';\r\n return `wsl:${distro}`;\r\n }\r\n if (subshellContext.type === 'docker') {\r\n const container = subshellContext.metadata?.containerId || 'container';\r\n return `docker:${container}`;\r\n }\r\n return 'local';\r\n }, [subshellContext]);\r\n\r\n // Autocomplete Logic\r\n useEffect(() => {\r\n if (!value || value.trim() === '') {\r\n setAutocompleteSuggestion(null);\r\n return;\r\n }\r\n\r\n // Only show suggestions if we are in command mode (manual or auto-detected)\r\n // OR if we are in Auto mode and it looks like a command\r\n const shouldSuggest = commandMode || (isAutoMode && detectedIntent === 'command');\r\n\r\n if (shouldSuggest) {\r\n const matches = CommandHistoryManager.getInstance().getMatches(value, currentDir, currentEnvironment);\r\n if (matches.length > 0) {\r\n setAutocompleteSuggestion(matches[0]);\r\n } else {\r\n setAutocompleteSuggestion(null);\r\n }\r\n } else {\r\n setAutocompleteSuggestion(null);\r\n }\r\n }, [value, commandMode, isAutoMode, detectedIntent, aiAutoSuggestEnabled, currentDir, currentEnvironment]);\r\n\r\n // AI Autocomplete Logic (5-second debounce)\r\n\r\n useEffect(() => {\r\n // Clear AI suggestion when value changes\r\n setAiAutocompleteSuggestion(null);\r\n\r\n // Clear any existing debounce timer\r\n if (aiAutocompleteDebounceRef.current) {\r\n clearTimeout(aiAutocompleteDebounceRef.current);\r\n aiAutocompleteDebounceRef.current = null;\r\n }\r\n\r\n // Abort any pending AI request\r\n if (aiAutocompleteAbortRef.current) {\r\n aiAutocompleteAbortRef.current.abort();\r\n aiAutocompleteAbortRef.current = null;\r\n }\r\n\r\n // Debug logging for trigger ref\r\n /*\r\n try {\r\n if (detectedIntent !== 'ai' || value.length > 5) {\r\n quickLog(`[InputBox] AI Effect: val=\"${value}\", enabled=${aiAutoSuggestEnabled}, mode=${commandMode}, auto=${isAutoMode}, intent=${detectedIntent}`);\r\n }\r\n } catch (e) {}\r\n */\r\n\r\n // Don't trigger AI autocomplete if disabled or not in command mode\r\n if (!aiAutoSuggestEnabled) {\r\n // quickLog('[InputBox] AI skipped: disabled');\r\n return;\r\n }\r\n\r\n const shouldSuggest = commandMode || (isAutoMode && detectedIntent === 'command');\r\n if (!shouldSuggest) {\r\n // if (value.length > 3) quickLog(`[InputBox] AI skipped: !shouldSuggest (cmd=${commandMode}, auto=${isAutoMode}, intent=${detectedIntent})`);\r\n return;\r\n }\r\n\r\n // Don't suggest for empty, very short, or slash commands\r\n if (!value || value.trim().length < 2 || value.startsWith('/')) {\r\n // quickLog('[InputBox] AI skipped: too short or slash');\r\n return;\r\n }\r\n\r\n // quickLog('[InputBox] AI Triggering debounce...');\r\n\r\n // Set up 5-second debounce timer\r\n aiAutocompleteDebounceRef.current = setTimeout(async () => {\r\n setIsAiAutocompleteLoading(true);\r\n\r\n // Create abort controller for this request\r\n const abortController = new AbortController();\r\n aiAutocompleteAbortRef.current = abortController;\r\n\r\n try {\r\n if (!aiAutoSuggestEnabled) return; // double check inside timeout\r\n\r\n // Get directory history using the correct method\r\n const directoryHistory = CommandHistoryManager.getInstance().getDirectoryHistory(currentDir, currentEnvironment);\r\n\r\n // Get files in current directory (local or remote)\r\n let files: string[] = [];\r\n try {\r\n if (subshellContext && subshellContext.type !== 'local' && subshellContext.handler) {\r\n // Remote/Subshell environment\r\n // Check if we can list files\r\n try {\r\n const dirEntries = await subshellContext.handler.listDirectory(currentDir);\r\n files = dirEntries\r\n .slice(0, 50)\r\n .map((e: any) => e.name + (e.type === 'directory' ? '/' : ''));\r\n } catch (remoteErr) {\r\n // quickLog('Remote list error: ' + remoteErr);\r\n }\r\n } else {\r\n // Local environment\r\n const dir = currentDir || process.cwd();\r\n if (fs.existsSync(dir)) {\r\n const entries = fs.readdirSync(dir, { withFileTypes: true });\r\n files = entries\r\n .slice(0, 50)\r\n .map(e => e.name + (e.isDirectory() ? '/' : ''));\r\n }\r\n }\r\n } catch (e) {\r\n // Ignore file access errors\r\n }\r\n\r\n // Determine OS and Platform from subshell context if available\r\n let osContext = process.platform;\r\n let platformContext = process.platform;\r\n\r\n if (subshellContext && subshellContext.type !== 'local' && subshellContext.metadata) {\r\n const metaOs = subshellContext.metadata.os;\r\n if (metaOs === 'windows') {\r\n osContext = 'win32';\r\n platformContext = 'win32';\r\n } else if (metaOs === 'macos') {\r\n osContext = 'darwin';\r\n platformContext = 'darwin';\r\n } else if (metaOs === 'linux') {\r\n osContext = 'linux';\r\n platformContext = 'linux';\r\n }\r\n }\r\n\r\n const context: AutocompleteContext = {\r\n os: osContext,\r\n platform: platformContext,\r\n cwd: currentDir || process.cwd(),\r\n directoryHistory: directoryHistory.slice(0, 10),\r\n sessionCommands: sessionCommands.slice(-10),\r\n files: files,\r\n currentInput: value\r\n };\r\n\r\n const prediction = await AIAutocompleteAgent.predictCommand(context, abortController.signal);\r\n\r\n if (prediction && !abortController.signal.aborted) {\r\n setAiAutocompleteSuggestion(prediction);\r\n }\r\n } catch (error) {\r\n // Ignore errors (likely aborted)\r\n } finally {\r\n setIsAiAutocompleteLoading(false);\r\n if (aiAutocompleteAbortRef.current === abortController) {\r\n aiAutocompleteAbortRef.current = null;\r\n }\r\n }\r\n }, AI_AUTOCOMPLETE_DEBOUNCE_MS);\r\n\r\n return () => {\r\n if (aiAutocompleteDebounceRef.current) {\r\n clearTimeout(aiAutocompleteDebounceRef.current);\r\n }\r\n if (aiAutocompleteAbortRef.current) {\r\n aiAutocompleteAbortRef.current.abort();\r\n }\r\n };\r\n }, [value, commandMode, isAutoMode, detectedIntent, aiAutoSuggestEnabled, currentDir, currentEnvironment, sessionCommands]);\r\n\r\n // Auto-classification effect (Synchronous Heuristics Only)\r\n useEffect(() => {\r\n // Only run classification if in Auto Mode\r\n if (!isAutoMode) {\r\n return;\r\n }\r\n\r\n // Only classify if value is non-empty and not just whitespace\r\n const trimmedValue = value.trim();\r\n if (!trimmedValue || !onToggleCommandMode) {\r\n // Default to AI if empty\r\n setDetectedIntent('ai');\r\n if (commandMode) onToggleCommandMode();\r\n return;\r\n }\r\n\r\n // Run local heuristic detection immediately\r\n const intent = detectIntent(trimmedValue);\r\n setDetectedIntent(intent);\r\n\r\n // Switch mode based on intent\r\n if (intent === 'command') {\r\n if (!commandMode) onToggleCommandMode();\r\n } else {\r\n // intent === 'ai'\r\n if (commandMode) onToggleCommandMode();\r\n }\r\n }, [value, commandMode, onToggleCommandMode, isAutoMode]);\r\n\r\n const showSlashAutocomplete = React.useCallback((commands: SlashCommand[]) => {\r\n if (commands.length > 0) {\r\n setSlashAutocompleteCommands(commands);\r\n setSlashAutocompleteVisible(true);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n }, []);\r\n\r\n const getRuleNameAutocompleteEntries = React.useCallback((partialName: string): SlashCommand[] => {\r\n const normalized = partialName.toLowerCase();\r\n const rules = rulesStorage.list();\r\n\r\n if (rules.length === 0) {\r\n return [{\r\n name: '(no rules)',\r\n description: 'Create one with /rules add'\r\n }];\r\n }\r\n\r\n const matches = rules\r\n .filter(rule => rule.name.toLowerCase().includes(normalized))\r\n .slice(0, 10)\r\n .map(rule => ({\r\n name: rule.name,\r\n description: rule.preview || 'Saved rule'\r\n }));\r\n\r\n if (matches.length === 0) {\r\n return [{\r\n name: '(no matches)',\r\n description: 'No saved rules match that name'\r\n }];\r\n }\r\n\r\n return matches;\r\n }, []);\r\n\r\n const updateSlashAutocomplete = React.useCallback((nextValue: string) => {\r\n // Handle # skill autocomplete\r\n if (nextValue.startsWith('#')) {\r\n const query = nextValue.slice(1).split(/\\s+/)[0].toLowerCase();\r\n // Only show dropdown before the first space (while typing the skill name)\r\n if (!nextValue.includes(' ')) {\r\n const skills = skillStorage.list();\r\n const matches: SlashCommand[] = skills\r\n .filter(s => s.name.toLowerCase().startsWith(query) || s.name.toLowerCase().includes(query))\r\n .map(s => ({ name: s.name, description: `${s.accessLevel} — ${s.promptPreview}` }));\r\n if (matches.length > 0 || query.length === 0) {\r\n showSlashAutocomplete(matches.length > 0 ? matches : [{ name: '(no skills)', description: 'Use /skill new to create one' }]);\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n return;\r\n }\r\n\r\n if (!nextValue.startsWith('/')) {\r\n setSlashAutocompleteVisible(false);\r\n return;\r\n }\r\n\r\n if (!nextValue.includes(' ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/mcp ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/chat ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/add-command ') || nextValue.startsWith('/add-command-auto-detect ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/background-task ') || nextValue.startsWith('/bkg ') || nextValue.startsWith('/bg-task ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/sync ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/models ') || nextValue.startsWith('/model ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/settings auto-suggest ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/settings limit-chat-history ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/settings ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/revert ')) {\r\n const partialId = nextValue.slice(8).toLowerCase();\r\n const checkpoints = getCheckpoints ? getCheckpoints() : [];\r\n\r\n if (checkpoints.length === 0) {\r\n showSlashAutocomplete([{\r\n name: '(no checkpoints)',\r\n description: 'Ask AI a question first to create a checkpoint'\r\n }]);\r\n return;\r\n }\r\n\r\n const checkpointCommands: SlashCommand[] = checkpoints\r\n .filter(cp => cp.id.toLowerCase().includes(partialId) || cp.prompt.toLowerCase().includes(partialId))\r\n .slice(0, 10)\r\n .map(cp => ({\r\n name: cp.id,\r\n description: cp.prompt.length > 50 ? cp.prompt.slice(0, 50) + '...' : cp.prompt\r\n }));\r\n\r\n showSlashAutocomplete(checkpointCommands);\r\n return;\r\n }\r\n\r\n if (nextValue.match(/^\\/rules\\s+(edit|delete)\\s+/)) {\r\n const match = nextValue.match(/^\\/rules\\s+(?:edit|delete)\\s+(.*)$/);\r\n const partialName = match ? match[1] : '';\r\n showSlashAutocomplete(getRuleNameAutocompleteEntries(partialName));\r\n return;\r\n }\r\n\r\n if (nextValue.match(/^\\/skill\\s+(edit|delete|rm)\\s+/)) {\r\n const match = nextValue.match(/^\\/skill\\s+(?:edit|delete|rm)\\s+(.*)$/);\r\n const partialName = (match ? match[1] : '').toLowerCase();\r\n const skills = skillStorage.list();\r\n const matchingSkills: SlashCommand[] = skills\r\n .filter(s => s.name.toLowerCase().includes(partialName))\r\n .slice(0, 10)\r\n .map(s => ({ name: s.name, description: `${s.accessLevel} — ${s.promptPreview}` }));\r\n showSlashAutocomplete(matchingSkills.length > 0 ? matchingSkills : [{ name: '(no skills)', description: 'Use /skill new to create one' }]);\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/skill ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/rules ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (\r\n nextValue.match(/^\\/workflow\\s+(run|view|delete)\\s+/) ||\r\n nextValue.match(/^\\/wf\\s+(run|view|delete)\\s+/)\r\n ) {\r\n const match = nextValue.match(/^\\/(?:workflow|wf)\\s+(?:run|view|delete)\\s+(.*)$/);\r\n const partialName = match ? match[1].toLowerCase() : '';\r\n const workflows = workflowStorage.list();\r\n const matchingWorkflows: SlashCommand[] = workflows\r\n .filter(wf => wf.name.toLowerCase().includes(partialName))\r\n .slice(0, 10)\r\n .map(wf => ({\r\n name: wf.name,\r\n description: wf.description || `${wf.stepCount} step${wf.stepCount !== 1 ? 's' : ''}`\r\n }));\r\n\r\n showSlashAutocomplete(matchingWorkflows);\r\n return;\r\n }\r\n\r\n if (\r\n nextValue.match(/^\\/workflow\\s+new\\s+/) ||\r\n nextValue.match(/^\\/wf\\s+new\\s+/)\r\n ) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n if (nextValue.startsWith('/workflow ') || nextValue.startsWith('/wf ')) {\r\n showSlashAutocomplete(filterCommands(nextValue.slice(1)));\r\n return;\r\n }\r\n\r\n setSlashAutocompleteVisible(false);\r\n }, [getCheckpoints, getRuleNameAutocompleteEntries, showSlashAutocomplete]);\r\n\r\n const getMatchingFiles = React.useCallback((query: string): MentionSuggestion[] => {\r\n try {\r\n const cwd = currentWorkingDirectory || process.cwd();\r\n if (!fs.existsSync(cwd)) return [];\r\n\r\n const lowerQuery = query.toLowerCase();\r\n const results: MentionSuggestion[] = [];\r\n\r\n // Directories to skip when recursing\r\n const SKIP_DIRS = new Set([\r\n '.git', 'node_modules', 'dist', 'build', '.next', '__pycache__',\r\n '.cache', 'coverage', '.nyc_output', '.turbo', 'out', '.svelte-kit'\r\n ]);\r\n\r\n // When query is empty, show only top-level entries for a clean initial view\r\n if (lowerQuery === '') {\r\n let entries: fs.Dirent[];\r\n try { entries = fs.readdirSync(cwd, { withFileTypes: true }); } catch { return []; }\r\n for (const entry of entries) {\r\n if (entry.name.startsWith('.')) continue;\r\n results.push({\r\n name: entry.name,\r\n insertText: entry.isDirectory() ? `${entry.name}/` : entry.name,\r\n kind: entry.isDirectory() ? 'directory' as const : 'file' as const\r\n });\r\n }\r\n results.sort((a, b) => a.name.localeCompare(b.name));\r\n return results.slice(0, 15);\r\n }\r\n\r\n // For a non-empty query, recursively walk the entire CWD and return\r\n // all matching relative paths (e.g. \"src/components/App.tsx\")\r\n const walk = (dir: string, relativePath: string, depth: number) => {\r\n if (depth > 6 || results.length >= 60) return;\r\n let entries: fs.Dirent[];\r\n try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }\r\n\r\n for (const entry of entries) {\r\n if (entry.name.startsWith('.')) continue;\r\n const entryRelPath = relativePath ? `${relativePath}/${entry.name}` : entry.name;\r\n const lowerRelPath = entryRelPath.toLowerCase();\r\n const lowerBasename = entry.name.toLowerCase();\r\n\r\n if (entry.isDirectory()) {\r\n if (SKIP_DIRS.has(entry.name)) continue;\r\n // Include directory if any part of its relative path matches the query\r\n if (lowerRelPath.includes(lowerQuery) || lowerBasename.includes(lowerQuery)) {\r\n results.push({\r\n name: entryRelPath,\r\n insertText: `${entryRelPath}/`,\r\n kind: 'directory' as const\r\n });\r\n }\r\n walk(path.join(dir, entry.name), entryRelPath, depth + 1);\r\n } else {\r\n if (lowerRelPath.includes(lowerQuery) || lowerBasename.includes(lowerQuery)) {\r\n results.push({\r\n name: entryRelPath,\r\n insertText: entryRelPath,\r\n kind: 'file' as const\r\n });\r\n }\r\n }\r\n }\r\n };\r\n\r\n walk(cwd, '', 0);\r\n\r\n // Sort: exact basename prefix match first, then shallower paths, then alphabetical\r\n results.sort((a, b) => {\r\n const aBasename = a.name.split('/').pop()!.toLowerCase();\r\n const bBasename = b.name.split('/').pop()!.toLowerCase();\r\n const aStartsBasename = aBasename.startsWith(lowerQuery);\r\n const bStartsBasename = bBasename.startsWith(lowerQuery);\r\n const aStartsFull = a.name.toLowerCase().startsWith(lowerQuery);\r\n const bStartsFull = b.name.toLowerCase().startsWith(lowerQuery);\r\n\r\n if ((aStartsFull || aStartsBasename) && !(bStartsFull || bStartsBasename)) return -1;\r\n if (!(aStartsFull || aStartsBasename) && (bStartsFull || bStartsBasename)) return 1;\r\n\r\n // Shallower paths first\r\n const aDepth = a.name.split('/').length;\r\n const bDepth = b.name.split('/').length;\r\n if (aDepth !== bDepth) return aDepth - bDepth;\r\n\r\n return a.name.localeCompare(b.name);\r\n });\r\n\r\n return results.slice(0, 15);\r\n } catch (error) {\r\n return [];\r\n }\r\n }, [currentWorkingDirectory]);\r\n\r\n const getMatchingMentionSuggestions = React.useCallback((query: string): MentionSuggestion[] => {\r\n const normalized = query.toLowerCase();\r\n\r\n if (normalized.startsWith('rules:')) {\r\n const ruleQuery = query.slice('rules:'.length).toLowerCase();\r\n return rulesStorage.list()\r\n .filter(rule => rule.name.toLowerCase().includes(ruleQuery))\r\n .slice(0, 10)\r\n .map(rule => ({\r\n name: `rules:${rule.name}`,\r\n insertText: `rules:${rule.name}`,\r\n kind: 'rule' as const,\r\n description: rule.preview || 'Saved rule'\r\n }));\r\n }\r\n\r\n const suggestions: MentionSuggestion[] = [];\r\n if ('rules:'.startsWith(normalized) || normalized.startsWith('rules')) {\r\n suggestions.push({\r\n name: 'rules:',\r\n insertText: 'rules:',\r\n kind: 'rule-namespace',\r\n description: 'Insert a saved reusable rule'\r\n });\r\n }\r\n\r\n return [...suggestions, ...getMatchingFiles(query)].slice(0, 15);\r\n }, [getMatchingFiles]);\r\n\r\n // File tag (@) detection effect — supports both @path and @\"path with spaces\"\r\n useEffect(() => {\r\n // Don't show file tag autocomplete in command mode\r\n if (commandMode) {\r\n setFileTagAutocompleteVisible(false);\r\n return;\r\n }\r\n\r\n // Find if cursor is within a potential file tag\r\n // Look backwards from cursor to find @ — support quoted paths @\"...\"\r\n let atPosition = -1;\r\n let isQuoted = false;\r\n\r\n // Check for quoted form: @\"...\"\r\n // Scan backwards looking for a pattern like @\" ... cursor\r\n for (let i = cursorOffset - 1; i >= 0; i--) {\r\n const char = value[i];\r\n if (char === '\"' && i > 0 && value[i - 1] === '@') {\r\n // Found opening @\"\r\n atPosition = i - 1;\r\n isQuoted = true;\r\n break;\r\n }\r\n if (char === '@') {\r\n // Check if next char is \" for quoted form at cursor\r\n if (i + 1 < value.length && value[i + 1] === '\"') {\r\n atPosition = i;\r\n isQuoted = true;\r\n } else {\r\n atPosition = i;\r\n }\r\n break;\r\n }\r\n // For unquoted paths, stop at whitespace\r\n if (!isQuoted && /[\\s\\n]/.test(char)) break;\r\n }\r\n\r\n // Only treat @ as file tag if it's at start of input OR preceded by whitespace\r\n if (atPosition === -1 || (atPosition > 0 && !/[\\s\\n]/.test(value[atPosition - 1]))) {\r\n setFileTagAutocompleteVisible(false);\r\n setActiveFileTagStart(null);\r\n return;\r\n }\r\n\r\n // Extract the query after @ (strip quotes if present)\r\n let query: string;\r\n if (isQuoted) {\r\n // @\"query...\" — skip the @\" prefix\r\n query = value.slice(atPosition + 2, cursorOffset).replace(/^\"/, '');\r\n } else {\r\n query = value.slice(atPosition + 1, cursorOffset);\r\n }\r\n\r\n const matches = getMatchingMentionSuggestions(query);\r\n\r\n if (matches.length > 0) {\r\n setFileTagSuggestions(matches);\r\n setFileTagAutocompleteVisible(true);\r\n setActiveFileTagStart(atPosition);\r\n setFileTagSelectedIndex(0);\r\n } else {\r\n setFileTagAutocompleteVisible(false);\r\n setActiveFileTagStart(null);\r\n }\r\n }, [value, cursorOffset, commandMode, currentWorkingDirectory, getMatchingMentionSuggestions]);\r\n\r\n const pushToUndoStack = () => {\r\n setUndoStack(prev => [...prev, { value, cursorOffset }]);\r\n setRedoStack([]); // Clear redo stack on new action\r\n };\r\n\r\n const handleUndo = () => {\r\n if (undoStack.length === 0) return;\r\n const previousState = undoStack[undoStack.length - 1];\r\n setRedoStack(prev => [...prev, { value, cursorOffset }]);\r\n setUndoStack(prev => prev.slice(0, -1));\r\n setValue(previousState.value);\r\n setCursorOffset(previousState.cursorOffset);\r\n setSelection(null);\r\n };\r\n\r\n const applyMentionSuggestion = (selected: MentionSuggestion, viaTab: boolean) => {\r\n if (activeFileTagStart === null) {\r\n return;\r\n }\r\n\r\n pushToUndoStack();\r\n\r\n const beforeTag = value.slice(0, activeFileTagStart);\r\n const afterCursor = value.slice(cursorOffset);\r\n\r\n // Quote the insertText if it contains spaces\r\n const needsQuotes = /\\s/.test(selected.insertText);\r\n const insertStr = needsQuotes ? `\"${selected.insertText}\"` : selected.insertText;\r\n const baseValue = beforeTag + '@' + insertStr;\r\n const insertLen = 1 + insertStr.length; // @ + insertStr\r\n\r\n if (selected.kind === 'rule-namespace') {\r\n const newValue = baseValue + afterCursor;\r\n const newCursorPos = activeFileTagStart + insertLen;\r\n setValue(newValue);\r\n setCursorOffset(newCursorPos);\r\n return;\r\n }\r\n\r\n if (viaTab && selected.kind === 'directory') {\r\n const newValue = baseValue + afterCursor;\r\n const newCursorPos = activeFileTagStart + insertLen;\r\n setValue(newValue);\r\n setCursorOffset(newCursorPos);\r\n return;\r\n }\r\n\r\n const trailingSuffix = viaTab ? '' : ' ';\r\n const newValue = baseValue + trailingSuffix + afterCursor;\r\n const newCursorPos = activeFileTagStart + insertLen + trailingSuffix.length;\r\n\r\n setValue(newValue);\r\n setCursorOffset(newCursorPos);\r\n\r\n setConfirmedFileTags(prev => [\r\n ...prev.filter(tag =>\r\n !(tag.start >= activeFileTagStart && tag.start <= cursorOffset)\r\n ),\r\n {\r\n start: activeFileTagStart,\r\n end: activeFileTagStart + insertLen,\r\n fileName: selected.name\r\n }\r\n ]);\r\n\r\n setFileTagAutocompleteVisible(false);\r\n setActiveFileTagStart(null);\r\n };\r\n\r\n useInput((input, key) => {\r\n if (!isActive) return;\r\n\r\n // Detect OS for platform-specific key handling\r\n const isWindows = process.platform === 'win32';\r\n const inputCharCode = input ? input.charCodeAt(0) : null;\r\n const normalizedInput = input ? input.toLowerCase() : '';\r\n\r\n // Shift+Enter may arrive as terminal remap sequences instead of key.shift.\r\n // Handle common variants used by iTerm/Kitty/VS Code keybinding remaps.\r\n const isTerminalShiftEnterSequence =\r\n input === '\\u001b\\r' ||\r\n input === '\\u001b\\n' ||\r\n normalizedInput === '\\u001b[13;2u' ||\r\n normalizedInput === '\\u001b[13;2~' ||\r\n normalizedInput === '\\u001b[27;2;13~';\r\n const isEnterEvent = key.return || isTerminalShiftEnterSequence;\r\n\r\n // macOS Option+Arrow often arrives as ESC-prefixed sequences.\r\n // Handle these explicitly without changing any existing backspace/delete behavior.\r\n const isMacOptionWordBackwardSequence = isMac && (\r\n normalizedInput === '\\u001bb' ||\r\n normalizedInput === '\\u001b[1;3d' ||\r\n normalizedInput === '\\u001b[1;9d' ||\r\n (key.meta && normalizedInput === 'b') ||\r\n (key.escape && key.leftArrow)\r\n );\r\n const isMacOptionWordForwardSequence = isMac && (\r\n normalizedInput === '\\u001bf' ||\r\n normalizedInput === '\\u001b[1;3c' ||\r\n normalizedInput === '\\u001b[1;9c' ||\r\n (key.meta && normalizedInput === 'f') ||\r\n (key.escape && key.rightArrow)\r\n );\r\n\r\n // Handle slash command autocomplete navigation\r\n if (slashAutocompleteVisible) {\r\n if (key.downArrow) {\r\n const newIndex = Math.min(slashAutocompleteSelectedIndex + 1, slashAutocompleteCommands.length - 1);\r\n setSlashAutocompleteSelectedIndex(newIndex);\r\n // Scroll down if selected is below visible window\r\n if (newIndex >= slashAutocompleteScrollOffset + slashMaxVisibleItems) {\r\n setSlashAutocompleteScrollOffset(newIndex - slashMaxVisibleItems + 1);\r\n }\r\n return;\r\n }\r\n\r\n if (key.upArrow) {\r\n const newIndex = Math.max(slashAutocompleteSelectedIndex - 1, 0);\r\n setSlashAutocompleteSelectedIndex(newIndex);\r\n // Scroll up if selected is above visible window\r\n if (newIndex < slashAutocompleteScrollOffset) {\r\n setSlashAutocompleteScrollOffset(newIndex);\r\n }\r\n return;\r\n }\r\n\r\n if (key.return && input.length <= 1 && !key.shift && !key.ctrl && !key.meta) {\r\n // Select the highlighted command\r\n const selected = slashAutocompleteCommands[slashAutocompleteSelectedIndex];\r\n if (!selected || selected.name.startsWith('(no ')) {\r\n setSlashAutocompleteVisible(false);\r\n return;\r\n }\r\n\r\n // Handle # skill selection\r\n if (value.startsWith('#')) {\r\n const newValue = `#${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n return;\r\n }\r\n\r\n // Check if we're in MCP subcommand mode\r\n if (value.startsWith('/mcp ')) {\r\n // We're selecting an MCP subcommand, keep \"/mcp \" and append the subcommand\r\n const newValue = `/mcp ${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/chat ')) {\r\n // We're selecting a chat subcommand, keep \"/chat \" and append the subcommand\r\n const newValue = `/chat ${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/add-command ') || value.startsWith('/add-command-auto-detect ')) {\r\n // We're selecting an add-command subcommand\r\n const prefix = value.startsWith('/add-command-auto-detect ') ? '/add-command-auto-detect ' : '/add-command ';\r\n const newValue = `${prefix}${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/background-task ') || value.startsWith('/bkg ') || value.startsWith('/bg-task ')) {\r\n // We're selecting a background-task subcommand\r\n const prefix = value.startsWith('/bkg ') ? '/bkg ' : (value.startsWith('/bg-task ') ? '/bg-task ' : '/background-task ');\r\n const newValue = `${prefix}${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/sync ')) {\r\n // We're selecting a sync subcommand\r\n const newValue = `/sync ${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/revert ')) {\r\n // We're selecting a checkpoint from /revert dropdown\r\n const newValue = `/revert ${selected.name}`;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/models ') || value.startsWith('/model ')) {\r\n // We're selecting a models subcommand\r\n const prefix = value.startsWith('/models ') ? '/models ' : '/model ';\r\n const newValue = `${prefix}${selected.name}`;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/rules ')) {\r\n const ruleNameMatch = value.match(/^\\/rules\\s+(edit|delete)\\s+/);\r\n if (ruleNameMatch) {\r\n const prefix = value.match(/^\\/rules\\s+(?:edit|delete)\\s+/)?.[0] || '';\r\n const newValue = `${prefix}${selected.name}`;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else {\r\n const newValue = `/rules ${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n\r\n if (selected.name === 'edit' || selected.name === 'delete') {\r\n const ruleMatches = getRuleNameAutocompleteEntries('');\r\n if (ruleMatches.length > 0) {\r\n setSlashAutocompleteCommands(ruleMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n }\r\n } else if (value.startsWith('/workflow new ') || value.startsWith('/wf new ')) {\r\n // We're in workflow new subcommand mode (manual or learn-workflow)\r\n const prefix = value.startsWith('/workflow new ') ? '/workflow new ' : '/wf new ';\r\n const newValue = `${prefix}${selected.name}`;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/workflow ') || value.startsWith('/wf ')) {\r\n // Check if we're in workflow name selection mode (after run/view/delete)\r\n const workflowNameMatch = value.match(/^\\/(?:workflow|wf)\\s+(run|view|delete)\\s+/);\r\n if (workflowNameMatch) {\r\n // We're selecting a workflow name\r\n const prefix = value.match(/^\\/(?:workflow|wf)\\s+(?:run|view|delete)\\s+/)?.[0] || '';\r\n const newValue = `${prefix}${selected.name}`;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else {\r\n // We're selecting a workflow subcommand\r\n const prefix = value.startsWith('/workflow ') ? '/workflow ' : '/wf ';\r\n const newValue = `${prefix}${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n\r\n // For run/view/delete, show workflow names immediately\r\n if (selected.name === 'run' || selected.name === 'view' || selected.name === 'delete') {\r\n const workflows = workflowStorage.list();\r\n const matchingWorkflows: SlashCommand[] = workflows\r\n .slice(0, 10)\r\n .map(wf => ({\r\n name: wf.name,\r\n description: wf.description || `${wf.stepCount} step${wf.stepCount !== 1 ? 's' : ''}`\r\n }));\r\n\r\n if (matchingWorkflows.length > 0) {\r\n setSlashAutocompleteCommands(matchingWorkflows);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'new') {\r\n // For 'new' subcommand, show manual/learn-workflow options\r\n const subcommandMatches = filterCommands('workflow new ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible for next level\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n }\r\n } else if (value.startsWith('/sub-agent ') || value.startsWith('/subagent ')) {\r\n // We're selecting a sub-agent subcommand\r\n const prefix = value.startsWith('/sub-agent ') ? '/sub-agent ' : '/subagent ';\r\n const newValue = `${prefix}${selected.name}`;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/skill edit ') || value.startsWith('/skill delete ') || value.startsWith('/skill rm ')) {\r\n // We're selecting a skill name for edit/delete\r\n const prefix = value.match(/^\\/skill\\s+(?:edit|delete|rm)\\s+/)?.[0] || '/skill edit ';\r\n const newValue = `${prefix}${selected.name}`;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/skill ')) {\r\n // We're selecting a skill subcommand\r\n const newValue = `/skill ${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n\r\n // For edit/delete, show skill names immediately\r\n if (selected.name === 'edit' || selected.name === 'delete') {\r\n const skills = skillStorage.list();\r\n const skillMatches: SlashCommand[] = skills.map(s => ({\r\n name: s.name,\r\n description: `${s.accessLevel} — ${s.promptPreview}`,\r\n }));\r\n if (skillMatches.length > 0) {\r\n setSlashAutocompleteCommands(skillMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (value.startsWith('/settings theme ')) {\r\n // We're selecting a theme color option\r\n const newValue = `/settings theme ${selected.name}`;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/settings auto-suggest ')) {\r\n // We're selecting an auto-suggest option (on/off)\r\n const newValue = `/settings auto-suggest ${selected.name}`;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/settings limit-chat-history ')) {\r\n const newValue = `/settings limit-chat-history ${selected.name}`;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n setSlashAutocompleteVisible(false);\r\n } else if (value.startsWith('/settings ')) {\r\n // We're selecting a settings subcommand (e.g., auto-suggest)\r\n const newValue = `/settings ${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n // Show the next level options (on/off for auto-suggest, colors for theme)\r\n if (selected.name === 'auto-suggest') {\r\n const optionMatches = filterCommands('settings auto-suggest ');\r\n if (optionMatches.length > 0) {\r\n setSlashAutocompleteCommands(optionMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'limit-chat-history') {\r\n const optionMatches = filterCommands('settings limit-chat-history ');\r\n if (optionMatches.length > 0) {\r\n setSlashAutocompleteCommands(optionMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'theme') {\r\n const themeMatches = filterCommands('settings theme ');\r\n if (themeMatches.length > 0) {\r\n setSlashAutocompleteCommands(themeMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else {\r\n // Regular slash command, replace everything\r\n const newValue = `/${selected.name} `;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n\r\n // Check if this command has subcommands (e.g., /mcp, /chat, /add-command)\r\n // If so, immediately show the subcommand list\r\n if (selected.name === 'mcp') {\r\n const subcommandMatches = filterCommands('mcp ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible for subcommands\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'chat') {\r\n const subcommandMatches = filterCommands('chat ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible for subcommands\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'add-command' || selected.name === 'add-command-auto-detect') {\r\n const subcommandMatches = filterCommands('add-command ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible for subcommands\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'background-task' || selected.name === 'bkg' || selected.name === 'bg-task') {\r\n const subcommandMatches = filterCommands('background-task ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible for subcommands\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'sync') {\r\n const subcommandMatches = filterCommands('sync ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible for subcommands\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'models' || selected.name === 'model') {\r\n const subcommandMatches = filterCommands('models ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible for subcommands\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'settings') {\r\n const subcommandMatches = filterCommands('settings ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible for subcommands\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'workflow' || selected.name === 'wf') {\r\n const subcommandMatches = filterCommands('workflow ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible for subcommands\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'rules') {\r\n const subcommandMatches = filterCommands('rules ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'sub-agent' || selected.name === 'subagent') {\r\n const subcommandMatches = filterCommands('sub-agent ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'skill') {\r\n const subcommandMatches = filterCommands('skill ');\r\n if (subcommandMatches.length > 0) {\r\n setSlashAutocompleteCommands(subcommandMatches);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n } else if (selected.name === 'revert') {\r\n // For revert, show checkpoints immediately\r\n const checkpoints = getCheckpoints ? getCheckpoints() : [];\r\n if (checkpoints.length === 0) {\r\n setSlashAutocompleteCommands([{\r\n name: '(no checkpoints)',\r\n description: 'Ask AI a question first to create a checkpoint'\r\n }]);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible\r\n } else {\r\n const checkpointCommands: SlashCommand[] = checkpoints\r\n .slice(0, 10)\r\n .map(cp => {\r\n const truncatedPrompt = cp.prompt.length > 50 ? cp.prompt.slice(0, 50) + '...' : cp.prompt;\r\n return {\r\n name: cp.id,\r\n description: truncatedPrompt\r\n };\r\n });\r\n setSlashAutocompleteCommands(checkpointCommands);\r\n setSlashAutocompleteSelectedIndex(0);\r\n setSlashAutocompleteScrollOffset(0);\r\n // Keep autocomplete visible\r\n }\r\n } else {\r\n setSlashAutocompleteVisible(false);\r\n }\r\n }\r\n return;\r\n }\r\n\r\n if (key.escape) {\r\n setSlashAutocompleteVisible(false);\r\n return;\r\n }\r\n }\r\n\r\n // Handle file tag (@) autocomplete navigation\r\n if (fileTagAutocompleteVisible) {\r\n if (key.downArrow) {\r\n setFileTagSelectedIndex(prev =>\r\n Math.min(prev + 1, fileTagSuggestions.length - 1)\r\n );\r\n return;\r\n }\r\n\r\n if (key.upArrow) {\r\n setFileTagSelectedIndex(prev => Math.max(prev - 1, 0));\r\n return;\r\n }\r\n\r\n if (key.return && input.length <= 1 && !key.shift && !key.ctrl && !key.meta) {\r\n // Select the highlighted file\r\n const selected = fileTagSuggestions[fileTagSelectedIndex];\r\n if (selected && activeFileTagStart !== null) {\r\n applyMentionSuggestion(selected, false);\r\n }\r\n return;\r\n }\r\n\r\n if (key.escape) {\r\n setFileTagAutocompleteVisible(false);\r\n setActiveFileTagStart(null);\r\n return;\r\n }\r\n\r\n // If Tab is pressed, also select the current file\r\n if (key.tab && !key.shift) {\r\n const selected = fileTagSuggestions[fileTagSelectedIndex];\r\n if (selected && activeFileTagStart !== null) {\r\n applyMentionSuggestion(selected, true);\r\n }\r\n return;\r\n }\r\n }\r\n\r\n // Ctrl+V: Paste image/file from clipboard\r\n // On Mac, Cmd+V is captured by the terminal for text paste, so we use Ctrl+V.\r\n // On Windows/Linux, Ctrl+V may also be terminal text paste depending on the terminal,\r\n // but many modern terminals (Windows Terminal, etc.) use Ctrl+Shift+V for text paste.\r\n // We also support Option+V on Mac as fallback (sends '√' character).\r\n const isPasteFile = (key.ctrl && input === 'v') || (input === '√');\r\n\r\n if (isPasteFile && !commandMode) {\r\n // Check clipboard for files asynchronously\r\n (async () => {\r\n try {\r\n const files = await getClipboardFiles();\r\n if (files.length > 0) {\r\n // Check limits (max 5 files allowed)\r\n const currentCount = confirmedClipboardFiles.length;\r\n const newCount = files.length;\r\n\r\n if (currentCount + newCount > 5) {\r\n logDebug(`Ctrl+V: Rejected file paste, limit exceeded (${currentCount} + ${newCount} > 5)`);\r\n setRejectFlash(true);\r\n setTimeout(() => setRejectFlash(false), 1000);\r\n return;\r\n }\r\n\r\n logDebug(`Ctrl+V: Found ${files.length} file(s) in clipboard, adding to input`);\r\n\r\n // Add files to confirmed list with unique ID\r\n const newFilesWithIds = files.map(file => ({\r\n ...file,\r\n id: `${file.id}_${Date.now()}_${Math.random().toString(36).substring(7)}`\r\n }));\r\n\r\n setConfirmedClipboardFiles(prev => [...prev, ...newFilesWithIds]);\r\n } else {\r\n logDebug('Ctrl+V: No file in clipboard');\r\n }\r\n } catch (error) {\r\n logDebug(`Ctrl+V: Failed to check clipboard: ${error instanceof Error ? error.message : 'Unknown error'}`);\r\n }\r\n })();\r\n return;\r\n }\r\n\r\n // ── File selection mode: navigate and remove attached files ──\r\n // When fileSelectionIndex >= 0, the user is browsing attached files.\r\n // Left/Right to move between files, Backspace to remove, Down/Escape to exit.\r\n if (fileSelectionIndex >= 0) {\r\n if (key.leftArrow) {\r\n setFileSelectionIndex(prev => Math.max(prev - 1, 0));\r\n return;\r\n }\r\n if (key.rightArrow) {\r\n setFileSelectionIndex(prev => Math.min(prev + 1, confirmedClipboardFiles.length - 1));\r\n return;\r\n }\r\n if (key.backspace || key.delete) {\r\n // Remove the selected file\r\n const idxToRemove = fileSelectionIndex;\r\n setConfirmedClipboardFiles(prev => prev.filter((_, i) => i !== idxToRemove));\r\n // Adjust selection index after removal\r\n const newLen = confirmedClipboardFiles.length - 1;\r\n if (newLen <= 0) {\r\n // No files left, exit selection mode\r\n setFileSelectionIndex(-1);\r\n } else {\r\n // Keep index valid\r\n setFileSelectionIndex(Math.min(idxToRemove, newLen - 1));\r\n }\r\n return;\r\n }\r\n if (key.downArrow || key.escape) {\r\n // Exit file selection mode\r\n setFileSelectionIndex(-1);\r\n return;\r\n }\r\n if (key.upArrow) {\r\n // Already at the top - stay in file selection mode\r\n return;\r\n }\r\n // Any other key exits file selection mode and falls through to normal handling\r\n setFileSelectionIndex(-1);\r\n }\r\n\r\n // macOS Option+Left / Option+Right word navigation.\r\n if (isMacOptionWordBackwardSequence) {\r\n if (cursorOffset > 0) {\r\n let newOffset = cursorOffset;\r\n while (newOffset > 0 && /\\s/.test(value[newOffset - 1])) {\r\n newOffset--;\r\n }\r\n while (newOffset > 0 && !/\\s/.test(value[newOffset - 1])) {\r\n newOffset--;\r\n }\r\n setCursorOffset(newOffset);\r\n }\r\n return;\r\n }\r\n\r\n if (isMacOptionWordForwardSequence) {\r\n if (cursorOffset < value.length) {\r\n let newOffset = cursorOffset;\r\n while (newOffset < value.length && /\\s/.test(value[newOffset])) {\r\n newOffset++;\r\n }\r\n while (newOffset < value.length && !/\\s/.test(value[newOffset])) {\r\n newOffset++;\r\n }\r\n setCursorOffset(newOffset);\r\n }\r\n return;\r\n }\r\n\r\n\r\n // DELETE WORD BACKWARDS\r\n // 1. Ctrl+W\r\n // 2. Cmd+Backspace (Mac) - often mapped to delete line, but here we treat key.meta as modifier\r\n // 3. Alt+Backspace (Windows/Linux)\r\n const isDeleteWord =\r\n inputCharCode === 23 || // Ctrl+W\r\n (key.meta && (key.backspace || key.delete)) || // Cmd+Backspace (Mac) or Alt+Backspace (Win)\r\n (key.ctrl && key.delete) || // Ctrl+Delete\r\n (isWindows && inputCharCode === 127); // Windows: Ctrl+Del sends char 127\r\n\r\n if (isDeleteWord) {\r\n pushToUndoStack();\r\n if (cursorOffset > 0) {\r\n let newOffset = cursorOffset;\r\n // Skip whitespace backwards\r\n while (newOffset > 0 && /\\s/.test(value[newOffset - 1])) {\r\n newOffset--;\r\n }\r\n // Skip non-whitespace backwards\r\n while (newOffset > 0 && !/\\s/.test(value[newOffset - 1])) {\r\n newOffset--;\r\n }\r\n const newValue = value.slice(0, newOffset) + value.slice(cursorOffset);\r\n setValue(newValue);\r\n setCursorOffset(newOffset);\r\n updateSlashAutocomplete(newValue);\r\n }\r\n setHistoryIndex(-1);\r\n setCompletions([]);\r\n return;\r\n }\r\n\r\n // Ctrl+T: Toggle auto-accept\r\n if (key.ctrl && input.toLowerCase() === 't') {\r\n ignoreNextChangeRef.current = true;\r\n onToggleAutoAccept();\r\n setTimeout(() => { ignoreNextChangeRef.current = false; }, 100);\r\n return;\r\n }\r\n\r\n // Ctrl+P: Toggle plan mode\r\n if (key.ctrl && input.toLowerCase() === 'p') {\r\n if (onTogglePlanMode) {\r\n ignoreNextChangeRef.current = true;\r\n onTogglePlanMode();\r\n setTimeout(() => { ignoreNextChangeRef.current = false; }, 100);\r\n }\r\n return;\r\n }\r\n\r\n // Ctrl+D: Cycle modes (Agent -> Terminal -> Background -> Auto -> Agent)\r\n if (key.ctrl && input.toLowerCase() === 'd') {\r\n if (onToggleCommandMode) {\r\n ignoreNextChangeRef.current = true;\r\n\r\n // Cycle Logic: Agent -> Terminal -> Background -> Auto -> Agent\r\n if (!isAutoMode && !commandMode && !backgroundMode) {\r\n // Agent -> Terminal\r\n onToggleCommandMode();\r\n } else if (!isAutoMode && commandMode && !backgroundMode) {\r\n // Terminal -> Background\r\n onToggleCommandMode(); // Exit terminal mode\r\n if (onToggleBackgroundMode) onToggleBackgroundMode(); // Enter background mode\r\n } else if (!isAutoMode && !commandMode && backgroundMode) {\r\n // Background -> Auto\r\n if (onToggleBackgroundMode) onToggleBackgroundMode(); // Exit background mode\r\n setIsAutoMode(true);\r\n // Trigger initial detection for Auto mode\r\n const intent = detectIntent(value);\r\n setDetectedIntent(intent);\r\n // Set command mode based on intent\r\n if (intent === 'command') onToggleCommandMode();\r\n } else if (isAutoMode) {\r\n // Auto -> Agent\r\n setIsAutoMode(false);\r\n // Ensure we go back to Agent mode (commandMode = false, backgroundMode = false)\r\n if (commandMode) onToggleCommandMode();\r\n if (backgroundMode && onToggleBackgroundMode) onToggleBackgroundMode();\r\n }\r\n\r\n setTimeout(() => { ignoreNextChangeRef.current = false; }, 100);\r\n }\r\n return;\r\n }\r\n\r\n // Ctrl+Z / Cmd+Z: Undo\r\n if ((key.ctrl && input.toLowerCase() === 'z') || (key.meta && input.toLowerCase() === 'z')) {\r\n handleUndo();\r\n return;\r\n }\r\n\r\n // Ctrl+A / Cmd+A: Select All\r\n if ((key.ctrl && input.toLowerCase() === 'a') || (key.meta && input.toLowerCase() === 'a')) {\r\n setSelection({ start: 0, end: value.length });\r\n setCursorOffset(value.length);\r\n return;\r\n }\r\n\r\n // Home: Start of Line\r\n // Note: In single-line inputs, this goes to start of text. \r\n // In multi-line wrapped view, we ideally want start of logical line or start of text? \r\n // Standard terminal Home = Start of command. Editor Home = Start of line.\r\n // Let's stick to Start of Text for now as it's a single \"input box\".\r\n // Home: Start of Line\r\n // @ts-ignore\r\n if (key.home) {\r\n const width = (process.stdout.columns || 80) - 6;\r\n const visualLines = getVisualLines(value, width);\r\n\r\n const currentLine = visualLines.find(line =>\r\n (cursorOffset >= line.start && cursorOffset < line.end) ||\r\n (cursorOffset === line.end && line.isHardEnd)\r\n );\r\n\r\n if (currentLine) {\r\n setCursorOffset(currentLine.start);\r\n } else {\r\n setCursorOffset(0);\r\n }\r\n return;\r\n }\r\n\r\n // End: End of Line\r\n // @ts-ignore\r\n if (key.end) {\r\n const width = (process.stdout.columns || 80) - 6;\r\n const visualLines = getVisualLines(value, width);\r\n\r\n const currentLine = visualLines.find(line =>\r\n (cursorOffset >= line.start && cursorOffset < line.end) ||\r\n (cursorOffset === line.end && line.isHardEnd)\r\n );\r\n\r\n if (currentLine) {\r\n setCursorOffset(currentLine.end);\r\n } else {\r\n setCursorOffset(value.length);\r\n }\r\n return;\r\n }\r\n\r\n\r\n // Note: Clipboard images are handled via Ctrl+V keyboard shortcut\r\n\r\n // DELETE CHAR - Only runs if Delete Word did NOT trigger\r\n // Triggers on:\r\n // 1. Backspace or Delete key flag is present\r\n // 2. OR char code 8 (standard backspace)\r\n // 3. OR char code 127 (DEL) on non-Windows (Mac/Linux treat 127 as normal backspace)\r\n // NOTE: On Windows/Ink, Backspace often reports as 'delete: true', so we treat key.delete as Backspace to ensure the Backspace key works correctly.\r\n const isDeleteChar =\r\n key.backspace ||\r\n key.delete ||\r\n inputCharCode === 8 ||\r\n (!isWindows && inputCharCode === 127);\r\n\r\n if (isDeleteChar) {\r\n pushToUndoStack();\r\n\r\n let newValue = value;\r\n\r\n if (selection) {\r\n // Delete selection\r\n const start = Math.min(selection.start, selection.end);\r\n const end = Math.max(selection.start, selection.end);\r\n newValue = value.slice(0, start) + value.slice(end);\r\n setValue(newValue);\r\n setCursorOffset(start);\r\n setSelection(null);\r\n } else if (cursorOffset > 0) {\r\n // Backspace (or Delete acting as Backspace): Delete character before cursor\r\n newValue = value.slice(0, cursorOffset - 1) + value.slice(cursorOffset);\r\n setValue(newValue);\r\n setCursorOffset(cursorOffset - 1);\r\n }\r\n\r\n // Reset history/completions on edit\r\n setHistoryIndex(-1);\r\n setCompletions([]);\r\n updateSlashAutocomplete(newValue);\r\n\r\n return;\r\n }\r\n\r\n // Handle Enter\r\n // Check input length to distinguish single key press from paste\r\n if (isEnterEvent && (input.length <= 1 || isTerminalShiftEnterSequence)) {\r\n // Newline insertion triggers:\r\n // 1) Shift/Ctrl/Meta + Enter\r\n // 2) Remapped Shift+Enter terminal sequences (ESC+CR / CSI variants)\r\n // 3) Universal fallback: \"\\\" immediately before Enter\r\n const isBackslashEnterFallback =\r\n !key.shift &&\r\n !key.ctrl &&\r\n !key.meta &&\r\n !isTerminalShiftEnterSequence &&\r\n !selection &&\r\n cursorOffset > 0 &&\r\n value[cursorOffset - 1] === '\\\\';\r\n\r\n if (key.shift || key.ctrl || key.meta || input === '\\n' || isTerminalShiftEnterSequence || isBackslashEnterFallback) {\r\n pushToUndoStack();\r\n // Insert newline, optionally replacing trailing backslash fallback marker.\r\n // If selection exists, replace it\r\n let newValue = value;\r\n let newOffset = cursorOffset;\r\n\r\n if (selection) {\r\n const start = Math.min(selection.start, selection.end);\r\n const end = Math.max(selection.start, selection.end);\r\n newValue = value.slice(0, start) + '\\n' + value.slice(end);\r\n newOffset = start + 1;\r\n setSelection(null);\r\n } else if (isBackslashEnterFallback) {\r\n newValue = value.slice(0, cursorOffset - 1) + '\\n' + value.slice(cursorOffset);\r\n newOffset = cursorOffset;\r\n } else {\r\n newValue = value.slice(0, cursorOffset) + '\\n' + value.slice(cursorOffset);\r\n newOffset = cursorOffset + 1;\r\n }\r\n\r\n setValue(newValue);\r\n setCursorOffset(newOffset);\r\n } else {\r\n // Enter: Submit\r\n // Check if submission is allowed when disconnected\r\n // Allowed: /exit command, OR Command Mode is active, OR detected intent is 'command'\r\n const isExitCommand = value.trim() === '/exit';\r\n const isCommandIntent = detectedIntent === 'command';\r\n const isAllowedOffline = isConnected || isExitCommand || commandMode || isCommandIntent;\r\n\r\n if (!isAllowedOffline) {\r\n setRejectFlash(true);\r\n setTimeout(() => setRejectFlash(false), 1000);\r\n return;\r\n }\r\n\r\n const isSlashCommand = value.trim().startsWith('/');\r\n\r\n // Check session quota (only for AI mode, not command mode or slash commands)\r\n // Slash commands and terminal commands should always be allowed\r\n if (!commandMode && !isCommandIntent && !isSlashCommand && sessionQuotaExhausted) {\r\n setRejectFlash(true);\r\n setShowQuotaMessage(true);\r\n setTimeout(() => {\r\n setRejectFlash(false);\r\n setShowQuotaMessage(false);\r\n }, 3000); // Show quota message for 3 seconds\r\n return;\r\n }\r\n\r\n handleSubmit();\r\n }\r\n return;\r\n }\r\n\r\n // Handle Arrows\r\n if (key.upArrow || key.downArrow || key.leftArrow || key.rightArrow) {\r\n // Clear selection on arrow keys\r\n if (selection) {\r\n setSelection(null);\r\n // If left/right, maybe move cursor to start/end of selection?\r\n // For now, just clear selection and let default logic run (or reset cursor to one end)\r\n if (key.leftArrow) setCursorOffset(Math.min(selection.start, selection.end));\r\n if (key.rightArrow) setCursorOffset(Math.max(selection.start, selection.end));\r\n if (key.upArrow || key.downArrow) {\r\n // Keep cursor where it is (at the end usually) or move it?\r\n // Let's just fall through to normal arrow logic from current cursorOffset\r\n }\r\n if (key.leftArrow || key.rightArrow) return; // We handled the move\r\n }\r\n }\r\n\r\n if (key.upArrow) {\r\n const width = (process.stdout.columns || 80) - 6;\r\n const visualLines = getVisualLines(value, width);\r\n\r\n let currentVisualLineIndex = visualLines.findIndex(line => {\r\n if (cursorOffset >= line.start && cursorOffset < line.end) return true;\r\n if (cursorOffset === line.end && line.isHardEnd) return true;\r\n return false;\r\n });\r\n\r\n // If cursor is at the very end of the last line\r\n if (currentVisualLineIndex === -1 && cursorOffset === value.length) {\r\n currentVisualLineIndex = visualLines.length - 1;\r\n }\r\n\r\n if (currentVisualLineIndex <= 0) {\r\n // Top line: If files are attached and we're at the top of history (or no history),\r\n // enter file selection mode to allow file removal via backspace\r\n if (confirmedClipboardFiles.length > 0 && (historyIndex <= 0 || commandHistory.length === 0)) {\r\n // If not yet browsing history, save current value first\r\n if (historyIndex === -1 && commandHistory.length > 0) {\r\n setTempValue(value);\r\n }\r\n // Enter file selection mode - select the last file\r\n setFileSelectionIndex(confirmedClipboardFiles.length - 1);\r\n return;\r\n }\r\n // Normal history navigation\r\n if (commandHistory.length > 0) {\r\n if (historyIndex === -1) {\r\n setTempValue(value);\r\n const newIndex = commandHistory.length - 1;\r\n setHistoryIndex(newIndex);\r\n const newValue = commandHistory[newIndex];\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n } else if (historyIndex > 0) {\r\n const newIndex = historyIndex - 1;\r\n setHistoryIndex(newIndex);\r\n const newValue = commandHistory[newIndex];\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n }\r\n }\r\n } else {\r\n // Move cursor up one visual line\r\n const currentLine = visualLines[currentVisualLineIndex];\r\n const targetLine = visualLines[currentVisualLineIndex - 1];\r\n const offsetInLine = cursorOffset - currentLine.start;\r\n\r\n const newOffset = targetLine.start + Math.min(offsetInLine, targetLine.end - targetLine.start);\r\n setCursorOffset(newOffset);\r\n }\r\n return;\r\n }\r\n\r\n if (key.downArrow) {\r\n const width = (process.stdout.columns || 80) - 6;\r\n const visualLines = getVisualLines(value, width);\r\n\r\n let currentVisualLineIndex = visualLines.findIndex(line => {\r\n if (cursorOffset >= line.start && cursorOffset < line.end) return true;\r\n if (cursorOffset === line.end && line.isHardEnd) return true;\r\n return false;\r\n });\r\n\r\n // If cursor is at the very end of the last line\r\n if (currentVisualLineIndex === -1 && cursorOffset === value.length) {\r\n currentVisualLineIndex = visualLines.length - 1;\r\n }\r\n\r\n if (currentVisualLineIndex === visualLines.length - 1) {\r\n // Bottom line: History navigation\r\n if (historyIndex !== -1) {\r\n if (historyIndex < commandHistory.length - 1) {\r\n const newIndex = historyIndex + 1;\r\n setHistoryIndex(newIndex);\r\n const newValue = commandHistory[newIndex];\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n } else {\r\n setHistoryIndex(-1);\r\n setValue(tempValue);\r\n setCursorOffset(tempValue.length);\r\n }\r\n }\r\n } else {\r\n // Move cursor down one visual line\r\n const currentLine = visualLines[currentVisualLineIndex];\r\n const targetLine = visualLines[currentVisualLineIndex + 1];\r\n const offsetInLine = cursorOffset - currentLine.start;\r\n\r\n const newOffset = targetLine.start + Math.min(offsetInLine, targetLine.end - targetLine.start);\r\n setCursorOffset(newOffset);\r\n }\r\n return;\r\n }\r\n\r\n if (key.leftArrow) {\r\n if (isMac && key.meta) {\r\n // macOS fallback: many terminals map Option+Left to meta+left.\r\n // Treat as word-backward navigation.\r\n let newOffset = cursorOffset;\r\n if (newOffset > 0) {\r\n while (newOffset > 0 && /\\s/.test(value[newOffset - 1])) {\r\n newOffset--;\r\n }\r\n while (newOffset > 0 && !/\\s/.test(value[newOffset - 1])) {\r\n newOffset--;\r\n }\r\n setCursorOffset(newOffset);\r\n }\r\n return;\r\n }\r\n\r\n if (key.ctrl || (!isMac && key.meta)) {\r\n // Ctrl+Left (All) or Alt+Left (Win/Linux): Move word backwards\r\n // Note: On Mac, Option+Left is the standard for word back, but Ink doesn't expose 'alt'.\r\n // Users can use Ctrl+Left or rely on terminal mapping Option to Meta which effectively makes it key.meta\r\n // BUT if key.meta is Cmd on Mac, we map that to Home.\r\n // So standard Mac \"Option+Left\" might not work unless it sends Esc sequence or mapped to Ctrl.\r\n // We allow Ctrl+Left for Mac users.\r\n let newOffset = cursorOffset;\r\n if (newOffset > 0) {\r\n // Skip whitespace backwards\r\n while (newOffset > 0 && /\\s/.test(value[newOffset - 1])) {\r\n newOffset--;\r\n }\r\n // Skip non-whitespace backwards\r\n while (newOffset > 0 && !/\\s/.test(value[newOffset - 1])) {\r\n newOffset--;\r\n }\r\n setCursorOffset(newOffset);\r\n }\r\n return;\r\n }\r\n\r\n // Standard Left Arrow\r\n if (cursorOffset > 0) {\r\n setCursorOffset(cursorOffset - 1);\r\n }\r\n return;\r\n }\r\n\r\n if (key.rightArrow) {\r\n // Autocomplete Logic (Only at end of line)\r\n // AI suggestion takes priority over passive suggestion\r\n // Autocomplete Logic\r\n const effectiveSuggestion = aiAutocompleteSuggestion || autocompleteSuggestion;\r\n if (effectiveSuggestion && cursorOffset === value.length) {\r\n if (key.ctrl || (!isMac && key.meta)) {\r\n // Ctrl+Right (or Alt+Right on non-macOS): Accept FULL suggestion\r\n // (Wait, Cmd+Right is usually End of Line on Mac. We should prioritize Navigation over Autocomplete?\r\n // Actually, if we are at end of line, End of Line does nothing. So we can use it for accept full?)\r\n // Convention: Right Arrow accepts word. Ctrl+Right accepts full?\r\n // On Mac, Cmd+Right is End. If at End, it's a no-op for nav.\r\n // Let's allow Cmd+Right to accept full IF at end.\r\n setValue(effectiveSuggestion);\r\n setCursorOffset(effectiveSuggestion.length);\r\n setAutocompleteSuggestion(null);\r\n setAiAutocompleteSuggestion(null);\r\n return;\r\n } else {\r\n // Right: Accept NEXT WORD\r\n const remaining = effectiveSuggestion.slice(value.length);\r\n // Match next chunk of non-whitespace\r\n const match = remaining.match(/^(\\s*\\S+)/);\r\n\r\n if (match) {\r\n const toAdd = match[0];\r\n const newValue = value + toAdd;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n return; // Done\r\n } else if (remaining.length > 0) {\r\n const newValue = value + remaining;\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // Navigation Logic\r\n if (isMac && key.meta) {\r\n // macOS fallback: many terminals map Option+Right to meta+right.\r\n // Treat as word-forward navigation.\r\n let newOffset = cursorOffset;\r\n if (newOffset < value.length) {\r\n while (newOffset < value.length && /\\s/.test(value[newOffset])) {\r\n newOffset++;\r\n }\r\n while (newOffset < value.length && !/\\s/.test(value[newOffset])) {\r\n newOffset++;\r\n }\r\n setCursorOffset(newOffset);\r\n }\r\n return;\r\n }\r\n\r\n if ((!isMac && key.meta) || key.ctrl) {\r\n // Alt+Right (Win) or Ctrl+Right: Word Forward\r\n // (Note: Ink uses key.meta for Alt on Windows)\r\n let newOffset = cursorOffset;\r\n if (newOffset < value.length) {\r\n // Skip whitespace forwards\r\n while (newOffset < value.length && /\\s/.test(value[newOffset])) {\r\n newOffset++;\r\n }\r\n // Skip non-whitespace forwards\r\n while (newOffset < value.length && !/\\s/.test(value[newOffset])) {\r\n newOffset++;\r\n }\r\n setCursorOffset(newOffset);\r\n }\r\n return;\r\n }\r\n\r\n // Navigation Logic (if not completing)\r\n if (key.ctrl || key.meta) {\r\n // Ctrl+Right / Meta+Right (Option+Right): Move word forwards\r\n let newOffset = cursorOffset;\r\n if (newOffset < value.length) {\r\n // Skip non-whitespace forwards\r\n while (newOffset < value.length && !/\\s/.test(value[newOffset])) {\r\n newOffset++;\r\n }\r\n // Skip whitespace forwards\r\n while (newOffset < value.length && /\\s/.test(value[newOffset])) {\r\n newOffset++;\r\n }\r\n setCursorOffset(newOffset);\r\n }\r\n } else if (cursorOffset < value.length) {\r\n setCursorOffset(cursorOffset + 1);\r\n }\r\n return;\r\n }\r\n\r\n // Tab Completion\r\n if (key.tab && !key.shift) {\r\n // Only file completion (only in command mode)\r\n if (commandMode) {\r\n handleTabCompletion();\r\n return;\r\n }\r\n }\r\n\r\n // Regular Input\r\n // Ignore control keys to prevent printing garbage (like 'v' for Ctrl+V)\r\n if (input && !key.ctrl && !key.meta) {\r\n pushToUndoStack();\r\n // Handle paste with newlines\r\n const cleanedInput = input.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\r\n\r\n // Use refs to get the latest value and cursor position\r\n // This prevents stale closure issues when Ink calls useInput multiple times during paste\r\n const currentValue = valueRef.current;\r\n const currentCursorOffset = cursorOffsetRef.current;\r\n\r\n let newValue = currentValue;\r\n let newOffset = currentCursorOffset;\r\n\r\n if (selection) {\r\n const start = Math.min(selection.start, selection.end);\r\n const end = Math.max(selection.start, selection.end);\r\n newValue = currentValue.slice(0, start) + cleanedInput + currentValue.slice(end);\r\n newOffset = start + cleanedInput.length;\r\n setSelection(null);\r\n } else {\r\n newValue = currentValue.slice(0, currentCursorOffset) + cleanedInput + currentValue.slice(currentCursorOffset);\r\n newOffset = currentCursorOffset + cleanedInput.length;\r\n }\r\n\r\n // Update refs immediately for subsequent paste chunks\r\n valueRef.current = newValue;\r\n cursorOffsetRef.current = newOffset;\r\n\r\n setValue(newValue);\r\n setCursorOffsetWithRef(newOffset);\r\n\r\n // Reset history/completions\r\n setHistoryIndex(-1);\r\n setCompletions([]);\r\n updateSlashAutocomplete(newValue);\r\n }\r\n }, { isActive });\r\n\r\n const handleTabCompletion = async () => {\r\n if (!value) return;\r\n\r\n const words = value.split(' ');\r\n const lastWord = words[words.length - 1];\r\n\r\n if (completions.length > 0) {\r\n const nextIndex = (completionIndex + 1) % completions.length;\r\n setCompletionIndex(nextIndex);\r\n words[words.length - 1] = completions[nextIndex];\r\n const newValue = words.join(' ');\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n return;\r\n }\r\n\r\n try {\r\n const cwd = currentWorkingDirectory || process.cwd();\r\n let searchDir = cwd;\r\n let searchPattern = lastWord;\r\n let dirPart = '';\r\n\r\n if (lastWord.includes('/') || lastWord.includes('\\\\')) {\r\n const lastSep = Math.max(lastWord.lastIndexOf('/'), lastWord.lastIndexOf('\\\\'));\r\n dirPart = lastWord.substring(0, lastSep + 1);\r\n searchPattern = lastWord.substring(lastSep + 1);\r\n\r\n if (subshellContext && subshellContext.type !== 'local') {\r\n searchDir = dirPart.startsWith('/') ? dirPart.slice(0, -1) : cwd + '/' + dirPart.slice(0, -1);\r\n } else {\r\n searchDir = path.resolve(cwd, dirPart);\r\n }\r\n }\r\n\r\n let entries: Array<{ name: string; type: 'file' | 'directory' }>;\r\n\r\n if (subshellContext && subshellContext.type !== 'local' && subshellContext.handler) {\r\n const dirEntries = await subshellContext.handler.listDirectory(searchDir);\r\n entries = dirEntries.map(entry => ({ name: entry.name, type: entry.type }));\r\n } else {\r\n if (!fs.existsSync(searchDir)) return;\r\n const fsEntries = fs.readdirSync(searchDir, { withFileTypes: true });\r\n entries = fsEntries.map(entry => ({\r\n name: entry.name,\r\n type: entry.isDirectory() ? 'directory' : 'file'\r\n }));\r\n }\r\n\r\n const matches = entries\r\n .filter(entry => entry.name.toLowerCase().startsWith(searchPattern.toLowerCase()))\r\n .map(entry => {\r\n const separator = (subshellContext && subshellContext.type !== 'local') ? '/' : path.sep;\r\n const fullPath = dirPart ? dirPart + entry.name : entry.name;\r\n return entry.type === 'directory' ? fullPath + separator : fullPath;\r\n })\r\n .sort();\r\n\r\n if (matches.length > 0) {\r\n if (matches.length > 1) {\r\n setCompletions(matches);\r\n setCompletionIndex(0);\r\n }\r\n words[words.length - 1] = matches[0];\r\n const newValue = words.join(' ');\r\n setValue(newValue);\r\n setCursorOffset(newValue.length);\r\n }\r\n } catch (error) {\r\n // Ignore errors\r\n }\r\n };\r\n\r\n const handleSubmit = () => {\r\n if (!isActive) return;\r\n\r\n // Block submission while shell command is running - flash red\r\n if (isShellRunning && !allowSubmitWhileShellRunning) {\r\n setRejectFlash(true);\r\n setTimeout(() => setRejectFlash(false), 1000); // Flash for 1.0 seconds\r\n return;\r\n }\r\n\r\n const trimmedValue = value.trim();\r\n if (trimmedValue) {\r\n // Save to history if it was a command\r\n if (commandMode) {\r\n CommandHistoryManager.getInstance().addCommand(trimmedValue, currentDir, currentEnvironment);\r\n }\r\n\r\n // File tags (@relative/path) are kept as-is in the message content and\r\n // resolved to absolute paths in cli-adapter before being sent to the AI.\r\n // This preserves the short @tag display in the chat UI.\r\n onSubmit(trimmedValue, confirmedClipboardFiles.length > 0 ? confirmedClipboardFiles : undefined);\r\n setValue('');\r\n setCursorOffset(0);\r\n setCompletions([]);\r\n setCompletionIndex(0);\r\n setHistoryIndex(-1);\r\n setTempValue('');\r\n setUndoStack([]);\r\n setRedoStack([]);\r\n setSelection(null);\r\n setAutocompleteSuggestion(null);\r\n setConfirmedFileTags([]); // Clear confirmed tags on submit\r\n setConfirmedClipboardFiles([]); // Clear confirmed clipboard files on submit\r\n setFileSelectionIndex(-1); // Reset file selection on submit\r\n }\r\n };\r\n // Rendering Logic with Scrolling\r\n const renderInput = () => {\r\n const effectivePlaceholder = backgroundMode\r\n ? 'Run commands in the background'\r\n : commandMode\r\n ? 'Run a command'\r\n : placeholder;\r\n\r\n // Get terminal width for visual line calculation\r\n // Account for borders (2) + padding (2) + prompt \"> \" (2) = 6 chars\r\n const termWidth = (process.stdout.columns || 80) - 6;\r\n\r\n // Use getVisualLines to properly calculate wrapped lines\r\n const visualLines = getVisualLines(value, termWidth);\r\n const logicalLines = value.split('\\n');\r\n\r\n // If empty, show placeholder\r\n if (logicalLines.length === 1 && logicalLines[0] === '') {\r\n return <Text color=\"gray\">{effectivePlaceholder}</Text>;\r\n }\r\n\r\n // For rendering, we still use logical lines (split by \\n) since we render character-by-character\r\n // But for height calculation, we use visualLines.length\r\n const lines = logicalLines;\r\n\r\n // Calculate cursor line and column (based on logical lines)\r\n let currentPos = 0;\r\n let cursorLine = 0;\r\n let cursorCol = 0;\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n if (currentPos + lines[i].length >= cursorOffset) {\r\n cursorLine = i;\r\n cursorCol = cursorOffset - currentPos;\r\n break;\r\n }\r\n currentPos += lines[i].length + 1; // +1 for newline\r\n }\r\n // Edge case: cursor at very end of content\r\n if (cursorOffset === value.length && lines.length > 0) {\r\n cursorLine = lines.length - 1;\r\n cursorCol = lines[lines.length - 1].length;\r\n }\r\n\r\n // For scrolling, calculate which VISUAL line the cursor is on\r\n let cursorVisualLine = 0;\r\n for (let i = 0; i < visualLines.length; i++) {\r\n if (cursorOffset >= visualLines[i].start && cursorOffset <= visualLines[i].end) {\r\n cursorVisualLine = i;\r\n break;\r\n }\r\n }\r\n // Handle cursor at very end\r\n if (cursorOffset === value.length && visualLines.length > 0) {\r\n cursorVisualLine = visualLines.length - 1;\r\n }\r\n\r\n // Calculate visible range using VISUAL lines count for proper scrolling\r\n const totalVisualLines = visualLines.length;\r\n let startLine = 0;\r\n if (totalVisualLines > MAX_VISIBLE_LINES) {\r\n // Use visual line position for scrolling calculation\r\n if (cursorVisualLine < MAX_VISIBLE_LINES) {\r\n startLine = 0;\r\n } else {\r\n startLine = cursorVisualLine - MAX_VISIBLE_LINES + 1;\r\n }\r\n }\r\n const endLine = Math.min(startLine + MAX_VISIBLE_LINES, totalVisualLines);\r\n\r\n // Get the text content for each visual line\r\n const visibleVisualLines = visualLines.slice(startLine, endLine);\r\n\r\n return (\r\n <Box flexDirection=\"column\" flexGrow={1}>\r\n {startLine > 0 && <Text color=\"gray\">↑ ...</Text>}\r\n {visibleVisualLines.map((vLine, idx) => {\r\n const actualVisualLineIndex = startLine + idx;\r\n\r\n // Extract the text content for this visual line\r\n const lineText = value.slice(vLine.start, vLine.end);\r\n const lineStartPos = vLine.start;\r\n\r\n // Determine if cursor is on this visual line\r\n const isCursorLine = cursorOffset >= vLine.start && cursorOffset <= vLine.end;\r\n const cursorCol = isCursorLine ? cursorOffset - vLine.start : -1;\r\n\r\n // Is this the last visual line?\r\n const isLastLine = actualVisualLineIndex === totalVisualLines - 1;\r\n\r\n if (!isActive) {\r\n if (lineText.length === 0) {\r\n return <Text key={idx}> </Text>;\r\n }\r\n return <Text key={idx}>{lineText}</Text>;\r\n }\r\n\r\n // Render with selection and cursor\r\n const chars = lineText.split('');\r\n const renderedChars = chars.map((char, charIdx) => {\r\n const absPos = lineStartPos + charIdx;\r\n const isSelected = selection &&\r\n absPos >= Math.min(selection.start, selection.end) &&\r\n absPos < Math.max(selection.start, selection.end);\r\n\r\n // Check if this character is part of an active file tag (being typed after @)\r\n let activeFileTagEnd = activeFileTagStart !== null ? activeFileTagStart : 0;\r\n if (activeFileTagStart !== null) {\r\n for (let j = activeFileTagStart; j < value.length && j < cursorOffset; j++) {\r\n if (/[\\s\\n]/.test(value[j])) {\r\n break;\r\n }\r\n activeFileTagEnd = j + 1;\r\n }\r\n }\r\n const isInActiveFileTag = activeFileTagStart !== null &&\r\n absPos >= activeFileTagStart &&\r\n absPos < activeFileTagEnd;\r\n\r\n // Check if this character is part of a confirmed file tag\r\n let isInConfirmedFileTag = false;\r\n if (!commandMode) {\r\n const fileTagRegex = /(?:^|[\\s\\n])(@\"[^\"]*\"|@[^\\s@]+)/g;\r\n let match;\r\n while ((match = fileTagRegex.exec(value)) !== null) {\r\n const fullMatch = match[0];\r\n const tagContent = match[1];\r\n const tagStart = match.index + (fullMatch.length - tagContent.length);\r\n const tagEnd = tagStart + tagContent.length;\r\n if (activeFileTagStart !== null && tagStart === activeFileTagStart) {\r\n continue;\r\n }\r\n if (absPos >= tagStart && absPos < tagEnd) {\r\n isInConfirmedFileTag = true;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n const isCursor = isCursorLine && charIdx === cursorCol;\r\n\r\n if (isCursor) {\r\n return <Text key={charIdx} inverse color={isSelected ? \"yellow\" : undefined}>{char}</Text>;\r\n }\r\n if (isSelected) {\r\n return <Text key={charIdx} backgroundColor=\"white\" color=\"black\">{char}</Text>;\r\n }\r\n // Highlight file tags with cyan color\r\n if (isInConfirmedFileTag || isInActiveFileTag) {\r\n return <Text key={charIdx} color={theme.accent} bold>{char}</Text>;\r\n }\r\n\r\n return <Text key={charIdx}>{char}</Text>;\r\n });\r\n\r\n // Handle cursor at end of line\r\n if (isCursorLine && cursorCol === lineText.length) {\r\n renderedChars.push(<Text key=\"cursor\" inverse> </Text>);\r\n }\r\n\r\n // Render Autocomplete Ghost Text\r\n // Only on the last line, if suggestion exists and matches start\r\n // AI suggestion takes priority over passive suggestion\r\n const effectiveSuggestion = aiAutocompleteSuggestion || autocompleteSuggestion;\r\n if (isLastLine && effectiveSuggestion && effectiveSuggestion.startsWith(value)) {\r\n const suffix = effectiveSuggestion.slice(value.length);\r\n if (suffix) {\r\n // Use slightly different color for AI suggestion to differentiate\r\n const ghostColor = aiAutocompleteSuggestion ? '#888888' : 'gray';\r\n renderedChars.push(<Text key=\"ghost\" color={ghostColor}>{suffix}</Text>);\r\n }\r\n }\r\n\r\n if (renderedChars.length === 0) {\r\n return <Text key={idx}> </Text>;\r\n }\r\n\r\n return <Text key={idx}>{renderedChars}</Text>;\r\n })}\r\n {endLine < totalVisualLines && <Text color=\"gray\">↓ ...</Text>}\r\n </Box>\r\n );\r\n };\r\n\r\n // ── Compact mode: minimal single-line input bar for small terminals ──\r\n if (isCompactMode) {\r\n // Determine border color (same logic as full mode)\r\n const compactBorderColor =\r\n rejectFlash ? '#ff3366' :\r\n sessionQuotaExhausted ? '#ff3366' :\r\n backgroundMode ? '#9966ff' :\r\n commandMode ? '#00cc66' :\r\n theme.border;\r\n\r\n // Compute the horizontal rule width (fill entire parent width)\r\n const ruleWidth = Math.max(10, dimensions.columns - 4);\r\n\r\n return (\r\n <Box flexDirection=\"column\" width=\"100%\">\r\n {/* ── Info row above the rules: CWD when idle, loading indicator when AI working ── */}\r\n <Box justifyContent=\"space-between\" width=\"100%\" flexDirection=\"row\">\r\n {isAiWorking ? (\r\n <Box flexDirection=\"row\">\r\n <LoadingIndicator />\r\n <AgentTimer />\r\n </Box>\r\n ) : (\r\n <Box flexShrink={1} minWidth={0} flexDirection=\"row\">\r\n {subshellContext && subshellContext.type !== 'local' && (\r\n <Breadcrumbs context={subshellContext} stack={subshellContextStack} />\r\n )}\r\n {customTunnelCommand && (\r\n <Box marginRight={1}>\r\n {subshellContext && subshellContext.type !== 'local' && <Text color=\"gray\"> › </Text>}\r\n <Text color=\"#9945FF\" bold>[tunnel: {customTunnelCommand}]</Text>\r\n </Box>\r\n )}\r\n <Text color=\"#666666\">CWD: </Text>\r\n <Text color={theme.accent} bold wrap=\"truncate-start\">{currentDir}</Text>\r\n {gitDiffStats && (gitDiffStats.additions > 0 || gitDiffStats.deletions > 0) && (\r\n <GitDiffBreadcrumb\r\n additions={gitDiffStats.additions}\r\n deletions={gitDiffStats.deletions}\r\n />\r\n )}\r\n {confirmedClipboardFiles.length > 0 && confirmedClipboardFiles.map((_, i) => (\r\n <Text key={i} color={fileSelectionIndex === i ? '#000000' : '#ff69b4'} backgroundColor={fileSelectionIndex === i ? '#ff69b4' : undefined} bold={fileSelectionIndex === i}> [file_{i + 1}]</Text>\r\n ))}\r\n </Box>\r\n )}\r\n {lastFileChangeSummary && lastFileChangeSummary.filesChanged > 0 && (\r\n <Box paddingRight={1} flexDirection=\"row\" flexShrink={0}>\r\n <Text color=\"#666666\">{lastFileChangeSummary.filesChanged} file{lastFileChangeSummary.filesChanged !== 1 ? 's' : ''} changed </Text>\r\n {lastFileChangeSummary.insertions > 0 && (\r\n <Text color=\"green\">+{lastFileChangeSummary.insertions}</Text>\r\n )}\r\n {lastFileChangeSummary.insertions > 0 && lastFileChangeSummary.deletions > 0 && (\r\n <Text color=\"#666666\"> </Text>\r\n )}\r\n {lastFileChangeSummary.deletions > 0 && (\r\n <Text color=\"red\">-{lastFileChangeSummary.deletions}</Text>\r\n )}\r\n </Box>\r\n )}\r\n </Box>\r\n\r\n {/* ── Top horizontal rule ── */}\r\n <Text color={compactBorderColor}>{'─'.repeat(ruleWidth)}</Text>\r\n\r\n {/* ── Single-line prompt ── */}\r\n <Box flexDirection=\"row\" width=\"100%\">\r\n <Text color=\"#666666\">> </Text>\r\n {renderInput()}\r\n </Box>\r\n\r\n {/* ── Bottom horizontal rule ── */}\r\n <Text color={compactBorderColor}>{'─'.repeat(ruleWidth)}</Text>\r\n\r\n {/* ── Below the rules: show autocomplete dropdown (1 item) OR status line ── */}\r\n {slashAutocompleteVisible && slashAutocompleteCommands.length > 0 ? (\r\n <Box width=\"100%\">\r\n {(() => {\r\n const selected = slashAutocompleteCommands[slashAutocompleteSelectedIndex];\r\n if (!selected) return null;\r\n return (\r\n <Box gap={1}>\r\n <Text color={theme.accent} bold inverse> {selected.name} </Text>\r\n {selected.swatchColor ? (\r\n <>\r\n <Text color={selected.swatchColor}>████</Text>\r\n <Text color=\"#666666\">{selected.description}</Text>\r\n </>\r\n ) : (\r\n <Text color=\"#666666\">{selected.description}</Text>\r\n )}\r\n {slashAutocompleteCommands.length > 1 && (\r\n <Text color=\"#555555\" dimColor> ({slashAutocompleteSelectedIndex + 1}/{slashAutocompleteCommands.length}) ↑↓</Text>\r\n )}\r\n </Box>\r\n );\r\n })()}\r\n </Box>\r\n ) : fileTagAutocompleteVisible && fileTagSuggestions.length > 0 ? (\r\n <Box width=\"100%\">\r\n {(() => {\r\n const selected = fileTagSuggestions[fileTagSelectedIndex];\r\n if (!selected) return null;\r\n const icon = selected.kind === 'directory' ? '📁' : selected.kind === 'rule' ? '📜' : '📄';\r\n return (\r\n <Box gap={1}>\r\n <Text color={theme.accent} bold inverse> {icon} {selected.name} </Text>\r\n {selected.description && <Text color=\"#666666\">{selected.description}</Text>}\r\n {fileTagSuggestions.length > 1 && (\r\n <Text color=\"#555555\" dimColor> ({fileTagSelectedIndex + 1}/{fileTagSuggestions.length}) ↑↓</Text>\r\n )}\r\n </Box>\r\n );\r\n })()}\r\n </Box>\r\n ) : (\r\n /* ── Normal status line ── */\r\n <Box justifyContent=\"space-between\" width=\"100%\">\r\n <Box>\r\n <Text color=\"#666666\">Mode: </Text>\r\n {isAutoMode ? (\r\n <Text>\r\n <Text color={theme.accent} bold>Auto [</Text>\r\n {detectedIntent === 'command' ? (\r\n <Text color=\"#00cc66\" bold>Terminal</Text>\r\n ) : (\r\n <Text color={theme.accent}>Agent</Text>\r\n )}\r\n <Text color={theme.accent} bold>]</Text>\r\n </Text>\r\n ) : backgroundMode ? (\r\n <Text color=\"#9966ff\" bold>Background</Text>\r\n ) : commandMode ? (\r\n <Text color=\"#00cc66\" bold>Terminal</Text>\r\n ) : planMode ? (\r\n <Text color=\"#ffaa00\" bold>Plan</Text>\r\n ) : (\r\n <Text color={theme.accent}>Agent</Text>\r\n )}\r\n {model && !commandMode && !backgroundMode && (\r\n <>\r\n <Text> </Text>\r\n <Text color=\"#666666\">Model: </Text>\r\n <Text color={theme.accent}>{model}</Text>\r\n </>\r\n )}\r\n </Box>\r\n <Box gap={1}>\r\n {subAgentCount > 0 && (\r\n <Text color={theme.accent} bold>[sub-agent: {subAgentCount}]</Text>\r\n )}\r\n {backgroundTaskCount > 0 && (\r\n <Text color=\"#9966ff\" bold>[bkg tasks: {backgroundTaskCount}]</Text>\r\n )}\r\n {!commandMode && !backgroundMode && planMode && (\r\n <Text color=\"#ffaa00\" bold>[PLANNING]</Text>\r\n )}\r\n {!commandMode && !backgroundMode && autoAcceptMode && (\r\n <Text color=\"#00cc66\" bold>[AUTO-ACCEPT: ON]</Text>\r\n )}\r\n {!commandMode && !backgroundMode && currentTokens > 0 ? (\r\n <ContextWindowIndicator\r\n currentTokens={currentTokens}\r\n maxTokens={maxTokens}\r\n />\r\n ) : (\r\n <Text color=\"#666666\" dimColor>\r\n {isAutoMode ? (\r\n showBottomHints\r\n ? (autoAcceptMode ? 'Ctrl+D to switch modes' : 'Ctrl+D to switch modes • Ctrl+T to auto-approve')\r\n : 'Ctrl+D to switch modes'\r\n ) : backgroundMode ? (\r\n 'Ctrl+D to switch modes • Commands run in background'\r\n ) : commandMode ? (\r\n 'Ctrl+D to switch modes • Tab for autocomplete'\r\n ) : (\r\n showBottomHints\r\n ? (autoAcceptMode ? 'Ctrl+D to switch modes' : 'Ctrl+D to switch modes • Ctrl+T to auto-approve')\r\n : 'Ctrl+D to switch modes'\r\n )}\r\n </Text>\r\n )}\r\n </Box>\r\n </Box>\r\n )}\r\n </Box>\r\n );\r\n }\r\n\r\n return (\r\n <Box\r\n flexDirection=\"column\"\r\n borderStyle=\"round\"\r\n borderColor={\r\n rejectFlash ? \"#ff3366\" :\r\n sessionQuotaExhausted ? \"#ff3366\" : // Red when quota exhausted\r\n backgroundMode ? \"#9966ff\" :\r\n commandMode ? \"#00cc66\" :\r\n theme.border\r\n }\r\n paddingX={1}\r\n paddingY={0}\r\n width=\"100%\"\r\n >\r\n <Box marginY={1} justifyContent=\"space-between\" width=\"100%\">\r\n <Box flexShrink={1} minWidth={0} flexDirection=\"row\">\r\n {subshellContext && subshellContext.type !== 'local' && (\r\n <Breadcrumbs context={subshellContext} stack={subshellContextStack} />\r\n )}\r\n {customTunnelCommand && (\r\n <Box marginRight={1}>\r\n {subshellContext && subshellContext.type !== 'local' && <Text color=\"gray\"> › </Text>}\r\n <Text color=\"#9945FF\" bold>[tunnel: {customTunnelCommand}]</Text>\r\n </Box>\r\n )}\r\n <Text color=\"#666666\">CWD: </Text>\r\n <Text color={theme.accent} bold wrap=\"truncate-start\">{currentDir}</Text>\r\n {gitDiffStats && (gitDiffStats.additions > 0 || gitDiffStats.deletions > 0) && (\r\n <GitDiffBreadcrumb\r\n additions={gitDiffStats.additions}\r\n deletions={gitDiffStats.deletions}\r\n />\r\n )}\r\n {confirmedClipboardFiles.length > 0 && confirmedClipboardFiles.map((_, i) => (\r\n <Text key={i} color={fileSelectionIndex === i ? '#000000' : '#ff69b4'} backgroundColor={fileSelectionIndex === i ? '#ff69b4' : undefined} bold={fileSelectionIndex === i}> [file_{i + 1}]</Text>\r\n ))}\r\n </Box>\r\n <Box flexShrink={0}>\r\n\r\n {model && !commandMode && !backgroundMode && (\r\n <Box marginRight={1}>\r\n <Text color=\"#666666\">Model: </Text>\r\n <Text color={theme.accent}>{model}</Text>\r\n </Box>\r\n )}\r\n <Box>\r\n {showModeIndicator && (\r\n <>\r\n <Text color=\"#666666\">Mode: </Text>\r\n {isAutoMode ? (\r\n <Text>\r\n <Text color={theme.accent} bold>Auto [</Text>\r\n {detectedIntent === 'command' ? (\r\n <Text color=\"#00cc66\" bold>Terminal</Text>\r\n ) : (\r\n <Text color={theme.accent}>Agent</Text>\r\n )}\r\n <Text color={theme.accent} bold>]</Text>\r\n </Text>\r\n ) : backgroundMode ? (\r\n <Text color=\"#9966ff\" bold>Background</Text>\r\n ) : commandMode ? (\r\n <Text color=\"#00cc66\" bold>Terminal</Text>\r\n ) : planMode ? (\r\n <Text color=\"#ffaa00\" bold>Plan</Text>\r\n ) : (\r\n <Text color={theme.accent}>Agent</Text>\r\n )}\r\n </>\r\n )}\r\n </Box>\r\n </Box>\r\n </Box>\r\n\r\n\r\n {/* Session Quota Exhausted Message */}\r\n {showQuotaMessage && (\r\n <Box justifyContent=\"flex-end\" marginBottom={1}>\r\n <Text color=\"#ff3366\" bold>\r\n Session quota reached. Try again in {sessionQuotaTimeRemaining}\r\n </Text>\r\n </Box>\r\n )}\r\n\r\n\r\n <Box flexDirection=\"row\" width=\"100%\">\r\n <Text color=\"#666666\">> </Text>\r\n {renderInput()}\r\n </Box>\r\n\r\n <Box marginY={1} justifyContent=\"space-between\" width=\"100%\">\r\n <Text color=\"#666666\" dimColor>\r\n {isAutoMode ? (\r\n showBottomHints ? 'Ctrl+D to switch modes • Ctrl+T to auto-approve' : 'Ctrl+D to switch modes'\r\n ) : backgroundMode ? (\r\n 'Ctrl+D to switch modes • Commands run in background'\r\n ) : commandMode ? (\r\n 'Ctrl+D to switch modes • Tab for autocomplete'\r\n ) : (\r\n showBottomHints ? 'Ctrl+D to switch modes • Ctrl+T to auto-approve' : 'Ctrl+D to switch modes'\r\n )}\r\n </Text>\r\n <Box gap={1}>\r\n {subAgentCount > 0 && (\r\n <Text color={theme.accent} bold>[sub-agent: {subAgentCount}]</Text>\r\n )}\r\n {backgroundTaskCount > 0 && (\r\n <Text color=\"#9966ff\" bold>[bkg tasks: {backgroundTaskCount}]</Text>\r\n )}\r\n {!commandMode && !backgroundMode && planMode && (\r\n <Text color=\"#ffaa00\" bold>[PLANNING]</Text>\r\n )}\r\n {!commandMode && !backgroundMode && autoAcceptMode ? (\r\n <Text color=\"#00cc66\" bold>[AUTO-ACCEPT: ON]</Text>\r\n ) : !commandMode && !backgroundMode ? (\r\n <Text color=\"#666666\" dimColor>[AUTO-ACCEPT: OFF]</Text>\r\n ) : null}\r\n {!commandMode && !backgroundMode && (\r\n <Box marginLeft={1}>\r\n <ContextWindowIndicator\r\n currentTokens={currentTokens}\r\n maxTokens={maxTokens}\r\n />\r\n </Box>\r\n )}\r\n </Box>\r\n </Box>\r\n\r\n {/* Slash Command Autocomplete Dropdown */}\r\n {\r\n slashAutocompleteVisible && slashMaxVisibleItems > 0 && (\r\n <SlashCommandAutocomplete\r\n commands={slashAutocompleteCommands}\r\n selectedIndex={slashAutocompleteSelectedIndex}\r\n maxVisibleItems={slashMaxVisibleItems}\r\n scrollOffset={slashAutocompleteScrollOffset}\r\n />\r\n )\r\n }\r\n\r\n {/* File Tag (@) Autocomplete Dropdown */}\r\n {\r\n fileTagAutocompleteVisible && (\r\n <FileTagAutocomplete\r\n files={fileTagSuggestions}\r\n selectedIndex={fileTagSelectedIndex}\r\n />\r\n )\r\n }\r\n\r\n\r\n </Box>\r\n );\r\n});\r\n"],"mappings":"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","names":["newValue","newCursorPos","cursorCol"]}
|