@dbsp/cli 1.0.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/repl/index.tsx","../src/repl/components/CompletionDisplay.tsx","../src/repl/components/Header.tsx","../src/repl/components/HelpDisplay.tsx","../src/repl/components/InputPrompt.tsx","../src/repl/components/EnhancedTextInput.tsx","../src/repl/components/InspectionPanel.tsx","../src/repl/result-formatter.tsx","../src/repl/components/OutputDisplay.tsx","../src/repl/conversation/ConversationView.tsx","../src/repl/conversation/conversation-model.ts","../src/repl/history.ts"],"sourcesContent":["/**\n * DX-030: REPL Main Entry Point\n *\n * Thin Ink UI wrapper around ReplEngine + ConversationView.\n * Business logic lives in engine/repl-engine.ts.\n * History is displayed as a scrollable conversation.\n * Inspection panel anchored below input for detail views.\n */\n\nimport { Box, render, useApp, useInput } from 'ink';\nimport React, {\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport type { CompletionSuggestion } from './completion.js';\nimport {\n\tCompletionDisplay,\n\tHeader,\n\tHelpDisplay,\n\tInputPrompt,\n\tInspectionPanel,\n} from './components/index.js';\nimport { ConversationManager, ConversationView } from './conversation/index.js';\nimport { getDatabaseName } from './db-connection.js';\nimport {\n\ttype EngineEvent,\n\ttype EngineState,\n\ttype PanelView,\n\tReplEngine,\n} from './engine/index.js';\nimport { getHistory } from './history.js';\nimport type { ExecutionResult, QueryResult, ReplConfig } from './types.js';\n\ninterface ReplAppProps {\n\tconfig: ReplConfig;\n}\n\nfunction ReplApp({ config }: ReplAppProps) {\n\tconst { exit } = useApp();\n\n\t// --- Engine (owns all business state) ---\n\tconst engineRef = useRef<ReplEngine | null>(null);\n\tif (!engineRef.current) {\n\t\tengineRef.current = new ReplEngine({\n\t\t\tschema: config.schema,\n\t\t\tschemaPath: config.schemaPath,\n\t\t\t...(config.databaseUrl !== undefined && {\n\t\t\t\tdatabaseUrl: config.databaseUrl,\n\t\t\t}),\n\t\t\t...(config.initialSchemaName !== undefined && {\n\t\t\t\tinitialSchemaName: config.initialSchemaName,\n\t\t\t}),\n\t\t\t...(config.initialParseMode !== undefined && {\n\t\t\t\tinitialParseMode: config.initialParseMode,\n\t\t\t}),\n\t\t\t...(config.initialExecMode !== undefined && {\n\t\t\t\tinitialExecMode: config.initialExecMode,\n\t\t\t}),\n\t\t\t...(config.dbCasing !== undefined && { dbCasing: config.dbCasing }),\n\t\t});\n\t}\n\tconst engine = engineRef.current;\n\n\t// --- Conversation model (stacked entries) ---\n\tconst conversationRef = useRef<ConversationManager | null>(null);\n\tif (!conversationRef.current) {\n\t\tconversationRef.current = new ConversationManager();\n\t}\n\tconst conversation = conversationRef.current;\n\n\t// --- UI-only state ---\n\tconst [engineState, setEngineState] = useState<EngineState>(\n\t\tengine.getState(),\n\t);\n\tconst [entries, setEntries] = useState(conversation.getEntries());\n\tconst [showHelp, setShowHelp] = useState(false);\n\tconst [inputKey, setInputKey] = useState(0);\n\n\t// --- Inspection panel state ---\n\tconst [panelView, setPanelView] = useState<PanelView | null>(null);\n\tconst [lastQueryResult, setLastQueryResult] = useState<QueryResult | null>(\n\t\tnull,\n\t);\n\tconst [lastExecResult, setLastExecResult] = useState<ExecutionResult | null>(\n\t\tnull,\n\t);\n\n\t// --- Completions ---\n\tconst completionProvider = useMemo(\n\t\t() => engine.getCompletionProvider(),\n\t\t[engine],\n\t);\n\tconst [completions, setCompletions] = useState<CompletionSuggestion[]>([]);\n\tconst [selectedCompletionIndex, setSelectedCompletionIndex] = useState(-1);\n\n\t// Get command history singleton\n\tconst history = useMemo(() => getHistory(), []);\n\n\t// --- Engine initialization (DB connection) ---\n\tuseEffect(() => {\n\t\tengine.init();\n\t\treturn () => {\n\t\t\tengine.destroy();\n\t\t};\n\t}, [engine]);\n\n\t// --- Engine event subscription ---\n\t// Track the current entry being built\n\tconst currentEntryIdRef = useRef<number | null>(null);\n\n\tuseEffect(() => {\n\t\tconst refreshEntries = () => setEntries([...conversation.getEntries()]);\n\n\t\t/** Append event to current entry, or create synthetic entry if orphan. */\n\t\tconst appendToCurrentOrCreate = (event: EngineEvent) => {\n\t\t\tif (currentEntryIdRef.current !== null) {\n\t\t\t\tconversation.appendEvent(currentEntryIdRef.current, event);\n\t\t\t} else {\n\t\t\t\tconst entry = conversation.addEntry('');\n\t\t\t\tconversation.appendEvent(entry.id, event);\n\t\t\t}\n\t\t\trefreshEntries();\n\t\t};\n\n\t\tconst unsub = engine.on((event: EngineEvent) => {\n\t\t\tswitch (event.type) {\n\t\t\t\tcase 'state-change':\n\t\t\t\t\tsetEngineState(event.state);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'exit':\n\t\t\t\t\texit();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'clear':\n\t\t\t\t\tconversation.clear();\n\t\t\t\t\tsetShowHelp(false);\n\t\t\t\t\tsetPanelView(null);\n\t\t\t\t\tsetLastQueryResult(null);\n\t\t\t\t\tsetLastExecResult(null);\n\t\t\t\t\trefreshEntries();\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'info':\n\t\t\t\t\tif (event.message === 'SHOW_HELP') {\n\t\t\t\t\t\tsetShowHelp(true);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tappendToCurrentOrCreate(event);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'error':\n\t\t\t\t\tappendToCurrentOrCreate(event);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'query-result':\n\t\t\t\t\tif (currentEntryIdRef.current !== null) {\n\t\t\t\t\t\tconversation.appendEvent(currentEntryIdRef.current, event);\n\t\t\t\t\t\trefreshEntries();\n\t\t\t\t\t}\n\t\t\t\t\t// Track for panel inspection\n\t\t\t\t\tsetLastQueryResult(event.result);\n\t\t\t\t\t// Auto-update panel if open\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'execution-result':\n\t\t\t\t\tif (currentEntryIdRef.current !== null) {\n\t\t\t\t\t\tconversation.appendEvent(currentEntryIdRef.current, event);\n\t\t\t\t\t\trefreshEntries();\n\t\t\t\t\t}\n\t\t\t\t\t// Track for panel inspection\n\t\t\t\t\tsetLastExecResult(event.result);\n\t\t\t\t\tsetLastQueryResult(event.query);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'show-history': {\n\t\t\t\t\tconst recent = history.getRecent(20);\n\t\t\t\t\tconst msg =\n\t\t\t\t\t\trecent.length === 0\n\t\t\t\t\t\t\t? 'No command history yet.'\n\t\t\t\t\t\t\t: `📜 Recent Commands (${recent.length}):\\n${recent.map((cmd, i) => ` ${i + 1}. ${cmd}`).join('\\n')}`;\n\t\t\t\t\tappendToCurrentOrCreate({ type: 'info', message: msg });\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tcase 'show-panel':\n\t\t\t\t\tsetPanelView(event.view);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'close-panel':\n\t\t\t\t\tsetPanelView(null);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'layout-change':\n\t\t\t\t\t// Layout state is in engine, UI re-renders via state-change\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t});\n\t\treturn unsub;\n\t}, [engine, conversation, exit]);\n\n\t// --- Input handling ---\n\tuseInput((inputChar, key) => {\n\t\tif (key.ctrl && inputChar === 'c') {\n\t\t\texit();\n\t\t}\n\t\t// Escape closes panel\n\t\tif (key.escape && panelView !== null) {\n\t\t\tsetPanelView(null);\n\t\t\treturn;\n\t\t}\n\t\t// Tab: cycle panel views when panel is open, otherwise cycle completions\n\t\tif (key.tab) {\n\t\t\tif (panelView !== null) {\n\t\t\t\tconst views: PanelView[] = ['sql', 'plan', 'results', 'params', 'dump'];\n\t\t\t\tconst currentIdx = views.indexOf(panelView);\n\t\t\t\tconst nextIdx = (currentIdx + 1) % views.length;\n\t\t\t\tconst nextView = views[nextIdx];\n\t\t\t\tif (nextView) setPanelView(nextView);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (completions.length > 0 && engineState.mode === 'natural') {\n\t\t\t\tconst nextIndex =\n\t\t\t\t\tselectedCompletionIndex < 0\n\t\t\t\t\t\t? 0\n\t\t\t\t\t\t: (selectedCompletionIndex + 1) % completions.length;\n\t\t\t\tsetSelectedCompletionIndex(nextIndex);\n\t\t\t}\n\t\t}\n\t});\n\n\tconst handleInputChange = useCallback(\n\t\t(value: string) => {\n\t\t\tsetSelectedCompletionIndex(-1);\n\t\t\tif (engineState.mode === 'natural') {\n\t\t\t\tconst suggestions = completionProvider.complete(value);\n\t\t\t\tsetCompletions(suggestions);\n\t\t\t} else {\n\t\t\t\tsetCompletions([]);\n\t\t\t}\n\t\t},\n\t\t[completionProvider, engineState.mode],\n\t);\n\n\tconst handleCompletionAccepted = useCallback(() => {\n\t\tsetSelectedCompletionIndex(-1);\n\t\tsetCompletions([]);\n\t}, []);\n\n\tconst handleApplyCompletion = useCallback(\n\t\t(currentInput: string, completionText: string) => {\n\t\t\treturn completionProvider.applyCompletion(currentInput, completionText);\n\t\t},\n\t\t[completionProvider],\n\t);\n\n\tconst selectedCompletion =\n\t\tselectedCompletionIndex >= 0\n\t\t\t? completions[selectedCompletionIndex]?.text\n\t\t\t: undefined;\n\n\t// --- Submission queue (handles multiline paste safely) ---\n\tconst submitQueueRef = useRef<string[]>([]);\n\tconst isProcessingRef = useRef(false);\n\n\tconst processQueue = useCallback(async () => {\n\t\tif (isProcessingRef.current) return;\n\t\tisProcessingRef.current = true;\n\n\t\twhile (submitQueueRef.current.length > 0) {\n\t\t\tconst trimmed = submitQueueRef.current.shift();\n\t\t\tif (trimmed === undefined) break;\n\n\t\t\t// Save to command history (up/down navigation + .history)\n\t\t\thistory.add(trimmed);\n\n\t\t\t// Create conversation entry BEFORE submitting to engine\n\t\t\tconst entry = conversation.addEntry(trimmed);\n\t\t\tcurrentEntryIdRef.current = entry.id;\n\t\t\tsetEntries([...conversation.getEntries()]);\n\n\t\t\t// Submit to engine (events flow back via subscription)\n\t\t\tawait engine.submit(trimmed);\n\n\t\t\t// Clear current entry ref\n\t\t\tcurrentEntryIdRef.current = null;\n\t\t}\n\n\t\tisProcessingRef.current = false;\n\t}, [engine, conversation, history]);\n\n\tconst handleSubmit = useCallback(\n\t\t(value: string) => {\n\t\t\tconst trimmed = value.trim();\n\t\t\tif (!trimmed) return;\n\n\t\t\t// Reset UI\n\t\t\tsetInputKey((k) => k + 1);\n\t\t\tsetCompletions([]);\n\t\t\tsetShowHelp(false);\n\n\t\t\t// Enqueue and process sequentially\n\t\t\tsubmitQueueRef.current.push(trimmed);\n\t\t\tprocessQueue();\n\t\t},\n\t\t[processQueue],\n\t);\n\n\t// --- Derived values for Header ---\n\tconst tableCount = config.schema.tableNames.length;\n\tconst relationCount = config.schema.model.relations.size;\n\n\t// --- Render ---\n\tconst contentArea = (\n\t\t<Box flexDirection=\"column\">\n\t\t\t{showHelp && <HelpDisplay />}\n\n\t\t\t{/* Conversation history */}\n\t\t\t<ConversationView\n\t\t\t\tentries={entries}\n\t\t\t\toutputLayout={engineState.outputLayout}\n\t\t\t\tplanVerbosity={engineState.planVerbosity}\n\t\t\t/>\n\n\t\t\t{/* Completions (only in natural mode) */}\n\t\t\t{engineState.mode === 'natural' &&\n\t\t\t\tcompletions.length > 0 &&\n\t\t\t\t!showHelp && (\n\t\t\t\t\t<CompletionDisplay\n\t\t\t\t\t\tsuggestions={completions}\n\t\t\t\t\t\tselectedIndex={selectedCompletionIndex}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\n\t\t\t{/* Input area */}\n\t\t\t<InputPrompt\n\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\tmode={engineState.mode}\n\t\t\t\tresetKey={inputKey}\n\t\t\t\thistory={history}\n\t\t\t\tonInputChange={handleInputChange}\n\t\t\t\t{...(selectedCompletion !== undefined && { selectedCompletion })}\n\t\t\t\tonCompletionAccepted={handleCompletionAccepted}\n\t\t\t\tapplyCompletion={handleApplyCompletion}\n\t\t\t/>\n\n\t\t\t{/* Anchored inspection panel (below input, above status) */}\n\t\t\t{panelView !== null && (\n\t\t\t\t<InspectionPanel\n\t\t\t\t\tview={panelView}\n\t\t\t\t\tqueryResult={lastQueryResult}\n\t\t\t\t\texecutionResult={lastExecResult}\n\t\t\t\t\texecMode={engineState.execMode}\n\t\t\t\t\tonViewChange={setPanelView}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</Box>\n\t);\n\n\treturn (\n\t\t<Box flexDirection=\"column\" padding={1}>\n\t\t\t<Header\n\t\t\t\tschemaPath={config.schemaPath}\n\t\t\t\tmode={engineState.mode}\n\t\t\t\ttableCount={tableCount}\n\t\t\t\trelationCount={relationCount}\n\t\t\t\tdialect={engineState.dialect}\n\t\t\t\tincludeStrategy={engineState.includeStrategy}\n\t\t\t\taliasingMode={engineState.aliasingMode}\n\t\t\t\tconnected={engineState.connected}\n\t\t\t\texecMode={engineState.execMode}\n\t\t\t\tparseMode={engineState.parseMode}\n\t\t\t\texplainMode={engineState.explainMode}\n\t\t\t\t{...(engineState.schemaName && { schemaName: engineState.schemaName })}\n\t\t\t\t{...(config.databaseUrl && {\n\t\t\t\t\tdatabaseName: getDatabaseName(config.databaseUrl),\n\t\t\t\t})}\n\t\t\t/>\n\n\t\t\t{contentArea}\n\t\t</Box>\n\t);\n}\n\n/**\n * Start the REPL with the given configuration\n */\nexport async function startRepl(config: ReplConfig): Promise<void> {\n\tconsole.log('Starting REPL...\\n');\n\n\tconst instance = render(<ReplApp config={config} />);\n\tawait instance.waitUntilExit();\n}\n","import React from 'react';\n/**\n * DX-030 Block 6: Completion Display Component\n *\n * Shows inline completion suggestions as the user types.\n */\n\nimport { Box, Text } from 'ink';\nimport type { CompletionSuggestion } from '../completion.js';\n\ninterface CompletionDisplayProps {\n\tsuggestions: CompletionSuggestion[];\n\tmaxItems?: number;\n\t/** Index of the currently selected suggestion (-1 = none) */\n\tselectedIndex?: number;\n}\n\n/**\n * Type icons for visual distinction\n */\nconst TYPE_ICONS: Record<CompletionSuggestion['type'], string> = {\n\ttable: '🗃️',\n\tcolumn: '📋',\n\tkeyword: '🔑',\n\tcommand: '⚡',\n\trelation: '🔗',\n};\n\n/**\n * Type colors for visual distinction\n */\nconst TYPE_COLORS: Record<CompletionSuggestion['type'], string> = {\n\ttable: 'cyan',\n\tcolumn: 'blue',\n\tkeyword: 'yellow',\n\tcommand: 'magenta',\n\trelation: 'green',\n};\n\nexport function CompletionDisplay({\n\tsuggestions,\n\tmaxItems = 8,\n\tselectedIndex = -1,\n}: CompletionDisplayProps) {\n\tif (suggestions.length === 0) {\n\t\treturn null;\n\t}\n\n\t// Calculate sliding window to keep selected item visible\n\tlet startIndex = 0;\n\tif (selectedIndex >= 0) {\n\t\t// Center the selected item in the window when possible\n\t\tconst halfWindow = Math.floor(maxItems / 2);\n\t\tstartIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(selectedIndex - halfWindow, suggestions.length - maxItems),\n\t\t);\n\t}\n\t// Ensure startIndex doesn't go negative for small lists\n\tstartIndex = Math.max(0, startIndex);\n\n\tconst endIndex = Math.min(startIndex + maxItems, suggestions.length);\n\tconst items = suggestions.slice(startIndex, endIndex);\n\tconst hasBefore = startIndex > 0;\n\tconst hasAfter = endIndex < suggestions.length;\n\n\treturn (\n\t\t<Box flexDirection=\"row\" flexWrap=\"wrap\" marginTop={0}>\n\t\t\t<Text color=\"gray\" dimColor>\n\t\t\t\t[Tab]{' '}\n\t\t\t</Text>\n\t\t\t{hasBefore && (\n\t\t\t\t<Text color=\"gray\" dimColor>\n\t\t\t\t\t◀{' '}\n\t\t\t\t</Text>\n\t\t\t)}\n\t\t\t{items.map((suggestion, idx) => {\n\t\t\t\t// Convert local index to global index for selection check\n\t\t\t\tconst globalIndex = startIndex + idx;\n\t\t\t\tconst isSelected = globalIndex === selectedIndex;\n\t\t\t\treturn (\n\t\t\t\t\t<Box key={globalIndex} marginRight={1}>\n\t\t\t\t\t\t<Text>{TYPE_ICONS[suggestion.type]} </Text>\n\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\tcolor={isSelected ? 'white' : TYPE_COLORS[suggestion.type]}\n\t\t\t\t\t\t\t{...(isSelected && { backgroundColor: 'blue' as const })}\n\t\t\t\t\t\t\tbold={isSelected}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{suggestion.label}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t</Box>\n\t\t\t\t);\n\t\t\t})}\n\t\t\t{hasAfter && (\n\t\t\t\t<Text color=\"gray\" dimColor>\n\t\t\t\t\t▶ +{suggestions.length - endIndex}\n\t\t\t\t</Text>\n\t\t\t)}\n\t\t</Box>\n\t);\n}\n","import React from 'react';\n/**\n * DX-030: REPL Header Component\n * CLI-013: Enhanced status line with dialect, strategy, aliasing mode\n */\n\nimport { Box, Text } from 'ink';\nimport type {\n\tAliasingMode,\n\tDialectMode,\n\tIncludeStrategyMode,\n\tQueryMode,\n} from '../types.js';\n\ninterface HeaderProps {\n\tschemaPath: string;\n\tmode: QueryMode;\n\ttableCount: number;\n\trelationCount: number;\n\tdialect: DialectMode;\n\tincludeStrategy: IncludeStrategyMode;\n\taliasingMode: AliasingMode;\n\t/** CLI-020: Database connection status */\n\tconnected?: boolean;\n\t/** CLI-020: Execution mode enabled */\n\texecMode?: boolean;\n\t/** CLI-020: Database name for display */\n\tdatabaseName?: string;\n\t/** CLI-021: Active schema name for schema-scoped queries */\n\tschemaName?: string;\n\t/** CLI-NQL: Parse mode for AST output */\n\tparseMode?: boolean;\n\t/** CLI-NQL: Explain mode for EXPLAIN prefix */\n\texplainMode?: boolean;\n}\n\n/** Short display names for dialects */\nconst DIALECT_DISPLAY: Record<DialectMode, string> = {\n\tpostgresql: 'PG',\n\tmysql: 'MySQL',\n\tsqlite: 'SQLite',\n\tmssql: 'MSSQL',\n\tduckdb: 'DuckDB',\n};\n\n/** Short display names for strategies */\nconst STRATEGY_DISPLAY: Record<IncludeStrategyMode, string> = {\n\tauto: 'auto',\n\tjoin: 'join',\n\tsubquery: 'sep',\n\tcte: 'cte',\n\tlateral: 'lat',\n\tjson_agg: 'json',\n};\n\nexport function Header({\n\tschemaPath,\n\tmode,\n\ttableCount,\n\trelationCount,\n\tdialect,\n\tincludeStrategy,\n\taliasingMode,\n\tconnected,\n\texecMode,\n\tdatabaseName,\n\tschemaName,\n\tparseMode,\n\texplainMode,\n}: HeaderProps) {\n\treturn (\n\t\t<Box\n\t\t\tborderStyle=\"round\"\n\t\t\tborderColor=\"cyan\"\n\t\t\tpaddingX={2}\n\t\t\tmarginBottom={1}\n\t\t\tflexDirection=\"column\"\n\t\t>\n\t\t\t{/* Row 1: Title and help */}\n\t\t\t<Box>\n\t\t\t\t<Text bold color=\"cyan\">\n\t\t\t\t\t🔍 db-semantic-planner REPL\n\t\t\t\t</Text>\n\t\t\t\t<Text color=\"gray\"> | </Text>\n\t\t\t\t<Text color=\"gray\">.help for commands</Text>\n\t\t\t\t<Text color=\"gray\"> | </Text>\n\t\t\t\t<Text color=\"gray\">Ctrl+C to exit</Text>\n\t\t\t</Box>\n\n\t\t\t{/* Row 2: Schema info and mode */}\n\t\t\t<Box>\n\t\t\t\t<Text color=\"gray\">Schema: </Text>\n\t\t\t\t<Text color=\"white\">{schemaPath}</Text>\n\t\t\t\t<Text color=\"gray\">\n\t\t\t\t\t{' '}\n\t\t\t\t\t({tableCount} tables, {relationCount} relations)\n\t\t\t\t</Text>\n\t\t\t\t<Text color=\"gray\"> | Mode: </Text>\n\t\t\t\t<Text color={mode === 'natural' ? 'green' : 'yellow'}>{mode}</Text>\n\t\t\t\t{schemaName && (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<Text color=\"gray\"> | Schema: </Text>\n\t\t\t\t\t\t<Text color=\"cyan\">{schemaName}</Text>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</Box>\n\n\t\t\t{/* Row 3: Dialect, Strategy, Aliasing (CLI-013) */}\n\t\t\t<Box>\n\t\t\t\t<Text color=\"gray\">Dialect: </Text>\n\t\t\t\t<Text color=\"blue\">{DIALECT_DISPLAY[dialect]}</Text>\n\n\t\t\t\t<Text color=\"gray\"> | Strategy: </Text>\n\t\t\t\t<Text color=\"magenta\">{STRATEGY_DISPLAY[includeStrategy]}</Text>\n\n\t\t\t\t<Text color=\"gray\"> | Alias: </Text>\n\t\t\t\t<Text color={aliasingMode === 'always' ? 'cyan' : 'yellow'}>\n\t\t\t\t\t{aliasingMode === 'always' ? 'all' : 'collision'}\n\t\t\t\t</Text>\n\n\t\t\t\t{/* CLI-NQL: Parse and Explain mode indicators */}\n\t\t\t\t{parseMode && (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<Text color=\"gray\"> | </Text>\n\t\t\t\t\t\t<Text color=\"blue\">[parse]</Text>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t\t{explainMode && (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<Text color=\"gray\"> | </Text>\n\t\t\t\t\t\t<Text color=\"yellow\">[explain]</Text>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\n\t\t\t\t{/* CLI-020: Database connection status */}\n\t\t\t\t{connected && (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<Text color=\"gray\"> | </Text>\n\t\t\t\t\t\t<Text color=\"green\">DB: {databaseName}</Text>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t\t{/* Always show exec mode indicator when connected */}\n\t\t\t\t{connected && (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<Text color=\"gray\"> | </Text>\n\t\t\t\t\t\t<Text color={execMode ? 'green' : 'gray'}>\n\t\t\t\t\t\t\t[exec: {execMode ? 'ON' : 'OFF'}]\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</Box>\n\t\t</Box>\n\t);\n}\n","import React from 'react';\n/**\n * DX-030: REPL Help Display Component\n */\n\nimport { Box, Text } from 'ink';\n\nconst DOT_COMMANDS = [\n\t{ command: '.help', description: 'Show this help' },\n\t{ command: '.tables', description: 'List all tables in schema' },\n\t{\n\t\tcommand: '.schema [table]',\n\t\tdescription: 'Show schema info (or specific table)',\n\t},\n\t{ command: '.relations', description: 'List all relations' },\n\t{\n\t\tcommand: '.history',\n\t\tdescription: 'Show command history (↑/↓ to navigate, Ctrl+R to search)',\n\t},\n\t{\n\t\tcommand: '.sql',\n\t\tdescription: 'SQL mode: input is raw SQL, ! escapes to natural',\n\t},\n\t{\n\t\tcommand: '.natural',\n\t\tdescription: 'Natural mode: input is parsed, ! escapes to SQL',\n\t},\n\t{\n\t\tcommand: '.use [schema]',\n\t\tdescription: 'Set schema for queries (empty to clear)',\n\t},\n\t{ command: '.split', description: 'Toggle split view (schema | query)' },\n\t{\n\t\tcommand: '.aliasing',\n\t\tdescription: 'Toggle column aliasing mode (always/onCollision)',\n\t},\n\t{\n\t\tcommand: '.strategy [mode]',\n\t\tdescription:\n\t\t\t'Show/set include strategy (auto|join|separate|cte|lateral|json_agg)',\n\t},\n\t{\n\t\tcommand: '.dialect [name]',\n\t\tdescription: 'Show/set SQL dialect (postgresql|mysql|sqlite|mssql|duckdb)',\n\t},\n\t{\n\t\tcommand: '.exec [on|off]',\n\t\tdescription: 'Toggle execution mode (requires --db connection)',\n\t},\n\t{\n\t\tcommand: '.import <file>',\n\t\tdescription: 'Execute SQL file (DDL, seed data)',\n\t},\n\t{\n\t\tcommand: '.parse [on|off]',\n\t\tdescription: 'Toggle parse tree (AST) output for queries',\n\t},\n\t{\n\t\tcommand: '.explain [on|off]',\n\t\tdescription: 'Toggle EXPLAIN prefix for queries',\n\t},\n\t{\n\t\tcommand: '.table [option] [value]',\n\t\tdescription:\n\t\t\t'Configure table display (borders, overflow, headers, padding)',\n\t},\n\t{ command: '.clear', description: 'Clear screen and output' },\n\t{ command: '.exit / .quit', description: 'Exit REPL' },\n];\n\nconst NATURAL_SYNTAX = [\n\t{\n\t\tpattern: '<table>',\n\t\texample: 'users',\n\t\tdescription: 'Select all from table',\n\t},\n\t{\n\t\tpattern: '<table> where <cond>',\n\t\texample: 'users where active = true',\n\t\tdescription: 'Filter results',\n\t},\n\t{\n\t\tpattern: '<table> include <rel>',\n\t\texample: 'users include posts',\n\t\tdescription: 'Include related data',\n\t},\n\t{\n\t\tpattern: '<table> limit <n>',\n\t\texample: 'users limit 10',\n\t\tdescription: 'Limit results',\n\t},\n\t{\n\t\tpattern: '!<query>',\n\t\texample: '!SELECT... or !users',\n\t\tdescription: 'Mode escape: SQL in natural mode, natural in SQL mode',\n\t},\n];\n\nfunction SimpleTable({\n\tdata,\n\tcolumns,\n}: {\n\tdata: Record<string, string>[];\n\tcolumns: string[];\n}) {\n\treturn (\n\t\t<Box flexDirection=\"column\">\n\t\t\t{data.map((row, i) => (\n\t\t\t\t<Box key={i}>\n\t\t\t\t\t{columns.map((col, j) => (\n\t\t\t\t\t\t<Box key={col} width={col === 'description' ? 50 : 25}>\n\t\t\t\t\t\t\t<Text color={j === 0 ? 'cyan' : 'white'}>{row[col]}</Text>\n\t\t\t\t\t\t</Box>\n\t\t\t\t\t))}\n\t\t\t\t</Box>\n\t\t\t))}\n\t\t</Box>\n\t);\n}\n\nexport function HelpDisplay() {\n\treturn (\n\t\t<Box flexDirection=\"column\" marginY={1}>\n\t\t\t<Text bold color=\"yellow\">\n\t\t\t\t📚 Dot Commands:\n\t\t\t</Text>\n\t\t\t<Box marginTop={1} marginBottom={1} flexDirection=\"column\">\n\t\t\t\t<SimpleTable data={DOT_COMMANDS} columns={['command', 'description']} />\n\t\t\t</Box>\n\n\t\t\t<Text bold color=\"cyan\">\n\t\t\t\t📝 Natural Query Syntax:\n\t\t\t</Text>\n\t\t\t<Box marginTop={1} flexDirection=\"column\">\n\t\t\t\t<SimpleTable\n\t\t\t\t\tdata={NATURAL_SYNTAX}\n\t\t\t\t\tcolumns={['pattern', 'example', 'description']}\n\t\t\t\t/>\n\t\t\t</Box>\n\n\t\t\t<Box marginTop={1}>\n\t\t\t\t<Text color=\"gray\">\n\t\t\t\t\tTip: Use .sql to switch to raw SQL mode, .natural to return\n\t\t\t\t</Text>\n\t\t\t</Box>\n\t\t</Box>\n\t);\n}\n","import React from 'react';\n/**\n * DX-030: REPL Input Prompt Component with History Support\n * CLI-015: Enhanced keyboard shortcuts\n * CLI-MUT: Ctrl+R reverse history search\n */\n\nimport { Box, Text, useInput } from 'ink';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport type { CommandHistory } from '../history.js';\nimport type { QueryMode } from '../types.js';\nimport { EnhancedTextInput } from './EnhancedTextInput.js';\n\ninterface InputPromptProps {\n\tonSubmit: (value: string) => void;\n\tmode: QueryMode;\n\t/** Key to reset the input (increment to clear) */\n\tresetKey?: number;\n\t/** Command history instance for up/down navigation */\n\thistory?: CommandHistory;\n\t/** Callback when input value changes */\n\tonInputChange?: (value: string) => void;\n\t/** Currently selected completion text (from Tab navigation) */\n\tselectedCompletion?: string;\n\t/** Callback when a completion is accepted (Enter with selection) */\n\tonCompletionAccepted?: () => void;\n\t/** Function to apply completion to current input (replaces partial word) */\n\tapplyCompletion?: (currentInput: string, completionText: string) => string;\n}\n\nexport function InputPrompt({\n\tonSubmit,\n\tmode,\n\tresetKey = 0,\n\thistory,\n\tonInputChange,\n\tselectedCompletion,\n\tonCompletionAccepted,\n\tapplyCompletion,\n}: InputPromptProps) {\n\tconst promptSymbol = mode === 'natural' ? '>' : 'sql>';\n\tconst promptColor = mode === 'natural' ? 'green' : 'yellow';\n\n\t// Track current input for history navigation\n\tconst [currentInput, setCurrentInput] = useState('');\n\tconst [historyKey, setHistoryKey] = useState(0);\n\tconst [historyValue, setHistoryValue] = useState<string | undefined>(\n\t\tundefined,\n\t);\n\n\t// CLI-MUT: Reverse history search state (Ctrl+R)\n\tconst [searchMode, setSearchMode] = useState(false);\n\tconst [searchQuery, setSearchQuery] = useState('');\n\tconst [searchMatchIndex, setSearchMatchIndex] = useState(0);\n\n\t// Compute search matches when query changes\n\tconst searchMatches = useMemo(() => {\n\t\tif (!history || !searchQuery) return [];\n\t\treturn history.reverseSearch(searchQuery);\n\t}, [history, searchQuery]);\n\n\t// Current match from search results\n\tconst currentMatch = searchMatches[searchMatchIndex] ?? '';\n\n\t// Reset history navigation state when resetKey changes\n\tuseEffect(() => {\n\t\tsetCurrentInput('');\n\t\tsetHistoryValue(undefined);\n\t\tsetHistoryKey((k) => k + 1);\n\t\tsetSearchMode(false);\n\t\tsetSearchQuery('');\n\t\tsetSearchMatchIndex(0);\n\t\thistory?.resetIndex();\n\t}, [resetKey, history]);\n\n\t// Handle arrow keys for history navigation and Ctrl+R for reverse search\n\tuseInput((input, key) => {\n\t\tif (!history) return;\n\n\t\t// CLI-MUT: Ctrl+R triggers reverse search mode\n\t\tif (key.ctrl && input === 'r') {\n\t\t\tif (searchMode) {\n\t\t\t\t// Already in search mode - go to next match\n\t\t\t\tif (searchMatches.length > 0) {\n\t\t\t\t\tsetSearchMatchIndex((i) => (i + 1) % searchMatches.length);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Enter search mode\n\t\t\t\tsetSearchMode(true);\n\t\t\t\tsetSearchQuery('');\n\t\t\t\tsetSearchMatchIndex(0);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// In search mode, handle special keys\n\t\tif (searchMode) {\n\t\t\t// Escape cancels search\n\t\t\tif (key.escape) {\n\t\t\t\tsetSearchMode(false);\n\t\t\t\tsetSearchQuery('');\n\t\t\t\tsetSearchMatchIndex(0);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Enter accepts current match\n\t\t\tif (key.return) {\n\t\t\t\tif (currentMatch) {\n\t\t\t\t\tsetHistoryValue(currentMatch);\n\t\t\t\t\tsetHistoryKey((k) => k + 1);\n\t\t\t\t\tsetCurrentInput(currentMatch);\n\t\t\t\t\tonInputChange?.(currentMatch);\n\t\t\t\t}\n\t\t\t\tsetSearchMode(false);\n\t\t\t\tsetSearchQuery('');\n\t\t\t\tsetSearchMatchIndex(0);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Don't process other keys here - let EnhancedTextInput handle them\n\t\t\treturn;\n\t\t}\n\n\t\t// Normal mode: up/down arrow for history navigation\n\t\tif (key.upArrow) {\n\t\t\tconst prev = history.previous(currentInput);\n\t\t\tif (prev !== undefined) {\n\t\t\t\tsetHistoryValue(prev);\n\t\t\t\tsetHistoryKey((k) => k + 1);\n\t\t\t}\n\t\t} else if (key.downArrow) {\n\t\t\tconst next = history.next();\n\t\t\tif (next !== undefined) {\n\t\t\t\tsetHistoryValue(next);\n\t\t\t\tsetHistoryKey((k) => k + 1);\n\t\t\t}\n\t\t}\n\t});\n\n\tconst handleSubmit = useCallback(\n\t\t(value: string) => {\n\t\t\t// If a completion is selected, accept it instead of executing\n\t\t\tif (selectedCompletion) {\n\t\t\t\t// Apply completion: replace partial word with completion text\n\t\t\t\tconst newValue = applyCompletion\n\t\t\t\t\t? applyCompletion(value, selectedCompletion)\n\t\t\t\t\t: selectedCompletion; // Fallback to old behavior\n\t\t\t\tsetHistoryValue(newValue);\n\t\t\t\tsetHistoryKey((k) => k + 1);\n\t\t\t\tsetCurrentInput(newValue);\n\t\t\t\tonInputChange?.(newValue);\n\t\t\t\tonCompletionAccepted?.();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (history && value.trim()) {\n\t\t\t\thistory.add(value);\n\t\t\t}\n\t\t\tsetCurrentInput('');\n\t\t\tsetHistoryValue(undefined);\n\t\t\tonSubmit(value);\n\t\t},\n\t\t[\n\t\t\thistory,\n\t\t\tonSubmit,\n\t\t\tselectedCompletion,\n\t\t\tonCompletionAccepted,\n\t\t\tonInputChange,\n\t\t\tapplyCompletion,\n\t\t],\n\t);\n\n\tconst handleChange = useCallback(\n\t\t(value: string) => {\n\t\t\tsetCurrentInput(value);\n\t\t\tonInputChange?.(value);\n\t\t},\n\t\t[onInputChange],\n\t);\n\n\t// Use combined key for resetting: resetKey (external) + historyKey (internal from history nav)\n\tconst combinedKey = `${resetKey}-${historyKey}`;\n\n\t// CLI-MUT: Handle search query input changes\n\tconst handleSearchChange = useCallback((value: string) => {\n\t\tsetSearchQuery(value);\n\t\tsetSearchMatchIndex(0); // Reset to first match when query changes\n\t}, []);\n\n\t// CLI-MUT: Search mode UI\n\tif (searchMode) {\n\t\treturn (\n\t\t\t<Box flexDirection=\"column\" marginTop={1}>\n\t\t\t\t{/* Show current match preview */}\n\t\t\t\t{currentMatch && (\n\t\t\t\t\t<Box>\n\t\t\t\t\t\t<Text color=\"gray\">→ </Text>\n\t\t\t\t\t\t<Text color=\"cyan\">{currentMatch}</Text>\n\t\t\t\t\t</Box>\n\t\t\t\t)}\n\t\t\t\t{/* Search input */}\n\t\t\t\t<Box>\n\t\t\t\t\t<Text color=\"magenta\" bold>\n\t\t\t\t\t\t(reverse-i-search)`\n\t\t\t\t\t</Text>\n\t\t\t\t\t<EnhancedTextInput\n\t\t\t\t\t\tkey={`search-${combinedKey}`}\n\t\t\t\t\t\tdefaultValue={searchQuery}\n\t\t\t\t\t\tonChange={handleSearchChange}\n\t\t\t\t\t\tplaceholder=\"\"\n\t\t\t\t\t/>\n\t\t\t\t\t<Text color=\"magenta\" bold>\n\t\t\t\t\t\t':\n\t\t\t\t\t</Text>\n\t\t\t\t\t{searchMatches.length > 0 && (\n\t\t\t\t\t\t<Text color=\"gray\">\n\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t({searchMatchIndex + 1}/{searchMatches.length})\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t)}\n\t\t\t\t</Box>\n\t\t\t</Box>\n\t\t);\n\t}\n\n\t// Normal mode UI\n\treturn (\n\t\t<Box marginTop={1}>\n\t\t\t<Text color={promptColor} bold>\n\t\t\t\t{promptSymbol}{' '}\n\t\t\t</Text>\n\t\t\t<EnhancedTextInput\n\t\t\t\tkey={combinedKey}\n\t\t\t\tdefaultValue={historyValue ?? ''}\n\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\tonChange={handleChange}\n\t\t\t\tplaceholder={\n\t\t\t\t\tmode === 'natural'\n\t\t\t\t\t\t? 'Enter query (e.g., users where active = true) or .help'\n\t\t\t\t\t\t: 'Enter SQL query or .natural to switch mode'\n\t\t\t\t}\n\t\t\t/>\n\t\t</Box>\n\t);\n}\n","/**\n * CLI-015: Enhanced Text Input with keyboard shortcuts\n *\n * Supports standard terminal shortcuts:\n * - Home / Ctrl+A: Move to beginning\n * - End / Ctrl+E: Move to end\n * - Ctrl+W: Delete word backward\n * - Ctrl+U: Delete to beginning\n * - Ctrl+K: Delete to end\n * - Ctrl+Left / Alt+B: Move word backward\n * - Ctrl+Right / Alt+F: Move word forward\n */\n\nimport { Box, Text, useInput, useStdin, useStdout } from 'ink';\nimport React, { useEffect, useRef, useState } from 'react';\n\ninterface EnhancedTextInputProps {\n\t/** Current value (controlled) */\n\tvalue?: string;\n\t/** Default value (uncontrolled) */\n\tdefaultValue?: string;\n\t/** Placeholder text */\n\tplaceholder?: string;\n\t/** Called when value changes */\n\tonChange?: (value: string) => void;\n\t/** Called when Enter is pressed */\n\tonSubmit?: (value: string) => void;\n\t/** Whether input is disabled */\n\tisDisabled?: boolean;\n\t/** Focus state (for multi-input forms) */\n\tisFocused?: boolean;\n}\n\n/**\n * Find the start of the previous word\n */\nfunction findPrevWordStart(text: string, cursor: number): number {\n\tif (cursor <= 0) return 0;\n\n\tlet pos = cursor - 1;\n\n\t// Skip trailing spaces\n\twhile (pos > 0 && text[pos] === ' ') {\n\t\tpos--;\n\t}\n\n\t// Find start of word\n\twhile (pos > 0 && text[pos - 1] !== ' ') {\n\t\tpos--;\n\t}\n\n\treturn pos;\n}\n\n/**\n * Find the end of the next word\n */\nfunction findNextWordEnd(text: string, cursor: number): number {\n\tif (cursor >= text.length) return text.length;\n\n\tlet pos = cursor;\n\n\t// Skip leading spaces\n\twhile (pos < text.length && text[pos] === ' ') {\n\t\tpos++;\n\t}\n\n\t// Find end of word\n\twhile (pos < text.length && text[pos] !== ' ') {\n\t\tpos++;\n\t}\n\n\treturn pos;\n}\n\nexport function EnhancedTextInput({\n\tvalue: controlledValue,\n\tdefaultValue = '',\n\tplaceholder = '',\n\tonChange,\n\tonSubmit,\n\tisDisabled = false,\n\tisFocused = true,\n}: EnhancedTextInputProps) {\n\tconst [internalValue, setInternalValue] = useState(defaultValue);\n\tconst [cursor, setCursor] = useState(defaultValue.length);\n\n\t// Refs mirror state for synchronous access during paste batches.\n\t// React batches useState updates, so within a single stdin chunk (paste),\n\t// each useInput callback sees the stale closure value. Refs update\n\t// immediately, letting each keystroke build on the previous one.\n\tconst valueRef = useRef(defaultValue);\n\tconst cursorRef = useRef(defaultValue.length);\n\tconst { stdout } = useStdout();\n\n\t// Track raw input to distinguish Delete (\\x1b[3~) from Backspace (\\x7f)\n\t// Ink's parser maps BOTH to key.delete, but we need to differentiate\n\tconst lastRawInputRef = useRef<string>('');\n\tconst { stdin } = useStdin();\n\n\t// Listen to raw stdin to capture the actual escape sequence\n\tuseEffect(() => {\n\t\tif (!stdin || isDisabled || !isFocused) return;\n\n\t\tconst handleRawData = (data: Buffer) => {\n\t\t\tlastRawInputRef.current = data.toString();\n\t\t};\n\n\t\tstdin.on('data', handleRawData);\n\t\treturn () => {\n\t\t\tstdin.off('data', handleRawData);\n\t\t};\n\t}, [stdin, isDisabled, isFocused]);\n\n\t// Support both controlled and uncontrolled modes\n\tconst value = controlledValue ?? internalValue;\n\n\t// Sync cursor when value changes externally\n\tuseEffect(() => {\n\t\tif (controlledValue !== undefined) {\n\t\t\tconst synced = Math.min(cursorRef.current, controlledValue.length);\n\t\t\tcursorRef.current = synced;\n\t\t\tsetCursor(synced);\n\t\t\tvalueRef.current = controlledValue;\n\t\t}\n\t}, [controlledValue]);\n\n\t// Reset when defaultValue changes (for history navigation)\n\tuseEffect(() => {\n\t\tif (controlledValue === undefined) {\n\t\t\tsetInternalValue(defaultValue);\n\t\t\tsetCursor(defaultValue.length);\n\t\t\tvalueRef.current = defaultValue;\n\t\t\tcursorRef.current = defaultValue.length;\n\t\t}\n\t}, [defaultValue, controlledValue]);\n\n\tconst updateValue = (newValue: string, newCursor?: number) => {\n\t\tconst nc = newCursor ?? newValue.length;\n\t\t// Update refs synchronously (critical for paste batches)\n\t\tvalueRef.current = newValue;\n\t\tcursorRef.current = nc;\n\t\t// Update state for rendering\n\t\tif (controlledValue === undefined) {\n\t\t\tsetInternalValue(newValue);\n\t\t}\n\t\tsetCursor(nc);\n\t\tonChange?.(newValue);\n\t};\n\n\tuseInput(\n\t\t(input, key) => {\n\t\t\tif (isDisabled || !isFocused) return;\n\n\t\t\t// Read from refs for correct values during paste batches\n\t\t\tconst val = valueRef.current;\n\t\t\tconst cur = cursorRef.current;\n\n\t\t\t// Submit on Enter (with multiline support)\n\t\t\tif (key.return) {\n\t\t\t\t// Shift+Enter → insert newline (terminals that support distinct sequence)\n\t\t\t\tif (key.shift) {\n\t\t\t\t\tconst newValue = `${val.slice(0, cur)}\\n${val.slice(cur)}`;\n\t\t\t\t\tupdateValue(newValue, cur + 1);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// Backslash continuation: if line ends with \\, replace \\ with newline\n\t\t\t\tif (val.endsWith('\\\\')) {\n\t\t\t\t\tconst newValue = `${val.slice(0, -1)}\\n`;\n\t\t\t\t\tupdateValue(newValue, newValue.length);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// Normal Enter → submit, then reset refs immediately so next\n\t\t\t\t// pasted line starts fresh (before React re-renders)\n\t\t\t\tconst submitted = val;\n\t\t\t\tvalueRef.current = '';\n\t\t\t\tcursorRef.current = 0;\n\t\t\t\tonSubmit?.(submitted);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Escape - could be used to clear or cancel\n\t\t\tif (key.escape) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// === CURSOR MOVEMENT ===\n\n\t\t\t// Home key - move to beginning (native in Ink 6.6.0+)\n\t\t\tif (key.home) {\n\t\t\t\tcursorRef.current = 0;\n\t\t\t\tsetCursor(0);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// End key - move to end (native in Ink 6.6.0+)\n\t\t\tif (key.end) {\n\t\t\t\tcursorRef.current = val.length;\n\t\t\t\tsetCursor(val.length);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Left arrow\n\t\t\tif (key.leftArrow) {\n\t\t\t\tif (key.ctrl || key.meta) {\n\t\t\t\t\tconst nc = findPrevWordStart(val, cur);\n\t\t\t\t\tcursorRef.current = nc;\n\t\t\t\t\tsetCursor(nc);\n\t\t\t\t} else {\n\t\t\t\t\tconst nc = Math.max(0, cur - 1);\n\t\t\t\t\tcursorRef.current = nc;\n\t\t\t\t\tsetCursor(nc);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Right arrow\n\t\t\tif (key.rightArrow) {\n\t\t\t\tif (key.ctrl || key.meta) {\n\t\t\t\t\tconst nc = findNextWordEnd(val, cur);\n\t\t\t\t\tcursorRef.current = nc;\n\t\t\t\t\tsetCursor(nc);\n\t\t\t\t} else {\n\t\t\t\t\tconst nc = Math.min(val.length, cur + 1);\n\t\t\t\t\tcursorRef.current = nc;\n\t\t\t\t\tsetCursor(nc);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Home (Ctrl+A in terminal) - move to beginning\n\t\t\tif (key.ctrl && input === 'a') {\n\t\t\t\tcursorRef.current = 0;\n\t\t\t\tsetCursor(0);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// End (Ctrl+E in terminal) - move to end\n\t\t\tif (key.ctrl && input === 'e') {\n\t\t\t\tcursorRef.current = val.length;\n\t\t\t\tsetCursor(val.length);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Alt+B - move word backward (like Ctrl+Left)\n\t\t\tif (key.meta && input === 'b') {\n\t\t\t\tconst nc = findPrevWordStart(val, cur);\n\t\t\t\tcursorRef.current = nc;\n\t\t\t\tsetCursor(nc);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Alt+F - move word forward (like Ctrl+Right)\n\t\t\tif (key.meta && input === 'f') {\n\t\t\t\tconst nc = findNextWordEnd(val, cur);\n\t\t\t\tcursorRef.current = nc;\n\t\t\t\tsetCursor(nc);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// === DELETION ===\n\t\t\t// Use raw input ref to distinguish Delete from Backspace\n\t\t\t// Ink maps BOTH \\x7f and \\x1b[3~ to key.delete, but we need to differentiate\n\t\t\tconst rawInput = lastRawInputRef.current;\n\n\t\t\t// Delete key (forward delete) - Check RAW input for \\x1b[3~ sequence\n\t\t\t// This MUST come before backspace check since both trigger key.delete\n\t\t\tif (rawInput === '\\x1b[3~' || rawInput.startsWith('\\x1b[3~')) {\n\t\t\t\tif (cur < val.length) {\n\t\t\t\t\tconst newValue = val.slice(0, cur) + val.slice(cur + 1);\n\t\t\t\t\tupdateValue(newValue, cur);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Backspace - delete character BEFORE cursor\n\t\t\tconst isBackspace =\n\t\t\t\tkey.backspace ||\n\t\t\t\trawInput === '\\x7f' ||\n\t\t\t\trawInput === '\\x08' ||\n\t\t\t\tinput === '\\x7f' ||\n\t\t\t\tinput === '\\x08';\n\t\t\tif (isBackspace) {\n\t\t\t\tif (cur > 0) {\n\t\t\t\t\tconst newValue = val.slice(0, cur - 1) + val.slice(cur);\n\t\t\t\t\tupdateValue(newValue, cur - 1);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Ctrl+W - delete word backward\n\t\t\tif (key.ctrl && input === 'w') {\n\t\t\t\tconst wordStart = findPrevWordStart(val, cur);\n\t\t\t\tconst newValue = val.slice(0, wordStart) + val.slice(cur);\n\t\t\t\tupdateValue(newValue, wordStart);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Ctrl+U - delete from cursor to beginning\n\t\t\tif (key.ctrl && input === 'u') {\n\t\t\t\tconst newValue = val.slice(cur);\n\t\t\t\tupdateValue(newValue, 0);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Ctrl+K - delete from cursor to end\n\t\t\tif (key.ctrl && input === 'k') {\n\t\t\t\tconst newValue = val.slice(0, cur);\n\t\t\t\tupdateValue(newValue, cur);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Ctrl+H - same as backspace (terminal convention)\n\t\t\tif (key.ctrl && input === 'h') {\n\t\t\t\tif (cur > 0) {\n\t\t\t\t\tconst newValue = val.slice(0, cur - 1) + val.slice(cur);\n\t\t\t\t\tupdateValue(newValue, cur - 1);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// === CHARACTER INPUT ===\n\n\t\t\t// Tab - ignore (could be used for completion)\n\t\t\tif (key.tab) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Regular character input\n\t\t\tif (input && !key.ctrl && !key.meta) {\n\t\t\t\t// Detect multiline paste: input string contains line breaks.\n\t\t\t\t// Submit every non-empty line immediately — the user pasted\n\t\t\t\t// a block of text and expects all lines to execute.\n\t\t\t\tif (input.includes('\\n') || input.includes('\\r')) {\n\t\t\t\t\tconst fullText = val.slice(0, cur) + input + val.slice(cur);\n\t\t\t\t\tconst parts = fullText.split(/\\r\\n|\\r|\\n/);\n\t\t\t\t\tconst toSubmit = parts.map((l) => l.trim()).filter(Boolean);\n\n\t\t\t\t\tif (toSubmit.length > 0) {\n\t\t\t\t\t\tvalueRef.current = '';\n\t\t\t\t\t\tcursorRef.current = 0;\n\t\t\t\t\t\tfor (const line of toSubmit) {\n\t\t\t\t\t\t\tonSubmit?.(line);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// All lines were blank — clear buffer\n\t\t\t\t\tupdateValue('', 0);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst newValue = val.slice(0, cur) + input + val.slice(cur);\n\t\t\t\tupdateValue(newValue, cur + input.length);\n\t\t\t}\n\t\t},\n\t\t{ isActive: isFocused && !isDisabled },\n\t);\n\n\t// Render the input with cursor (supports multiline)\n\tconst showPlaceholder = value.length === 0;\n\tconst isMultiline = value.includes('\\n');\n\n\tif (showPlaceholder) {\n\t\treturn (\n\t\t\t<Box>\n\t\t\t\t<Text inverse> </Text>\n\t\t\t\t<Text dimColor>{placeholder}</Text>\n\t\t\t</Box>\n\t\t);\n\t}\n\n\t// Multiline rendering: split by newlines, show cursor on correct line\n\tif (isMultiline) {\n\t\tconst lines = value.split('\\n');\n\t\tlet charsSoFar = 0;\n\n\t\treturn (\n\t\t\t<Box flexDirection=\"column\">\n\t\t\t\t{lines.map((line, lineIdx) => {\n\t\t\t\t\tconst lineStart = charsSoFar;\n\t\t\t\t\tcharsSoFar += line.length + 1; // +1 for the \\n\n\n\t\t\t\t\tconst cursorInThisLine =\n\t\t\t\t\t\tcursor >= lineStart && cursor < lineStart + line.length + 1;\n\n\t\t\t\t\tif (!cursorInThisLine) {\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<Text key={lineIdx}>\n\t\t\t\t\t\t\t\t{lineIdx > 0 && <Text color=\"gray\">... </Text>}\n\t\t\t\t\t\t\t\t{line}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst cursorInLine = cursor - lineStart;\n\t\t\t\t\tconst before = line.slice(0, cursorInLine);\n\t\t\t\t\tconst at = line[cursorInLine] ?? ' ';\n\t\t\t\t\tconst after = line.slice(cursorInLine + 1);\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<Text key={lineIdx}>\n\t\t\t\t\t\t\t{lineIdx > 0 && <Text color=\"gray\">... </Text>}\n\t\t\t\t\t\t\t{before}\n\t\t\t\t\t\t\t<Text inverse>{at}</Text>\n\t\t\t\t\t\t\t{after}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</Box>\n\t\t);\n\t}\n\n\t// Single-line rendering with horizontal scrolling window\n\t// Prevents terminal wrapping issues by keeping visible text within terminal width\n\tconst termWidth = (stdout?.columns ?? 80) - 4; // Reserve space for prompt + margin\n\tconst len = value.length;\n\n\tif (len <= termWidth) {\n\t\t// Fits on one line — no scrolling needed\n\t\tconst beforeCursor = value.slice(0, cursor);\n\t\tconst atCursor = value[cursor] ?? ' ';\n\t\tconst afterCursor = value.slice(cursor + 1);\n\n\t\treturn (\n\t\t\t<Box>\n\t\t\t\t<Text>{beforeCursor}</Text>\n\t\t\t\t<Text inverse>{atCursor}</Text>\n\t\t\t\t<Text>{afterCursor}</Text>\n\t\t\t</Box>\n\t\t);\n\t}\n\n\t// Scrolling window: show a portion of the text, keep cursor visible\n\tconst ellipsis = '…';\n\tconst usable = termWidth - 2; // Reserve 2 chars for potential ellipsis on each side\n\t// Center the window on the cursor\n\tlet windowStart = cursor - Math.floor(usable / 2);\n\tif (windowStart < 0) windowStart = 0;\n\tif (windowStart + usable > len) windowStart = Math.max(0, len - usable);\n\n\tconst windowEnd = Math.min(windowStart + usable, len);\n\tconst showLeftEllipsis = windowStart > 0;\n\tconst showRightEllipsis = windowEnd < len;\n\n\tconst visibleText = value.slice(windowStart, windowEnd);\n\tconst cursorInWindow = cursor - windowStart;\n\n\tconst before = visibleText.slice(0, cursorInWindow);\n\tconst at = visibleText[cursorInWindow] ?? ' ';\n\tconst after = visibleText.slice(cursorInWindow + 1);\n\n\treturn (\n\t\t<Box>\n\t\t\t{showLeftEllipsis && <Text color=\"gray\">{ellipsis}</Text>}\n\t\t\t<Text>{before}</Text>\n\t\t\t<Text inverse>{at}</Text>\n\t\t\t<Text>{after}</Text>\n\t\t\t{showRightEllipsis && <Text color=\"gray\">{ellipsis}</Text>}\n\t\t</Box>\n\t);\n}\n","/**\n * InspectionPanel — Anchored panel below the input area.\n *\n * Displays detailed inspection of the last query result (SQL, plan, results,\n * params, dump) without polluting the conversation scroll.\n * Tab bar at top cycles through views with Tab key.\n * Activated by dot commands: .show sql|plan|results|params|dump\n * Closed by: .close, Esc\n */\n\nimport { Box, Text } from 'ink';\nimport React from 'react';\nimport type { PanelView } from '../engine/engine-types.js';\nimport { ExecutionResultDisplay } from '../result-formatter.js';\nimport type { ExecutionResult, QueryResult } from '../types.js';\nimport {\n\tParseTreeOutput,\n\tPlanOutput,\n\tSeparateQueriesOutput,\n\tSqlOutput,\n} from './OutputDisplay.js';\n\ninterface InspectionPanelProps {\n\tview: PanelView;\n\tqueryResult: QueryResult | null;\n\texecutionResult: ExecutionResult | null;\n\texecMode: boolean;\n\tonViewChange: (view: PanelView) => void;\n}\n\nconst ALL_VIEWS: PanelView[] = ['sql', 'plan', 'results', 'params', 'dump'];\n\nconst TAB_LABELS: Record<PanelView, string> = {\n\tsql: 'SQL',\n\tplan: 'Plan',\n\tresults: 'Results',\n\tparams: 'Params',\n\tdump: 'Dump',\n};\n\nfunction TabBar({\n\tactiveView,\n\texecMode,\n}: {\n\tactiveView: PanelView;\n\texecMode: boolean;\n}) {\n\treturn (\n\t\t<Box>\n\t\t\t{ALL_VIEWS.map((v, i) => {\n\t\t\t\tconst isActive = v === activeView;\n\t\t\t\tconst isDimmed = v === 'results' && !execMode;\n\t\t\t\treturn (\n\t\t\t\t\t<React.Fragment key={v}>\n\t\t\t\t\t\t{i > 0 && <Text color=\"gray\"> </Text>}\n\t\t\t\t\t\t{isActive ? (\n\t\t\t\t\t\t\t<Text bold inverse color=\"blue\">\n\t\t\t\t\t\t\t\t{` ${TAB_LABELS[v]} `}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<Text color={isDimmed ? 'gray' : 'white'} dimColor={isDimmed}>\n\t\t\t\t\t\t\t\t{` ${TAB_LABELS[v]} `}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</React.Fragment>\n\t\t\t\t);\n\t\t\t})}\n\t\t\t<Text color=\"gray\"> Tab↹ cycle · Esc close</Text>\n\t\t</Box>\n\t);\n}\n\nfunction PanelContent({\n\tview,\n\tqueryResult,\n\texecutionResult,\n\texecMode,\n}: InspectionPanelProps) {\n\tif (!queryResult && !executionResult) {\n\t\treturn <Text color=\"gray\">No query result to inspect.</Text>;\n\t}\n\n\tswitch (view) {\n\t\tcase 'sql': {\n\t\t\tif (!queryResult) return <Text color=\"gray\">No SQL available.</Text>;\n\t\t\treturn (\n\t\t\t\t<Box flexDirection=\"column\">\n\t\t\t\t\t<SqlOutput\n\t\t\t\t\t\tsql={queryResult.sql}\n\t\t\t\t\t\tparams={queryResult.params}\n\t\t\t\t\t\tlabel=\"Main SQL:\"\n\t\t\t\t\t/>\n\t\t\t\t\t{queryResult.separateQueries &&\n\t\t\t\t\t\tqueryResult.separateQueries.length > 0 && (\n\t\t\t\t\t\t\t<SeparateQueriesOutput queries={queryResult.separateQueries} />\n\t\t\t\t\t\t)}\n\t\t\t\t</Box>\n\t\t\t);\n\t\t}\n\n\t\tcase 'plan': {\n\t\t\tif (!queryResult?.plan)\n\t\t\t\treturn <Text color=\"gray\">No query plan available.</Text>;\n\t\t\treturn <PlanOutput plan={queryResult.plan} verbosity=\"verbose\" />;\n\t\t}\n\n\t\tcase 'results': {\n\t\t\tif (!execMode)\n\t\t\t\treturn (\n\t\t\t\t\t<Text color=\"gray\">Not in execution mode. Use .exec to enable.</Text>\n\t\t\t\t);\n\t\t\tif (!executionResult)\n\t\t\t\treturn (\n\t\t\t\t\t<Text color=\"gray\">\n\t\t\t\t\t\tNo execution results yet. Run a query with .exec enabled.\n\t\t\t\t\t</Text>\n\t\t\t\t);\n\t\t\treturn <ExecutionResultDisplay result={executionResult} />;\n\t\t}\n\n\t\tcase 'params': {\n\t\t\tif (!queryResult)\n\t\t\t\treturn <Text color=\"gray\">No parameters available.</Text>;\n\t\t\tconst params = queryResult.params;\n\t\t\tif (params.length === 0) {\n\t\t\t\treturn <Text color=\"gray\">No parameters (static query).</Text>;\n\t\t\t}\n\t\t\treturn (\n\t\t\t\t<Box flexDirection=\"column\">\n\t\t\t\t\t{params.map((p, i) => (\n\t\t\t\t\t\t<Text key={i}>\n\t\t\t\t\t\t\t<Text color=\"cyan\">${i + 1}</Text>\n\t\t\t\t\t\t\t<Text color=\"gray\"> = </Text>\n\t\t\t\t\t\t\t<Text color=\"green\">{JSON.stringify(p)}</Text>\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t))}\n\t\t\t\t</Box>\n\t\t\t);\n\t\t}\n\n\t\tcase 'dump': {\n\t\t\treturn (\n\t\t\t\t<Box flexDirection=\"column\">\n\t\t\t\t\t{queryResult && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<SqlOutput\n\t\t\t\t\t\t\t\tsql={queryResult.sql}\n\t\t\t\t\t\t\t\tparams={queryResult.params}\n\t\t\t\t\t\t\t\tlabel=\"Main SQL:\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t{queryResult.separateQueries &&\n\t\t\t\t\t\t\t\tqueryResult.separateQueries.length > 0 && (\n\t\t\t\t\t\t\t\t\t<SeparateQueriesOutput\n\t\t\t\t\t\t\t\t\t\tqueries={queryResult.separateQueries}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{queryResult.plan && (\n\t\t\t\t\t\t\t\t<PlanOutput plan={queryResult.plan} verbosity=\"verbose\" />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{queryResult.parsedQuery !== undefined && (\n\t\t\t\t\t\t\t\t<ParseTreeOutput parsed={queryResult.parsedQuery} />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t\t{executionResult && (\n\t\t\t\t\t\t<ExecutionResultDisplay result={executionResult} />\n\t\t\t\t\t)}\n\t\t\t\t</Box>\n\t\t\t);\n\t\t}\n\t}\n}\n\nexport function InspectionPanel(props: InspectionPanelProps) {\n\treturn (\n\t\t<Box\n\t\t\tflexDirection=\"column\"\n\t\t\tborderStyle=\"single\"\n\t\t\tborderColor=\"blue\"\n\t\t\tpaddingX={1}\n\t\t\tmarginTop={1}\n\t\t>\n\t\t\t<TabBar activeView={props.view} execMode={props.execMode} />\n\t\t\t<Box flexDirection=\"column\" marginTop={1}>\n\t\t\t\t<PanelContent {...props} />\n\t\t\t</Box>\n\t\t</Box>\n\t);\n}\n","/**\n * CLI-020: Result Formatter Component\n *\n * Displays database query results in a formatted table using @oclif/table.\n */\n\nimport { makeTable } from '@oclif/table';\nimport { Box, Text } from 'ink';\nimport React from 'react';\nimport { config } from '../config.js';\nimport type { ExecutionResult } from './db-connection.js';\n\n/** Format a cell value for display */\nfunction formatValue(value: unknown): string {\n\tif (value === null) return 'NULL';\n\tif (value === undefined) return '';\n\tif (typeof value === 'string') return value;\n\tif (typeof value === 'number') return String(value);\n\tif (typeof value === 'boolean') return value ? 'true' : 'false';\n\tif (value instanceof Date) return value.toISOString();\n\tif (Array.isArray(value)) return JSON.stringify(value);\n\tif (typeof value === 'object') return JSON.stringify(value);\n\treturn String(value);\n}\n\ninterface ExecutionResultDisplayProps {\n\tresult: ExecutionResult;\n}\n\nexport function ExecutionResultDisplay({\n\tresult,\n}: ExecutionResultDisplayProps) {\n\t// Handle error\n\tif (result.error) {\n\t\treturn (\n\t\t\t<Box flexDirection=\"column\" marginY={1}>\n\t\t\t\t<Text bold color=\"red\">\n\t\t\t\t\t❌ Database Error\n\t\t\t\t</Text>\n\t\t\t\t<Text color=\"red\">{result.error}</Text>\n\t\t\t\t<Text color=\"gray\" dimColor>\n\t\t\t\t\t({result.executionTimeMs}ms)\n\t\t\t\t</Text>\n\t\t\t</Box>\n\t\t);\n\t}\n\n\t// Handle empty result\n\tif (result.rows.length === 0) {\n\t\treturn (\n\t\t\t<Box flexDirection=\"column\" marginY={1}>\n\t\t\t\t<Text color=\"gray\">0 rows ({result.executionTimeMs}ms)</Text>\n\t\t\t</Box>\n\t\t);\n\t}\n\n\tconst { columns, rows, rowCount, executionTimeMs, truncated } = result;\n\n\t// Get table configuration\n\tconst tableConfig = config.getTable();\n\n\t// Format data for @oclif/table\n\tconst formattedData = rows.map((row) => {\n\t\tconst formatted: Record<string, string> = {};\n\t\tfor (const col of columns) {\n\t\t\tformatted[col] = formatValue(row[col]);\n\t\t}\n\t\treturn formatted;\n\t});\n\n\t// Build column config with configured overflow\n\tconst columnConfig = columns.map((col) => ({\n\t\tkey: col,\n\t\tname: col,\n\t\toverflow: tableConfig.overflow,\n\t}));\n\n\t// Generate table string using @oclif/table\n\t// Map 'none' formatter to identity function (oclif/table doesn't have 'none')\n\tconst headerFormatter =\n\t\ttableConfig.headerFormatter === 'none'\n\t\t\t? (h: string) => h\n\t\t\t: tableConfig.headerFormatter;\n\n\tconst tableOutput = makeTable({\n\t\tdata: formattedData,\n\t\tcolumns: columnConfig,\n\t\tborderStyle: tableConfig.borderStyle,\n\t\theaderOptions: {\n\t\t\tformatter: headerFormatter,\n\t\t},\n\t\tpadding: tableConfig.padding,\n\t});\n\n\treturn (\n\t\t<Box flexDirection=\"column\" marginY={1}>\n\t\t\t<Text>{tableOutput}</Text>\n\t\t\t<Text color=\"green\">\n\t\t\t\t{rowCount} row{rowCount !== 1 ? 's' : ''} ({executionTimeMs}ms)\n\t\t\t\t{truncated && (\n\t\t\t\t\t<Text color=\"yellow\"> (truncated, showing first 100)</Text>\n\t\t\t\t)}\n\t\t\t</Text>\n\t\t</Box>\n\t);\n}\n","import React from 'react';\n/**\n * DX-030: REPL Output Display Component\n */\n\nimport { Box, Text } from 'ink';\nimport type { PlanVerbosity } from '../engine/engine-types.js';\nimport type { QueryResult, SeparateQueryResult } from '../types.js';\n\ninterface OutputDisplayProps {\n\tresult: QueryResult | null;\n\tplanVerbosity?: PlanVerbosity;\n}\n\nexport function SqlOutput({\n\tsql,\n\tparams,\n\tlabel = '📝 Generated SQL:',\n}: {\n\tsql: string;\n\tparams: readonly unknown[];\n\tlabel?: string;\n}) {\n\treturn (\n\t\t<Box flexDirection=\"column\" marginY={1}>\n\t\t\t<Text bold color=\"yellow\">\n\t\t\t\t{label}\n\t\t\t</Text>\n\t\t\t<Box borderStyle=\"single\" borderColor=\"gray\" paddingX={1} marginTop={1}>\n\t\t\t\t<Text color=\"green\">{sql}</Text>\n\t\t\t</Box>\n\t\t\t{params.length > 0 && (\n\t\t\t\t<Text>\n\t\t\t\t\t<Text color=\"gray\">Parameters: </Text>\n\t\t\t\t\t<Text color=\"cyan\">{JSON.stringify(params)}</Text>\n\t\t\t\t</Text>\n\t\t\t)}\n\t\t</Box>\n\t);\n}\n\nexport function SeparateQueriesOutput({\n\tqueries,\n}: {\n\tqueries: SeparateQueryResult[];\n}) {\n\treturn (\n\t\t<Box flexDirection=\"column\" marginY={1}>\n\t\t\t{queries.map((q, i) => (\n\t\t\t\t<Box key={i} flexDirection=\"column\" marginBottom={1}>\n\t\t\t\t\t<Text bold color=\"cyan\">\n\t\t\t\t\t\t📎 Separate Query ({q.relation}):\n\t\t\t\t\t</Text>\n\t\t\t\t\t<Box\n\t\t\t\t\t\tborderStyle=\"single\"\n\t\t\t\t\t\tborderColor=\"cyan\"\n\t\t\t\t\t\tpaddingX={1}\n\t\t\t\t\t\tmarginTop={1}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Text color=\"green\">{q.sql}</Text>\n\t\t\t\t\t</Box>\n\t\t\t\t\t{q.params.length > 0 && (\n\t\t\t\t\t\t<Text>\n\t\t\t\t\t\t\t<Text color=\"gray\">Parameters: </Text>\n\t\t\t\t\t\t\t<Text color=\"cyan\">{JSON.stringify(q.params)}</Text>\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t)}\n\t\t\t\t</Box>\n\t\t\t))}\n\t\t</Box>\n\t);\n}\n\nexport function PlanOutput({\n\tplan,\n\tverbosity = 'normal',\n}: {\n\tplan: NonNullable<QueryResult['plan']>;\n\tverbosity?: PlanVerbosity;\n}) {\n\tconst hasDecisions = plan.decisions.length > 0;\n\tconst hasWarnings = plan.warnings.length > 0;\n\tconst hasCtes = plan.cteCount > 0;\n\n\t// Compact mode: always one-liner summary\n\tif (verbosity === 'compact' || (!hasDecisions && !hasCtes && !hasWarnings)) {\n\t\treturn (\n\t\t\t<Box marginY={1}>\n\t\t\t\t<Text bold color=\"magenta\">\n\t\t\t\t\t📋 Plan:{' '}\n\t\t\t\t</Text>\n\t\t\t\t<Text color=\"cyan\">\n\t\t\t\t\t{plan.rootTable || plan.strategy}\n\t\t\t\t\t{hasDecisions\n\t\t\t\t\t\t? ` (${plan.decisions.length} decision${plan.decisions.length > 1 ? 's' : ''}${hasWarnings ? `, ${plan.warnings.length} warning${plan.warnings.length > 1 ? 's' : ''}` : ''})`\n\t\t\t\t\t\t: ' (no decisions)'}\n\t\t\t\t</Text>\n\t\t\t\t{plan.planningTimeMs > 0 && (\n\t\t\t\t\t<Text color=\"gray\"> ⏱ {plan.planningTimeMs.toFixed(1)}ms</Text>\n\t\t\t\t)}\n\t\t\t</Box>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Box flexDirection=\"column\" marginY={1}>\n\t\t\t<Text bold color=\"magenta\">\n\t\t\t\t📋 Query Plan:\n\t\t\t</Text>\n\t\t\t<Box paddingLeft={2} flexDirection=\"column\">\n\t\t\t\t{plan.rootTable && (\n\t\t\t\t\t<Text>\n\t\t\t\t\t\tRoot: <Text color=\"cyan\">{plan.rootTable}</Text>\n\t\t\t\t\t</Text>\n\t\t\t\t)}\n\t\t\t\t{plan.tables.length > 0 && (\n\t\t\t\t\t<Text>\n\t\t\t\t\t\tTables: <Text color=\"cyan\">{plan.tables.join(', ')}</Text>\n\t\t\t\t\t</Text>\n\t\t\t\t)}\n\t\t\t\t{hasDecisions && (\n\t\t\t\t\t<Box flexDirection=\"column\" marginTop={1}>\n\t\t\t\t\t\t<Text bold>Decisions:</Text>\n\t\t\t\t\t\t{plan.decisions.map((d, i) => (\n\t\t\t\t\t\t\t<Box key={i} flexDirection=\"column\">\n\t\t\t\t\t\t\t\t<Text>\n\t\t\t\t\t\t\t\t\t<Text color=\"gray\"> • </Text>\n\t\t\t\t\t\t\t\t\t<Text color=\"blue\">{d.type}</Text>\n\t\t\t\t\t\t\t\t\t<Text color=\"gray\">: </Text>\n\t\t\t\t\t\t\t\t\t<Text color=\"cyan\">{d.context}</Text>\n\t\t\t\t\t\t\t\t\t<Text color=\"gray\"> — </Text>\n\t\t\t\t\t\t\t\t\t<Text color=\"green\">{d.choice}</Text>\n\t\t\t\t\t\t\t\t\t<Text color=\"gray\"> ({d.reasoning})</Text>\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t{verbosity === 'verbose' && (\n\t\t\t\t\t\t\t\t\t<Box paddingLeft={4} flexDirection=\"column\">\n\t\t\t\t\t\t\t\t\t\t{d.alternatives && d.alternatives.length > 0 && (\n\t\t\t\t\t\t\t\t\t\t\t<Text color=\"gray\">\n\t\t\t\t\t\t\t\t\t\t\t\t├ Alternatives: {d.alternatives.join(', ')}\n\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{d.foreignKey && (\n\t\t\t\t\t\t\t\t\t\t\t<Text color=\"gray\">\n\t\t\t\t\t\t\t\t\t\t\t\t├ FK:{' '}\n\t\t\t\t\t\t\t\t\t\t\t\t{Array.isArray(d.foreignKey)\n\t\t\t\t\t\t\t\t\t\t\t\t\t? d.foreignKey.join(', ')\n\t\t\t\t\t\t\t\t\t\t\t\t\t: d.foreignKey}\n\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{d.relationType && (\n\t\t\t\t\t\t\t\t\t\t\t<Text color=\"gray\">├ Relation: {d.relationType}</Text>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{(d.intentPath || d.relationPath) && (\n\t\t\t\t\t\t\t\t\t\t\t<Text color=\"gray\">\n\t\t\t\t\t\t\t\t\t\t\t\t└ Path: {d.intentPath ?? d.relationPath}\n\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</Box>\n\t\t\t\t)}\n\t\t\t\t{verbosity === 'verbose' && plan.ctes && plan.ctes.length > 0 ? (\n\t\t\t\t\t<Box flexDirection=\"column\" marginTop={1}>\n\t\t\t\t\t\t<Text bold>CTEs:</Text>\n\t\t\t\t\t\t{plan.ctes.map((c, i) => (\n\t\t\t\t\t\t\t<Box key={i} flexDirection=\"column\">\n\t\t\t\t\t\t\t\t<Text>\n\t\t\t\t\t\t\t\t\t<Text color=\"gray\"> • </Text>\n\t\t\t\t\t\t\t\t\t<Text color=\"cyan\">{c.name}</Text>\n\t\t\t\t\t\t\t\t\t<Text color=\"gray\">\n\t\t\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t\t\t— {c.purpose}\n\t\t\t\t\t\t\t\t\t\t{c.recursive ? ' (recursive)' : ''}\n\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t{c.referencedBy && c.referencedBy.length > 0 && (\n\t\t\t\t\t\t\t\t\t<Text color=\"gray\">\n\t\t\t\t\t\t\t\t\t\t{' └ Referenced by: '}\n\t\t\t\t\t\t\t\t\t\t{c.referencedBy.join(', ')}\n\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</Box>\n\t\t\t\t) : (\n\t\t\t\t\thasCtes && (\n\t\t\t\t\t\t<Text>\n\t\t\t\t\t\t\tCTEs: <Text color=\"cyan\">{plan.cteCount} extracted</Text>\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t)\n\t\t\t\t)}\n\t\t\t\t{hasWarnings && (\n\t\t\t\t\t<Box flexDirection=\"column\" marginTop={1}>\n\t\t\t\t\t\t<Text color=\"yellow\">⚠️ Warnings:</Text>\n\t\t\t\t\t\t{plan.warnings.map((w, i) => (\n\t\t\t\t\t\t\t<Box key={i} flexDirection=\"column\">\n\t\t\t\t\t\t\t\t<Text color=\"yellow\">\n\t\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t\t• {w.code ? `${w.code}: ` : ''}\n\t\t\t\t\t\t\t\t\t{w.message}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t{w.suggestion && <Text color=\"gray\"> → {w.suggestion}</Text>}\n\t\t\t\t\t\t\t\t{verbosity === 'verbose' && w.relatedDecision && (\n\t\t\t\t\t\t\t\t\t<Text color=\"gray\">\n\t\t\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t\t\t└ Related decision: {w.relatedDecision}\n\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</Box>\n\t\t\t\t)}\n\t\t\t\t{verbosity === 'verbose' && plan.metadata && (\n\t\t\t\t\t<Text color=\"gray\" dimColor>\n\t\t\t\t\t\t📊 Metadata: {plan.metadata.relationsAnalyzed} relation\n\t\t\t\t\t\t{plan.metadata.relationsAnalyzed !== 1 ? 's' : ''} analyzed\n\t\t\t\t\t\t{plan.metadata.isAmbiguous\n\t\t\t\t\t\t\t? ` | ambiguous (${plan.metadata.ambiguousOptions?.join(', ')})`\n\t\t\t\t\t\t\t: ' | not ambiguous'}\n\t\t\t\t\t</Text>\n\t\t\t\t)}\n\t\t\t\t{plan.planningTimeMs > 0 && (\n\t\t\t\t\t<Text color=\"gray\">\n\t\t\t\t\t\t⏱ Planning: {plan.planningTimeMs.toFixed(1)}ms\n\t\t\t\t\t</Text>\n\t\t\t\t)}\n\t\t\t</Box>\n\t\t</Box>\n\t);\n}\n\nexport function ErrorOutput({ message }: { message: string }) {\n\treturn (\n\t\t<Box marginY={1}>\n\t\t\t<Text color=\"red\">❌ Error: {message}</Text>\n\t\t</Box>\n\t);\n}\n\n/**\n * CLI-NQL: Format parsed query as a tree for .parse mode\n */\nexport function formatParseTree(parsed: unknown): string {\n\tconst lines: string[] = [];\n\n\tconst formatValue = (value: unknown, indent = 2): string => {\n\t\tconst pad = ' '.repeat(indent);\n\t\tif (value === null) return 'null';\n\t\tif (value === undefined) return 'undefined';\n\t\tif (typeof value === 'string') return `\"${value}\"`;\n\t\tif (typeof value === 'number' || typeof value === 'boolean')\n\t\t\treturn String(value);\n\t\tif (Array.isArray(value)) {\n\t\t\tif (value.length === 0) return '[]';\n\t\t\tconst items = value.map((v) => formatValue(v, indent + 2)).join(', ');\n\t\t\treturn `[${items}]`;\n\t\t}\n\t\tif (typeof value === 'object') {\n\t\t\tconst entries = Object.entries(value);\n\t\t\tif (entries.length === 0) return '{}';\n\t\t\tconst formatted = entries\n\t\t\t\t.map(([k, v]) => `${pad} ${k}: ${formatValue(v, indent + 2)}`)\n\t\t\t\t.join('\\n');\n\t\t\treturn `{\\n${formatted}\\n${pad}}`;\n\t\t}\n\t\treturn String(value);\n\t};\n\n\tlines.push('ParsedQuery {');\n\tconst obj = parsed as Record<string, unknown>;\n\tfor (const [key, value] of Object.entries(obj)) {\n\t\tif (value !== undefined) {\n\t\t\tlines.push(` ${key}: ${formatValue(value)}`);\n\t\t}\n\t}\n\tlines.push('}');\n\treturn lines.join('\\n');\n}\n\nexport function ParseTreeOutput({ parsed }: { parsed: unknown }) {\n\tconst treeText = formatParseTree(parsed);\n\treturn (\n\t\t<Box flexDirection=\"column\" marginY={1}>\n\t\t\t<Text bold color=\"blue\">\n\t\t\t\t🌳 Parse Tree (AST):\n\t\t\t</Text>\n\t\t\t<Box borderStyle=\"single\" borderColor=\"blue\" paddingX={1} marginTop={1}>\n\t\t\t\t<Text color=\"white\">{treeText}</Text>\n\t\t\t</Box>\n\t\t</Box>\n\t);\n}\n\nexport function OutputDisplay({ result, planVerbosity }: OutputDisplayProps) {\n\tif (!result) return null;\n\n\tif (result.error) {\n\t\treturn (\n\t\t\t<Box flexDirection=\"column\">\n\t\t\t\t<ErrorOutput message={result.error} />\n\t\t\t\t{result.parsedQuery !== undefined && (\n\t\t\t\t\t<ParseTreeOutput parsed={result.parsedQuery} />\n\t\t\t\t)}\n\t\t\t</Box>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Box flexDirection=\"column\">\n\t\t\t{result.parsedQuery !== undefined && (\n\t\t\t\t<ParseTreeOutput parsed={result.parsedQuery} />\n\t\t\t)}\n\t\t\t<SqlOutput sql={result.sql} params={result.params} label=\"📝 Main SQL:\" />\n\t\t\t{result.separateQueries && result.separateQueries.length > 0 && (\n\t\t\t\t<SeparateQueriesOutput queries={result.separateQueries} />\n\t\t\t)}\n\t\t\t{result.plan && (\n\t\t\t\t<PlanOutput plan={result.plan} verbosity={planVerbosity ?? 'normal'} />\n\t\t\t)}\n\t\t</Box>\n\t);\n}\n","/**\n * ConversationView — Renders stacked REPL entries like Claude Code's terminal.\n *\n * Each entry shows: prompt echo (\"> query\") followed by output.\n * Output detail is controlled by outputLayout:\n * - compact: summary line only (row count, timing)\n * - results: summary + execution results table\n * - sql: summary + SQL output\n * - full: everything inline (legacy behavior)\n */\n\nimport { Box, Text } from 'ink';\nimport React from 'react';\nimport { OutputDisplay } from '../components/OutputDisplay.js';\nimport type { OutputLayout, PlanVerbosity } from '../engine/engine-types.js';\nimport { ExecutionResultDisplay } from '../result-formatter.js';\nimport type { ExecutionResult, QueryResult } from '../types.js';\nimport type { ConversationEntry } from './conversation-model.js';\n\ninterface ConversationViewProps {\n\tentries: readonly ConversationEntry[];\n\toutputLayout: OutputLayout;\n\tplanVerbosity: PlanVerbosity;\n}\n\n/** Compact one-line summary for a query result. */\nfunction QuerySummary({\n\tqueryResult,\n\texecResult,\n}: {\n\tqueryResult: QueryResult | null;\n\texecResult: ExecutionResult | null;\n}) {\n\tif (!queryResult && !execResult) return null;\n\n\tconst parts: string[] = [];\n\n\tif (execResult) {\n\t\tif (execResult.error) {\n\t\t\treturn <Text color=\"red\">✗ {execResult.error}</Text>;\n\t\t}\n\t\tparts.push(\n\t\t\t`${execResult.rowCount} row${execResult.rowCount !== 1 ? 's' : ''}`,\n\t\t);\n\t\tparts.push(`${execResult.executionTimeMs.toFixed(0)}ms`);\n\t\tif (execResult.truncated) parts.push('truncated');\n\t}\n\n\tif (queryResult) {\n\t\tif (queryResult.error) {\n\t\t\treturn <Text color=\"red\">✗ {queryResult.error}</Text>;\n\t\t}\n\t\tif (!execResult) {\n\t\t\t// Compilation-only mode — show compact SQL preview\n\t\t\tconst plan = queryResult.plan;\n\t\t\tif (plan?.rootTable) parts.push(plan.rootTable);\n\t\t\tif (plan && plan.cteCount > 0)\n\t\t\t\tparts.push(`${plan.cteCount} CTE${plan.cteCount !== 1 ? 's' : ''}`);\n\t\t\tif (\n\t\t\t\tqueryResult.separateQueries &&\n\t\t\t\tqueryResult.separateQueries.length > 0\n\t\t\t) {\n\t\t\t\tparts.push(\n\t\t\t\t\t`+${queryResult.separateQueries.length} quer${queryResult.separateQueries.length !== 1 ? 'ies' : 'y'}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (plan && plan.planningTimeMs > 0)\n\t\t\t\tparts.push(`${plan.planningTimeMs.toFixed(1)}ms`);\n\t\t\tif (plan?.warnings && plan.warnings.length > 0)\n\t\t\t\tparts.push(\n\t\t\t\t\t`${plan.warnings.length} warning${plan.warnings.length !== 1 ? 's' : ''}`,\n\t\t\t\t);\n\t\t}\n\t}\n\n\treturn (\n\t\t<Text>\n\t\t\t<Text color=\"green\">✓ </Text>\n\t\t\t<Text color=\"gray\">{parts.join(' · ')}</Text>\n\t\t</Text>\n\t);\n}\n\n/** Render a single conversation entry with layout-aware output. */\nfunction ConversationEntryView({\n\tentry,\n\toutputLayout,\n\tplanVerbosity,\n}: {\n\tentry: ConversationEntry;\n\toutputLayout: OutputLayout;\n\tplanVerbosity: PlanVerbosity;\n}) {\n\t// Extract relevant events for display\n\tlet queryResult: QueryResult | null = null;\n\tlet execResult: ExecutionResult | null = null;\n\tlet infoMessage: string | null = null;\n\tlet errorMessage: string | null = null;\n\n\tfor (const event of entry.events) {\n\t\tswitch (event.type) {\n\t\t\tcase 'query-result':\n\t\t\t\tqueryResult = event.result;\n\t\t\t\tbreak;\n\t\t\tcase 'execution-result':\n\t\t\t\texecResult = event.result;\n\t\t\t\tbreak;\n\t\t\tcase 'info':\n\t\t\t\tinfoMessage = event.message;\n\t\t\t\tbreak;\n\t\t\tcase 'error':\n\t\t\t\terrorMessage = event.message;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tconst hasQueryOutput = queryResult !== null || execResult !== null;\n\n\treturn (\n\t\t<Box flexDirection=\"column\" marginBottom={1}>\n\t\t\t{/* Prompt echo */}\n\t\t\t{entry.input && (\n\t\t\t\t<Text>\n\t\t\t\t\t<Text color=\"blue\" bold>\n\t\t\t\t\t\t{'❯ '}\n\t\t\t\t\t</Text>\n\t\t\t\t\t<Text bold>{entry.input}</Text>\n\t\t\t\t</Text>\n\t\t\t)}\n\n\t\t\t{/* Info messages (dot command output) — always shown */}\n\t\t\t{infoMessage && <Text>{infoMessage}</Text>}\n\n\t\t\t{/* Error messages — always shown */}\n\t\t\t{errorMessage && <Text color=\"red\">{errorMessage}</Text>}\n\n\t\t\t{/* Query/execution output — layout-dependent */}\n\t\t\t{hasQueryOutput && outputLayout === 'compact' && (\n\t\t\t\t<QuerySummary queryResult={queryResult} execResult={execResult} />\n\t\t\t)}\n\n\t\t\t{hasQueryOutput && outputLayout === 'sql' && (\n\t\t\t\t<Box flexDirection=\"column\">\n\t\t\t\t\t<QuerySummary queryResult={queryResult} execResult={execResult} />\n\t\t\t\t\t{queryResult && (\n\t\t\t\t\t\t<OutputDisplay result={queryResult} planVerbosity={planVerbosity} />\n\t\t\t\t\t)}\n\t\t\t\t</Box>\n\t\t\t)}\n\n\t\t\t{hasQueryOutput && outputLayout === 'results' && (\n\t\t\t\t<Box flexDirection=\"column\">\n\t\t\t\t\t<QuerySummary queryResult={queryResult} execResult={execResult} />\n\t\t\t\t\t{execResult && <ExecutionResultDisplay result={execResult} />}\n\t\t\t\t</Box>\n\t\t\t)}\n\n\t\t\t{hasQueryOutput && outputLayout === 'full' && (\n\t\t\t\t<Box flexDirection=\"column\">\n\t\t\t\t\t{queryResult && (\n\t\t\t\t\t\t<OutputDisplay result={queryResult} planVerbosity={planVerbosity} />\n\t\t\t\t\t)}\n\t\t\t\t\t{execResult && <ExecutionResultDisplay result={execResult} />}\n\t\t\t\t</Box>\n\t\t\t)}\n\t\t</Box>\n\t);\n}\n\nexport function ConversationView({\n\tentries,\n\toutputLayout,\n\tplanVerbosity,\n}: ConversationViewProps) {\n\tif (entries.length === 0) return null;\n\n\treturn (\n\t\t<Box flexDirection=\"column\">\n\t\t\t{entries.map((entry) => (\n\t\t\t\t<ConversationEntryView\n\t\t\t\t\tkey={entry.id}\n\t\t\t\t\tentry={entry}\n\t\t\t\t\toutputLayout={outputLayout}\n\t\t\t\t\tplanVerbosity={planVerbosity}\n\t\t\t\t/>\n\t\t\t))}\n\t\t</Box>\n\t);\n}\n","/**\n * Conversation Model — manages the scrollable history of REPL entries.\n *\n * Each entry captures user input and all engine events that resulted from it.\n * The conversation stacks entries (like Claude Code's terminal) rather than\n * replacing the previous result.\n */\n\nimport type { EngineEvent } from '../engine/engine-types.js';\n\n/** Maximum number of entries kept in memory. */\nconst MAX_ENTRIES = 100;\n\nexport interface ConversationEntry {\n\tid: number;\n\ttimestamp: Date;\n\tinput: string;\n\tevents: EngineEvent[];\n}\n\nexport class ConversationManager {\n\tprivate entries: ConversationEntry[] = [];\n\tprivate nextId = 1;\n\n\t/** Create a new entry for user input. Returns the entry for event appending. */\n\taddEntry(input: string): ConversationEntry {\n\t\tconst entry: ConversationEntry = {\n\t\t\tid: this.nextId++,\n\t\t\ttimestamp: new Date(),\n\t\t\tinput,\n\t\t\tevents: [],\n\t\t};\n\t\tthis.entries.push(entry);\n\n\t\t// Cap history\n\t\tif (this.entries.length > MAX_ENTRIES) {\n\t\t\tthis.entries.splice(0, this.entries.length - MAX_ENTRIES);\n\t\t}\n\n\t\treturn entry;\n\t}\n\n\t/** Append an event to an existing entry. */\n\tappendEvent(entryId: number, event: EngineEvent): void {\n\t\tconst entry = this.entries.find((e) => e.id === entryId);\n\t\tif (entry) {\n\t\t\tentry.events.push(event);\n\t\t}\n\t}\n\n\t/** Get all entries (readonly). */\n\tgetEntries(): readonly ConversationEntry[] {\n\t\treturn this.entries;\n\t}\n\n\t/** Clear all entries. */\n\tclear(): void {\n\t\tthis.entries = [];\n\t}\n}\n","/**\n * DX-030 Block 5: Command History\n *\n * Manages command history with persistence to ~/.dbsp_history\n */\n\nimport {\n\tchmodSync,\n\texistsSync,\n\tmkdirSync,\n\treadFileSync,\n\twriteFileSync,\n} from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\n\nconst HISTORY_FILE = join(homedir(), '.dbsp_history');\nconst MAX_HISTORY_SIZE = 1000;\n\n/**\n * Decode a single history file line back to the original command string.\n *\n * This is the correct inverse of the save() encoding:\n * \\\\\\\\ → \\\\ (literal backslash)\n * \\\\n → \\n (newline)\n *\n * A regex-replace chain (replace /\\\\n/g then /\\\\\\\\/g) has a mis-ordering\n * hazard: an entry that contained a literal \"\\\\n\" sequence would decode as\n * an actual newline, corrupting round-trips that mix literal and escaped forms.\n */\nfunction unescapeHistoryLine(line: string): string {\n\tlet result = '';\n\tfor (let i = 0; i < line.length; i++) {\n\t\tif (line[i] === '\\\\' && i + 1 < line.length) {\n\t\t\tconst next = line[i + 1];\n\t\t\tif (next === '\\\\') {\n\t\t\t\tresult += '\\\\';\n\t\t\t\ti++;\n\t\t\t} else if (next === 'n') {\n\t\t\t\tresult += '\\n';\n\t\t\t\ti++;\n\t\t\t} else {\n\t\t\t\t// Unknown escape sequence — pass through unchanged\n\t\t\t\tresult += line[i];\n\t\t\t}\n\t\t} else {\n\t\t\tresult += line[i];\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Command history manager\n */\nexport class CommandHistory {\n\tprivate history: string[] = [];\n\tprivate index = -1;\n\tprivate currentInput = '';\n\n\tconstructor() {\n\t\tthis.load();\n\t}\n\n\t/**\n\t * Load history from file\n\t */\n\tprivate load(): void {\n\t\ttry {\n\t\t\tif (existsSync(HISTORY_FILE)) {\n\t\t\t\t// SEC-5: Tighten permissions on load (fire-and-forget)\n\t\t\t\ttry {\n\t\t\t\t\tchmodSync(HISTORY_FILE, 0o600);\n\t\t\t\t} catch {\n\t\t\t\t\t// Best-effort — ignore if we can't chmod (e.g., read-only FS)\n\t\t\t\t}\n\t\t\t\tconst content = readFileSync(HISTORY_FILE, 'utf-8');\n\t\t\t\tthis.history = content\n\t\t\t\t\t.split('\\n')\n\t\t\t\t\t.filter((line) => line.trim().length > 0)\n\t\t\t\t\t// C8 / F1: Char-by-char decode is the correct inverse of save().\n\t\t\t\t\t// A regex-replace chain has a mis-ordering hazard: an entry\n\t\t\t\t\t// containing literal \"\\n\" (backslash + n) would decode to an actual\n\t\t\t\t\t// newline, corrupting round-trips that mix literal and escaped forms.\n\t\t\t\t\t.map((line) => unescapeHistoryLine(line));\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore load errors, start with empty history\n\t\t}\n\t}\n\n\t/**\n\t * Save history to file\n\t */\n\tprivate save(): void {\n\t\ttry {\n\t\t\tconst dir = dirname(HISTORY_FILE);\n\t\t\tif (!existsSync(dir)) {\n\t\t\t\tmkdirSync(dir, { recursive: true });\n\t\t\t}\n\t\t\t// C8: Escape embedded newlines so multiline queries survive the \\n-based\n\t\t\t// line separator. Each entry has its \\ → \\\\, then \\n → \\n-literal before\n\t\t\t// join so load() can reverse the escaping.\n\t\t\tconst encoded = this.history\n\t\t\t\t.map((entry) => entry.replace(/\\\\/g, '\\\\\\\\').replace(/\\n/g, '\\\\n'))\n\t\t\t\t.join('\\n');\n\t\t\t// SEC-5: Write with mode 0600 (user-only read/write)\n\t\t\twriteFileSync(HISTORY_FILE, encoded, {\n\t\t\t\tencoding: 'utf-8',\n\t\t\t\tmode: 0o600,\n\t\t\t});\n\t\t\t// Best-effort: chmod after write in case the file pre-existed at a broader\n\t\t\t// permission (e.g., created by another tool at 0644). May throw on\n\t\t\t// non-POSIX filesystems.\n\t\t\ttry {\n\t\t\t\tchmodSync(HISTORY_FILE, 0o600);\n\t\t\t} catch {\n\t\t\t\t// Best-effort: may throw on non-POSIX filesystems\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore save errors\n\t\t}\n\t}\n\n\t/**\n\t * Add a command to history.\n\t *\n\t * @param command - Command string to record\n\t * @param persist - Whether to persist to disk (default: true). Pass false for\n\t * batch-mode queries that should not be saved to ~/.dbsp_history (SEC-13).\n\t */\n\tadd(command: string, persist = true): void {\n\t\tconst trimmed = command.trim();\n\t\tif (!trimmed) return;\n\n\t\t// Don't add duplicates of the last command\n\t\tif (this.history[this.history.length - 1] === trimmed) return;\n\n\t\tthis.history.push(trimmed);\n\n\t\t// Trim history if too large\n\t\tif (this.history.length > MAX_HISTORY_SIZE) {\n\t\t\tthis.history = this.history.slice(-MAX_HISTORY_SIZE);\n\t\t}\n\n\t\tthis.resetIndex();\n\t\tif (persist) {\n\t\t\tthis.save();\n\t\t}\n\t}\n\n\t/**\n\t * Reset the navigation index\n\t */\n\tresetIndex(): void {\n\t\tthis.index = -1;\n\t\tthis.currentInput = '';\n\t}\n\n\t/**\n\t * Navigate to previous command (up arrow)\n\t * Returns the command to display, or undefined if at start of history\n\t */\n\tprevious(currentInput: string): string | undefined {\n\t\t// Save current input when starting navigation\n\t\tif (this.index === -1) {\n\t\t\tthis.currentInput = currentInput;\n\t\t}\n\n\t\tif (this.history.length === 0) return undefined;\n\n\t\t// Move up in history\n\t\tif (this.index < this.history.length - 1) {\n\t\t\tthis.index++;\n\t\t}\n\n\t\treturn this.history[this.history.length - 1 - this.index];\n\t}\n\n\t/**\n\t * Navigate to next command (down arrow)\n\t * Returns the command to display, or the saved current input if past history\n\t */\n\tnext(): string | undefined {\n\t\tif (this.index <= 0) {\n\t\t\tthis.index = -1;\n\t\t\treturn this.currentInput;\n\t\t}\n\n\t\tthis.index--;\n\t\treturn this.history[this.history.length - 1 - this.index];\n\t}\n\n\t/**\n\t * Search history for commands containing the query\n\t */\n\tsearch(query: string): string[] {\n\t\tif (!query) return this.history.slice(-10);\n\t\tconst lower = query.toLowerCase();\n\t\treturn this.history.filter((cmd) => cmd.toLowerCase().includes(lower));\n\t}\n\n\t/**\n\t * CLI-MUT: Reverse incremental search (Ctrl+R functionality)\n\t * Returns matches from most recent to oldest\n\t */\n\treverseSearch(query: string): string[] {\n\t\tif (!query) return [];\n\t\tconst lower = query.toLowerCase();\n\t\t// Return matches in reverse order (most recent first)\n\t\treturn this.history\n\t\t\t.filter((cmd) => cmd.toLowerCase().includes(lower))\n\t\t\t.reverse();\n\t}\n\n\t/**\n\t * Get all history entries\n\t */\n\tgetAll(): readonly string[] {\n\t\treturn this.history;\n\t}\n\n\t/**\n\t * Get recent history (last N entries)\n\t */\n\tgetRecent(count = 10): string[] {\n\t\treturn this.history.slice(-count);\n\t}\n\n\t/**\n\t * Clear all history\n\t */\n\tclear(): void {\n\t\tthis.history = [];\n\t\tthis.resetIndex();\n\t\tthis.save();\n\t}\n\n\t/**\n\t * Get total count\n\t */\n\tget length(): number {\n\t\treturn this.history.length;\n\t}\n}\n\n/**\n * Create a singleton history instance\n */\nlet historyInstance: CommandHistory | null = null;\n\nexport function getHistory(): CommandHistory {\n\tif (!historyInstance) {\n\t\thistoryInstance = new CommandHistory();\n\t}\n\treturn historyInstance;\n}\n"],"mappings":";;;;;;;;;AASA,SAAS,OAAAA,OAAK,QAAQ,QAAQ,YAAAC,iBAAgB;AAC9C,OAAOC;AAAA,EACN,eAAAC;AAAA,EACA,aAAAC;AAAA,EACA,WAAAC;AAAA,EACA,UAAAC;AAAA,EACA,YAAAC;AAAA,OACM;;;AChBP,OAAO,WAAW;AAOlB,SAAS,KAAK,YAAY;AAa1B,IAAM,aAA2D;AAAA,EAChE,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,SAAS;AAAA,EACT,UAAU;AACX;AAKA,IAAM,cAA4D;AAAA,EACjE,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,SAAS;AAAA,EACT,UAAU;AACX;AAEO,SAAS,kBAAkB;AAAA,EACjC;AAAA,EACA,WAAW;AAAA,EACX,gBAAgB;AACjB,GAA2B;AAC1B,MAAI,YAAY,WAAW,GAAG;AAC7B,WAAO;AAAA,EACR;AAGA,MAAI,aAAa;AACjB,MAAI,iBAAiB,GAAG;AAEvB,UAAM,aAAa,KAAK,MAAM,WAAW,CAAC;AAC1C,iBAAa,KAAK;AAAA,MACjB;AAAA,MACA,KAAK,IAAI,gBAAgB,YAAY,YAAY,SAAS,QAAQ;AAAA,IACnE;AAAA,EACD;AAEA,eAAa,KAAK,IAAI,GAAG,UAAU;AAEnC,QAAM,WAAW,KAAK,IAAI,aAAa,UAAU,YAAY,MAAM;AACnE,QAAM,QAAQ,YAAY,MAAM,YAAY,QAAQ;AACpD,QAAM,YAAY,aAAa;AAC/B,QAAM,WAAW,WAAW,YAAY;AAExC,SACC,oCAAC,OAAI,eAAc,OAAM,UAAS,QAAO,WAAW,KACnD,oCAAC,QAAK,OAAM,QAAO,UAAQ,QAAC,SACrB,GACP,GACC,aACA,oCAAC,QAAK,OAAM,QAAO,UAAQ,QAAC,UACzB,GACH,GAEA,MAAM,IAAI,CAAC,YAAY,QAAQ;AAE/B,UAAM,cAAc,aAAa;AACjC,UAAM,aAAa,gBAAgB;AACnC,WACC,oCAAC,OAAI,KAAK,aAAa,aAAa,KACnC,oCAAC,YAAM,WAAW,WAAW,IAAI,GAAE,GAAC,GACpC;AAAA,MAAC;AAAA;AAAA,QACA,OAAO,aAAa,UAAU,YAAY,WAAW,IAAI;AAAA,QACxD,GAAI,cAAc,EAAE,iBAAiB,OAAgB;AAAA,QACtD,MAAM;AAAA;AAAA,MAEL,WAAW;AAAA,IACb,CACD;AAAA,EAEF,CAAC,GACA,YACA,oCAAC,QAAK,OAAM,QAAO,UAAQ,QAAC,YACvB,YAAY,SAAS,QAC1B,CAEF;AAEF;;;ACpGA,OAAOC,YAAW;AAMlB,SAAS,OAAAC,MAAK,QAAAC,aAAY;AA+B1B,IAAM,kBAA+C;AAAA,EACpD,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AACT;AAGA,IAAM,mBAAwD;AAAA,EAC7D,MAAM;AAAA,EACN,MAAM;AAAA,EACN,UAAU;AAAA,EACV,KAAK;AAAA,EACL,SAAS;AAAA,EACT,UAAU;AACX;AAEO,SAAS,OAAO;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAgB;AACf,SACC,gBAAAF,OAAA;AAAA,IAACC;AAAA,IAAA;AAAA,MACA,aAAY;AAAA,MACZ,aAAY;AAAA,MACZ,UAAU;AAAA,MACV,cAAc;AAAA,MACd,eAAc;AAAA;AAAA,IAGd,gBAAAD,OAAA,cAACC,MAAA,MACA,gBAAAD,OAAA,cAACE,OAAA,EAAK,MAAI,MAAC,OAAM,UAAO,oCAExB,GACA,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,KAAG,GACtB,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,oBAAkB,GACrC,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,KAAG,GACtB,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,gBAAc,CAClC;AAAA,IAGA,gBAAAF,OAAA,cAACC,MAAA,MACA,gBAAAD,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,UAAQ,GAC3B,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,WAAS,UAAW,GAChC,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UACV,KAAI,KACH,YAAW,aAAU,eAAc,aACtC,GACA,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,WAAS,GAC5B,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAO,SAAS,YAAY,UAAU,YAAW,IAAK,GAC3D,cACA,gBAAAF,OAAA,cAAAA,OAAA,gBACC,gBAAAA,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,aAAW,GAC9B,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAQ,UAAW,CAChC,CAEF;AAAA,IAGA,gBAAAF,OAAA,cAACC,MAAA,MACA,gBAAAD,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,WAAS,GAC5B,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAQ,gBAAgB,OAAO,CAAE,GAE7C,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,eAAa,GAChC,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,aAAW,iBAAiB,eAAe,CAAE,GAEzD,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,YAAU,GAC7B,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAO,iBAAiB,WAAW,SAAS,YAChD,iBAAiB,WAAW,QAAQ,WACtC,GAGC,aACA,gBAAAF,OAAA,cAAAA,OAAA,gBACC,gBAAAA,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,KAAG,GACtB,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,SAAO,CAC3B,GAEA,eACA,gBAAAF,OAAA,cAAAA,OAAA,gBACC,gBAAAA,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,KAAG,GACtB,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,YAAS,WAAS,CAC/B,GAIA,aACA,gBAAAF,OAAA,cAAAA,OAAA,gBACC,gBAAAA,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,KAAG,GACtB,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,WAAQ,QAAK,YAAa,CACvC,GAGA,aACA,gBAAAF,OAAA,cAAAA,OAAA,gBACC,gBAAAA,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,KAAG,GACtB,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAO,WAAW,UAAU,UAAQ,WACjC,WAAW,OAAO,OAAM,GACjC,CACD,CAEF;AAAA,EACD;AAEF;;;ACzJA,OAAOC,YAAW;AAKlB,SAAS,OAAAC,MAAK,QAAAC,aAAY;AAE1B,IAAM,eAAe;AAAA,EACpB,EAAE,SAAS,SAAS,aAAa,iBAAiB;AAAA,EAClD,EAAE,SAAS,WAAW,aAAa,4BAA4B;AAAA,EAC/D;AAAA,IACC,SAAS;AAAA,IACT,aAAa;AAAA,EACd;AAAA,EACA,EAAE,SAAS,cAAc,aAAa,qBAAqB;AAAA,EAC3D;AAAA,IACC,SAAS;AAAA,IACT,aAAa;AAAA,EACd;AAAA,EACA;AAAA,IACC,SAAS;AAAA,IACT,aAAa;AAAA,EACd;AAAA,EACA;AAAA,IACC,SAAS;AAAA,IACT,aAAa;AAAA,EACd;AAAA,EACA;AAAA,IACC,SAAS;AAAA,IACT,aAAa;AAAA,EACd;AAAA,EACA,EAAE,SAAS,UAAU,aAAa,qCAAqC;AAAA,EACvE;AAAA,IACC,SAAS;AAAA,IACT,aAAa;AAAA,EACd;AAAA,EACA;AAAA,IACC,SAAS;AAAA,IACT,aACC;AAAA,EACF;AAAA,EACA;AAAA,IACC,SAAS;AAAA,IACT,aAAa;AAAA,EACd;AAAA,EACA;AAAA,IACC,SAAS;AAAA,IACT,aAAa;AAAA,EACd;AAAA,EACA;AAAA,IACC,SAAS;AAAA,IACT,aAAa;AAAA,EACd;AAAA,EACA;AAAA,IACC,SAAS;AAAA,IACT,aAAa;AAAA,EACd;AAAA,EACA;AAAA,IACC,SAAS;AAAA,IACT,aAAa;AAAA,EACd;AAAA,EACA;AAAA,IACC,SAAS;AAAA,IACT,aACC;AAAA,EACF;AAAA,EACA,EAAE,SAAS,UAAU,aAAa,0BAA0B;AAAA,EAC5D,EAAE,SAAS,iBAAiB,aAAa,YAAY;AACtD;AAEA,IAAM,iBAAiB;AAAA,EACtB;AAAA,IACC,SAAS;AAAA,IACT,SAAS;AAAA,IACT,aAAa;AAAA,EACd;AAAA,EACA;AAAA,IACC,SAAS;AAAA,IACT,SAAS;AAAA,IACT,aAAa;AAAA,EACd;AAAA,EACA;AAAA,IACC,SAAS;AAAA,IACT,SAAS;AAAA,IACT,aAAa;AAAA,EACd;AAAA,EACA;AAAA,IACC,SAAS;AAAA,IACT,SAAS;AAAA,IACT,aAAa;AAAA,EACd;AAAA,EACA;AAAA,IACC,SAAS;AAAA,IACT,SAAS;AAAA,IACT,aAAa;AAAA,EACd;AACD;AAEA,SAAS,YAAY;AAAA,EACpB;AAAA,EACA;AACD,GAGG;AACF,SACC,gBAAAF,OAAA,cAACC,MAAA,EAAI,eAAc,YACjB,KAAK,IAAI,CAAC,KAAK,MACf,gBAAAD,OAAA,cAACC,MAAA,EAAI,KAAK,KACR,QAAQ,IAAI,CAAC,KAAK,MAClB,gBAAAD,OAAA,cAACC,MAAA,EAAI,KAAK,KAAK,OAAO,QAAQ,gBAAgB,KAAK,MAClD,gBAAAD,OAAA,cAACE,OAAA,EAAK,OAAO,MAAM,IAAI,SAAS,WAAU,IAAI,GAAG,CAAE,CACpD,CACA,CACF,CACA,CACF;AAEF;AAEO,SAAS,cAAc;AAC7B,SACC,gBAAAF,OAAA,cAACC,MAAA,EAAI,eAAc,UAAS,SAAS,KACpC,gBAAAD,OAAA,cAACE,OAAA,EAAK,MAAI,MAAC,OAAM,YAAS,yBAE1B,GACA,gBAAAF,OAAA,cAACC,MAAA,EAAI,WAAW,GAAG,cAAc,GAAG,eAAc,YACjD,gBAAAD,OAAA,cAAC,eAAY,MAAM,cAAc,SAAS,CAAC,WAAW,aAAa,GAAG,CACvE,GAEA,gBAAAA,OAAA,cAACE,OAAA,EAAK,MAAI,MAAC,OAAM,UAAO,iCAExB,GACA,gBAAAF,OAAA,cAACC,MAAA,EAAI,WAAW,GAAG,eAAc,YAChC,gBAAAD,OAAA;AAAA,IAAC;AAAA;AAAA,MACA,MAAM;AAAA,MACN,SAAS,CAAC,WAAW,WAAW,aAAa;AAAA;AAAA,EAC9C,CACD,GAEA,gBAAAA,OAAA,cAACC,MAAA,EAAI,WAAW,KACf,gBAAAD,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,6DAEnB,CACD,CACD;AAEF;;;ACnJA,OAAOC,YAAW;AAOlB,SAAS,OAAAC,MAAK,QAAAC,OAAM,YAAAC,iBAAgB;AACpC,SAAS,aAAa,aAAAC,YAAW,SAAS,YAAAC,iBAAgB;;;ACK1D,SAAS,OAAAC,MAAK,QAAAC,OAAM,UAAU,UAAU,iBAAiB;AACzD,OAAOC,UAAS,WAAW,QAAQ,gBAAgB;AAsBnD,SAAS,kBAAkB,MAAc,QAAwB;AAChE,MAAI,UAAU,EAAG,QAAO;AAExB,MAAI,MAAM,SAAS;AAGnB,SAAO,MAAM,KAAK,KAAK,GAAG,MAAM,KAAK;AACpC;AAAA,EACD;AAGA,SAAO,MAAM,KAAK,KAAK,MAAM,CAAC,MAAM,KAAK;AACxC;AAAA,EACD;AAEA,SAAO;AACR;AAKA,SAAS,gBAAgB,MAAc,QAAwB;AAC9D,MAAI,UAAU,KAAK,OAAQ,QAAO,KAAK;AAEvC,MAAI,MAAM;AAGV,SAAO,MAAM,KAAK,UAAU,KAAK,GAAG,MAAM,KAAK;AAC9C;AAAA,EACD;AAGA,SAAO,MAAM,KAAK,UAAU,KAAK,GAAG,MAAM,KAAK;AAC9C;AAAA,EACD;AAEA,SAAO;AACR;AAEO,SAAS,kBAAkB;AAAA,EACjC,OAAO;AAAA,EACP,eAAe;AAAA,EACf,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,YAAY;AACb,GAA2B;AAC1B,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,YAAY;AAC/D,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,aAAa,MAAM;AAMxD,QAAM,WAAW,OAAO,YAAY;AACpC,QAAM,YAAY,OAAO,aAAa,MAAM;AAC5C,QAAM,EAAE,OAAO,IAAI,UAAU;AAI7B,QAAM,kBAAkB,OAAe,EAAE;AACzC,QAAM,EAAE,MAAM,IAAI,SAAS;AAG3B,YAAU,MAAM;AACf,QAAI,CAAC,SAAS,cAAc,CAAC,UAAW;AAExC,UAAM,gBAAgB,CAAC,SAAiB;AACvC,sBAAgB,UAAU,KAAK,SAAS;AAAA,IACzC;AAEA,UAAM,GAAG,QAAQ,aAAa;AAC9B,WAAO,MAAM;AACZ,YAAM,IAAI,QAAQ,aAAa;AAAA,IAChC;AAAA,EACD,GAAG,CAAC,OAAO,YAAY,SAAS,CAAC;AAGjC,QAAM,QAAQ,mBAAmB;AAGjC,YAAU,MAAM;AACf,QAAI,oBAAoB,QAAW;AAClC,YAAM,SAAS,KAAK,IAAI,UAAU,SAAS,gBAAgB,MAAM;AACjE,gBAAU,UAAU;AACpB,gBAAU,MAAM;AAChB,eAAS,UAAU;AAAA,IACpB;AAAA,EACD,GAAG,CAAC,eAAe,CAAC;AAGpB,YAAU,MAAM;AACf,QAAI,oBAAoB,QAAW;AAClC,uBAAiB,YAAY;AAC7B,gBAAU,aAAa,MAAM;AAC7B,eAAS,UAAU;AACnB,gBAAU,UAAU,aAAa;AAAA,IAClC;AAAA,EACD,GAAG,CAAC,cAAc,eAAe,CAAC;AAElC,QAAM,cAAc,CAAC,UAAkB,cAAuB;AAC7D,UAAM,KAAK,aAAa,SAAS;AAEjC,aAAS,UAAU;AACnB,cAAU,UAAU;AAEpB,QAAI,oBAAoB,QAAW;AAClC,uBAAiB,QAAQ;AAAA,IAC1B;AACA,cAAU,EAAE;AACZ,eAAW,QAAQ;AAAA,EACpB;AAEA;AAAA,IACC,CAAC,OAAO,QAAQ;AACf,UAAI,cAAc,CAAC,UAAW;AAG9B,YAAM,MAAM,SAAS;AACrB,YAAM,MAAM,UAAU;AAGtB,UAAI,IAAI,QAAQ;AAEf,YAAI,IAAI,OAAO;AACd,gBAAM,WAAW,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC;AAAA,EAAK,IAAI,MAAM,GAAG,CAAC;AACxD,sBAAY,UAAU,MAAM,CAAC;AAC7B;AAAA,QACD;AAEA,YAAI,IAAI,SAAS,IAAI,GAAG;AACvB,gBAAM,WAAW,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC;AAAA;AACpC,sBAAY,UAAU,SAAS,MAAM;AACrC;AAAA,QACD;AAGA,cAAM,YAAY;AAClB,iBAAS,UAAU;AACnB,kBAAU,UAAU;AACpB,mBAAW,SAAS;AACpB;AAAA,MACD;AAGA,UAAI,IAAI,QAAQ;AACf;AAAA,MACD;AAKA,UAAI,IAAI,MAAM;AACb,kBAAU,UAAU;AACpB,kBAAU,CAAC;AACX;AAAA,MACD;AAGA,UAAI,IAAI,KAAK;AACZ,kBAAU,UAAU,IAAI;AACxB,kBAAU,IAAI,MAAM;AACpB;AAAA,MACD;AAGA,UAAI,IAAI,WAAW;AAClB,YAAI,IAAI,QAAQ,IAAI,MAAM;AACzB,gBAAM,KAAK,kBAAkB,KAAK,GAAG;AACrC,oBAAU,UAAU;AACpB,oBAAU,EAAE;AAAA,QACb,OAAO;AACN,gBAAM,KAAK,KAAK,IAAI,GAAG,MAAM,CAAC;AAC9B,oBAAU,UAAU;AACpB,oBAAU,EAAE;AAAA,QACb;AACA;AAAA,MACD;AAGA,UAAI,IAAI,YAAY;AACnB,YAAI,IAAI,QAAQ,IAAI,MAAM;AACzB,gBAAM,KAAK,gBAAgB,KAAK,GAAG;AACnC,oBAAU,UAAU;AACpB,oBAAU,EAAE;AAAA,QACb,OAAO;AACN,gBAAM,KAAK,KAAK,IAAI,IAAI,QAAQ,MAAM,CAAC;AACvC,oBAAU,UAAU;AACpB,oBAAU,EAAE;AAAA,QACb;AACA;AAAA,MACD;AAGA,UAAI,IAAI,QAAQ,UAAU,KAAK;AAC9B,kBAAU,UAAU;AACpB,kBAAU,CAAC;AACX;AAAA,MACD;AAGA,UAAI,IAAI,QAAQ,UAAU,KAAK;AAC9B,kBAAU,UAAU,IAAI;AACxB,kBAAU,IAAI,MAAM;AACpB;AAAA,MACD;AAGA,UAAI,IAAI,QAAQ,UAAU,KAAK;AAC9B,cAAM,KAAK,kBAAkB,KAAK,GAAG;AACrC,kBAAU,UAAU;AACpB,kBAAU,EAAE;AACZ;AAAA,MACD;AAGA,UAAI,IAAI,QAAQ,UAAU,KAAK;AAC9B,cAAM,KAAK,gBAAgB,KAAK,GAAG;AACnC,kBAAU,UAAU;AACpB,kBAAU,EAAE;AACZ;AAAA,MACD;AAKA,YAAM,WAAW,gBAAgB;AAIjC,UAAI,aAAa,aAAa,SAAS,WAAW,SAAS,GAAG;AAC7D,YAAI,MAAM,IAAI,QAAQ;AACrB,gBAAM,WAAW,IAAI,MAAM,GAAG,GAAG,IAAI,IAAI,MAAM,MAAM,CAAC;AACtD,sBAAY,UAAU,GAAG;AAAA,QAC1B;AACA;AAAA,MACD;AAGA,YAAM,cACL,IAAI,aACJ,aAAa,UACb,aAAa,QACb,UAAU,UACV,UAAU;AACX,UAAI,aAAa;AAChB,YAAI,MAAM,GAAG;AACZ,gBAAM,WAAW,IAAI,MAAM,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,GAAG;AACtD,sBAAY,UAAU,MAAM,CAAC;AAAA,QAC9B;AACA;AAAA,MACD;AAGA,UAAI,IAAI,QAAQ,UAAU,KAAK;AAC9B,cAAM,YAAY,kBAAkB,KAAK,GAAG;AAC5C,cAAM,WAAW,IAAI,MAAM,GAAG,SAAS,IAAI,IAAI,MAAM,GAAG;AACxD,oBAAY,UAAU,SAAS;AAC/B;AAAA,MACD;AAGA,UAAI,IAAI,QAAQ,UAAU,KAAK;AAC9B,cAAM,WAAW,IAAI,MAAM,GAAG;AAC9B,oBAAY,UAAU,CAAC;AACvB;AAAA,MACD;AAGA,UAAI,IAAI,QAAQ,UAAU,KAAK;AAC9B,cAAM,WAAW,IAAI,MAAM,GAAG,GAAG;AACjC,oBAAY,UAAU,GAAG;AACzB;AAAA,MACD;AAGA,UAAI,IAAI,QAAQ,UAAU,KAAK;AAC9B,YAAI,MAAM,GAAG;AACZ,gBAAM,WAAW,IAAI,MAAM,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,GAAG;AACtD,sBAAY,UAAU,MAAM,CAAC;AAAA,QAC9B;AACA;AAAA,MACD;AAKA,UAAI,IAAI,KAAK;AACZ;AAAA,MACD;AAGA,UAAI,SAAS,CAAC,IAAI,QAAQ,CAAC,IAAI,MAAM;AAIpC,YAAI,MAAM,SAAS,IAAI,KAAK,MAAM,SAAS,IAAI,GAAG;AACjD,gBAAM,WAAW,IAAI,MAAM,GAAG,GAAG,IAAI,QAAQ,IAAI,MAAM,GAAG;AAC1D,gBAAM,QAAQ,SAAS,MAAM,YAAY;AACzC,gBAAM,WAAW,MAAM,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AAE1D,cAAI,SAAS,SAAS,GAAG;AACxB,qBAAS,UAAU;AACnB,sBAAU,UAAU;AACpB,uBAAW,QAAQ,UAAU;AAC5B,yBAAW,IAAI;AAAA,YAChB;AACA;AAAA,UACD;AAGA,sBAAY,IAAI,CAAC;AACjB;AAAA,QACD;AACA,cAAM,WAAW,IAAI,MAAM,GAAG,GAAG,IAAI,QAAQ,IAAI,MAAM,GAAG;AAC1D,oBAAY,UAAU,MAAM,MAAM,MAAM;AAAA,MACzC;AAAA,IACD;AAAA,IACA,EAAE,UAAU,aAAa,CAAC,WAAW;AAAA,EACtC;AAGA,QAAM,kBAAkB,MAAM,WAAW;AACzC,QAAM,cAAc,MAAM,SAAS,IAAI;AAEvC,MAAI,iBAAiB;AACpB,WACC,gBAAAA,OAAA,cAACF,MAAA,MACA,gBAAAE,OAAA,cAACD,OAAA,EAAK,SAAO,QAAC,GAAC,GACf,gBAAAC,OAAA,cAACD,OAAA,EAAK,UAAQ,QAAE,WAAY,CAC7B;AAAA,EAEF;AAGA,MAAI,aAAa;AAChB,UAAM,QAAQ,MAAM,MAAM,IAAI;AAC9B,QAAI,aAAa;AAEjB,WACC,gBAAAC,OAAA,cAACF,MAAA,EAAI,eAAc,YACjB,MAAM,IAAI,CAAC,MAAM,YAAY;AAC7B,YAAM,YAAY;AAClB,oBAAc,KAAK,SAAS;AAE5B,YAAM,mBACL,UAAU,aAAa,SAAS,YAAY,KAAK,SAAS;AAE3D,UAAI,CAAC,kBAAkB;AACtB,eACC,gBAAAE,OAAA,cAACD,OAAA,EAAK,KAAK,WACT,UAAU,KAAK,gBAAAC,OAAA,cAACD,OAAA,EAAK,OAAM,UAAO,MAAI,GACtC,IACF;AAAA,MAEF;AAEA,YAAM,eAAe,SAAS;AAC9B,YAAME,UAAS,KAAK,MAAM,GAAG,YAAY;AACzC,YAAMC,MAAK,KAAK,YAAY,KAAK;AACjC,YAAMC,SAAQ,KAAK,MAAM,eAAe,CAAC;AAEzC,aACC,gBAAAH,OAAA,cAACD,OAAA,EAAK,KAAK,WACT,UAAU,KAAK,gBAAAC,OAAA,cAACD,OAAA,EAAK,OAAM,UAAO,MAAI,GACtCE,SACD,gBAAAD,OAAA,cAACD,OAAA,EAAK,SAAO,QAAEG,GAAG,GACjBC,MACF;AAAA,IAEF,CAAC,CACF;AAAA,EAEF;AAIA,QAAM,aAAa,QAAQ,WAAW,MAAM;AAC5C,QAAM,MAAM,MAAM;AAElB,MAAI,OAAO,WAAW;AAErB,UAAM,eAAe,MAAM,MAAM,GAAG,MAAM;AAC1C,UAAM,WAAW,MAAM,MAAM,KAAK;AAClC,UAAM,cAAc,MAAM,MAAM,SAAS,CAAC;AAE1C,WACC,gBAAAH,OAAA,cAACF,MAAA,MACA,gBAAAE,OAAA,cAACD,OAAA,MAAM,YAAa,GACpB,gBAAAC,OAAA,cAACD,OAAA,EAAK,SAAO,QAAE,QAAS,GACxB,gBAAAC,OAAA,cAACD,OAAA,MAAM,WAAY,CACpB;AAAA,EAEF;AAGA,QAAM,WAAW;AACjB,QAAM,SAAS,YAAY;AAE3B,MAAI,cAAc,SAAS,KAAK,MAAM,SAAS,CAAC;AAChD,MAAI,cAAc,EAAG,eAAc;AACnC,MAAI,cAAc,SAAS,IAAK,eAAc,KAAK,IAAI,GAAG,MAAM,MAAM;AAEtE,QAAM,YAAY,KAAK,IAAI,cAAc,QAAQ,GAAG;AACpD,QAAM,mBAAmB,cAAc;AACvC,QAAM,oBAAoB,YAAY;AAEtC,QAAM,cAAc,MAAM,MAAM,aAAa,SAAS;AACtD,QAAM,iBAAiB,SAAS;AAEhC,QAAM,SAAS,YAAY,MAAM,GAAG,cAAc;AAClD,QAAM,KAAK,YAAY,cAAc,KAAK;AAC1C,QAAM,QAAQ,YAAY,MAAM,iBAAiB,CAAC;AAElD,SACC,gBAAAC,OAAA,cAACF,MAAA,MACC,oBAAoB,gBAAAE,OAAA,cAACD,OAAA,EAAK,OAAM,UAAQ,QAAS,GAClD,gBAAAC,OAAA,cAACD,OAAA,MAAM,MAAO,GACd,gBAAAC,OAAA,cAACD,OAAA,EAAK,SAAO,QAAE,EAAG,GAClB,gBAAAC,OAAA,cAACD,OAAA,MAAM,KAAM,GACZ,qBAAqB,gBAAAC,OAAA,cAACD,OAAA,EAAK,OAAM,UAAQ,QAAS,CACpD;AAEF;;;AD9aO,SAAS,YAAY;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAqB;AACpB,QAAM,eAAe,SAAS,YAAY,MAAM;AAChD,QAAM,cAAc,SAAS,YAAY,UAAU;AAGnD,QAAM,CAAC,cAAc,eAAe,IAAIK,UAAS,EAAE;AACnD,QAAM,CAAC,YAAY,aAAa,IAAIA,UAAS,CAAC;AAC9C,QAAM,CAAC,cAAc,eAAe,IAAIA;AAAA,IACvC;AAAA,EACD;AAGA,QAAM,CAAC,YAAY,aAAa,IAAIA,UAAS,KAAK;AAClD,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAS,EAAE;AACjD,QAAM,CAAC,kBAAkB,mBAAmB,IAAIA,UAAS,CAAC;AAG1D,QAAM,gBAAgB,QAAQ,MAAM;AACnC,QAAI,CAAC,WAAW,CAAC,YAAa,QAAO,CAAC;AACtC,WAAO,QAAQ,cAAc,WAAW;AAAA,EACzC,GAAG,CAAC,SAAS,WAAW,CAAC;AAGzB,QAAM,eAAe,cAAc,gBAAgB,KAAK;AAGxD,EAAAC,WAAU,MAAM;AACf,oBAAgB,EAAE;AAClB,oBAAgB,MAAS;AACzB,kBAAc,CAAC,MAAM,IAAI,CAAC;AAC1B,kBAAc,KAAK;AACnB,mBAAe,EAAE;AACjB,wBAAoB,CAAC;AACrB,aAAS,WAAW;AAAA,EACrB,GAAG,CAAC,UAAU,OAAO,CAAC;AAGtB,EAAAC,UAAS,CAAC,OAAO,QAAQ;AACxB,QAAI,CAAC,QAAS;AAGd,QAAI,IAAI,QAAQ,UAAU,KAAK;AAC9B,UAAI,YAAY;AAEf,YAAI,cAAc,SAAS,GAAG;AAC7B,8BAAoB,CAAC,OAAO,IAAI,KAAK,cAAc,MAAM;AAAA,QAC1D;AAAA,MACD,OAAO;AAEN,sBAAc,IAAI;AAClB,uBAAe,EAAE;AACjB,4BAAoB,CAAC;AAAA,MACtB;AACA;AAAA,IACD;AAGA,QAAI,YAAY;AAEf,UAAI,IAAI,QAAQ;AACf,sBAAc,KAAK;AACnB,uBAAe,EAAE;AACjB,4BAAoB,CAAC;AACrB;AAAA,MACD;AAGA,UAAI,IAAI,QAAQ;AACf,YAAI,cAAc;AACjB,0BAAgB,YAAY;AAC5B,wBAAc,CAAC,MAAM,IAAI,CAAC;AAC1B,0BAAgB,YAAY;AAC5B,0BAAgB,YAAY;AAAA,QAC7B;AACA,sBAAc,KAAK;AACnB,uBAAe,EAAE;AACjB,4BAAoB,CAAC;AACrB;AAAA,MACD;AAGA;AAAA,IACD;AAGA,QAAI,IAAI,SAAS;AAChB,YAAM,OAAO,QAAQ,SAAS,YAAY;AAC1C,UAAI,SAAS,QAAW;AACvB,wBAAgB,IAAI;AACpB,sBAAc,CAAC,MAAM,IAAI,CAAC;AAAA,MAC3B;AAAA,IACD,WAAW,IAAI,WAAW;AACzB,YAAM,OAAO,QAAQ,KAAK;AAC1B,UAAI,SAAS,QAAW;AACvB,wBAAgB,IAAI;AACpB,sBAAc,CAAC,MAAM,IAAI,CAAC;AAAA,MAC3B;AAAA,IACD;AAAA,EACD,CAAC;AAED,QAAM,eAAe;AAAA,IACpB,CAAC,UAAkB;AAElB,UAAI,oBAAoB;AAEvB,cAAM,WAAW,kBACd,gBAAgB,OAAO,kBAAkB,IACzC;AACH,wBAAgB,QAAQ;AACxB,sBAAc,CAAC,MAAM,IAAI,CAAC;AAC1B,wBAAgB,QAAQ;AACxB,wBAAgB,QAAQ;AACxB,+BAAuB;AACvB;AAAA,MACD;AAEA,UAAI,WAAW,MAAM,KAAK,GAAG;AAC5B,gBAAQ,IAAI,KAAK;AAAA,MAClB;AACA,sBAAgB,EAAE;AAClB,sBAAgB,MAAS;AACzB,eAAS,KAAK;AAAA,IACf;AAAA,IACA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAEA,QAAM,eAAe;AAAA,IACpB,CAAC,UAAkB;AAClB,sBAAgB,KAAK;AACrB,sBAAgB,KAAK;AAAA,IACtB;AAAA,IACA,CAAC,aAAa;AAAA,EACf;AAGA,QAAM,cAAc,GAAG,QAAQ,IAAI,UAAU;AAG7C,QAAM,qBAAqB,YAAY,CAAC,UAAkB;AACzD,mBAAe,KAAK;AACpB,wBAAoB,CAAC;AAAA,EACtB,GAAG,CAAC,CAAC;AAGL,MAAI,YAAY;AACf,WACC,gBAAAC,OAAA,cAACC,MAAA,EAAI,eAAc,UAAS,WAAW,KAErC,gBACA,gBAAAD,OAAA,cAACC,MAAA,MACA,gBAAAD,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,SAAE,GACrB,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAQ,YAAa,CAClC,GAGD,gBAAAF,OAAA,cAACC,MAAA,MACA,gBAAAD,OAAA,cAACE,OAAA,EAAK,OAAM,WAAU,MAAI,QAAC,qBAE3B,GACA,gBAAAF,OAAA;AAAA,MAAC;AAAA;AAAA,QACA,KAAK,UAAU,WAAW;AAAA,QAC1B,cAAc;AAAA,QACd,UAAU;AAAA,QACV,aAAY;AAAA;AAAA,IACb,GACA,gBAAAA,OAAA,cAACE,OAAA,EAAK,OAAM,WAAU,MAAI,QAAC,IAE3B,GACC,cAAc,SAAS,KACvB,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UACV,KAAI,KACH,mBAAmB,GAAE,KAAE,cAAc,QAAO,GAC/C,CAEF,CACD;AAAA,EAEF;AAGA,SACC,gBAAAF,OAAA,cAACC,MAAA,EAAI,WAAW,KACf,gBAAAD,OAAA,cAACE,OAAA,EAAK,OAAO,aAAa,MAAI,QAC5B,cAAc,GAChB,GACA,gBAAAF,OAAA;AAAA,IAAC;AAAA;AAAA,MACA,KAAK;AAAA,MACL,cAAc,gBAAgB;AAAA,MAC9B,UAAU;AAAA,MACV,UAAU;AAAA,MACV,aACC,SAAS,YACN,2DACA;AAAA;AAAA,EAEL,CACD;AAEF;;;AE1OA,SAAS,OAAAG,MAAK,QAAAC,aAAY;AAC1B,OAAOC,YAAW;;;ACLlB,SAAS,iBAAiB;AAC1B,SAAS,OAAAC,MAAK,QAAAC,aAAY;AAC1B,OAAOC,YAAW;AAKlB,SAAS,YAAY,OAAwB;AAC5C,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,UAAU,OAAW,QAAO;AAChC,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,OAAO,UAAU,SAAU,QAAO,OAAO,KAAK;AAClD,MAAI,OAAO,UAAU,UAAW,QAAO,QAAQ,SAAS;AACxD,MAAI,iBAAiB,KAAM,QAAO,MAAM,YAAY;AACpD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,KAAK,UAAU,KAAK;AACrD,MAAI,OAAO,UAAU,SAAU,QAAO,KAAK,UAAU,KAAK;AAC1D,SAAO,OAAO,KAAK;AACpB;AAMO,SAAS,uBAAuB;AAAA,EACtC;AACD,GAAgC;AAE/B,MAAI,OAAO,OAAO;AACjB,WACC,gBAAAC,OAAA,cAACC,MAAA,EAAI,eAAc,UAAS,SAAS,KACpC,gBAAAD,OAAA,cAACE,OAAA,EAAK,MAAI,MAAC,OAAM,SAAM,uBAEvB,GACA,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,SAAO,OAAO,KAAM,GAChC,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,QAAO,UAAQ,QAAC,KACzB,OAAO,iBAAgB,KAC1B,CACD;AAAA,EAEF;AAGA,MAAI,OAAO,KAAK,WAAW,GAAG;AAC7B,WACC,gBAAAF,OAAA,cAACC,MAAA,EAAI,eAAc,UAAS,SAAS,KACpC,gBAAAD,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,YAAS,OAAO,iBAAgB,KAAG,CACvD;AAAA,EAEF;AAEA,QAAM,EAAE,SAAS,MAAM,UAAU,iBAAiB,UAAU,IAAI;AAGhE,QAAM,cAAc,OAAO,SAAS;AAGpC,QAAM,gBAAgB,KAAK,IAAI,CAAC,QAAQ;AACvC,UAAM,YAAoC,CAAC;AAC3C,eAAW,OAAO,SAAS;AAC1B,gBAAU,GAAG,IAAI,YAAY,IAAI,GAAG,CAAC;AAAA,IACtC;AACA,WAAO;AAAA,EACR,CAAC;AAGD,QAAM,eAAe,QAAQ,IAAI,CAAC,SAAS;AAAA,IAC1C,KAAK;AAAA,IACL,MAAM;AAAA,IACN,UAAU,YAAY;AAAA,EACvB,EAAE;AAIF,QAAM,kBACL,YAAY,oBAAoB,SAC7B,CAAC,MAAc,IACf,YAAY;AAEhB,QAAM,cAAc,UAAU;AAAA,IAC7B,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa,YAAY;AAAA,IACzB,eAAe;AAAA,MACd,WAAW;AAAA,IACZ;AAAA,IACA,SAAS,YAAY;AAAA,EACtB,CAAC;AAED,SACC,gBAAAF,OAAA,cAACC,MAAA,EAAI,eAAc,UAAS,SAAS,KACpC,gBAAAD,OAAA,cAACE,OAAA,MAAM,WAAY,GACnB,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,WACV,UAAS,QAAK,aAAa,IAAI,MAAM,IAAG,MAAG,iBAAgB,OAC3D,aACA,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,YAAS,iCAA+B,CAEtD,CACD;AAEF;;;ACzGA,OAAOC,YAAW;AAKlB,SAAS,OAAAC,MAAK,QAAAC,aAAY;AASnB,SAAS,UAAU;AAAA,EACzB;AAAA,EACA;AAAA,EACA,QAAQ;AACT,GAIG;AACF,SACC,gBAAAF,OAAA,cAACC,MAAA,EAAI,eAAc,UAAS,SAAS,KACpC,gBAAAD,OAAA,cAACE,OAAA,EAAK,MAAI,MAAC,OAAM,YACf,KACF,GACA,gBAAAF,OAAA,cAACC,MAAA,EAAI,aAAY,UAAS,aAAY,QAAO,UAAU,GAAG,WAAW,KACpE,gBAAAD,OAAA,cAACE,OAAA,EAAK,OAAM,WAAS,GAAI,CAC1B,GACC,OAAO,SAAS,KAChB,gBAAAF,OAAA,cAACE,OAAA,MACA,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,cAAY,GAC/B,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAQ,KAAK,UAAU,MAAM,CAAE,CAC5C,CAEF;AAEF;AAEO,SAAS,sBAAsB;AAAA,EACrC;AACD,GAEG;AACF,SACC,gBAAAF,OAAA,cAACC,MAAA,EAAI,eAAc,UAAS,SAAS,KACnC,QAAQ,IAAI,CAAC,GAAG,MAChB,gBAAAD,OAAA,cAACC,MAAA,EAAI,KAAK,GAAG,eAAc,UAAS,cAAc,KACjD,gBAAAD,OAAA,cAACE,OAAA,EAAK,MAAI,MAAC,OAAM,UAAO,8BACH,EAAE,UAAS,IAChC,GACA,gBAAAF,OAAA;AAAA,IAACC;AAAA,IAAA;AAAA,MACA,aAAY;AAAA,MACZ,aAAY;AAAA,MACZ,UAAU;AAAA,MACV,WAAW;AAAA;AAAA,IAEX,gBAAAD,OAAA,cAACE,OAAA,EAAK,OAAM,WAAS,EAAE,GAAI;AAAA,EAC5B,GACC,EAAE,OAAO,SAAS,KAClB,gBAAAF,OAAA,cAACE,OAAA,MACA,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,cAAY,GAC/B,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAQ,KAAK,UAAU,EAAE,MAAM,CAAE,CAC9C,CAEF,CACA,CACF;AAEF;AAEO,SAAS,WAAW;AAAA,EAC1B;AAAA,EACA,YAAY;AACb,GAGG;AACF,QAAM,eAAe,KAAK,UAAU,SAAS;AAC7C,QAAM,cAAc,KAAK,SAAS,SAAS;AAC3C,QAAM,UAAU,KAAK,WAAW;AAGhC,MAAI,cAAc,aAAc,CAAC,gBAAgB,CAAC,WAAW,CAAC,aAAc;AAC3E,WACC,gBAAAF,OAAA,cAACC,MAAA,EAAI,SAAS,KACb,gBAAAD,OAAA,cAACE,OAAA,EAAK,MAAI,MAAC,OAAM,aAAU,mBACjB,GACV,GACA,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UACV,KAAK,aAAa,KAAK,UACvB,eACE,KAAK,KAAK,UAAU,MAAM,YAAY,KAAK,UAAU,SAAS,IAAI,MAAM,EAAE,GAAG,cAAc,KAAK,KAAK,SAAS,MAAM,WAAW,KAAK,SAAS,SAAS,IAAI,MAAM,EAAE,KAAK,EAAE,MACzK,iBACJ,GACC,KAAK,iBAAiB,KACtB,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,YAAI,KAAK,eAAe,QAAQ,CAAC,GAAE,IAAE,CAE1D;AAAA,EAEF;AAEA,SACC,gBAAAF,OAAA,cAACC,MAAA,EAAI,eAAc,UAAS,SAAS,KACpC,gBAAAD,OAAA,cAACE,OAAA,EAAK,MAAI,MAAC,OAAM,aAAU,uBAE3B,GACA,gBAAAF,OAAA,cAACC,MAAA,EAAI,aAAa,GAAG,eAAc,YACjC,KAAK,aACL,gBAAAD,OAAA,cAACE,OAAA,MAAK,UACC,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAQ,KAAK,SAAU,CAC1C,GAEA,KAAK,OAAO,SAAS,KACrB,gBAAAF,OAAA,cAACE,OAAA,MAAK,YACG,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAQ,KAAK,OAAO,KAAK,IAAI,CAAE,CACpD,GAEA,gBACA,gBAAAF,OAAA,cAACC,MAAA,EAAI,eAAc,UAAS,WAAW,KACtC,gBAAAD,OAAA,cAACE,OAAA,EAAK,MAAI,QAAC,YAAU,GACpB,KAAK,UAAU,IAAI,CAAC,GAAG,MACvB,gBAAAF,OAAA,cAACC,MAAA,EAAI,KAAK,GAAG,eAAc,YAC1B,gBAAAD,OAAA,cAACE,OAAA,MACA,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,UAAG,GACtB,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAQ,EAAE,IAAK,GAC3B,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,IAAE,GACrB,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAQ,EAAE,OAAQ,GAC9B,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,UAAG,GACtB,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,WAAS,EAAE,MAAO,GAC9B,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,MAAG,EAAE,WAAU,GAAC,CACpC,GACC,cAAc,aACd,gBAAAF,OAAA,cAACC,MAAA,EAAI,aAAa,GAAG,eAAc,YACjC,EAAE,gBAAgB,EAAE,aAAa,SAAS,KAC1C,gBAAAD,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,yBACD,EAAE,aAAa,KAAK,IAAI,CAC1C,GAEA,EAAE,cACF,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,cACZ,KACL,MAAM,QAAQ,EAAE,UAAU,IACxB,EAAE,WAAW,KAAK,IAAI,IACtB,EAAE,UACN,GAEA,EAAE,gBACF,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,qBAAa,EAAE,YAAa,IAE9C,EAAE,cAAc,EAAE,iBACnB,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,iBACT,EAAE,cAAc,EAAE,YAC5B,CAEF,CAEF,CACA,CACF,GAEA,cAAc,aAAa,KAAK,QAAQ,KAAK,KAAK,SAAS,IAC3D,gBAAAF,OAAA,cAACC,MAAA,EAAI,eAAc,UAAS,WAAW,KACtC,gBAAAD,OAAA,cAACE,OAAA,EAAK,MAAI,QAAC,OAAK,GACf,KAAK,KAAK,IAAI,CAAC,GAAG,MAClB,gBAAAF,OAAA,cAACC,MAAA,EAAI,KAAK,GAAG,eAAc,YAC1B,gBAAAD,OAAA,cAACE,OAAA,MACA,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,UAAG,GACtB,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAQ,EAAE,IAAK,GAC3B,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UACV,KAAI,WACF,EAAE,SACJ,EAAE,YAAY,iBAAiB,EACjC,CACD,GACC,EAAE,gBAAgB,EAAE,aAAa,SAAS,KAC1C,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UACV,6BACA,EAAE,aAAa,KAAK,IAAI,CAC1B,CAEF,CACA,CACF,IAEA,WACC,gBAAAF,OAAA,cAACE,OAAA,MAAK,UACC,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAQ,KAAK,UAAS,YAAU,CACnD,GAGD,eACA,gBAAAF,OAAA,cAACC,MAAA,EAAI,eAAc,UAAS,WAAW,KACtC,gBAAAD,OAAA,cAACE,OAAA,EAAK,OAAM,YAAS,wBAAY,GAChC,KAAK,SAAS,IAAI,CAAC,GAAG,MACtB,gBAAAF,OAAA,cAACC,MAAA,EAAI,KAAK,GAAG,eAAc,YAC1B,gBAAAD,OAAA,cAACE,OAAA,EAAK,OAAM,YACV,KAAI,WACF,EAAE,OAAO,GAAG,EAAE,IAAI,OAAO,IAC3B,EAAE,OACJ,GACC,EAAE,cAAc,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,YAAI,EAAE,UAAW,GACpD,cAAc,aAAa,EAAE,mBAC7B,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UACV,KAAI,6BACgB,EAAE,eACxB,CAEF,CACA,CACF,GAEA,cAAc,aAAa,KAAK,YAChC,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,QAAO,UAAQ,QAAC,wBACb,KAAK,SAAS,mBAAkB,aAC7C,KAAK,SAAS,sBAAsB,IAAI,MAAM,IAAG,aACjD,KAAK,SAAS,cACZ,iBAAiB,KAAK,SAAS,kBAAkB,KAAK,IAAI,CAAC,MAC3D,kBACJ,GAEA,KAAK,iBAAiB,KACtB,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,qBACL,KAAK,eAAe,QAAQ,CAAC,GAAE,IAC7C,CAEF,CACD;AAEF;AAEO,SAAS,YAAY,EAAE,QAAQ,GAAwB;AAC7D,SACC,gBAAAF,OAAA,cAACC,MAAA,EAAI,SAAS,KACb,gBAAAD,OAAA,cAACE,OAAA,EAAK,OAAM,SAAM,kBAAU,OAAQ,CACrC;AAEF;AAKO,SAAS,gBAAgB,QAAyB;AACxD,QAAM,QAAkB,CAAC;AAEzB,QAAMC,eAAc,CAAC,OAAgB,SAAS,MAAc;AAC3D,UAAM,MAAM,IAAI,OAAO,MAAM;AAC7B,QAAI,UAAU,KAAM,QAAO;AAC3B,QAAI,UAAU,OAAW,QAAO;AAChC,QAAI,OAAO,UAAU,SAAU,QAAO,IAAI,KAAK;AAC/C,QAAI,OAAO,UAAU,YAAY,OAAO,UAAU;AACjD,aAAO,OAAO,KAAK;AACpB,QAAI,MAAM,QAAQ,KAAK,GAAG;AACzB,UAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,YAAM,QAAQ,MAAM,IAAI,CAAC,MAAMA,aAAY,GAAG,SAAS,CAAC,CAAC,EAAE,KAAK,IAAI;AACpE,aAAO,IAAI,KAAK;AAAA,IACjB;AACA,QAAI,OAAO,UAAU,UAAU;AAC9B,YAAM,UAAU,OAAO,QAAQ,KAAK;AACpC,UAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,YAAM,YAAY,QAChB,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,GAAG,KAAK,CAAC,KAAKA,aAAY,GAAG,SAAS,CAAC,CAAC,EAAE,EAC7D,KAAK,IAAI;AACX,aAAO;AAAA,EAAM,SAAS;AAAA,EAAK,GAAG;AAAA,IAC/B;AACA,WAAO,OAAO,KAAK;AAAA,EACpB;AAEA,QAAM,KAAK,eAAe;AAC1B,QAAM,MAAM;AACZ,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC/C,QAAI,UAAU,QAAW;AACxB,YAAM,KAAK,KAAK,GAAG,KAAKA,aAAY,KAAK,CAAC,EAAE;AAAA,IAC7C;AAAA,EACD;AACA,QAAM,KAAK,GAAG;AACd,SAAO,MAAM,KAAK,IAAI;AACvB;AAEO,SAAS,gBAAgB,EAAE,OAAO,GAAwB;AAChE,QAAM,WAAW,gBAAgB,MAAM;AACvC,SACC,gBAAAH,OAAA,cAACC,MAAA,EAAI,eAAc,UAAS,SAAS,KACpC,gBAAAD,OAAA,cAACE,OAAA,EAAK,MAAI,MAAC,OAAM,UAAO,6BAExB,GACA,gBAAAF,OAAA,cAACC,MAAA,EAAI,aAAY,UAAS,aAAY,QAAO,UAAU,GAAG,WAAW,KACpE,gBAAAD,OAAA,cAACE,OAAA,EAAK,OAAM,WAAS,QAAS,CAC/B,CACD;AAEF;AAEO,SAAS,cAAc,EAAE,QAAQ,cAAc,GAAuB;AAC5E,MAAI,CAAC,OAAQ,QAAO;AAEpB,MAAI,OAAO,OAAO;AACjB,WACC,gBAAAF,OAAA,cAACC,MAAA,EAAI,eAAc,YAClB,gBAAAD,OAAA,cAAC,eAAY,SAAS,OAAO,OAAO,GACnC,OAAO,gBAAgB,UACvB,gBAAAA,OAAA,cAAC,mBAAgB,QAAQ,OAAO,aAAa,CAE/C;AAAA,EAEF;AAEA,SACC,gBAAAA,OAAA,cAACC,MAAA,EAAI,eAAc,YACjB,OAAO,gBAAgB,UACvB,gBAAAD,OAAA,cAAC,mBAAgB,QAAQ,OAAO,aAAa,GAE9C,gBAAAA,OAAA,cAAC,aAAU,KAAK,OAAO,KAAK,QAAQ,OAAO,QAAQ,OAAM,uBAAe,GACvE,OAAO,mBAAmB,OAAO,gBAAgB,SAAS,KAC1D,gBAAAA,OAAA,cAAC,yBAAsB,SAAS,OAAO,iBAAiB,GAExD,OAAO,QACP,gBAAAA,OAAA,cAAC,cAAW,MAAM,OAAO,MAAM,WAAW,iBAAiB,UAAU,CAEvE;AAEF;;;AFrSA,IAAM,YAAyB,CAAC,OAAO,QAAQ,WAAW,UAAU,MAAM;AAE1E,IAAM,aAAwC;AAAA,EAC7C,KAAK;AAAA,EACL,MAAM;AAAA,EACN,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,MAAM;AACP;AAEA,SAAS,OAAO;AAAA,EACf;AAAA,EACA;AACD,GAGG;AACF,SACC,gBAAAI,OAAA,cAACC,MAAA,MACC,UAAU,IAAI,CAAC,GAAG,MAAM;AACxB,UAAM,WAAW,MAAM;AACvB,UAAM,WAAW,MAAM,aAAa,CAAC;AACrC,WACC,gBAAAD,OAAA,cAACA,OAAM,UAAN,EAAe,KAAK,KACnB,IAAI,KAAK,gBAAAA,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,GAAC,GAC7B,WACA,gBAAAF,OAAA,cAACE,OAAA,EAAK,MAAI,MAAC,SAAO,MAAC,OAAM,UACvB,IAAI,WAAW,CAAC,CAAC,GACnB,IAEA,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAO,WAAW,SAAS,SAAS,UAAU,YAClD,IAAI,WAAW,CAAC,CAAC,GACnB,CAEF;AAAA,EAEF,CAAC,GACD,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,iCAAuB,CAC3C;AAEF;AAEA,SAAS,aAAa;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAyB;AACxB,MAAI,CAAC,eAAe,CAAC,iBAAiB;AACrC,WAAO,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,6BAA2B;AAAA,EACtD;AAEA,UAAQ,MAAM;AAAA,IACb,KAAK,OAAO;AACX,UAAI,CAAC,YAAa,QAAO,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,mBAAiB;AAC7D,aACC,gBAAAF,OAAA,cAACC,MAAA,EAAI,eAAc,YAClB,gBAAAD,OAAA;AAAA,QAAC;AAAA;AAAA,UACA,KAAK,YAAY;AAAA,UACjB,QAAQ,YAAY;AAAA,UACpB,OAAM;AAAA;AAAA,MACP,GACC,YAAY,mBACZ,YAAY,gBAAgB,SAAS,KACpC,gBAAAA,OAAA,cAAC,yBAAsB,SAAS,YAAY,iBAAiB,CAEhE;AAAA,IAEF;AAAA,IAEA,KAAK,QAAQ;AACZ,UAAI,CAAC,aAAa;AACjB,eAAO,gBAAAA,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,0BAAwB;AACnD,aAAO,gBAAAF,OAAA,cAAC,cAAW,MAAM,YAAY,MAAM,WAAU,WAAU;AAAA,IAChE;AAAA,IAEA,KAAK,WAAW;AACf,UAAI,CAAC;AACJ,eACC,gBAAAA,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,6CAA2C;AAEhE,UAAI,CAAC;AACJ,eACC,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,2DAEnB;AAEF,aAAO,gBAAAF,OAAA,cAAC,0BAAuB,QAAQ,iBAAiB;AAAA,IACzD;AAAA,IAEA,KAAK,UAAU;AACd,UAAI,CAAC;AACJ,eAAO,gBAAAA,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,0BAAwB;AACnD,YAAM,SAAS,YAAY;AAC3B,UAAI,OAAO,WAAW,GAAG;AACxB,eAAO,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,+BAA6B;AAAA,MACxD;AACA,aACC,gBAAAF,OAAA,cAACC,MAAA,EAAI,eAAc,YACjB,OAAO,IAAI,CAAC,GAAG,MACf,gBAAAD,OAAA,cAACE,OAAA,EAAK,KAAK,KACV,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,KAAE,IAAI,CAAE,GAC3B,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,UAAO,KAAG,GACtB,gBAAAF,OAAA,cAACE,OAAA,EAAK,OAAM,WAAS,KAAK,UAAU,CAAC,CAAE,CACxC,CACA,CACF;AAAA,IAEF;AAAA,IAEA,KAAK,QAAQ;AACZ,aACC,gBAAAF,OAAA,cAACC,MAAA,EAAI,eAAc,YACjB,eACA,gBAAAD,OAAA,cAAAA,OAAA,gBACC,gBAAAA,OAAA;AAAA,QAAC;AAAA;AAAA,UACA,KAAK,YAAY;AAAA,UACjB,QAAQ,YAAY;AAAA,UACpB,OAAM;AAAA;AAAA,MACP,GACC,YAAY,mBACZ,YAAY,gBAAgB,SAAS,KACpC,gBAAAA,OAAA;AAAA,QAAC;AAAA;AAAA,UACA,SAAS,YAAY;AAAA;AAAA,MACtB,GAED,YAAY,QACZ,gBAAAA,OAAA,cAAC,cAAW,MAAM,YAAY,MAAM,WAAU,WAAU,GAExD,YAAY,gBAAgB,UAC5B,gBAAAA,OAAA,cAAC,mBAAgB,QAAQ,YAAY,aAAa,CAEpD,GAEA,mBACA,gBAAAA,OAAA,cAAC,0BAAuB,QAAQ,iBAAiB,CAEnD;AAAA,IAEF;AAAA,EACD;AACD;AAEO,SAAS,gBAAgB,OAA6B;AAC5D,SACC,gBAAAA,OAAA;AAAA,IAACC;AAAA,IAAA;AAAA,MACA,eAAc;AAAA,MACd,aAAY;AAAA,MACZ,aAAY;AAAA,MACZ,UAAU;AAAA,MACV,WAAW;AAAA;AAAA,IAEX,gBAAAD,OAAA,cAAC,UAAO,YAAY,MAAM,MAAM,UAAU,MAAM,UAAU;AAAA,IAC1D,gBAAAA,OAAA,cAACC,MAAA,EAAI,eAAc,UAAS,WAAW,KACtC,gBAAAD,OAAA,cAAC,gBAAc,GAAG,OAAO,CAC1B;AAAA,EACD;AAEF;;;AGjLA,SAAS,OAAAG,MAAK,QAAAC,aAAY;AAC1B,OAAOC,YAAW;AAclB,SAAS,aAAa;AAAA,EACrB;AAAA,EACA;AACD,GAGG;AACF,MAAI,CAAC,eAAe,CAAC,WAAY,QAAO;AAExC,QAAM,QAAkB,CAAC;AAEzB,MAAI,YAAY;AACf,QAAI,WAAW,OAAO;AACrB,aAAO,gBAAAC,OAAA,cAACC,OAAA,EAAK,OAAM,SAAM,WAAG,WAAW,KAAM;AAAA,IAC9C;AACA,UAAM;AAAA,MACL,GAAG,WAAW,QAAQ,OAAO,WAAW,aAAa,IAAI,MAAM,EAAE;AAAA,IAClE;AACA,UAAM,KAAK,GAAG,WAAW,gBAAgB,QAAQ,CAAC,CAAC,IAAI;AACvD,QAAI,WAAW,UAAW,OAAM,KAAK,WAAW;AAAA,EACjD;AAEA,MAAI,aAAa;AAChB,QAAI,YAAY,OAAO;AACtB,aAAO,gBAAAD,OAAA,cAACC,OAAA,EAAK,OAAM,SAAM,WAAG,YAAY,KAAM;AAAA,IAC/C;AACA,QAAI,CAAC,YAAY;AAEhB,YAAM,OAAO,YAAY;AACzB,UAAI,MAAM,UAAW,OAAM,KAAK,KAAK,SAAS;AAC9C,UAAI,QAAQ,KAAK,WAAW;AAC3B,cAAM,KAAK,GAAG,KAAK,QAAQ,OAAO,KAAK,aAAa,IAAI,MAAM,EAAE,EAAE;AACnE,UACC,YAAY,mBACZ,YAAY,gBAAgB,SAAS,GACpC;AACD,cAAM;AAAA,UACL,IAAI,YAAY,gBAAgB,MAAM,QAAQ,YAAY,gBAAgB,WAAW,IAAI,QAAQ,GAAG;AAAA,QACrG;AAAA,MACD;AACA,UAAI,QAAQ,KAAK,iBAAiB;AACjC,cAAM,KAAK,GAAG,KAAK,eAAe,QAAQ,CAAC,CAAC,IAAI;AACjD,UAAI,MAAM,YAAY,KAAK,SAAS,SAAS;AAC5C,cAAM;AAAA,UACL,GAAG,KAAK,SAAS,MAAM,WAAW,KAAK,SAAS,WAAW,IAAI,MAAM,EAAE;AAAA,QACxE;AAAA,IACF;AAAA,EACD;AAEA,SACC,gBAAAD,OAAA,cAACC,OAAA,MACA,gBAAAD,OAAA,cAACC,OAAA,EAAK,OAAM,WAAQ,SAAE,GACtB,gBAAAD,OAAA,cAACC,OAAA,EAAK,OAAM,UAAQ,MAAM,KAAK,QAAK,CAAE,CACvC;AAEF;AAGA,SAAS,sBAAsB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AACD,GAIG;AAEF,MAAI,cAAkC;AACtC,MAAI,aAAqC;AACzC,MAAI,cAA6B;AACjC,MAAI,eAA8B;AAElC,aAAW,SAAS,MAAM,QAAQ;AACjC,YAAQ,MAAM,MAAM;AAAA,MACnB,KAAK;AACJ,sBAAc,MAAM;AACpB;AAAA,MACD,KAAK;AACJ,qBAAa,MAAM;AACnB;AAAA,MACD,KAAK;AACJ,sBAAc,MAAM;AACpB;AAAA,MACD,KAAK;AACJ,uBAAe,MAAM;AACrB;AAAA,IACF;AAAA,EACD;AAEA,QAAM,iBAAiB,gBAAgB,QAAQ,eAAe;AAE9D,SACC,gBAAAD,OAAA,cAACE,MAAA,EAAI,eAAc,UAAS,cAAc,KAExC,MAAM,SACN,gBAAAF,OAAA,cAACC,OAAA,MACA,gBAAAD,OAAA,cAACC,OAAA,EAAK,OAAM,QAAO,MAAI,QACrB,SACF,GACA,gBAAAD,OAAA,cAACC,OAAA,EAAK,MAAI,QAAE,MAAM,KAAM,CACzB,GAIA,eAAe,gBAAAD,OAAA,cAACC,OAAA,MAAM,WAAY,GAGlC,gBAAgB,gBAAAD,OAAA,cAACC,OAAA,EAAK,OAAM,SAAO,YAAa,GAGhD,kBAAkB,iBAAiB,aACnC,gBAAAD,OAAA,cAAC,gBAAa,aAA0B,YAAwB,GAGhE,kBAAkB,iBAAiB,SACnC,gBAAAA,OAAA,cAACE,MAAA,EAAI,eAAc,YAClB,gBAAAF,OAAA,cAAC,gBAAa,aAA0B,YAAwB,GAC/D,eACA,gBAAAA,OAAA,cAAC,iBAAc,QAAQ,aAAa,eAA8B,CAEpE,GAGA,kBAAkB,iBAAiB,aACnC,gBAAAA,OAAA,cAACE,MAAA,EAAI,eAAc,YAClB,gBAAAF,OAAA,cAAC,gBAAa,aAA0B,YAAwB,GAC/D,cAAc,gBAAAA,OAAA,cAAC,0BAAuB,QAAQ,YAAY,CAC5D,GAGA,kBAAkB,iBAAiB,UACnC,gBAAAA,OAAA,cAACE,MAAA,EAAI,eAAc,YACjB,eACA,gBAAAF,OAAA,cAAC,iBAAc,QAAQ,aAAa,eAA8B,GAElE,cAAc,gBAAAA,OAAA,cAAC,0BAAuB,QAAQ,YAAY,CAC5D,CAEF;AAEF;AAEO,SAAS,iBAAiB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AACD,GAA0B;AACzB,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,SACC,gBAAAA,OAAA,cAACE,MAAA,EAAI,eAAc,YACjB,QAAQ,IAAI,CAAC,UACb,gBAAAF,OAAA;AAAA,IAAC;AAAA;AAAA,MACA,KAAK,MAAM;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA;AAAA,EACD,CACA,CACF;AAEF;;;ACjLA,IAAM,cAAc;AASb,IAAM,sBAAN,MAA0B;AAAA,EACxB,UAA+B,CAAC;AAAA,EAChC,SAAS;AAAA;AAAA,EAGjB,SAAS,OAAkC;AAC1C,UAAM,QAA2B;AAAA,MAChC,IAAI,KAAK;AAAA,MACT,WAAW,oBAAI,KAAK;AAAA,MACpB;AAAA,MACA,QAAQ,CAAC;AAAA,IACV;AACA,SAAK,QAAQ,KAAK,KAAK;AAGvB,QAAI,KAAK,QAAQ,SAAS,aAAa;AACtC,WAAK,QAAQ,OAAO,GAAG,KAAK,QAAQ,SAAS,WAAW;AAAA,IACzD;AAEA,WAAO;AAAA,EACR;AAAA;AAAA,EAGA,YAAY,SAAiB,OAA0B;AACtD,UAAM,QAAQ,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO;AACvD,QAAI,OAAO;AACV,YAAM,OAAO,KAAK,KAAK;AAAA,IACxB;AAAA,EACD;AAAA;AAAA,EAGA,aAA2C;AAC1C,WAAO,KAAK;AAAA,EACb;AAAA;AAAA,EAGA,QAAc;AACb,SAAK,UAAU,CAAC;AAAA,EACjB;AACD;;;ACrDA;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,eAAe;AACxB,SAAS,SAAS,YAAY;AAE9B,IAAM,eAAe,KAAK,QAAQ,GAAG,eAAe;AACpD,IAAM,mBAAmB;AAazB,SAAS,oBAAoB,MAAsB;AAClD,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACrC,QAAI,KAAK,CAAC,MAAM,QAAQ,IAAI,IAAI,KAAK,QAAQ;AAC5C,YAAM,OAAO,KAAK,IAAI,CAAC;AACvB,UAAI,SAAS,MAAM;AAClB,kBAAU;AACV;AAAA,MACD,WAAW,SAAS,KAAK;AACxB,kBAAU;AACV;AAAA,MACD,OAAO;AAEN,kBAAU,KAAK,CAAC;AAAA,MACjB;AAAA,IACD,OAAO;AACN,gBAAU,KAAK,CAAC;AAAA,IACjB;AAAA,EACD;AACA,SAAO;AACR;AAKO,IAAM,iBAAN,MAAqB;AAAA,EACnB,UAAoB,CAAC;AAAA,EACrB,QAAQ;AAAA,EACR,eAAe;AAAA,EAEvB,cAAc;AACb,SAAK,KAAK;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKQ,OAAa;AACpB,QAAI;AACH,UAAI,WAAW,YAAY,GAAG;AAE7B,YAAI;AACH,oBAAU,cAAc,GAAK;AAAA,QAC9B,QAAQ;AAAA,QAER;AACA,cAAM,UAAU,aAAa,cAAc,OAAO;AAClD,aAAK,UAAU,QACb,MAAM,IAAI,EACV,OAAO,CAAC,SAAS,KAAK,KAAK,EAAE,SAAS,CAAC,EAKvC,IAAI,CAAC,SAAS,oBAAoB,IAAI,CAAC;AAAA,MAC1C;AAAA,IACD,QAAQ;AAAA,IAER;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKQ,OAAa;AACpB,QAAI;AACH,YAAM,MAAM,QAAQ,YAAY;AAChC,UAAI,CAAC,WAAW,GAAG,GAAG;AACrB,kBAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAAA,MACnC;AAIA,YAAM,UAAU,KAAK,QACnB,IAAI,CAAC,UAAU,MAAM,QAAQ,OAAO,MAAM,EAAE,QAAQ,OAAO,KAAK,CAAC,EACjE,KAAK,IAAI;AAEX,oBAAc,cAAc,SAAS;AAAA,QACpC,UAAU;AAAA,QACV,MAAM;AAAA,MACP,CAAC;AAID,UAAI;AACH,kBAAU,cAAc,GAAK;AAAA,MAC9B,QAAQ;AAAA,MAER;AAAA,IACD,QAAQ;AAAA,IAER;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAI,SAAiB,UAAU,MAAY;AAC1C,UAAM,UAAU,QAAQ,KAAK;AAC7B,QAAI,CAAC,QAAS;AAGd,QAAI,KAAK,QAAQ,KAAK,QAAQ,SAAS,CAAC,MAAM,QAAS;AAEvD,SAAK,QAAQ,KAAK,OAAO;AAGzB,QAAI,KAAK,QAAQ,SAAS,kBAAkB;AAC3C,WAAK,UAAU,KAAK,QAAQ,MAAM,CAAC,gBAAgB;AAAA,IACpD;AAEA,SAAK,WAAW;AAChB,QAAI,SAAS;AACZ,WAAK,KAAK;AAAA,IACX;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,aAAmB;AAClB,SAAK,QAAQ;AACb,SAAK,eAAe;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS,cAA0C;AAElD,QAAI,KAAK,UAAU,IAAI;AACtB,WAAK,eAAe;AAAA,IACrB;AAEA,QAAI,KAAK,QAAQ,WAAW,EAAG,QAAO;AAGtC,QAAI,KAAK,QAAQ,KAAK,QAAQ,SAAS,GAAG;AACzC,WAAK;AAAA,IACN;AAEA,WAAO,KAAK,QAAQ,KAAK,QAAQ,SAAS,IAAI,KAAK,KAAK;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAA2B;AAC1B,QAAI,KAAK,SAAS,GAAG;AACpB,WAAK,QAAQ;AACb,aAAO,KAAK;AAAA,IACb;AAEA,SAAK;AACL,WAAO,KAAK,QAAQ,KAAK,QAAQ,SAAS,IAAI,KAAK,KAAK;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,OAAyB;AAC/B,QAAI,CAAC,MAAO,QAAO,KAAK,QAAQ,MAAM,GAAG;AACzC,UAAM,QAAQ,MAAM,YAAY;AAChC,WAAO,KAAK,QAAQ,OAAO,CAAC,QAAQ,IAAI,YAAY,EAAE,SAAS,KAAK,CAAC;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,OAAyB;AACtC,QAAI,CAAC,MAAO,QAAO,CAAC;AACpB,UAAM,QAAQ,MAAM,YAAY;AAEhC,WAAO,KAAK,QACV,OAAO,CAAC,QAAQ,IAAI,YAAY,EAAE,SAAS,KAAK,CAAC,EACjD,QAAQ;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,SAA4B;AAC3B,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,QAAQ,IAAc;AAC/B,WAAO,KAAK,QAAQ,MAAM,CAAC,KAAK;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACb,SAAK,UAAU,CAAC;AAChB,SAAK,WAAW;AAChB,SAAK,KAAK;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAiB;AACpB,WAAO,KAAK,QAAQ;AAAA,EACrB;AACD;AAKA,IAAI,kBAAyC;AAEtC,SAAS,aAA6B;AAC5C,MAAI,CAAC,iBAAiB;AACrB,sBAAkB,IAAI,eAAe;AAAA,EACtC;AACA,SAAO;AACR;;;AXxNA,SAAS,QAAQ,EAAE,QAAAG,QAAO,GAAiB;AAC1C,QAAM,EAAE,KAAK,IAAI,OAAO;AAGxB,QAAM,YAAYC,QAA0B,IAAI;AAChD,MAAI,CAAC,UAAU,SAAS;AACvB,cAAU,UAAU,IAAI,WAAW;AAAA,MAClC,QAAQD,QAAO;AAAA,MACf,YAAYA,QAAO;AAAA,MACnB,GAAIA,QAAO,gBAAgB,UAAa;AAAA,QACvC,aAAaA,QAAO;AAAA,MACrB;AAAA,MACA,GAAIA,QAAO,sBAAsB,UAAa;AAAA,QAC7C,mBAAmBA,QAAO;AAAA,MAC3B;AAAA,MACA,GAAIA,QAAO,qBAAqB,UAAa;AAAA,QAC5C,kBAAkBA,QAAO;AAAA,MAC1B;AAAA,MACA,GAAIA,QAAO,oBAAoB,UAAa;AAAA,QAC3C,iBAAiBA,QAAO;AAAA,MACzB;AAAA,MACA,GAAIA,QAAO,aAAa,UAAa,EAAE,UAAUA,QAAO,SAAS;AAAA,IAClE,CAAC;AAAA,EACF;AACA,QAAM,SAAS,UAAU;AAGzB,QAAM,kBAAkBC,QAAmC,IAAI;AAC/D,MAAI,CAAC,gBAAgB,SAAS;AAC7B,oBAAgB,UAAU,IAAI,oBAAoB;AAAA,EACnD;AACA,QAAM,eAAe,gBAAgB;AAGrC,QAAM,CAAC,aAAa,cAAc,IAAIC;AAAA,IACrC,OAAO,SAAS;AAAA,EACjB;AACA,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,aAAa,WAAW,CAAC;AAChE,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAS,KAAK;AAC9C,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAS,CAAC;AAG1C,QAAM,CAAC,WAAW,YAAY,IAAIA,UAA2B,IAAI;AACjE,QAAM,CAAC,iBAAiB,kBAAkB,IAAIA;AAAA,IAC7C;AAAA,EACD;AACA,QAAM,CAAC,gBAAgB,iBAAiB,IAAIA;AAAA,IAC3C;AAAA,EACD;AAGA,QAAM,qBAAqBC;AAAA,IAC1B,MAAM,OAAO,sBAAsB;AAAA,IACnC,CAAC,MAAM;AAAA,EACR;AACA,QAAM,CAAC,aAAa,cAAc,IAAID,UAAiC,CAAC,CAAC;AACzE,QAAM,CAAC,yBAAyB,0BAA0B,IAAIA,UAAS,EAAE;AAGzE,QAAM,UAAUC,SAAQ,MAAM,WAAW,GAAG,CAAC,CAAC;AAG9C,EAAAC,WAAU,MAAM;AACf,WAAO,KAAK;AACZ,WAAO,MAAM;AACZ,aAAO,QAAQ;AAAA,IAChB;AAAA,EACD,GAAG,CAAC,MAAM,CAAC;AAIX,QAAM,oBAAoBH,QAAsB,IAAI;AAEpD,EAAAG,WAAU,MAAM;AACf,UAAM,iBAAiB,MAAM,WAAW,CAAC,GAAG,aAAa,WAAW,CAAC,CAAC;AAGtE,UAAM,0BAA0B,CAAC,UAAuB;AACvD,UAAI,kBAAkB,YAAY,MAAM;AACvC,qBAAa,YAAY,kBAAkB,SAAS,KAAK;AAAA,MAC1D,OAAO;AACN,cAAM,QAAQ,aAAa,SAAS,EAAE;AACtC,qBAAa,YAAY,MAAM,IAAI,KAAK;AAAA,MACzC;AACA,qBAAe;AAAA,IAChB;AAEA,UAAM,QAAQ,OAAO,GAAG,CAAC,UAAuB;AAC/C,cAAQ,MAAM,MAAM;AAAA,QACnB,KAAK;AACJ,yBAAe,MAAM,KAAK;AAC1B;AAAA,QAED,KAAK;AACJ,eAAK;AACL;AAAA,QAED,KAAK;AACJ,uBAAa,MAAM;AACnB,sBAAY,KAAK;AACjB,uBAAa,IAAI;AACjB,6BAAmB,IAAI;AACvB,4BAAkB,IAAI;AACtB,yBAAe;AACf;AAAA,QAED,KAAK;AACJ,cAAI,MAAM,YAAY,aAAa;AAClC,wBAAY,IAAI;AAChB;AAAA,UACD;AACA,kCAAwB,KAAK;AAC7B;AAAA,QAED,KAAK;AACJ,kCAAwB,KAAK;AAC7B;AAAA,QAED,KAAK;AACJ,cAAI,kBAAkB,YAAY,MAAM;AACvC,yBAAa,YAAY,kBAAkB,SAAS,KAAK;AACzD,2BAAe;AAAA,UAChB;AAEA,6BAAmB,MAAM,MAAM;AAE/B;AAAA,QAED,KAAK;AACJ,cAAI,kBAAkB,YAAY,MAAM;AACvC,yBAAa,YAAY,kBAAkB,SAAS,KAAK;AACzD,2BAAe;AAAA,UAChB;AAEA,4BAAkB,MAAM,MAAM;AAC9B,6BAAmB,MAAM,KAAK;AAC9B;AAAA,QAED,KAAK,gBAAgB;AACpB,gBAAM,SAAS,QAAQ,UAAU,EAAE;AACnC,gBAAM,MACL,OAAO,WAAW,IACf,4BACA,8BAAuB,OAAO,MAAM;AAAA,EAAO,OAAO,IAAI,CAAC,KAAK,MAAM,KAAK,IAAI,CAAC,KAAK,GAAG,EAAE,EAAE,KAAK,IAAI,CAAC;AACtG,kCAAwB,EAAE,MAAM,QAAQ,SAAS,IAAI,CAAC;AACtD;AAAA,QACD;AAAA,QAEA,KAAK;AACJ,uBAAa,MAAM,IAAI;AACvB;AAAA,QAED,KAAK;AACJ,uBAAa,IAAI;AACjB;AAAA,QAED,KAAK;AAEJ;AAAA,MACF;AAAA,IACD,CAAC;AACD,WAAO;AAAA,EACR,GAAG,CAAC,QAAQ,cAAc,IAAI,CAAC;AAG/B,EAAAC,UAAS,CAAC,WAAW,QAAQ;AAC5B,QAAI,IAAI,QAAQ,cAAc,KAAK;AAClC,WAAK;AAAA,IACN;AAEA,QAAI,IAAI,UAAU,cAAc,MAAM;AACrC,mBAAa,IAAI;AACjB;AAAA,IACD;AAEA,QAAI,IAAI,KAAK;AACZ,UAAI,cAAc,MAAM;AACvB,cAAM,QAAqB,CAAC,OAAO,QAAQ,WAAW,UAAU,MAAM;AACtE,cAAM,aAAa,MAAM,QAAQ,SAAS;AAC1C,cAAM,WAAW,aAAa,KAAK,MAAM;AACzC,cAAM,WAAW,MAAM,OAAO;AAC9B,YAAI,SAAU,cAAa,QAAQ;AACnC;AAAA,MACD;AACA,UAAI,YAAY,SAAS,KAAK,YAAY,SAAS,WAAW;AAC7D,cAAM,YACL,0BAA0B,IACvB,KACC,0BAA0B,KAAK,YAAY;AAChD,mCAA2B,SAAS;AAAA,MACrC;AAAA,IACD;AAAA,EACD,CAAC;AAED,QAAM,oBAAoBC;AAAA,IACzB,CAAC,UAAkB;AAClB,iCAA2B,EAAE;AAC7B,UAAI,YAAY,SAAS,WAAW;AACnC,cAAM,cAAc,mBAAmB,SAAS,KAAK;AACrD,uBAAe,WAAW;AAAA,MAC3B,OAAO;AACN,uBAAe,CAAC,CAAC;AAAA,MAClB;AAAA,IACD;AAAA,IACA,CAAC,oBAAoB,YAAY,IAAI;AAAA,EACtC;AAEA,QAAM,2BAA2BA,aAAY,MAAM;AAClD,+BAA2B,EAAE;AAC7B,mBAAe,CAAC,CAAC;AAAA,EAClB,GAAG,CAAC,CAAC;AAEL,QAAM,wBAAwBA;AAAA,IAC7B,CAAC,cAAsB,mBAA2B;AACjD,aAAO,mBAAmB,gBAAgB,cAAc,cAAc;AAAA,IACvE;AAAA,IACA,CAAC,kBAAkB;AAAA,EACpB;AAEA,QAAM,qBACL,2BAA2B,IACxB,YAAY,uBAAuB,GAAG,OACtC;AAGJ,QAAM,iBAAiBL,QAAiB,CAAC,CAAC;AAC1C,QAAM,kBAAkBA,QAAO,KAAK;AAEpC,QAAM,eAAeK,aAAY,YAAY;AAC5C,QAAI,gBAAgB,QAAS;AAC7B,oBAAgB,UAAU;AAE1B,WAAO,eAAe,QAAQ,SAAS,GAAG;AACzC,YAAM,UAAU,eAAe,QAAQ,MAAM;AAC7C,UAAI,YAAY,OAAW;AAG3B,cAAQ,IAAI,OAAO;AAGnB,YAAM,QAAQ,aAAa,SAAS,OAAO;AAC3C,wBAAkB,UAAU,MAAM;AAClC,iBAAW,CAAC,GAAG,aAAa,WAAW,CAAC,CAAC;AAGzC,YAAM,OAAO,OAAO,OAAO;AAG3B,wBAAkB,UAAU;AAAA,IAC7B;AAEA,oBAAgB,UAAU;AAAA,EAC3B,GAAG,CAAC,QAAQ,cAAc,OAAO,CAAC;AAElC,QAAM,eAAeA;AAAA,IACpB,CAAC,UAAkB;AAClB,YAAM,UAAU,MAAM,KAAK;AAC3B,UAAI,CAAC,QAAS;AAGd,kBAAY,CAAC,MAAM,IAAI,CAAC;AACxB,qBAAe,CAAC,CAAC;AACjB,kBAAY,KAAK;AAGjB,qBAAe,QAAQ,KAAK,OAAO;AACnC,mBAAa;AAAA,IACd;AAAA,IACA,CAAC,YAAY;AAAA,EACd;AAGA,QAAM,aAAaN,QAAO,OAAO,WAAW;AAC5C,QAAM,gBAAgBA,QAAO,OAAO,MAAM,UAAU;AAGpD,QAAM,cACL,gBAAAO,QAAA,cAACC,OAAA,EAAI,eAAc,YACjB,YAAY,gBAAAD,QAAA,cAAC,iBAAY,GAG1B,gBAAAA,QAAA;AAAA,IAAC;AAAA;AAAA,MACA;AAAA,MACA,cAAc,YAAY;AAAA,MAC1B,eAAe,YAAY;AAAA;AAAA,EAC5B,GAGC,YAAY,SAAS,aACrB,YAAY,SAAS,KACrB,CAAC,YACA,gBAAAA,QAAA;AAAA,IAAC;AAAA;AAAA,MACA,aAAa;AAAA,MACb,eAAe;AAAA;AAAA,EAChB,GAIF,gBAAAA,QAAA;AAAA,IAAC;AAAA;AAAA,MACA,UAAU;AAAA,MACV,MAAM,YAAY;AAAA,MAClB,UAAU;AAAA,MACV;AAAA,MACA,eAAe;AAAA,MACd,GAAI,uBAAuB,UAAa,EAAE,mBAAmB;AAAA,MAC9D,sBAAsB;AAAA,MACtB,iBAAiB;AAAA;AAAA,EAClB,GAGC,cAAc,QACd,gBAAAA,QAAA;AAAA,IAAC;AAAA;AAAA,MACA,MAAM;AAAA,MACN,aAAa;AAAA,MACb,iBAAiB;AAAA,MACjB,UAAU,YAAY;AAAA,MACtB,cAAc;AAAA;AAAA,EACf,CAEF;AAGD,SACC,gBAAAA,QAAA,cAACC,OAAA,EAAI,eAAc,UAAS,SAAS,KACpC,gBAAAD,QAAA;AAAA,IAAC;AAAA;AAAA,MACA,YAAYP,QAAO;AAAA,MACnB,MAAM,YAAY;AAAA,MAClB;AAAA,MACA;AAAA,MACA,SAAS,YAAY;AAAA,MACrB,iBAAiB,YAAY;AAAA,MAC7B,cAAc,YAAY;AAAA,MAC1B,WAAW,YAAY;AAAA,MACvB,UAAU,YAAY;AAAA,MACtB,WAAW,YAAY;AAAA,MACvB,aAAa,YAAY;AAAA,MACxB,GAAI,YAAY,cAAc,EAAE,YAAY,YAAY,WAAW;AAAA,MACnE,GAAIA,QAAO,eAAe;AAAA,QAC1B,cAAc,gBAAgBA,QAAO,WAAW;AAAA,MACjD;AAAA;AAAA,EACD,GAEC,WACF;AAEF;AAKA,eAAsB,UAAUA,SAAmC;AAClE,UAAQ,IAAI,oBAAoB;AAEhC,QAAM,WAAW,OAAO,gBAAAO,QAAA,cAAC,WAAQ,QAAQP,SAAQ,CAAE;AACnD,QAAM,SAAS,cAAc;AAC9B;","names":["Box","useInput","React","useCallback","useEffect","useMemo","useRef","useState","React","Box","Text","React","Box","Text","React","Box","Text","useInput","useEffect","useState","Box","Text","React","before","at","after","useState","useEffect","useInput","React","Box","Text","Box","Text","React","Box","Text","React","React","Box","Text","React","Box","Text","formatValue","React","Box","Text","Box","Text","React","React","Text","Box","config","useRef","useState","useMemo","useEffect","useInput","useCallback","React","Box"]}
@@ -0,0 +1,47 @@
1
+ import { LoadedSchema } from '@dbsp/types';
2
+ export { LoadedSchema } from '@dbsp/types';
3
+
4
+ /**
5
+ * Schema Loader Utility
6
+ *
7
+ * Loads dbsp.schema.ts files using tsx for TypeScript support.
8
+ * Falls back to native import for .js files.
9
+ *
10
+ * NOTE: Similar code exists in packages/mcp-server/src/schema-loader.ts
11
+ * The MCP version has additional security features (path traversal protection,
12
+ * allowedRoots, error codes) that are required for network-exposed services.
13
+ * This CLI version is simpler as it runs locally with user trust.
14
+ * See ARCH-004 for analysis of this intentional duplication.
15
+ */
16
+
17
+ /**
18
+ * Default schema file names to search for.
19
+ */
20
+ declare const DEFAULT_SCHEMA_FILES: string[];
21
+ /**
22
+ * Error thrown when schema loading fails.
23
+ */
24
+ declare class SchemaLoadError extends Error {
25
+ constructor(message: string);
26
+ }
27
+ /**
28
+ * Find the schema file in the given directory.
29
+ */
30
+ declare function findSchemaFile(cwd: string): string | null;
31
+ /**
32
+ * Load a schema from a TypeScript or JavaScript file.
33
+ *
34
+ * ARCH-005: Only accepts new schema() format, not legacy defineSchema().
35
+ * For TypeScript files, this uses tsx loader via dynamic import.
36
+ */
37
+ declare function loadSchema(schemaPath: string): Promise<LoadedSchema>;
38
+ /**
39
+ * Load schema from the current working directory.
40
+ * Searches for default schema file names.
41
+ */
42
+ declare function loadSchemaFromCwd(cwd?: string): Promise<{
43
+ schema: LoadedSchema;
44
+ path: string;
45
+ }>;
46
+
47
+ export { DEFAULT_SCHEMA_FILES, SchemaLoadError, findSchemaFile, loadSchema, loadSchemaFromCwd };
@@ -0,0 +1,15 @@
1
+ import {
2
+ DEFAULT_SCHEMA_FILES,
3
+ SchemaLoadError,
4
+ findSchemaFile,
5
+ loadSchema,
6
+ loadSchemaFromCwd
7
+ } from "../chunk-AQC34IO5.js";
8
+ export {
9
+ DEFAULT_SCHEMA_FILES,
10
+ SchemaLoadError,
11
+ findSchemaFile,
12
+ loadSchema,
13
+ loadSchemaFromCwd
14
+ };
15
+ //# sourceMappingURL=schema-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json ADDED
@@ -0,0 +1,94 @@
1
+ {
2
+ "name": "@dbsp/cli",
3
+ "version": "1.0.0",
4
+ "description": "CLI tools for db-semantic-planner — REPL, schema generation, DDL provisioning",
5
+ "author": "Olivier Orabona <oorabona@users.noreply.github.com>",
6
+ "license": "MIT",
7
+ "engines": {
8
+ "node": ">=20"
9
+ },
10
+ "keywords": [
11
+ "cli",
12
+ "database",
13
+ "repl",
14
+ "schema",
15
+ "ddl",
16
+ "migrations",
17
+ "postgresql"
18
+ ],
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/oorabona/db-semantic-planner.git",
22
+ "directory": "packages/cli"
23
+ },
24
+ "homepage": "https://github.com/oorabona/db-semantic-planner/tree/main/packages/cli",
25
+ "bugs": {
26
+ "url": "https://github.com/oorabona/db-semantic-planner/issues"
27
+ },
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "type": "module",
32
+ "bin": {
33
+ "dbsp": "./dist/index.js"
34
+ },
35
+ "main": "./dist/index.js",
36
+ "types": "./dist/index.d.ts",
37
+ "exports": {
38
+ ".": {
39
+ "types": "./dist/index.d.ts",
40
+ "import": "./dist/index.js"
41
+ },
42
+ "./generators/schema-codegen": {
43
+ "types": "./dist/generators/schema-codegen.d.ts",
44
+ "import": "./dist/generators/schema-codegen.js"
45
+ },
46
+ "./batch": {
47
+ "types": "./dist/repl/batch.d.ts",
48
+ "import": "./dist/repl/batch.js"
49
+ },
50
+ "./schema-loader": {
51
+ "types": "./dist/utils/schema-loader.d.ts",
52
+ "import": "./dist/utils/schema-loader.js"
53
+ }
54
+ },
55
+ "files": [
56
+ "dist"
57
+ ],
58
+ "scripts": {
59
+ "build": "tsup",
60
+ "test": "vitest run",
61
+ "test:watch": "vitest",
62
+ "typecheck": "tsc --noEmit"
63
+ },
64
+ "dependencies": {
65
+ "@dbsp/adapter-pgsql": "workspace:*",
66
+ "@dbsp/core": "workspace:*",
67
+ "@dbsp/nql": "workspace:*",
68
+ "@dbsp/types": "workspace:*",
69
+ "@oclif/table": "^0.5.4",
70
+ "commander": "catalog:",
71
+ "ink": "catalog:",
72
+ "react": "catalog:"
73
+ },
74
+ "peerDependencies": {
75
+ "pg": "^8.16.0",
76
+ "tsx": "^4.21.0"
77
+ },
78
+ "peerDependenciesMeta": {
79
+ "tsx": {
80
+ "optional": true
81
+ },
82
+ "pg": {
83
+ "optional": true
84
+ }
85
+ },
86
+ "devDependencies": {
87
+ "@types/node": "catalog:",
88
+ "@types/react": "catalog:",
89
+ "tsup": "catalog:",
90
+ "tsx": "catalog:",
91
+ "typescript": "catalog:",
92
+ "vitest": "catalog:"
93
+ }
94
+ }