@gendive/chatllm 0.3.1 → 0.4.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/index.ts","../../src/react/ChatUI.tsx","../../src/react/hooks/useChatUI.ts","../../src/types.ts","../../src/react/components/Icon.tsx","../../src/react/components/ChatSidebar.tsx","../../src/react/components/ChatHeader.tsx","../../src/react/components/ChatInput.tsx","../../src/react/components/MessageList.tsx","../../src/react/components/MessageBubble.tsx","../../src/react/components/MarkdownRenderer.tsx","../../src/react/components/LinkChip.tsx","../../src/react/components/EmptyState.tsx","../../src/react/components/MemoryPanel.tsx","../../src/react/components/SettingsModal.tsx"],"sourcesContent":["/**\n * @description @gendive/chatllm/react - React UI 컴포넌트 패키지\n */\n\n// Main Component\nexport { ChatUI } from './ChatUI';\nexport type { ChatUIProps } from './types';\n\n// Headless Hook\nexport { useChatUI } from './hooks/useChatUI';\nexport type { UseChatUIOptions } from './hooks/useChatUI';\n\n// UseChatUIReturn is exported from types\n\n// Sub-components\nexport {\n Icon,\n IconSvg,\n ChatSidebar,\n ChatInput,\n ChatHeader,\n MessageBubble,\n MessageList,\n EmptyState,\n MemoryPanel,\n // Markdown & Link components\n MarkdownRenderer,\n LinkChip,\n // Settings\n SettingsModal,\n} from './components';\n\nexport type {\n MemoryItem,\n MemoryPanelProps,\n MarkdownRendererProps,\n LinkChipProps,\n SettingsModalProps,\n} from './components';\n\n// Types\nexport type {\n // Message Types\n ChatMessage,\n ChatSession,\n AlternativeResponse,\n // Action Types\n ActionItem,\n // Model Types\n ModelConfig,\n ProviderType,\n // Template Types\n PromptTemplate,\n // Settings Types\n SettingsTab,\n // Theme Types\n ThemeMode,\n ThemeConfig,\n // Component Props\n SendMessageParams,\n ChatUIComponents,\n SidebarProps,\n MessageListProps,\n MessageBubbleProps,\n InputProps,\n HeaderProps,\n EmptyStateProps,\n ActionMenuProps,\n ModelSelectorProps,\n // Personalization (re-export)\n PersonalizationConfig,\n ResponseStyle,\n UserProfile,\n // Hook return type\n UseChatUIReturn,\n} from './types';\n\nexport type { IconName, IconProps } from './components/Icon';\n","/**\n * @description ChatUI 메인 컴포넌트\n * 풀 기능 채팅 UI\n */\n\nimport React, { useState } from 'react';\nimport { useChatUI, UseChatUIOptions } from './hooks/useChatUI';\nimport { ChatSidebar } from './components/ChatSidebar';\nimport { ChatHeader } from './components/ChatHeader';\nimport { ChatInput } from './components/ChatInput';\nimport { MessageList } from './components/MessageList';\nimport { EmptyState } from './components/EmptyState';\nimport { MemoryPanel, MemoryItem } from './components/MemoryPanel';\nimport { SettingsModal } from './components/SettingsModal';\nimport type { ChatUIProps, ActionItem, PromptTemplate } from './types';\n\n// ============================================================================\n// Default Actions\n// ============================================================================\n\nconst DEFAULT_ACTIONS: ActionItem[] = [\n {\n id: 'webSearch',\n label: '웹 검색',\n icon: 'search',\n description: '웹에서 정보를 검색합니다',\n systemPrompt: '웹 검색 결과를 기반으로 답변해주세요.',\n },\n {\n id: 'imageGen',\n label: '이미지 생성',\n icon: 'image',\n description: '프롬프트로 이미지를 생성합니다',\n systemPrompt: '이미지 생성 요청입니다.',\n },\n {\n id: 'codeAnalysis',\n label: '코드 분석',\n icon: 'code',\n description: '코드를 분석하고 설명합니다',\n systemPrompt: '코드를 분석하고 자세히 설명해주세요.',\n },\n {\n id: 'summarize',\n label: '요약',\n icon: 'document',\n description: '긴 텍스트를 요약합니다',\n systemPrompt: '다음 내용을 핵심만 간결하게 요약해주세요.',\n },\n];\n\n// ============================================================================\n// Default Templates\n// ============================================================================\n\nconst DEFAULT_TEMPLATES: PromptTemplate[] = [\n {\n id: '1',\n title: 'AI 기반 글쓰기',\n description: '블로그, 이메일, 보고서 작성 도움',\n prompt: '다음 주제에 대해 블로그 글을 작성해주세요: ',\n category: '글쓰기',\n },\n {\n id: '2',\n title: '코드 리뷰',\n description: '코드 분석 및 개선점 제안',\n prompt: '다음 코드를 리뷰하고 개선점을 제안해주세요: ',\n category: '개발',\n },\n {\n id: '3',\n title: '번역 도우미',\n description: '자연스러운 번역 및 교정',\n prompt: '다음 텍스트를 자연스럽게 번역해주세요: ',\n category: '번역',\n },\n {\n id: '4',\n title: '요약 정리',\n description: '긴 문서를 핵심만 요약',\n prompt: '다음 내용을 핵심만 요약해주세요: ',\n category: '정리',\n },\n];\n\n// ============================================================================\n// CSS Styles (injected)\n// ============================================================================\n\nconst injectStyles = () => {\n if (typeof document === 'undefined') return;\n\n const styleId = 'chatllm-styles';\n if (document.getElementById(styleId)) return;\n\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = `\n @keyframes chatllm-typing {\n 0%, 80%, 100% {\n transform: scale(0);\n opacity: 0.5;\n }\n 40% {\n transform: scale(1);\n opacity: 1;\n }\n }\n\n .chatllm-root {\n --chatllm-primary: #3b82f6;\n --chatllm-primary-hover: #2563eb;\n --chatllm-primary-light: #dbeafe;\n --chatllm-bg: #ffffff;\n --chatllm-bg-secondary: #f9fafb;\n --chatllm-bg-tertiary: #f3f4f6;\n --chatllm-bg-hover: #f3f4f6;\n --chatllm-bg-active: #eff6ff;\n --chatllm-bg-disabled: #e5e7eb;\n --chatllm-sidebar-bg: #ffffff;\n --chatllm-input-bg: #f9fafb;\n --chatllm-text: #1f2937;\n --chatllm-text-muted: #6b7280;\n --chatllm-border: #e5e7eb;\n --chatllm-border-light: #f3f4f6;\n --chatllm-error: #ef4444;\n --chatllm-success: #22c55e;\n --chatllm-user-avatar: #e5e7eb;\n --chatllm-assistant-avatar: #dbeafe;\n }\n\n .chatllm-root.chatllm-dark {\n --chatllm-primary: #60a5fa;\n --chatllm-primary-hover: #3b82f6;\n --chatllm-primary-light: #1e3a5f;\n --chatllm-bg: #111827;\n --chatllm-bg-secondary: #1f2937;\n --chatllm-bg-tertiary: #374151;\n --chatllm-bg-hover: #374151;\n --chatllm-bg-active: #1e3a5f;\n --chatllm-bg-disabled: #374151;\n --chatllm-sidebar-bg: #111827;\n --chatllm-input-bg: #1f2937;\n --chatllm-text: #f9fafb;\n --chatllm-text-muted: #9ca3af;\n --chatllm-border: #374151;\n --chatllm-border-light: #1f2937;\n --chatllm-user-avatar: #374151;\n --chatllm-assistant-avatar: #1e3a5f;\n }\n\n .chatllm-root * {\n box-sizing: border-box;\n }\n\n .chatllm-root textarea::placeholder {\n color: var(--chatllm-text-muted);\n }\n\n .chatllm-root button:focus-visible {\n outline: 2px solid var(--chatllm-primary);\n outline-offset: 2px;\n }\n\n .chatllm-message-list::-webkit-scrollbar {\n width: 6px;\n }\n\n .chatllm-message-list::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .chatllm-message-list::-webkit-scrollbar-thumb {\n background-color: var(--chatllm-border);\n border-radius: 3px;\n }\n `;\n\n document.head.appendChild(style);\n};\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport const ChatUI: React.FC<ChatUIProps> = ({\n models,\n actions = DEFAULT_ACTIONS,\n templates = DEFAULT_TEMPLATES,\n personalization,\n apiKey,\n onApiKeyChange,\n apiEndpoint = '/api/chat',\n theme,\n showSidebar = true,\n showSettings = true,\n showModelSelector = true,\n systemPrompt,\n contextCompressionThreshold = 20,\n keepRecentMessages = 6,\n storageKey = 'chatllm_sessions',\n className = '',\n onSendMessage,\n onSessionChange,\n onError,\n}) => {\n // Inject styles on mount\n React.useEffect(() => {\n injectStyles();\n }, []);\n\n // Initialize hook\n const hookOptions: UseChatUIOptions = {\n models,\n actions,\n initialPersonalization: personalization,\n apiKey,\n apiEndpoint,\n initialModel: models[0]?.id,\n storageKey,\n contextCompressionThreshold,\n keepRecentMessages,\n onSendMessage,\n onSessionChange,\n onError,\n };\n\n const {\n sessions,\n currentSession,\n currentSessionId,\n messages,\n input,\n isLoading,\n selectedModel,\n sidebarOpen,\n settingsOpen,\n quotedText,\n selectedAction,\n copiedMessageId,\n editingMessageId,\n personalization: currentPersonalization,\n setInput,\n sendMessage,\n stopGeneration,\n newSession,\n selectSession,\n deleteSession,\n setModel,\n toggleSidebar,\n openSettings,\n closeSettings,\n setQuotedText,\n setSelectedAction,\n copyMessage,\n startEdit,\n cancelEdit,\n saveEdit,\n regenerate,\n updatePersonalization,\n } = useChatUI(hookOptions);\n\n // Generate greeting\n const greeting = currentPersonalization.userProfile.nickname\n ? `안녕하세요, ${currentPersonalization.userProfile.nickname}님`\n : '안녕하세요';\n\n // Handle template click\n const handleTemplateClick = (template: PromptTemplate) => {\n setInput(template.prompt);\n };\n\n // Handle action select from empty state\n const handleActionSelect = (action: ActionItem) => {\n setSelectedAction(action);\n };\n\n // Handle submit\n const handleSubmit = () => {\n sendMessage();\n };\n\n // Memory panel state\n const [memoryPanelOpen, setMemoryPanelOpen] = useState(false);\n\n // Build memory items from session context\n const memoryItems: MemoryItem[] = React.useMemo(() => {\n const items: MemoryItem[] = [];\n\n // Add context summary as memory item if exists\n if (currentSession?.contextSummary) {\n items.push({\n id: 'context_summary',\n key: '대화 컨텍스트 요약',\n value: currentSession.contextSummary,\n category: 'context',\n timestamp: currentSession.updatedAt,\n });\n }\n\n // Add personalization as preference items\n if (currentPersonalization.userProfile.nickname) {\n items.push({\n id: 'pref_nickname',\n key: '사용자 닉네임',\n value: currentPersonalization.userProfile.nickname,\n category: 'preference',\n timestamp: Date.now(),\n });\n }\n if (currentPersonalization.userProfile.occupation) {\n items.push({\n id: 'pref_occupation',\n key: '직업/역할',\n value: currentPersonalization.userProfile.occupation,\n category: 'preference',\n timestamp: Date.now(),\n });\n }\n if (currentPersonalization.userProfile.additionalInfo) {\n items.push({\n id: 'pref_info',\n key: '추가 정보',\n value: currentPersonalization.userProfile.additionalInfo,\n category: 'preference',\n timestamp: Date.now(),\n });\n }\n\n return items;\n }, [currentSession, currentPersonalization]);\n\n // Theme class\n const themeClass = theme?.mode === 'dark' ? 'chatllm-dark' : '';\n\n return (\n <div\n className={`chatllm-root ${themeClass} ${className}`}\n style={{\n display: 'flex',\n height: '100%',\n backgroundColor: 'var(--chatllm-bg-secondary)',\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n }}\n >\n {/* Sidebar */}\n {showSidebar && (\n <ChatSidebar\n sessions={sessions}\n currentSessionId={currentSessionId}\n onSelectSession={selectSession}\n onNewSession={newSession}\n onDeleteSession={deleteSession}\n isOpen={sidebarOpen}\n onToggle={toggleSidebar}\n />\n )}\n\n {/* Main Content */}\n <main\n style={{\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n backgroundColor: 'var(--chatllm-bg)',\n minWidth: 0,\n }}\n >\n {/* Header */}\n <ChatHeader\n title={currentSession?.title || '새 대화'}\n model={selectedModel}\n models={models}\n onModelChange={setModel}\n onSettingsOpen={openSettings}\n onSidebarToggle={toggleSidebar}\n sidebarOpen={sidebarOpen}\n />\n\n {/* Messages or Empty State */}\n {messages.length === 0 ? (\n <EmptyState\n greeting={greeting}\n templates={templates}\n onTemplateClick={handleTemplateClick}\n actions={actions}\n onActionSelect={handleActionSelect}\n />\n ) : (\n <MessageList\n messages={messages}\n isLoading={isLoading}\n onCopy={copyMessage}\n onEdit={startEdit}\n onRegenerate={regenerate}\n onQuote={setQuotedText}\n copiedId={copiedMessageId}\n editingId={editingMessageId}\n />\n )}\n\n {/* Input */}\n <ChatInput\n value={input}\n onChange={setInput}\n onSubmit={handleSubmit}\n onStop={stopGeneration}\n isLoading={isLoading}\n placeholder=\"메시지를 입력하세요...\"\n quotedText={quotedText}\n onClearQuote={() => setQuotedText(null)}\n selectedAction={selectedAction}\n onClearAction={() => setSelectedAction(null)}\n onActionSelect={setSelectedAction}\n actions={actions}\n />\n </main>\n\n {/* Memory Panel */}\n <MemoryPanel\n items={memoryItems}\n contextSummary={currentSession?.contextSummary}\n isOpen={memoryPanelOpen}\n onToggle={() => setMemoryPanelOpen(!memoryPanelOpen)}\n />\n\n {/* Settings Modal */}\n {showSettings && (\n <SettingsModal\n isOpen={settingsOpen}\n onClose={closeSettings}\n personalization={currentPersonalization}\n onPersonalizationChange={updatePersonalization}\n apiKey={apiKey}\n onApiKeyChange={onApiKeyChange}\n onClearAllData={() => {\n // 세션 전체 삭제\n sessions.forEach((s) => deleteSession(s.id));\n }}\n apiKeyLabel=\"API Key\"\n apiKeyDescription=\"Cloud 모델 사용에 필요합니다\"\n />\n )}\n </div>\n );\n};\n\nexport default ChatUI;\n","/**\n * @description Headless Chat UI Hook\n * 상태 관리와 로직만 제공, UI는 자유롭게 구현 가능\n */\n\nimport { useState, useRef, useCallback, useEffect } from 'react';\nimport type {\n ChatSession,\n ChatMessage,\n ActionItem,\n ModelConfig,\n PersonalizationConfig,\n UseChatUIReturn,\n SendMessageParams,\n ProviderType,\n} from '../types';\nimport { DEFAULT_PERSONALIZATION } from '../../types';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_STORAGE_KEY = 'chatllm_sessions';\nconst DEFAULT_PERSONALIZATION_KEY = 'chatllm_personalization';\nconst DEFAULT_COMPRESSION_THRESHOLD = 20;\nconst DEFAULT_KEEP_RECENT = 6;\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\nconst generateId = (prefix: string): string =>\n `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\nconst generateTitle = (messages: ChatMessage[]): string => {\n const firstUserMessage = messages.find((m) => m.role === 'user');\n if (!firstUserMessage) return '새 대화';\n const content = firstUserMessage.content;\n return content.length > 30 ? content.substring(0, 30) + '...' : content;\n};\n\n// ============================================================================\n// Hook Options\n// ============================================================================\n\nexport interface UseChatUIOptions {\n /** 사용 가능한 모델 목록 */\n models: ModelConfig[];\n /** 사용 가능한 Actions */\n actions?: ActionItem[];\n /** 초기 개인화 설정 */\n initialPersonalization?: Partial<PersonalizationConfig>;\n /** API 키 */\n apiKey?: string;\n /** API 엔드포인트 */\n apiEndpoint?: string;\n /** 초기 모델 */\n initialModel?: string;\n /** 스토리지 키 */\n storageKey?: string;\n /** 컨텍스트 압축 임계값 */\n contextCompressionThreshold?: number;\n /** 압축 후 유지할 메시지 수 */\n keepRecentMessages?: number;\n /** 커스텀 메시지 전송 핸들러 */\n onSendMessage?: (params: SendMessageParams) => Promise<ReadableStream<Uint8Array> | string>;\n /** 세션 변경 핸들러 */\n onSessionChange?: (session: ChatSession | null) => void;\n /** 에러 핸들러 */\n onError?: (error: Error) => void;\n}\n\n// ============================================================================\n// Main Hook\n// ============================================================================\n\nexport const useChatUI = (options: UseChatUIOptions): UseChatUIReturn => {\n const {\n models,\n actions = [],\n initialPersonalization,\n apiKey,\n apiEndpoint = '/api/chat',\n initialModel,\n storageKey = DEFAULT_STORAGE_KEY,\n contextCompressionThreshold = DEFAULT_COMPRESSION_THRESHOLD,\n keepRecentMessages = DEFAULT_KEEP_RECENT,\n onSendMessage,\n onSessionChange,\n onError,\n } = options;\n\n // ============================================================================\n // State\n // ============================================================================\n\n const [sessions, setSessions] = useState<ChatSession[]>([]);\n const [currentSessionId, setCurrentSessionId] = useState<string | null>(null);\n const [input, setInput] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [selectedModel, setSelectedModel] = useState(initialModel || models[0]?.id || '');\n const [sidebarOpen, setSidebarOpen] = useState(true);\n const [settingsOpen, setSettingsOpen] = useState(false);\n const [quotedText, setQuotedText] = useState<string | null>(null);\n const [selectedAction, setSelectedAction] = useState<ActionItem | null>(null);\n const [copiedMessageId, setCopiedMessageId] = useState<string | null>(null);\n const [editingMessageId, setEditingMessageId] = useState<string | null>(null);\n const [personalization, setPersonalization] = useState<PersonalizationConfig>({\n ...DEFAULT_PERSONALIZATION,\n ...initialPersonalization,\n });\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n // ============================================================================\n // Derived State\n // ============================================================================\n\n const currentSession = sessions.find((s) => s.id === currentSessionId) || null;\n const messages = currentSession?.messages || [];\n\n // ============================================================================\n // Persistence\n // ============================================================================\n\n useEffect(() => {\n if (typeof window === 'undefined') return;\n\n const saved = localStorage.getItem(storageKey);\n if (saved) {\n try {\n const parsed = JSON.parse(saved) as ChatSession[];\n setSessions(parsed);\n if (parsed.length > 0) {\n setCurrentSessionId(parsed[0].id);\n setSelectedModel(parsed[0].model);\n }\n } catch {\n // Ignore parse errors\n }\n }\n\n const savedPersonalization = localStorage.getItem(`${storageKey}_personalization`);\n if (savedPersonalization) {\n try {\n setPersonalization(JSON.parse(savedPersonalization));\n } catch {\n // Ignore parse errors\n }\n }\n }, [storageKey]);\n\n useEffect(() => {\n if (typeof window === 'undefined') return;\n\n if (sessions.length > 0) {\n localStorage.setItem(storageKey, JSON.stringify(sessions));\n }\n }, [sessions, storageKey]);\n\n useEffect(() => {\n if (typeof window === 'undefined') return;\n localStorage.setItem(`${storageKey}_personalization`, JSON.stringify(personalization));\n }, [personalization, storageKey]);\n\n // ============================================================================\n // Session Change Callback\n // ============================================================================\n\n useEffect(() => {\n onSessionChange?.(currentSession);\n }, [currentSession, onSessionChange]);\n\n // ============================================================================\n // System Prompt Builder\n // ============================================================================\n\n const buildSystemPrompt = useCallback((): string => {\n const parts: string[] = [];\n const { userProfile, responseStyle, language } = personalization;\n\n if (userProfile.nickname) {\n parts.push(`사용자의 이름/닉네임: ${userProfile.nickname}`);\n }\n if (userProfile.occupation) {\n parts.push(`사용자의 직업: ${userProfile.occupation}`);\n }\n if (userProfile.additionalInfo) {\n parts.push(`사용자 추가 정보: ${userProfile.additionalInfo}`);\n }\n\n const styleDescriptions: string[] = [];\n if (responseStyle.warmth === 'high') styleDescriptions.push('따뜻하고 친근하게');\n else if (responseStyle.warmth === 'low') styleDescriptions.push('간결하고 사무적으로');\n\n if (responseStyle.enthusiasm === 'high') styleDescriptions.push('열정적이고 적극적으로');\n else if (responseStyle.enthusiasm === 'low') styleDescriptions.push('차분하게');\n\n if (responseStyle.emojiUsage === 'high') styleDescriptions.push('이모지를 적극 활용해서');\n else if (responseStyle.emojiUsage === 'low') styleDescriptions.push('이모지 사용을 자제해서');\n\n if (responseStyle.verbosity === 'concise') styleDescriptions.push('핵심만 간결하게');\n else if (responseStyle.verbosity === 'detailed') styleDescriptions.push('상세하고 자세하게');\n\n if (styleDescriptions.length > 0) {\n parts.push(`응답 스타일: ${styleDescriptions.join(', ')} 응답해주세요.`);\n }\n\n if (language !== 'auto') {\n const languageNames: Record<string, string> = { ko: '한국어', en: '영어', ja: '일본어' };\n parts.push(`응답 언어: ${languageNames[language] || language}로 응답해주세요.`);\n }\n\n return parts.length > 0 ? parts.join('\\n') : '';\n }, [personalization]);\n\n // ============================================================================\n // Context Compression\n // ============================================================================\n\n const compressContext = useCallback(async (\n messagesToCompress: ChatMessage[],\n model: string\n ): Promise<string> => {\n const conversationText = messagesToCompress\n .map((m) => `${m.role === 'user' ? '사용자' : 'AI'}: ${m.content}`)\n .join('\\n\\n');\n\n const summaryPrompt = `다음 대화 내용을 핵심 정보만 유지하면서 간결하게 요약해주세요.\n중요한 결정사항, 사용자 요구사항, 맥락 정보를 보존하세요.\n\n대화:\n${conversationText}\n\n요약:`;\n\n try {\n const response = await fetch(apiEndpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n messages: [{ role: 'user', content: summaryPrompt }],\n model,\n }),\n });\n\n if (!response.ok) return '';\n\n const reader = response.body?.getReader();\n if (!reader) return '';\n\n const decoder = new TextDecoder();\n let buffer = '';\n let summary = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6);\n if (data === '[DONE]') continue;\n try {\n const parsed = JSON.parse(data);\n if (parsed.content) summary += parsed.content;\n } catch {\n // Ignore parse errors\n }\n }\n }\n }\n\n return summary;\n } catch {\n return '';\n }\n }, [apiEndpoint]);\n\n // ============================================================================\n // Actions\n // ============================================================================\n\n const newSession = useCallback(() => {\n const now = Date.now();\n const newSess: ChatSession = {\n id: generateId('session'),\n title: '새 대화',\n messages: [],\n model: selectedModel,\n createdAt: now,\n updatedAt: now,\n };\n setSessions((prev) => [newSess, ...prev]);\n setCurrentSessionId(newSess.id);\n }, [selectedModel]);\n\n const selectSession = useCallback((id: string) => {\n const session = sessions.find((s) => s.id === id);\n if (session) {\n setCurrentSessionId(id);\n setSelectedModel(session.model);\n }\n }, [sessions]);\n\n const deleteSession = useCallback((id: string) => {\n setSessions((prev) => {\n const filtered = prev.filter((s) => s.id !== id);\n if (currentSessionId === id) {\n setCurrentSessionId(filtered.length > 0 ? filtered[0].id : null);\n }\n if (filtered.length === 0 && typeof window !== 'undefined') {\n localStorage.removeItem(storageKey);\n }\n return filtered;\n });\n }, [currentSessionId, storageKey]);\n\n const setModel = useCallback((model: string) => {\n setSelectedModel(model);\n if (currentSessionId) {\n setSessions((prev) =>\n prev.map((s) => (s.id === currentSessionId ? { ...s, model } : s))\n );\n }\n }, [currentSessionId]);\n\n const toggleSidebar = useCallback(() => setSidebarOpen((prev) => !prev), []);\n const openSettings = useCallback(() => setSettingsOpen(true), []);\n const closeSettings = useCallback(() => setSettingsOpen(false), []);\n\n const copyMessage = useCallback((content: string, id: string) => {\n if (typeof navigator !== 'undefined') {\n navigator.clipboard.writeText(content).then(() => {\n setCopiedMessageId(id);\n setTimeout(() => setCopiedMessageId(null), 2000);\n });\n }\n }, []);\n\n const startEdit = useCallback((message: ChatMessage) => {\n if (message.role === 'user') {\n setEditingMessageId(message.id);\n }\n }, []);\n\n const cancelEdit = useCallback(() => {\n setEditingMessageId(null);\n }, []);\n\n const stopGeneration = useCallback(() => {\n abortControllerRef.current?.abort();\n }, []);\n\n const updatePersonalization = useCallback((config: Partial<PersonalizationConfig>) => {\n setPersonalization((prev) => ({ ...prev, ...config }));\n }, []);\n\n // ============================================================================\n // Send Message\n // ============================================================================\n\n const sendMessage = useCallback(async (content?: string) => {\n const messageContent = content || input;\n if (!messageContent.trim() || isLoading) return;\n\n let sessionId = currentSessionId;\n if (!sessionId) {\n const now = Date.now();\n const newSess: ChatSession = {\n id: generateId('session'),\n title: '새 대화',\n messages: [],\n model: selectedModel,\n createdAt: now,\n updatedAt: now,\n };\n setSessions((prev) => [newSess, ...prev]);\n sessionId = newSess.id;\n setCurrentSessionId(sessionId);\n }\n\n // 메시지 조합\n let finalContent = messageContent.trim();\n if (quotedText) {\n finalContent = `\"${quotedText}\"\\n\\n${finalContent}`;\n }\n if (selectedAction) {\n finalContent = `[${selectedAction.label}] ${finalContent}`;\n }\n\n const actionPrompt = selectedAction?.systemPrompt;\n const userMessage: ChatMessage = {\n id: generateId('msg'),\n role: 'user',\n content: finalContent,\n timestamp: Date.now(),\n };\n\n const assistantMessageId = generateId('msg');\n const assistantMessage: ChatMessage = {\n id: assistantMessageId,\n role: 'assistant',\n content: '',\n model: selectedModel,\n timestamp: Date.now(),\n };\n\n // Clear input state\n setInput('');\n setQuotedText(null);\n setSelectedAction(null);\n\n // Add messages to session\n const capturedSessionId = sessionId;\n setSessions((prev) =>\n prev.map((s) => {\n if (s.id === capturedSessionId) {\n const newMessages = [...s.messages, userMessage, assistantMessage];\n return {\n ...s,\n messages: newMessages,\n title: s.messages.length === 0 ? generateTitle([userMessage]) : s.title,\n updatedAt: Date.now(),\n };\n }\n return s;\n })\n );\n\n setIsLoading(true);\n abortControllerRef.current = new AbortController();\n\n try {\n const session = sessions.find((s) => s.id === capturedSessionId);\n const existingMessages = session?.messages || [];\n let messagesToSend = [...existingMessages, userMessage];\n\n // Context compression\n let contextSummary = session?.contextSummary;\n if (messagesToSend.length > contextCompressionThreshold && !contextSummary) {\n const toCompress = messagesToSend.slice(0, -keepRecentMessages);\n const summary = await compressContext(toCompress, selectedModel);\n if (summary) {\n contextSummary = summary;\n setSessions((prev) =>\n prev.map((s) =>\n s.id === capturedSessionId\n ? { ...s, contextSummary: summary, summaryAfterIndex: toCompress.length }\n : s\n )\n );\n }\n }\n\n // Build chat messages\n let chatMessages: { role: 'user' | 'assistant' | 'system'; content: string }[];\n if (contextSummary) {\n const recentMessages = messagesToSend.slice(-keepRecentMessages);\n chatMessages = [\n { role: 'system', content: `[이전 대화 요약]\\n${contextSummary}` },\n ...recentMessages.map((m) => ({ role: m.role, content: m.content })),\n ];\n } else {\n chatMessages = messagesToSend.map((m) => ({ role: m.role, content: m.content }));\n }\n\n // Build system prompt\n const baseSystemPrompt = buildSystemPrompt();\n const combinedSystemPrompt = [baseSystemPrompt, actionPrompt].filter(Boolean).join('\\n\\n');\n const messagesForApi = combinedSystemPrompt\n ? [{ role: 'system' as const, content: combinedSystemPrompt }, ...chatMessages]\n : chatMessages;\n\n // Get provider\n const modelConfig = models.find((m) => m.id === selectedModel);\n const provider = modelConfig?.provider || 'ollama';\n\n // Send request\n let response: Response;\n if (onSendMessage) {\n const result = await onSendMessage({\n messages: messagesForApi,\n model: selectedModel,\n provider,\n apiKey,\n systemPrompt: combinedSystemPrompt,\n });\n\n if (typeof result === 'string') {\n // Direct string response\n setSessions((prev) =>\n prev.map((s) => {\n if (s.id === capturedSessionId) {\n return {\n ...s,\n messages: s.messages.map((m) =>\n m.id === assistantMessageId ? { ...m, content: result } : m\n ),\n };\n }\n return s;\n })\n );\n return;\n }\n\n // Create fake response from stream\n response = new Response(result);\n } else {\n response = await fetch(apiEndpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n messages: messagesForApi,\n model: selectedModel,\n provider,\n apiKey: provider === 'devdive' ? apiKey : undefined,\n }),\n signal: abortControllerRef.current.signal,\n });\n }\n\n if (!response.ok) throw new Error('API error');\n\n const reader = response.body?.getReader();\n if (!reader) throw new Error('No reader');\n\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6);\n if (data === '[DONE]') continue;\n\n try {\n const parsed = JSON.parse(data);\n if (parsed.content) {\n setSessions((prev) =>\n prev.map((s) => {\n if (s.id === capturedSessionId) {\n return {\n ...s,\n messages: s.messages.map((m) =>\n m.id === assistantMessageId\n ? { ...m, content: m.content + parsed.content }\n : m\n ),\n };\n }\n return s;\n })\n );\n }\n } catch {\n // Ignore parse errors\n }\n }\n }\n }\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n return;\n }\n const err = error instanceof Error ? error : new Error('Unknown error');\n onError?.(err);\n\n setSessions((prev) =>\n prev.map((s) => {\n if (s.id === capturedSessionId) {\n return {\n ...s,\n messages: s.messages.map((m) =>\n m.id === assistantMessageId\n ? { ...m, content: '오류가 발생했습니다. 다시 시도해주세요.' }\n : m\n ),\n };\n }\n return s;\n })\n );\n } finally {\n setIsLoading(false);\n abortControllerRef.current = null;\n }\n }, [\n input,\n isLoading,\n currentSessionId,\n sessions,\n selectedModel,\n quotedText,\n selectedAction,\n apiEndpoint,\n apiKey,\n models,\n contextCompressionThreshold,\n keepRecentMessages,\n buildSystemPrompt,\n compressContext,\n onSendMessage,\n onError,\n ]);\n\n // ============================================================================\n // Edit & Regenerate\n // ============================================================================\n\n const saveEdit = useCallback(async (content: string) => {\n if (!editingMessageId || !currentSession || !currentSessionId) return;\n\n const messageIndex = currentSession.messages.findIndex((m) => m.id === editingMessageId);\n if (messageIndex === -1) return;\n\n const capturedSessionId = currentSessionId;\n setSessions((prev) =>\n prev.map((s) => {\n if (s.id === capturedSessionId) {\n const newMessages = s.messages.slice(0, messageIndex);\n return { ...s, messages: newMessages, updatedAt: Date.now() };\n }\n return s;\n })\n );\n\n setEditingMessageId(null);\n await sendMessage(content);\n }, [editingMessageId, currentSession, currentSessionId, sendMessage]);\n\n const regenerate = useCallback(async (messageId: string) => {\n if (!currentSession || !currentSessionId || isLoading) return;\n\n const assistantIndex = currentSession.messages.findIndex((m) => m.id === messageId);\n if (assistantIndex === -1) return;\n\n const userMessage = currentSession.messages[assistantIndex - 1];\n if (!userMessage || userMessage.role !== 'user') return;\n\n const capturedSessionId = currentSessionId;\n setSessions((prev) =>\n prev.map((s) => {\n if (s.id === capturedSessionId) {\n return {\n ...s,\n messages: s.messages.slice(0, assistantIndex),\n updatedAt: Date.now(),\n };\n }\n return s;\n })\n );\n\n // Re-send the user message\n setInput(userMessage.content);\n await sendMessage(userMessage.content);\n }, [currentSession, currentSessionId, isLoading, sendMessage]);\n\n // ============================================================================\n // Return\n // ============================================================================\n\n return {\n // State\n sessions,\n currentSession,\n currentSessionId,\n messages,\n input,\n isLoading,\n selectedModel,\n sidebarOpen,\n settingsOpen,\n quotedText,\n selectedAction,\n copiedMessageId,\n editingMessageId,\n personalization,\n\n // Actions\n setInput,\n sendMessage,\n stopGeneration,\n newSession,\n selectSession,\n deleteSession,\n setModel,\n toggleSidebar,\n openSettings,\n closeSettings,\n setQuotedText,\n setSelectedAction,\n copyMessage,\n startEdit,\n cancelEdit,\n saveEdit,\n regenerate,\n updatePersonalization,\n };\n};\n\nexport default useChatUI;\n","/**\n * Core types for devdive-chatLLM\n */\n\n// ============================================================================\n// Provider Types\n// ============================================================================\n\nexport type ProviderType = 'openai' | 'anthropic' | 'google' | 'naver' | 'ollama';\n\nexport interface ProviderConfigs {\n openai?: OpenAIConfig;\n anthropic?: AnthropicConfig;\n google?: GoogleConfig;\n naver?: NaverConfig;\n ollama?: OllamaConfig;\n}\n\nexport interface OpenAIConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\nexport interface AnthropicConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\nexport interface GoogleConfig {\n apiKey: string;\n}\n\nexport interface NaverConfig {\n apiKey: string;\n apiGatewayKey: string;\n baseUrl?: string;\n}\n\nexport interface OllamaConfig {\n baseUrl?: string; // default: http://localhost:11434\n}\n\n// ============================================================================\n// Message Types\n// ============================================================================\n\nexport type Role = 'system' | 'user' | 'assistant' | 'tool';\n\nexport interface Message {\n id: string;\n role: Role;\n content: string;\n provider?: ProviderType;\n model?: string;\n toolCalls?: ToolCall[];\n toolCallId?: string;\n timestamp: number;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ToolCall {\n id: string;\n name: string;\n arguments: Record<string, unknown>;\n}\n\nexport interface ToolResult {\n toolCallId: string;\n result: unknown;\n error?: string;\n}\n\n// ============================================================================\n// Tool/Function Types\n// ============================================================================\n\nexport interface ParameterSchema {\n type: 'string' | 'number' | 'boolean' | 'object' | 'array';\n description?: string;\n enum?: string[];\n items?: ParameterSchema;\n properties?: Record<string, ParameterSchema>;\n required?: string[];\n}\n\nexport interface ToolDefinition {\n name: string;\n description: string;\n parameters: {\n type: 'object';\n properties: Record<string, ParameterSchema>;\n required?: string[];\n };\n handler: (params: Record<string, unknown>) => Promise<unknown> | unknown;\n}\n\n// ============================================================================\n// Chat & Session Types\n// ============================================================================\n\nexport interface ChatConfig {\n id?: string;\n providers: ProviderConfigs;\n defaultProvider: ProviderType;\n defaultModel?: string;\n storagePath?: string;\n systemPrompt?: string;\n /** 개인화 설정 */\n personalization?: Partial<PersonalizationConfig>;\n}\n\nexport interface Chat {\n id: string;\n config: ChatConfig;\n messages: Message[];\n tools: Map<string, ToolDefinition>;\n memory: Map<string, MemoryEntry>;\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface SendOptions {\n provider?: ProviderType;\n model?: string;\n temperature?: number;\n maxTokens?: number;\n tools?: ToolDefinition[];\n systemPrompt?: string;\n}\n\n// ============================================================================\n// Streaming Types\n// ============================================================================\n\nexport type StreamEventType = 'text' | 'tool_call' | 'tool_result' | 'done' | 'error';\n\nexport interface StreamEvent {\n type: StreamEventType;\n content?: string;\n toolCall?: ToolCall;\n toolResult?: ToolResult;\n error?: Error;\n message?: Message;\n}\n\n// ============================================================================\n// Memory Types\n// ============================================================================\n\nexport interface MemoryEntry {\n key: string;\n value: unknown;\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface GlobalMemoryStore {\n entries: Map<string, MemoryEntry>;\n storagePath: string;\n}\n\n// ============================================================================\n// Acontext Types\n// ============================================================================\n\nexport type TaskStatus = 'pending' | 'in_progress' | 'completed' | 'failed';\n\nexport interface ObservedTask {\n id: string;\n description: string;\n status: TaskStatus;\n progress: number; // 0-100\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface UserPreference {\n key: string;\n value: unknown;\n confidence: number; // 0-1\n source: string; // which message extracted this\n}\n\nexport interface LearnedSkill {\n id: string;\n name: string;\n description: string;\n category: string;\n steps: SkillStep[];\n successRate: number;\n usageCount: number;\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface SkillStep {\n order: number;\n action: string;\n expectedInput?: string;\n expectedOutput?: string;\n}\n\nexport interface ObserverConfig {\n extractTasks: boolean;\n extractPreferences: boolean;\n autoLearn: boolean;\n}\n\nexport interface ObserverState {\n enabled: boolean;\n config: ObserverConfig;\n tasks: ObservedTask[];\n preferences: UserPreference[];\n}\n\n// ============================================================================\n// Personalization Types (ChatGPT-style settings)\n// ============================================================================\n\nexport type StyleLevel = 'low' | 'medium' | 'high';\nexport type FormattingStyle = 'minimal' | 'default' | 'rich';\n\n/**\n * 응답 스타일 설정\n */\nexport interface ResponseStyle {\n /** 따뜻함 수준 */\n warmth: StyleLevel;\n /** 열정/에너지 수준 */\n enthusiasm: StyleLevel;\n /** 이모지 사용 수준 */\n emojiUsage: StyleLevel;\n /** 포맷팅 스타일 (헤더, 목록 등) */\n formatting: FormattingStyle;\n /** 응답 길이 선호 */\n verbosity: 'concise' | 'balanced' | 'detailed';\n}\n\n/**\n * 사용자 프로필 정보\n */\nexport interface UserProfile {\n /** 사용자 닉네임/호칭 */\n nickname?: string;\n /** 직업/역할 */\n occupation?: string;\n /** 추가 정보 (관심사, 가치, 선호 사항) */\n additionalInfo?: string;\n /** 선호 언어 */\n preferredLanguage?: string;\n /** 전문 분야 */\n expertise?: string[];\n /** 커스텀 지시사항 */\n customInstructions?: string;\n}\n\n/**\n * 개인화 설정 전체\n */\nexport interface PersonalizationConfig {\n /** 응답 스타일 */\n responseStyle: ResponseStyle;\n /** 사용자 프로필 */\n userProfile: UserProfile;\n /** 메모리 참조 활성화 */\n useMemory: boolean;\n /** 언어 설정 ('auto' | 'ko' | 'en' | etc.) */\n language: string;\n}\n\n/**\n * 개인화 설정 기본값\n */\nexport const DEFAULT_PERSONALIZATION: PersonalizationConfig = {\n responseStyle: {\n warmth: 'medium',\n enthusiasm: 'medium',\n emojiUsage: 'low',\n formatting: 'default',\n verbosity: 'balanced',\n },\n userProfile: {},\n useMemory: true,\n language: 'auto',\n};\n\n// ============================================================================\n// LLM Chat Hook Integration Types\n// ============================================================================\n\n/**\n * @description Hook 결과 타입 (React Query UseMutationResult 호환)\n */\nexport interface MutationResult<TData = unknown, TError = Error, TVariables = unknown> {\n mutate: (variables: TVariables) => void;\n mutateAsync: (variables: TVariables) => Promise<TData>;\n isPending: boolean;\n isError: boolean;\n isSuccess: boolean;\n data?: TData;\n error?: TError;\n reset: () => void;\n}\n\n/**\n * @description Tool/Action Hook 타입\n */\nexport type ToolHook<TRequest = unknown, TResponse = unknown> = () => MutationResult<TResponse, Error, TRequest>;\n\n/**\n * @description AI가 자동으로 호출하는 Tool 설정\n * AI가 사용자 메시지를 분석해서 필요시 자동 호출\n */\nexport interface LLMToolConfig<TRequest = unknown, TResponse = unknown> {\n /** Tool hook */\n hook: ToolHook<TRequest, TResponse>;\n /** AI가 판단할 때 사용하는 설명 */\n description: string;\n /** JSON Schema 형태의 파라미터 정의 (선택) */\n parameters?: {\n type: 'object';\n properties: Record<string, {\n type: string;\n description?: string;\n enum?: string[];\n }>;\n required?: string[];\n };\n}\n\n/**\n * @description 사용자가 UI에서 직접 선택하는 Action 설정\n */\nexport interface LLMActionConfig<TRequest = unknown, TResponse = unknown> {\n /** Action hook */\n hook: ToolHook<TRequest, TResponse>;\n /** UI에 표시할 레이블 */\n label: string;\n /** 아이콘 이름 또는 컴포넌트 */\n icon?: string;\n /** 비활성화 여부 */\n disabled?: boolean;\n}\n\n/**\n * @description 기본 채팅(텍스트 생성) 설정\n */\nexport interface LLMChatHookConfig<TRequest = unknown, TResponse = unknown> {\n /** 텍스트 생성 hook */\n hook: ToolHook<TRequest, TResponse>;\n /** 기본 시스템 프롬프트 */\n systemPrompt?: string;\n}\n\n/**\n * @description LLM Chat 컴포넌트 Props\n */\nexport interface LLMChatComponentProps {\n /** AI가 자동 호출하는 Tools */\n tools?: Record<string, LLMToolConfig>;\n /** 사용자가 직접 선택하는 Actions */\n actions?: Record<string, LLMActionConfig>;\n /** 기본 채팅 설정 */\n chat: LLMChatHookConfig;\n /** 스타일 클래스 */\n className?: string;\n /** 개인화 설정 */\n personalization?: Partial<PersonalizationConfig>;\n}\n","/**\n * @description Remix Icons wrapper component\n * @see https://remixicon.com/\n * Using Remix Icons 4.6.0 via CDN or npm package\n */\n\nimport React from 'react';\n\nexport type IconName =\n // Navigation & UI\n | 'menu-line'\n | 'close-line'\n | 'arrow-left-line'\n | 'arrow-right-line'\n | 'arrow-down-s-line'\n | 'arrow-up-s-line'\n | 'more-line'\n | 'more-2-line'\n | 'settings-3-line'\n | 'settings-4-line'\n // Chat & Communication\n | 'chat-1-line'\n | 'chat-3-line'\n | 'chat-new-line'\n | 'message-2-line'\n | 'send-plane-line'\n | 'send-plane-fill'\n | 'question-answer-line'\n // Actions\n | 'add-line'\n | 'add-circle-line'\n | 'delete-bin-line'\n | 'delete-bin-6-line'\n | 'edit-line'\n | 'edit-2-line'\n | 'pencil-line'\n | 'check-line'\n | 'close-circle-line'\n | 'refresh-line'\n | 'loop-left-line'\n | 'stop-line'\n | 'stop-circle-line'\n | 'play-line'\n | 'pause-line'\n // Content\n | 'file-copy-line'\n | 'clipboard-line'\n | 'quote-text'\n | 'double-quotes-l'\n | 'double-quotes-r'\n // Search & Find\n | 'search-line'\n | 'search-2-line'\n | 'global-line'\n // Media\n | 'image-line'\n | 'image-add-line'\n | 'gallery-line'\n | 'video-line'\n | 'mic-line'\n // Code & Development\n | 'code-line'\n | 'code-s-slash-line'\n | 'terminal-box-line'\n | 'bug-line'\n | 'git-branch-line'\n // Document\n | 'file-text-line'\n | 'file-list-line'\n | 'article-line'\n | 'draft-line'\n | 'book-2-line'\n // AI & Magic\n | 'magic-line'\n | 'sparkling-line'\n | 'sparkling-2-line'\n | 'robot-line'\n | 'brain-line'\n // User\n | 'user-line'\n | 'user-3-line'\n | 'user-settings-line'\n | 'account-circle-line'\n // System\n | 'sun-line'\n | 'moon-line'\n | 'computer-line'\n | 'information-line'\n | 'error-warning-line'\n | 'checkbox-circle-line'\n | 'loader-4-line'\n // Misc\n | 'translate-2'\n | 'time-line'\n | 'history-line'\n | 'star-line'\n | 'star-fill'\n | 'heart-line'\n | 'thumb-up-line'\n | 'thumb-down-line'\n | 'attachment-line'\n | 'link'\n | 'links-line'\n | 'external-link-line'\n | 'download-line'\n | 'upload-line'\n | 'folder-line'\n | 'home-line'\n | 'dashboard-line'\n | 'list-check'\n | 'list-unordered'\n | 'key-line'\n | 'lock-line'\n | 'eye-line'\n | 'eye-off-line';\n\nexport interface IconProps {\n /** Icon name from Remix Icons */\n name: IconName;\n /** Size in pixels or CSS value */\n size?: number | string;\n /** CSS color value */\n color?: string;\n /** Additional CSS classes */\n className?: string;\n /** Additional inline styles */\n style?: React.CSSProperties;\n /** Click handler */\n onClick?: () => void;\n /** Accessibility label */\n 'aria-label'?: string;\n}\n\n/**\n * Remix Icons component\n * Uses CSS class-based icons (requires remixicon CSS)\n */\nexport const Icon: React.FC<IconProps> = ({\n name,\n size = 20,\n color,\n className = '',\n onClick,\n 'aria-label': ariaLabel,\n}) => {\n const sizeValue = typeof size === 'number' ? `${size}px` : size;\n\n return (\n <i\n className={`ri-${name} ${className}`}\n style={{\n fontSize: sizeValue,\n color,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n lineHeight: 1,\n }}\n onClick={onClick}\n aria-label={ariaLabel}\n role={onClick ? 'button' : undefined}\n tabIndex={onClick ? 0 : undefined}\n />\n );\n};\n\n/**\n * SVG-based Icon component (no external CSS required)\n * Icons are rendered inline as SVG\n */\nexport const IconSvg: React.FC<IconProps> = ({\n name,\n size = 20,\n color = 'currentColor',\n className = '',\n style,\n onClick,\n 'aria-label': ariaLabel,\n}) => {\n const sizeValue = typeof size === 'number' ? size : parseInt(size, 10) || 20;\n\n // Common SVG icons inline\n const icons: Partial<Record<IconName, React.ReactNode>> = {\n 'menu-line': (\n <path d=\"M3 4h18v2H3V4zm0 7h18v2H3v-2zm0 7h18v2H3v-2z\" />\n ),\n 'close-line': (\n <path d=\"M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z\" />\n ),\n 'add-line': (\n <path d=\"M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z\" />\n ),\n 'chat-1-line': (\n <path d=\"M10 3h4a8 8 0 1 1 0 16v3.5c-5-2-12-5-12-11.5a8 8 0 0 1 8-8zm2 14h2a6 6 0 0 0 0-12h-4a6 6 0 0 0-6 6c0 3.61 2.462 5.966 8 8.48V17z\" />\n ),\n 'send-plane-fill': (\n <path d=\"M1.946 9.315c-.522-.174-.527-.455.01-.634l19.087-6.362c.529-.176.832.12.684.638l-5.454 19.086c-.15.529-.455.547-.679.045L12 14l6-8-8 6-8.054-2.685z\" />\n ),\n 'send-plane-line': (\n <path d=\"M1.923 9.37c-.51-.205-.504-.51.034-.689l19.086-6.362c.529-.176.832.12.684.638l-5.454 19.086c-.15.529-.475.553-.717.07L12 14 3 10.5l8-4.25-9.077 3.12zM5.5 10.5l5.25 2.75 2.25 5.5 4-14-11.5 5.75z\" />\n ),\n 'search-line': (\n <path d=\"M18.031 16.617l4.283 4.282-1.415 1.415-4.282-4.283A8.96 8.96 0 0 1 11 20c-4.968 0-9-4.032-9-9s4.032-9 9-9 9 4.032 9 9a8.96 8.96 0 0 1-1.969 5.617zm-2.006-.742A6.977 6.977 0 0 0 18 11c0-3.868-3.133-7-7-7-3.868 0-7 3.132-7 7 0 3.867 3.132 7 7 7a6.977 6.977 0 0 0 4.875-1.975l.15-.15z\" />\n ),\n 'image-line': (\n <path d=\"M4.828 21l-.02.02-.021-.02H2.992A.993.993 0 0 1 2 20.007V3.993A1 1 0 0 1 2.992 3h18.016c.548 0 .992.445.992.993v16.014a1 1 0 0 1-.992.993H4.828zM20 15V5H4v14L14 9l6 6zm0 2.828l-6-6L6.828 19H20v-1.172zM8 11a2 2 0 1 1 0-4 2 2 0 0 1 0 4z\" />\n ),\n 'code-s-slash-line': (\n <path d=\"M24 12l-5.657 5.657-1.414-1.414L21.172 12l-4.243-4.243 1.414-1.414L24 12zM2.828 12l4.243 4.243-1.414 1.414L0 12l5.657-5.657L7.07 7.757 2.828 12zm6.96 9H7.66l6.552-18h2.128L9.788 21z\" />\n ),\n 'file-text-line': (\n <path d=\"M21 8v12.993A1 1 0 0 1 20.007 22H3.993A.993.993 0 0 1 3 21.008V2.992C3 2.455 3.449 2 4.002 2h10.995L21 8zm-2 1h-5V4H5v16h14V9zM8 7h3v2H8V7zm0 4h8v2H8v-2zm0 4h8v2H8v-2z\" />\n ),\n 'delete-bin-line': (\n <path d=\"M17 6h5v2h-2v13a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V8H2V6h5V3a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v3zm1 2H6v12h12V8zm-9 3h2v6H9v-6zm4 0h2v6h-2v-6zM9 4v2h6V4H9z\" />\n ),\n 'edit-line': (\n <path d=\"M6.414 16L16.556 5.858l-1.414-1.414L5 14.586V16h1.414zm.829 2H3v-4.243L14.435 2.322a1 1 0 0 1 1.414 0l2.829 2.829a1 1 0 0 1 0 1.414L7.243 18zM3 20h18v2H3v-2z\" />\n ),\n 'check-line': (\n <path d=\"M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414z\" />\n ),\n 'file-copy-line': (\n <path d=\"M7 6V3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1h-3v3c0 .552-.45 1-1.007 1H4.007A1.001 1.001 0 0 1 3 20l.003-14c0-.552.45-1 1.007-1H7zM5.003 8L5 20h10V8H5.003zM9 6h8v10h2V4H9v2z\" />\n ),\n 'refresh-line': (\n <path d=\"M5.463 4.433A9.961 9.961 0 0 1 12 2c5.523 0 10 4.477 10 10 0 2.136-.67 4.116-1.81 5.74L17 12h3a8 8 0 0 0-2.46-5.772A7.96 7.96 0 0 0 12 4a7.96 7.96 0 0 0-5.54 2.228l1.414 1.414A5.972 5.972 0 0 1 12 6a5.99 5.99 0 0 1 3.88 1.42l-1.42 1.42A4 4 0 0 0 8.54 12H6V7l.002-.002 1.461 1.435zM18.537 19.567A9.961 9.961 0 0 1 12 22C6.477 22 2 17.523 2 12c0-2.136.67-4.116 1.81-5.74L7 12H4a8 8 0 0 0 2.46 5.772A7.96 7.96 0 0 0 12 20a7.96 7.96 0 0 0 5.54-2.228l-1.414-1.414A5.972 5.972 0 0 1 12 18a5.99 5.99 0 0 1-3.88-1.42l1.42-1.42A4 4 0 0 0 15.46 12H18v5l-.002.002-1.461-1.435z\" />\n ),\n 'stop-circle-line': (\n <path d=\"M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zM9 9h6v6H9V9z\" />\n ),\n 'settings-3-line': (\n <path d=\"M3.34 17a10.018 10.018 0 0 1-.978-2.326 3 3 0 0 0 .002-5.347A9.99 9.99 0 0 1 4.865 4.99a3 3 0 0 0 4.631-2.674 9.99 9.99 0 0 1 5.007.002 3 3 0 0 0 4.632 2.672 10.018 10.018 0 0 1 2.525 4.337 3 3 0 0 0-.002 5.347 9.99 9.99 0 0 1-2.525 4.337 3 3 0 0 0-4.631 2.674 9.99 9.99 0 0 1-5.007-.002 3 3 0 0 0-4.632-2.672A10.018 10.018 0 0 1 3.34 17zm5.66.196a4.993 4.993 0 0 1 2.25 2.77c.499.047 1 .048 1.499.001A4.993 4.993 0 0 1 15 17.197a4.993 4.993 0 0 1 3.525-.565c.29-.408.54-.843.748-1.298A4.993 4.993 0 0 1 18 12c0-1.26.47-2.437 1.273-3.334a8.126 8.126 0 0 0-.75-1.298A4.993 4.993 0 0 1 15 6.804a4.993 4.993 0 0 1-2.25-2.77c-.499-.047-1-.048-1.499-.001A4.993 4.993 0 0 1 9 6.804a4.993 4.993 0 0 1-3.525.565 7.99 7.99 0 0 0-.748 1.298A4.993 4.993 0 0 1 6 12c0 1.26-.47 2.437-1.273 3.334a8.126 8.126 0 0 0 .75 1.298A4.993 4.993 0 0 1 9 17.196zM12 15a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2z\" />\n ),\n 'loader-4-line': (\n <path d=\"M12 3a9 9 0 0 1 9 9h-2a7 7 0 0 0-7-7V3z\" />\n ),\n 'sparkling-line': (\n <path d=\"M14 4.438A2 2 0 0 1 15.438 3l4.62.764a2 2 0 0 1 1.112.529l.152.152a2 2 0 0 1 .529 1.112L22.5 10a2 2 0 0 1-.436 1.559l-.095.11L21 10.5l-3.3-3.3L14 4.438zm-3 1.124l5.5 5.5-9.086 9.086a2 2 0 0 1-2.828 0l-.172-.172a2 2 0 0 1 0-2.828L13.5 8.062 11 5.562zm-8.657 14.95a1 1 0 0 0 1.414 0l9.9-9.9-1.414-1.413-9.9 9.9a1 1 0 0 0 0 1.414z\" />\n ),\n 'arrow-down-s-line': (\n <path d=\"M12 13.172l4.95-4.95 1.414 1.414L12 16 5.636 9.636 7.05 8.222z\" />\n ),\n 'arrow-up-s-line': (\n <path d=\"M12 10.828l-4.95 4.95-1.414-1.414L12 8l6.364 6.364-1.414 1.414z\" />\n ),\n 'double-quotes-l': (\n <path d=\"M4.583 17.321C3.553 16.227 3 15 3 13.011c0-3.5 2.457-6.637 6.03-8.188l.893 1.378c-3.335 1.804-3.987 4.145-4.247 5.621.537-.278 1.24-.375 1.929-.311 1.804.167 3.226 1.648 3.226 3.489a3.5 3.5 0 0 1-3.5 3.5c-1.073 0-2.099-.49-2.748-1.179zm10 0C13.553 16.227 13 15 13 13.011c0-3.5 2.457-6.637 6.03-8.188l.893 1.378c-3.335 1.804-3.987 4.145-4.247 5.621.537-.278 1.24-.375 1.929-.311 1.804.167 3.226 1.648 3.226 3.489a3.5 3.5 0 0 1-3.5 3.5c-1.073 0-2.099-.49-2.748-1.179z\" />\n ),\n 'robot-line': (\n <path d=\"M13 4.055c4.5.497 8 4.312 8 8.945v9H3v-9c0-4.633 3.5-8.448 8-8.945V1h2v3.055zM5 20h14v-7a7 7 0 1 0-14 0v7zm2-7a5 5 0 0 1 10 0v4H7v-4zm2 0v2h2v-2H9zm4 0v2h2v-2h-2z\" />\n ),\n 'user-3-line': (\n <path d=\"M20 22h-2v-2a3 3 0 0 0-3-3H9a3 3 0 0 0-3 3v2H4v-2a5 5 0 0 1 5-5h6a5 5 0 0 1 5 5v2zm-8-9a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8z\" />\n ),\n 'sun-line': (\n <path d=\"M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z\" />\n ),\n 'moon-line': (\n <path d=\"M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2h.1A6.979 6.979 0 0 0 10 7zm-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938 7.999 7.999 0 0 0 4 12z\" />\n ),\n 'key-line': (\n <path d=\"M12.917 13A6.002 6.002 0 0 1 1 12a6 6 0 0 1 11.917-1H23v6h-2v-4h-2v4h-2v-4h-4.083zM7 10a2 2 0 1 0 0 4 2 2 0 0 0 0-4z\" />\n ),\n 'links-line': (\n <path d=\"M17.657 14.828l-1.414-1.414L17.657 12A4 4 0 1 0 12 6.343l-1.414 1.414-1.414-1.414 1.414-1.414a6 6 0 0 1 8.485 8.485l-1.414 1.414zm-2.829 2.829l-1.414 1.414a6 6 0 1 1-8.485-8.485l1.414-1.414 1.414 1.414L6.343 12A4 4 0 1 0 12 17.657l1.414-1.414 1.414 1.414zm0-9.9l1.415 1.415-7.071 7.07-1.415-1.414 7.071-7.07z\" />\n ),\n 'external-link-line': (\n <path d=\"M10 6v2H5v11h11v-5h2v6a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h6zm11-3v8h-2V6.413l-7.793 7.794-1.414-1.414L17.585 5H13V3h8z\" />\n ),\n 'arrow-left-line': (\n <path d=\"M7.828 11H20v2H7.828l5.364 5.364-1.414 1.414L4 12l7.778-7.778 1.414 1.414z\" />\n ),\n 'arrow-right-line': (\n <path d=\"M16.172 11l-5.364-5.364 1.414-1.414L20 12l-7.778 7.778-1.414-1.414L16.172 13H4v-2z\" />\n ),\n };\n\n const iconPath = icons[name];\n\n return (\n <svg\n className={className}\n width={sizeValue}\n height={sizeValue}\n viewBox=\"0 0 24 24\"\n fill={color}\n onClick={onClick}\n aria-label={ariaLabel}\n role={onClick ? 'button' : 'img'}\n tabIndex={onClick ? 0 : undefined}\n style={{ display: 'inline-block', verticalAlign: 'middle', ...style }}\n >\n {iconPath || <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z\" />}\n </svg>\n );\n};\n\nexport default Icon;\n","/**\n * @description 채팅 사이드바 컴포넌트\n * 세션 목록, 새 대화 버튼\n */\n\nimport React from 'react';\nimport { IconSvg } from './Icon';\nimport type { SidebarProps } from '../types';\n\nconst formatDate = (timestamp: number): string => {\n const date = new Date(timestamp);\n const now = new Date();\n const diff = now.getTime() - date.getTime();\n const days = Math.floor(diff / (1000 * 60 * 60 * 24));\n\n if (days === 0) return '오늘';\n if (days === 1) return '어제';\n if (days < 7) return `${days}일 전`;\n return date.toLocaleDateString('ko-KR');\n};\n\nexport const ChatSidebar: React.FC<SidebarProps> = ({\n sessions,\n currentSessionId,\n onSelectSession,\n onNewSession,\n onDeleteSession,\n isOpen,\n onToggle,\n}) => {\n return (\n <aside\n className={`chatllm-sidebar ${isOpen ? 'chatllm-sidebar--open' : 'chatllm-sidebar--closed'}`}\n style={{\n width: isOpen ? '288px' : '0',\n flexShrink: 0,\n backgroundColor: 'var(--chatllm-sidebar-bg, #ffffff)',\n borderRight: '1px solid var(--chatllm-border, #e5e7eb)',\n transition: 'width 0.3s ease',\n overflow: 'hidden',\n }}\n >\n <div style={{ width: '288px', height: '100%', display: 'flex', flexDirection: 'column' }}>\n {/* Header */}\n <div\n style={{\n padding: '16px',\n borderBottom: '1px solid var(--chatllm-border-light, #f3f4f6)',\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '16px' }}>\n <div\n style={{\n width: '32px',\n height: '32px',\n borderRadius: '8px',\n background: 'linear-gradient(135deg, #3b82f6, #2563eb)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <IconSvg name=\"chat-1-line\" size={20} color=\"#ffffff\" />\n </div>\n <span style={{ fontWeight: 600, color: 'var(--chatllm-text, #1f2937)' }}>\n ChatLLM\n </span>\n </div>\n\n {/* New Chat Button */}\n <button\n onClick={onNewSession}\n style={{\n width: '100%',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '8px',\n padding: '10px 16px',\n backgroundColor: 'var(--chatllm-primary, #3b82f6)',\n color: '#ffffff',\n border: 'none',\n borderRadius: '8px',\n fontSize: '14px',\n fontWeight: 500,\n cursor: 'pointer',\n transition: 'background-color 0.2s',\n }}\n onMouseOver={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-primary-hover, #2563eb)';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-primary, #3b82f6)';\n }}\n >\n <IconSvg name=\"add-line\" size={18} color=\"#ffffff\" />\n 새 대화\n </button>\n </div>\n\n {/* Sessions List */}\n <div style={{ flex: 1, overflow: 'auto', padding: '8px' }}>\n {sessions.length === 0 ? (\n <div\n style={{\n padding: '24px 16px',\n textAlign: 'center',\n color: 'var(--chatllm-text-muted, #9ca3af)',\n fontSize: '14px',\n }}\n >\n 대화 기록이 없습니다\n </div>\n ) : (\n sessions.map((session) => (\n <div\n key={session.id}\n onClick={() => onSelectSession(session.id)}\n style={{\n padding: '12px',\n marginBottom: '4px',\n borderRadius: '8px',\n backgroundColor:\n session.id === currentSessionId\n ? 'var(--chatllm-bg-active, #eff6ff)'\n : 'transparent',\n cursor: 'pointer',\n transition: 'background-color 0.2s',\n }}\n onMouseOver={(e) => {\n if (session.id !== currentSessionId) {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg-hover, #f9fafb)';\n }\n }}\n onMouseOut={(e) => {\n if (session.id !== currentSessionId) {\n e.currentTarget.style.backgroundColor = 'transparent';\n }\n }}\n >\n <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>\n <div style={{ flex: 1, minWidth: 0 }}>\n <div\n style={{\n fontWeight: session.id === currentSessionId ? 500 : 400,\n color: 'var(--chatllm-text, #1f2937)',\n fontSize: '14px',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {session.title}\n </div>\n <div\n style={{\n fontSize: '12px',\n color: 'var(--chatllm-text-muted, #9ca3af)',\n marginTop: '4px',\n }}\n >\n {formatDate(session.updatedAt)}\n </div>\n </div>\n <button\n onClick={(e) => {\n e.stopPropagation();\n onDeleteSession(session.id);\n }}\n style={{\n padding: '4px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n opacity: 0.5,\n transition: 'opacity 0.2s',\n }}\n onMouseOver={(e) => {\n e.currentTarget.style.opacity = '1';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.opacity = '0.5';\n }}\n >\n <IconSvg name=\"delete-bin-line\" size={16} color=\"var(--chatllm-text-muted, #9ca3af)\" />\n </button>\n </div>\n </div>\n ))\n )}\n </div>\n\n {/* Toggle Button (Mobile) */}\n <button\n onClick={onToggle}\n style={{\n position: 'absolute',\n top: '16px',\n right: '-40px',\n width: '32px',\n height: '32px',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '8px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n cursor: 'pointer',\n }}\n >\n <IconSvg name={isOpen ? 'arrow-left-line' : 'menu-line'} size={18} />\n </button>\n </div>\n </aside>\n );\n};\n\nexport default ChatSidebar;\n","/**\n * @description 채팅 헤더 컴포넌트\n * 모델 선택, 설정 버튼\n */\n\nimport React, { useState } from 'react';\nimport { IconSvg } from './Icon';\nimport type { HeaderProps } from '../types';\n\nexport const ChatHeader: React.FC<HeaderProps> = ({\n title,\n model,\n models,\n onModelChange,\n onSettingsOpen,\n onSidebarToggle,\n sidebarOpen,\n}) => {\n const [modelDropdownOpen, setModelDropdownOpen] = useState(false);\n\n const currentModel = models.find((m) => m.id === model);\n\n return (\n <header\n className=\"chatllm-header\"\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '12px 24px',\n borderBottom: '1px solid var(--chatllm-border, #e5e7eb)',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n }}\n >\n {/* Left: Sidebar Toggle & Title */}\n <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>\n <button\n onClick={onSidebarToggle}\n style={{\n width: '36px',\n height: '36px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '8px',\n cursor: 'pointer',\n transition: 'background-color 0.2s',\n }}\n onMouseOver={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg-hover, #f3f4f6)';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent';\n }}\n >\n <IconSvg name=\"menu-line\" size={20} color=\"var(--chatllm-text, #1f2937)\" />\n </button>\n <h1\n style={{\n fontSize: '16px',\n fontWeight: 500,\n color: 'var(--chatllm-text, #1f2937)',\n margin: 0,\n }}\n >\n {title}\n </h1>\n </div>\n\n {/* Right: Model Selector & Settings */}\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>\n {/* Model Selector */}\n <div style={{ position: 'relative' }}>\n <button\n onClick={() => setModelDropdownOpen(!modelDropdownOpen)}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '8px 12px',\n backgroundColor: 'var(--chatllm-bg-secondary, #f9fafb)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '8px',\n cursor: 'pointer',\n transition: 'all 0.2s',\n }}\n onMouseOver={(e) => {\n e.currentTarget.style.borderColor = 'var(--chatllm-primary, #3b82f6)';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.borderColor = 'var(--chatllm-border, #e5e7eb)';\n }}\n >\n <IconSvg name=\"robot-line\" size={16} color=\"var(--chatllm-primary, #3b82f6)\" />\n <span style={{ fontSize: '14px', fontWeight: 500, color: 'var(--chatllm-text, #1f2937)' }}>\n {currentModel?.name || model}\n </span>\n <IconSvg\n name={modelDropdownOpen ? 'arrow-up-s-line' : 'arrow-down-s-line'}\n size={16}\n color=\"var(--chatllm-text-muted, #9ca3af)\"\n />\n </button>\n\n {/* Model Dropdown */}\n {modelDropdownOpen && (\n <>\n {/* Backdrop */}\n <div\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 99,\n }}\n onClick={() => setModelDropdownOpen(false)}\n />\n <div\n style={{\n position: 'absolute',\n top: '100%',\n right: 0,\n marginTop: '8px',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n borderRadius: '12px',\n boxShadow: '0 4px 24px rgba(0, 0, 0, 0.12)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n padding: '8px',\n minWidth: '220px',\n zIndex: 100,\n }}\n >\n {/* Group by provider */}\n {Array.from(new Set(models.map((m) => m.provider))).map((provider) => (\n <div key={provider}>\n <div\n style={{\n padding: '8px 12px',\n fontSize: '11px',\n fontWeight: 600,\n color: 'var(--chatllm-text-muted, #9ca3af)',\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n }}\n >\n {provider}\n </div>\n {models\n .filter((m) => m.provider === provider)\n .map((m) => (\n <button\n key={m.id}\n onClick={() => {\n onModelChange(m.id);\n setModelDropdownOpen(false);\n }}\n style={{\n width: '100%',\n display: 'flex',\n alignItems: 'center',\n gap: '10px',\n padding: '10px 12px',\n backgroundColor: m.id === model ? 'var(--chatllm-bg-active, #eff6ff)' : 'transparent',\n border: 'none',\n borderRadius: '8px',\n cursor: 'pointer',\n textAlign: 'left',\n transition: 'background-color 0.2s',\n }}\n onMouseOver={(e) => {\n if (m.id !== model) {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg-hover, #f9fafb)';\n }\n }}\n onMouseOut={(e) => {\n if (m.id !== model) {\n e.currentTarget.style.backgroundColor = 'transparent';\n }\n }}\n >\n <div\n style={{\n width: '28px',\n height: '28px',\n borderRadius: '6px',\n backgroundColor: m.id === model\n ? 'var(--chatllm-primary, #3b82f6)'\n : 'var(--chatllm-bg-secondary, #f3f4f6)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <IconSvg\n name=\"robot-line\"\n size={14}\n color={m.id === model ? '#ffffff' : 'var(--chatllm-text-muted, #9ca3af)'}\n />\n </div>\n <div>\n <div\n style={{\n fontSize: '14px',\n fontWeight: m.id === model ? 500 : 400,\n color: 'var(--chatllm-text, #1f2937)',\n }}\n >\n {m.name}\n </div>\n {m.description && (\n <div style={{ fontSize: '12px', color: 'var(--chatllm-text-muted, #9ca3af)' }}>\n {m.description}\n </div>\n )}\n </div>\n {m.id === model && (\n <IconSvg\n name=\"check-line\"\n size={16}\n color=\"var(--chatllm-primary, #3b82f6)\"\n className=\"ml-auto\"\n />\n )}\n </button>\n ))}\n </div>\n ))}\n </div>\n </>\n )}\n </div>\n\n {/* Settings Button */}\n <button\n onClick={onSettingsOpen}\n style={{\n width: '36px',\n height: '36px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '8px',\n cursor: 'pointer',\n transition: 'background-color 0.2s',\n }}\n onMouseOver={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg-hover, #f3f4f6)';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent';\n }}\n >\n <IconSvg name=\"settings-3-line\" size={20} color=\"var(--chatllm-text-muted, #6b7280)\" />\n </button>\n </div>\n </header>\n );\n};\n\nexport default ChatHeader;\n","/**\n * @description 채팅 입력창 컴포넌트\n * 텍스트 입력, 액션 메뉴, 인용문 칩\n */\n\nimport React, { useRef, useEffect, useState } from 'react';\nimport { IconSvg } from './Icon';\nimport type { InputProps, ActionItem } from '../types';\n\nexport const ChatInput: React.FC<InputProps> = ({\n value,\n onChange,\n onSubmit,\n onStop,\n isLoading,\n placeholder = '메시지를 입력하세요...',\n quotedText,\n onClearQuote,\n selectedAction,\n onClearAction,\n onActionSelect,\n actions = [],\n}) => {\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const [actionMenuOpen, setActionMenuOpen] = useState(false);\n\n // Auto-resize textarea\n useEffect(() => {\n if (textareaRef.current) {\n textareaRef.current.style.height = 'auto';\n textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 200)}px`;\n }\n }, [value]);\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n onSubmit();\n }\n };\n\n const handleActionSelect = (action: ActionItem) => {\n onActionSelect?.(action);\n setActionMenuOpen(false);\n };\n\n return (\n <div\n className=\"chatllm-input-container\"\n style={{\n padding: '16px 24px',\n borderTop: '1px solid var(--chatllm-border, #e5e7eb)',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n }}\n >\n {/* Quote & Action Chips */}\n {(quotedText || selectedAction) && (\n <div style={{ display: 'flex', gap: '8px', marginBottom: '12px', flexWrap: 'wrap' }}>\n {/* Quote Chip */}\n {quotedText && (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '8px 12px',\n backgroundColor: 'var(--chatllm-bg-secondary, #f9fafb)',\n borderRadius: '8px',\n borderLeft: '3px solid var(--chatllm-primary, #3b82f6)',\n maxWidth: '100%',\n }}\n >\n <IconSvg name=\"double-quotes-l\" size={14} color=\"var(--chatllm-primary, #3b82f6)\" />\n <span\n style={{\n fontSize: '13px',\n color: 'var(--chatllm-text, #1f2937)',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n maxWidth: '300px',\n }}\n >\n {quotedText}\n </span>\n <button\n onClick={onClearQuote}\n style={{\n padding: '2px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <IconSvg name=\"close-line\" size={14} color=\"var(--chatllm-text-muted, #9ca3af)\" />\n </button>\n </div>\n )}\n\n {/* Action Chip */}\n {selectedAction && (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n padding: '6px 12px',\n backgroundColor: 'var(--chatllm-primary-light, #dbeafe)',\n borderRadius: '16px',\n fontSize: '13px',\n fontWeight: 500,\n color: 'var(--chatllm-primary, #3b82f6)',\n }}\n >\n <IconSvg name=\"sparkling-line\" size={14} color=\"var(--chatllm-primary, #3b82f6)\" />\n {selectedAction.label}\n <button\n onClick={onClearAction}\n style={{\n padding: '2px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <IconSvg name=\"close-line\" size={14} color=\"var(--chatllm-primary, #3b82f6)\" />\n </button>\n </div>\n )}\n </div>\n )}\n\n {/* Input Area */}\n <div\n style={{\n display: 'flex',\n alignItems: 'flex-end',\n gap: '12px',\n padding: '12px 16px',\n backgroundColor: 'var(--chatllm-input-bg, #f9fafb)',\n borderRadius: '16px',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n transition: 'border-color 0.2s, box-shadow 0.2s',\n }}\n >\n {/* Action Menu Button */}\n {actions.length > 0 && (\n <div style={{ position: 'relative' }}>\n <button\n onClick={() => setActionMenuOpen(!actionMenuOpen)}\n style={{\n width: '36px',\n height: '36px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '8px',\n cursor: 'pointer',\n transition: 'background-color 0.2s',\n }}\n onMouseOver={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg-hover, #f3f4f6)';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg, #ffffff)';\n }}\n >\n <IconSvg name=\"add-line\" size={20} color=\"var(--chatllm-text, #1f2937)\" />\n </button>\n\n {/* Action Menu Dropdown */}\n {actionMenuOpen && (\n <div\n style={{\n position: 'absolute',\n bottom: '100%',\n left: 0,\n marginBottom: '8px',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n borderRadius: '12px',\n boxShadow: '0 4px 24px rgba(0, 0, 0, 0.12)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n padding: '8px',\n minWidth: '200px',\n zIndex: 100,\n }}\n >\n {actions.map((action) => (\n <button\n key={action.id}\n onClick={() => handleActionSelect(action)}\n style={{\n width: '100%',\n display: 'flex',\n alignItems: 'center',\n gap: '12px',\n padding: '10px 12px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '8px',\n cursor: 'pointer',\n textAlign: 'left',\n transition: 'background-color 0.2s',\n }}\n onMouseOver={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg-hover, #f3f4f6)';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent';\n }}\n >\n <div\n style={{\n width: '32px',\n height: '32px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'var(--chatllm-primary-light, #dbeafe)',\n borderRadius: '8px',\n }}\n >\n <IconSvg\n name={\n action.icon === 'search'\n ? 'search-line'\n : action.icon === 'image'\n ? 'image-line'\n : action.icon === 'code'\n ? 'code-s-slash-line'\n : 'file-text-line'\n }\n size={18}\n color=\"var(--chatllm-primary, #3b82f6)\"\n />\n </div>\n <div>\n <div style={{ fontSize: '14px', fontWeight: 500, color: 'var(--chatllm-text, #1f2937)' }}>\n {action.label}\n </div>\n <div style={{ fontSize: '12px', color: 'var(--chatllm-text-muted, #9ca3af)' }}>\n {action.description}\n </div>\n </div>\n </button>\n ))}\n </div>\n )}\n </div>\n )}\n\n {/* Textarea */}\n <textarea\n ref={textareaRef}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n rows={1}\n style={{\n flex: 1,\n minHeight: '24px',\n maxHeight: '200px',\n padding: '6px 0',\n backgroundColor: 'transparent',\n border: 'none',\n outline: 'none',\n fontSize: '15px',\n lineHeight: '1.5',\n resize: 'none',\n color: 'var(--chatllm-text, #1f2937)',\n }}\n />\n\n {/* Send / Stop Button */}\n {isLoading ? (\n <button\n onClick={onStop}\n style={{\n width: '36px',\n height: '36px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'var(--chatllm-error, #ef4444)',\n border: 'none',\n borderRadius: '8px',\n cursor: 'pointer',\n transition: 'background-color 0.2s',\n }}\n >\n <IconSvg name=\"stop-circle-line\" size={20} color=\"#ffffff\" />\n </button>\n ) : (\n <button\n onClick={onSubmit}\n disabled={!value.trim()}\n style={{\n width: '36px',\n height: '36px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: value.trim()\n ? 'var(--chatllm-primary, #3b82f6)'\n : 'var(--chatllm-bg-disabled, #e5e7eb)',\n border: 'none',\n borderRadius: '8px',\n cursor: value.trim() ? 'pointer' : 'not-allowed',\n transition: 'background-color 0.2s',\n }}\n >\n <IconSvg name=\"send-plane-fill\" size={18} color={value.trim() ? '#ffffff' : '#9ca3af'} />\n </button>\n )}\n </div>\n </div>\n );\n};\n\nexport default ChatInput;\n","/**\n * @description 메시지 목록 컴포넌트\n */\n\nimport React, { useRef, useEffect, useCallback, useState } from 'react';\nimport { MessageBubble } from './MessageBubble';\nimport { IconSvg } from './Icon';\nimport type { MessageListProps } from '../types';\n\nexport const MessageList: React.FC<MessageListProps> = ({\n messages,\n isLoading,\n onCopy,\n onEdit,\n onRegenerate,\n onQuote,\n copiedId,\n editingId,\n}) => {\n const messagesEndRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const [selectedText, setSelectedText] = useState('');\n const [selectionPosition, setSelectionPosition] = useState<{ x: number; y: number } | null>(null);\n\n // Auto scroll to bottom\n useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n }, [messages]);\n\n // Handle text selection\n const handleMouseUp = useCallback(() => {\n const selection = window.getSelection();\n const text = selection?.toString().trim();\n\n if (text && text.length > 0) {\n const range = selection?.getRangeAt(0);\n const rect = range?.getBoundingClientRect();\n if (rect && containerRef.current) {\n const containerRect = containerRef.current.getBoundingClientRect();\n setSelectedText(text);\n setSelectionPosition({\n x: rect.left - containerRect.left + rect.width / 2,\n y: rect.top - containerRect.top - 10,\n });\n }\n } else {\n setTimeout(() => {\n const currentSelection = window.getSelection()?.toString().trim();\n if (!currentSelection) {\n setSelectionPosition(null);\n }\n }, 100);\n }\n }, []);\n\n // Handle quote\n const handleQuote = () => {\n if (selectedText && onQuote) {\n onQuote(selectedText);\n setSelectionPosition(null);\n setSelectedText('');\n window.getSelection()?.removeAllRanges();\n }\n };\n\n return (\n <div\n ref={containerRef}\n className=\"chatllm-message-list\"\n style={{\n flex: 1,\n overflow: 'auto',\n position: 'relative',\n }}\n onMouseUp={handleMouseUp}\n >\n {messages.map((message, index) => (\n <MessageBubble\n key={message.id}\n message={message}\n isLoading={isLoading && index === messages.length - 1 && message.role === 'assistant'}\n isCopied={copiedId === message.id}\n isEditing={editingId === message.id}\n onCopy={() => onCopy(message.content, message.id)}\n onEdit={() => onEdit(message)}\n onRegenerate={message.role === 'assistant' ? () => onRegenerate(message.id) : undefined}\n onQuote={onQuote}\n alternatives={message.alternatives}\n />\n ))}\n\n {/* Selection Popup */}\n {selectionPosition && (\n <div\n style={{\n position: 'absolute',\n left: selectionPosition.x,\n top: selectionPosition.y,\n transform: 'translate(-50%, -100%)',\n zIndex: 50,\n }}\n >\n <button\n onClick={handleQuote}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n padding: '8px 12px',\n backgroundColor: 'var(--chatllm-text, #1f2937)',\n color: '#ffffff',\n border: 'none',\n borderRadius: '8px',\n fontSize: '13px',\n fontWeight: 500,\n cursor: 'pointer',\n boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',\n }}\n >\n <IconSvg name=\"double-quotes-l\" size={14} color=\"#ffffff\" />\n 인용하기\n </button>\n {/* Arrow */}\n <div\n style={{\n position: 'absolute',\n left: '50%',\n bottom: '-6px',\n transform: 'translateX(-50%)',\n width: 0,\n height: 0,\n borderLeft: '6px solid transparent',\n borderRight: '6px solid transparent',\n borderTop: '6px solid var(--chatllm-text, #1f2937)',\n }}\n />\n </div>\n )}\n\n <div ref={messagesEndRef} />\n </div>\n );\n};\n\nexport default MessageList;\n","/**\n * @description 메시지 버블 컴포넌트\n * 사용자/AI 메시지 표시, 복사, 수정, 재생성\n * 마크다운 렌더링 및 출처 링크 칩 지원\n */\n\nimport React, { useState } from 'react';\nimport { IconSvg } from './Icon';\nimport { MarkdownRenderer } from './MarkdownRenderer';\nimport type { MessageBubbleProps } from '../types';\n\nexport const MessageBubble: React.FC<MessageBubbleProps> = ({\n message,\n isLoading,\n isCopied,\n isEditing,\n onCopy,\n onEdit,\n onRegenerate,\n onQuote,\n alternatives,\n activeAlternativeIndex = 0,\n onAlternativeChange,\n}) => {\n const [showActions, setShowActions] = useState(false);\n const isUser = message.role === 'user';\n const isAssistant = message.role === 'assistant';\n\n // Get content to display (main or alternative)\n const displayContent =\n alternatives && alternatives.length > 0 && activeAlternativeIndex > 0\n ? alternatives[activeAlternativeIndex - 1]?.content || message.content\n : message.content;\n\n const displayModel =\n alternatives && alternatives.length > 0 && activeAlternativeIndex > 0\n ? alternatives[activeAlternativeIndex - 1]?.model\n : message.model;\n\n // Handle text selection for quote\n const handleMouseUp = () => {\n if (!onQuote) return;\n const selection = window.getSelection();\n const text = selection?.toString().trim();\n if (text && text.length > 0) {\n // Will be handled by parent component\n }\n };\n\n return (\n <div\n className={`chatllm-message chatllm-message--${message.role}`}\n style={{\n display: 'flex',\n gap: '12px',\n padding: '16px 24px',\n backgroundColor: isUser ? 'transparent' : 'var(--chatllm-bg-secondary, #f9fafb)',\n }}\n onMouseEnter={() => setShowActions(true)}\n onMouseLeave={() => setShowActions(false)}\n onMouseUp={handleMouseUp}\n >\n {/* Avatar */}\n <div\n style={{\n width: '32px',\n height: '32px',\n borderRadius: '8px',\n backgroundColor: isUser\n ? 'var(--chatllm-user-avatar, #e5e7eb)'\n : 'var(--chatllm-assistant-avatar, #dbeafe)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n }}\n >\n <IconSvg\n name={isUser ? 'user-3-line' : 'robot-line'}\n size={18}\n color={isUser ? 'var(--chatllm-text-muted, #6b7280)' : 'var(--chatllm-primary, #3b82f6)'}\n />\n </div>\n\n {/* Content */}\n <div style={{ flex: 1, minWidth: 0 }}>\n {/* Header */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n marginBottom: '8px',\n }}\n >\n <span\n style={{\n fontSize: '14px',\n fontWeight: 500,\n color: 'var(--chatllm-text, #1f2937)',\n }}\n >\n {isUser ? '나' : 'AI'}\n </span>\n {displayModel && (\n <span\n style={{\n fontSize: '12px',\n padding: '2px 8px',\n backgroundColor: 'var(--chatllm-bg-tertiary, #f3f4f6)',\n borderRadius: '4px',\n color: 'var(--chatllm-text-muted, #6b7280)',\n }}\n >\n {displayModel}\n </span>\n )}\n </div>\n\n {/* Message Content */}\n <div\n style={{\n wordBreak: 'break-word',\n }}\n >\n {isAssistant ? (\n // AI 메시지는 마크다운 렌더링\n <MarkdownRenderer content={displayContent} />\n ) : (\n // 사용자 메시지는 일반 텍스트\n <div\n style={{\n fontSize: '15px',\n lineHeight: '1.7',\n color: 'var(--chatllm-text, #374151)',\n whiteSpace: 'pre-wrap',\n }}\n >\n {displayContent}\n </div>\n )}\n {isLoading && isAssistant && !displayContent && (\n <span\n style={{\n display: 'inline-flex',\n gap: '4px',\n }}\n >\n <span className=\"chatllm-typing-dot\" style={dotStyle} />\n <span className=\"chatllm-typing-dot\" style={{ ...dotStyle, animationDelay: '0.2s' }} />\n <span className=\"chatllm-typing-dot\" style={{ ...dotStyle, animationDelay: '0.4s' }} />\n </span>\n )}\n </div>\n\n {/* Alternatives Navigation */}\n {alternatives && alternatives.length > 0 && (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n marginTop: '12px',\n paddingTop: '12px',\n borderTop: '1px solid var(--chatllm-border-light, #f3f4f6)',\n }}\n >\n <button\n onClick={() => onAlternativeChange?.(Math.max(0, activeAlternativeIndex - 1))}\n disabled={activeAlternativeIndex === 0}\n style={{\n ...navButtonStyle,\n opacity: activeAlternativeIndex === 0 ? 0.5 : 1,\n cursor: activeAlternativeIndex === 0 ? 'not-allowed' : 'pointer',\n }}\n >\n <IconSvg name=\"arrow-left-line\" size={14} />\n </button>\n <span style={{ fontSize: '12px', color: 'var(--chatllm-text-muted, #9ca3af)' }}>\n {activeAlternativeIndex + 1} / {alternatives.length + 1}\n </span>\n <button\n onClick={() =>\n onAlternativeChange?.(Math.min(alternatives.length, activeAlternativeIndex + 1))\n }\n disabled={activeAlternativeIndex === alternatives.length}\n style={{\n ...navButtonStyle,\n opacity: activeAlternativeIndex === alternatives.length ? 0.5 : 1,\n cursor: activeAlternativeIndex === alternatives.length ? 'not-allowed' : 'pointer',\n }}\n >\n <IconSvg name=\"arrow-right-line\" size={14} />\n </button>\n </div>\n )}\n\n {/* Action Buttons */}\n {showActions && !isLoading && (\n <div\n style={{\n display: 'flex',\n gap: '4px',\n marginTop: '12px',\n }}\n >\n {/* Copy */}\n <button onClick={onCopy} style={actionButtonStyle} title=\"복사\">\n <IconSvg\n name={isCopied ? 'check-line' : 'file-copy-line'}\n size={16}\n color={isCopied ? 'var(--chatllm-success, #22c55e)' : 'var(--chatllm-text-muted, #9ca3af)'}\n />\n </button>\n\n {/* Edit (User only) */}\n {isUser && (\n <button onClick={onEdit} style={actionButtonStyle} title=\"수정\">\n <IconSvg name=\"edit-line\" size={16} color=\"var(--chatllm-text-muted, #9ca3af)\" />\n </button>\n )}\n\n {/* Regenerate (Assistant only) */}\n {isAssistant && onRegenerate && (\n <button onClick={onRegenerate} style={actionButtonStyle} title=\"다시 생성\">\n <IconSvg name=\"refresh-line\" size={16} color=\"var(--chatllm-text-muted, #9ca3af)\" />\n </button>\n )}\n </div>\n )}\n </div>\n </div>\n );\n};\n\nconst dotStyle: React.CSSProperties = {\n width: '8px',\n height: '8px',\n borderRadius: '50%',\n backgroundColor: 'var(--chatllm-primary, #3b82f6)',\n animation: 'chatllm-typing 1.4s infinite ease-in-out both',\n};\n\nconst actionButtonStyle: React.CSSProperties = {\n padding: '6px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '6px',\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n transition: 'background-color 0.2s',\n};\n\nconst navButtonStyle: React.CSSProperties = {\n width: '24px',\n height: '24px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '6px',\n};\n\nexport default MessageBubble;\n","/**\n * @description 마크다운 렌더러 컴포넌트\n * 외부 의존성 없이 기본 마크다운 파싱 지원\n */\n\nimport React, { useMemo } from 'react';\nimport { LinkChip } from './LinkChip';\n\nexport interface MarkdownRendererProps {\n /** 마크다운 텍스트 */\n content: string;\n /** 커스텀 클래스 */\n className?: string;\n}\n\n// 링크 정규식 - [text](url) 패턴\nconst LINK_REGEX = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n// 출처 링크 패턴 - 연속된 링크들 (예: [`1. brave`](url) [`2. brave`](url))\nconst SOURCE_LINKS_REGEX = /(\\*{0,2}출처:?\\*{0,2}\\s*)?((?:\\[`?[^\\]]+`?\\]\\([^)]+\\)\\s*)+)/gi;\n// 코드 블록 패턴\nconst CODE_BLOCK_REGEX = /```(\\w*)\\n?([\\s\\S]*?)```/g;\n// 인라인 코드 패턴\nconst INLINE_CODE_REGEX = /`([^`]+)`/g;\n// 굵게 패턴\nconst BOLD_REGEX = /\\*\\*([^*]+)\\*\\*/g;\n// 기울임 패턴 (굵게가 아닌 경우만)\nconst ITALIC_REGEX = /(?<!\\*)\\*([^*]+)\\*(?!\\*)/g;\n// 헤딩 패턴\nconst HEADING_REGEX = /^(#{1,6})\\s+(.+)$/gm;\n// 리스트 아이템 패턴\nconst LIST_ITEM_REGEX = /^[\\-\\*]\\s+(.+)$/gm;\n// 번호 리스트 패턴\nconst NUMBERED_LIST_REGEX = /^(\\d+)\\.\\s+(.+)$/gm;\n// 인용 패턴\nconst BLOCKQUOTE_REGEX = /^>\\s+(.+)$/gm;\n// 수평선 패턴\nconst HR_REGEX = /^---+$/gm;\n\ninterface ParsedLink {\n text: string;\n url: string;\n}\n\n/**\n * 출처 링크들을 파싱하여 배열로 반환\n */\nconst parseSourceLinks = (text: string): ParsedLink[] => {\n const links: ParsedLink[] = [];\n let match;\n const linkRegex = /\\[`?([^\\]`]+)`?\\]\\(([^)]+)\\)/g;\n\n while ((match = linkRegex.exec(text)) !== null) {\n links.push({\n text: match[1],\n url: match[2],\n });\n }\n\n return links;\n};\n\n/**\n * 텍스트에서 인라인 요소 파싱 (굵게, 기울임, 코드, 링크)\n */\nconst parseInlineElements = (text: string, key: string): React.ReactNode[] => {\n const elements: React.ReactNode[] = [];\n let lastIndex = 0;\n let currentText = text;\n\n // 인라인 코드 처리\n currentText = currentText.replace(INLINE_CODE_REGEX, '§CODE§$1§/CODE§');\n // 굵게 처리\n currentText = currentText.replace(BOLD_REGEX, '§BOLD§$1§/BOLD§');\n // 기울임 처리\n currentText = currentText.replace(ITALIC_REGEX, '§ITALIC§$1§/ITALIC§');\n // 일반 링크 처리 (출처 링크가 아닌 것)\n currentText = currentText.replace(LINK_REGEX, '§LINK§$1§URL§$2§/LINK§');\n\n // 파싱된 마커를 React 요소로 변환\n const parts = currentText.split(/(§CODE§.*?§\\/CODE§|§BOLD§.*?§\\/BOLD§|§ITALIC§.*?§\\/ITALIC§|§LINK§.*?§\\/LINK§)/);\n\n parts.forEach((part, index) => {\n if (part.startsWith('§CODE§')) {\n const content = part.replace('§CODE§', '').replace('§/CODE§', '');\n elements.push(\n <code\n key={`${key}-code-${index}`}\n style={{\n backgroundColor: 'var(--chatllm-code-bg, #f3f4f6)',\n padding: '2px 6px',\n borderRadius: '4px',\n fontSize: '0.9em',\n fontFamily: 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace',\n color: 'var(--chatllm-code-text, #e11d48)',\n }}\n >\n {content}\n </code>\n );\n } else if (part.startsWith('§BOLD§')) {\n const content = part.replace('§BOLD§', '').replace('§/BOLD§', '');\n elements.push(<strong key={`${key}-bold-${index}`}>{content}</strong>);\n } else if (part.startsWith('§ITALIC§')) {\n const content = part.replace('§ITALIC§', '').replace('§/ITALIC§', '');\n elements.push(<em key={`${key}-italic-${index}`}>{content}</em>);\n } else if (part.startsWith('§LINK§')) {\n const match = part.match(/§LINK§(.+?)§URL§(.+?)§\\/LINK§/);\n if (match) {\n elements.push(\n <a\n key={`${key}-link-${index}`}\n href={match[2]}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{\n color: 'var(--chatllm-link, #3b82f6)',\n textDecoration: 'none',\n }}\n >\n {match[1]}\n </a>\n );\n }\n } else if (part) {\n elements.push(part);\n }\n });\n\n return elements;\n};\n\n/**\n * 코드 블록 렌더링\n */\nconst CodeBlock: React.FC<{ language?: string; code: string }> = ({ language, code }) => {\n const [copied, setCopied] = React.useState(false);\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(code);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch (e) {\n console.error('Failed to copy');\n }\n };\n\n return (\n <div\n style={{\n position: 'relative',\n margin: '12px 0',\n borderRadius: '8px',\n overflow: 'hidden',\n backgroundColor: 'var(--chatllm-code-block-bg, #1f2937)',\n }}\n >\n {/* Header */}\n <div\n style={{\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: '8px 12px',\n backgroundColor: 'var(--chatllm-code-block-header, #374151)',\n borderBottom: '1px solid var(--chatllm-code-block-border, #4b5563)',\n }}\n >\n <span\n style={{\n fontSize: '12px',\n color: 'var(--chatllm-code-block-lang, #9ca3af)',\n textTransform: 'lowercase',\n }}\n >\n {language || 'code'}\n </span>\n <button\n onClick={handleCopy}\n style={{\n padding: '4px 8px',\n fontSize: '12px',\n backgroundColor: 'transparent',\n border: '1px solid var(--chatllm-code-block-border, #4b5563)',\n borderRadius: '4px',\n color: 'var(--chatllm-code-block-text, #e5e7eb)',\n cursor: 'pointer',\n }}\n >\n {copied ? '복사됨!' : '복사'}\n </button>\n </div>\n {/* Code */}\n <pre\n style={{\n margin: 0,\n padding: '16px',\n overflow: 'auto',\n fontSize: '13px',\n lineHeight: '1.6',\n fontFamily: 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace',\n color: 'var(--chatllm-code-block-text, #e5e7eb)',\n }}\n >\n <code>{code.trim()}</code>\n </pre>\n </div>\n );\n};\n\n/**\n * 출처 링크 섹션 렌더링\n */\nconst SourceLinksSection: React.FC<{ links: ParsedLink[]; label?: string }> = ({ links, label }) => {\n return (\n <div\n style={{\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n gap: '8px',\n margin: '12px 0',\n padding: '12px',\n backgroundColor: 'var(--chatllm-source-bg, #f8fafc)',\n borderRadius: '8px',\n border: '1px solid var(--chatllm-border-light, #e2e8f0)',\n }}\n >\n {label && (\n <span\n style={{\n fontSize: '13px',\n fontWeight: 500,\n color: 'var(--chatllm-text-muted, #64748b)',\n marginRight: '4px',\n }}\n >\n {label}\n </span>\n )}\n {links.map((link, index) => (\n <LinkChip key={index} text={link.text} url={link.url} />\n ))}\n </div>\n );\n};\n\nexport const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({ content, className }) => {\n const rendered = useMemo(() => {\n const elements: React.ReactNode[] = [];\n let processedContent = content;\n\n // 1. 코드 블록 추출 및 치환\n const codeBlocks: { language: string; code: string }[] = [];\n processedContent = processedContent.replace(CODE_BLOCK_REGEX, (_, lang, code) => {\n codeBlocks.push({ language: lang || '', code });\n return `§CODEBLOCK§${codeBlocks.length - 1}§/CODEBLOCK§`;\n });\n\n // 2. 출처 링크 섹션 추출 및 치환\n const sourceSections: { label: string; links: ParsedLink[] }[] = [];\n processedContent = processedContent.replace(SOURCE_LINKS_REGEX, (match, label, linksText) => {\n const links = parseSourceLinks(linksText);\n if (links.length > 0) {\n sourceSections.push({ label: label?.replace(/\\*+/g, '').trim() || '출처', links });\n return `§SOURCES§${sourceSections.length - 1}§/SOURCES§`;\n }\n return match;\n });\n\n // 3. 줄 단위로 파싱\n const lines = processedContent.split('\\n');\n let currentList: { type: 'ul' | 'ol'; items: React.ReactNode[] } | null = null;\n let blockquoteLines: string[] = [];\n\n const flushList = () => {\n if (currentList) {\n if (currentList.type === 'ul') {\n elements.push(\n <ul key={`ul-${elements.length}`} style={{ margin: '8px 0', paddingLeft: '24px' }}>\n {currentList.items}\n </ul>\n );\n } else {\n elements.push(\n <ol key={`ol-${elements.length}`} style={{ margin: '8px 0', paddingLeft: '24px' }}>\n {currentList.items}\n </ol>\n );\n }\n currentList = null;\n }\n };\n\n const flushBlockquote = () => {\n if (blockquoteLines.length > 0) {\n elements.push(\n <blockquote\n key={`bq-${elements.length}`}\n style={{\n margin: '12px 0',\n padding: '12px 16px',\n borderLeft: '4px solid var(--chatllm-primary, #3b82f6)',\n backgroundColor: 'var(--chatllm-bg-secondary, #f9fafb)',\n borderRadius: '0 8px 8px 0',\n color: 'var(--chatllm-text, #374151)',\n }}\n >\n {blockquoteLines.map((line, i) => (\n <React.Fragment key={i}>\n {parseInlineElements(line, `bq-line-${i}`)}\n {i < blockquoteLines.length - 1 && <br />}\n </React.Fragment>\n ))}\n </blockquote>\n );\n blockquoteLines = [];\n }\n };\n\n lines.forEach((line, lineIndex) => {\n // 코드 블록 마커 처리\n const codeBlockMatch = line.match(/§CODEBLOCK§(\\d+)§\\/CODEBLOCK§/);\n if (codeBlockMatch) {\n flushList();\n flushBlockquote();\n const index = parseInt(codeBlockMatch[1]);\n elements.push(\n <CodeBlock key={`codeblock-${lineIndex}`} {...codeBlocks[index]} />\n );\n return;\n }\n\n // 출처 링크 마커 처리\n const sourcesMatch = line.match(/§SOURCES§(\\d+)§\\/SOURCES§/);\n if (sourcesMatch) {\n flushList();\n flushBlockquote();\n const index = parseInt(sourcesMatch[1]);\n elements.push(\n <SourceLinksSection key={`sources-${lineIndex}`} {...sourceSections[index]} />\n );\n return;\n }\n\n // 수평선\n if (HR_REGEX.test(line)) {\n flushList();\n flushBlockquote();\n elements.push(\n <hr\n key={`hr-${lineIndex}`}\n style={{\n margin: '16px 0',\n border: 'none',\n borderTop: '1px solid var(--chatllm-border, #e5e7eb)',\n }}\n />\n );\n return;\n }\n\n // 헤딩\n const headingMatch = line.match(/^(#{1,6})\\s+(.+)$/);\n if (headingMatch) {\n flushList();\n flushBlockquote();\n const level = headingMatch[1].length;\n const text = headingMatch[2];\n const HeadingTag = `h${level}` as keyof JSX.IntrinsicElements;\n const sizes: Record<number, string> = {\n 1: '1.5em',\n 2: '1.3em',\n 3: '1.15em',\n 4: '1.05em',\n 5: '1em',\n 6: '0.95em',\n };\n elements.push(\n <HeadingTag\n key={`heading-${lineIndex}`}\n style={{\n fontSize: sizes[level],\n fontWeight: level <= 2 ? 600 : 500,\n margin: '16px 0 8px',\n color: 'var(--chatllm-text, #1f2937)',\n }}\n >\n {parseInlineElements(text, `heading-${lineIndex}`)}\n </HeadingTag>\n );\n return;\n }\n\n // 인용문\n const blockquoteMatch = line.match(/^>\\s*(.*)$/);\n if (blockquoteMatch) {\n flushList();\n blockquoteLines.push(blockquoteMatch[1]);\n return;\n } else {\n flushBlockquote();\n }\n\n // 비순서 리스트\n const ulMatch = line.match(/^[\\-\\*]\\s+(.+)$/);\n if (ulMatch) {\n flushBlockquote();\n if (!currentList || currentList.type !== 'ul') {\n flushList();\n currentList = { type: 'ul', items: [] };\n }\n currentList.items.push(\n <li key={`li-${lineIndex}`} style={{ margin: '4px 0' }}>\n {parseInlineElements(ulMatch[1], `li-${lineIndex}`)}\n </li>\n );\n return;\n }\n\n // 순서 리스트\n const olMatch = line.match(/^(\\d+)\\.\\s+(.+)$/);\n if (olMatch) {\n flushBlockquote();\n if (!currentList || currentList.type !== 'ol') {\n flushList();\n currentList = { type: 'ol', items: [] };\n }\n currentList.items.push(\n <li key={`li-${lineIndex}`} style={{ margin: '4px 0' }}>\n {parseInlineElements(olMatch[2], `li-${lineIndex}`)}\n </li>\n );\n return;\n }\n\n // 리스트 종료\n flushList();\n\n // 빈 줄\n if (!line.trim()) {\n elements.push(<br key={`br-${lineIndex}`} />);\n return;\n }\n\n // 일반 텍스트\n elements.push(\n <p key={`p-${lineIndex}`} style={{ margin: '4px 0' }}>\n {parseInlineElements(line, `p-${lineIndex}`)}\n </p>\n );\n });\n\n // 남은 리스트/인용문 처리\n flushList();\n flushBlockquote();\n\n return elements;\n }, [content]);\n\n return (\n <div\n className={`chatllm-markdown ${className || ''}`}\n style={{\n fontSize: '15px',\n lineHeight: '1.7',\n color: 'var(--chatllm-text, #374151)',\n }}\n >\n {rendered}\n </div>\n );\n};\n\nexport default MarkdownRenderer;\n","/**\n * @description 링크 칩 컴포넌트\n * 출처 링크를 칩 형태로 표시\n */\n\nimport React, { useState } from 'react';\nimport { IconSvg } from './Icon';\n\nexport interface LinkChipProps {\n /** 링크 텍스트 */\n text: string;\n /** 링크 URL */\n url: string;\n /** 파비콘 표시 여부 */\n showFavicon?: boolean;\n /** 번호 표시 */\n index?: number;\n /** 커스텀 스타일 */\n style?: React.CSSProperties;\n}\n\n/**\n * URL에서 도메인 추출\n */\nconst getDomain = (url: string): string => {\n try {\n const urlObj = new URL(url);\n return urlObj.hostname.replace('www.', '');\n } catch {\n return url;\n }\n};\n\n/**\n * 도메인에서 짧은 이름 추출\n */\nconst getShortName = (domain: string): string => {\n const parts = domain.split('.');\n if (parts.length >= 2) {\n return parts[parts.length - 2];\n }\n return domain;\n};\n\n/**\n * 도메인별 색상 매핑\n */\nconst getDomainColor = (domain: string): string => {\n const lowerDomain = domain.toLowerCase();\n\n // 주요 사이트 색상\n const colorMap: Record<string, string> = {\n 'google': '#4285f4',\n 'wikipedia': '#000000',\n 'github': '#24292e',\n 'stackoverflow': '#f48024',\n 'medium': '#00ab6c',\n 'youtube': '#ff0000',\n 'twitter': '#1da1f2',\n 'naver': '#03c75a',\n 'namu': '#00a495',\n 'tistory': '#eb531f',\n 'velog': '#20c997',\n 'brave': '#fb542b',\n 'mk': '#0066cc',\n 'ko': '#3366cc',\n };\n\n for (const [key, color] of Object.entries(colorMap)) {\n if (lowerDomain.includes(key)) {\n return color;\n }\n }\n\n // 기본 색상 (해시 기반)\n let hash = 0;\n for (let i = 0; i < domain.length; i++) {\n hash = domain.charCodeAt(i) + ((hash << 5) - hash);\n }\n const hue = hash % 360;\n return `hsl(${hue}, 60%, 45%)`;\n};\n\nexport const LinkChip: React.FC<LinkChipProps> = ({\n text,\n url,\n showFavicon = true,\n index,\n style,\n}) => {\n const [isHovered, setIsHovered] = useState(false);\n const domain = getDomain(url);\n const shortName = getShortName(domain);\n const domainColor = getDomainColor(domain);\n\n // 텍스트에서 번호 추출 (예: \"1. brave\" -> { number: 1, label: \"brave\" })\n const parseText = (t: string): { number?: string; label: string } => {\n const match = t.match(/^(\\d+)\\.\\s*(.+)$/);\n if (match) {\n return { number: match[1], label: match[2] };\n }\n return { label: t };\n };\n\n const parsed = parseText(text);\n const displayNumber = index !== undefined ? String(index + 1) : parsed.number;\n const displayLabel = parsed.label;\n\n return (\n <a\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: '6px',\n padding: '4px 10px',\n backgroundColor: isHovered\n ? 'var(--chatllm-chip-bg-hover, #e2e8f0)'\n : 'var(--chatllm-chip-bg, #f1f5f9)',\n border: '1px solid var(--chatllm-chip-border, #e2e8f0)',\n borderRadius: '16px',\n textDecoration: 'none',\n fontSize: '13px',\n fontWeight: 500,\n color: 'var(--chatllm-chip-text, #475569)',\n transition: 'all 0.15s ease',\n cursor: 'pointer',\n maxWidth: '180px',\n ...style,\n }}\n title={`${displayLabel} - ${domain}`}\n >\n {/* 번호 배지 */}\n {displayNumber && (\n <span\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '18px',\n height: '18px',\n borderRadius: '50%',\n backgroundColor: domainColor,\n color: '#ffffff',\n fontSize: '11px',\n fontWeight: 600,\n flexShrink: 0,\n }}\n >\n {displayNumber}\n </span>\n )}\n\n {/* 파비콘 또는 링크 아이콘 */}\n {showFavicon && !displayNumber && (\n <span\n style={{\n width: '16px',\n height: '16px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n }}\n >\n <IconSvg\n name=\"links-line\"\n size={14}\n color={domainColor}\n />\n </span>\n )}\n\n {/* 텍스트 */}\n <span\n style={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {displayLabel}\n </span>\n\n {/* 외부 링크 아이콘 */}\n <IconSvg\n name=\"external-link-line\"\n size={12}\n color=\"var(--chatllm-text-muted, #94a3b8)\"\n style={{\n opacity: isHovered ? 1 : 0.6,\n flexShrink: 0,\n }}\n />\n </a>\n );\n};\n\nexport default LinkChip;\n","/**\n * @description 빈 상태 컴포넌트\n * 대화가 없을 때 표시되는 시작 화면\n */\n\nimport React from 'react';\nimport { IconSvg, IconName } from './Icon';\nimport type { EmptyStateProps, ActionItem } from '../types';\n\nexport const EmptyState: React.FC<EmptyStateProps> = ({\n greeting,\n templates = [],\n onTemplateClick,\n actions = [],\n onActionSelect,\n}) => {\n const getActionIcon = (icon: string): IconName => {\n const iconMap: Record<string, IconName> = {\n search: 'search-line',\n image: 'image-line',\n code: 'code-s-slash-line',\n document: 'file-text-line',\n };\n return iconMap[icon] || 'sparkling-line';\n };\n\n return (\n <div\n className=\"chatllm-empty-state\"\n style={{\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '48px 24px',\n textAlign: 'center',\n }}\n >\n {/* Logo */}\n <div\n style={{\n width: '64px',\n height: '64px',\n borderRadius: '16px',\n background: 'linear-gradient(135deg, #3b82f6, #8b5cf6)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n marginBottom: '24px',\n boxShadow: '0 8px 32px rgba(59, 130, 246, 0.25)',\n }}\n >\n <IconSvg name=\"sparkling-line\" size={32} color=\"#ffffff\" />\n </div>\n\n {/* Greeting */}\n <h1\n style={{\n fontSize: '28px',\n fontWeight: 600,\n color: 'var(--chatllm-text, #1f2937)',\n marginBottom: '8px',\n }}\n >\n {greeting}\n </h1>\n <p\n style={{\n fontSize: '16px',\n color: 'var(--chatllm-text-muted, #6b7280)',\n marginBottom: '32px',\n }}\n >\n 무엇을 도와드릴까요?\n </p>\n\n {/* Actions Grid */}\n {actions.length > 0 && (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fit, minmax(140px, 1fr))',\n gap: '12px',\n width: '100%',\n maxWidth: '600px',\n marginBottom: '32px',\n }}\n >\n {actions.map((action) => (\n <button\n key={action.id}\n onClick={() => onActionSelect?.(action)}\n style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n gap: '12px',\n padding: '20px 16px',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '12px',\n cursor: 'pointer',\n transition: 'all 0.2s',\n }}\n onMouseOver={(e) => {\n e.currentTarget.style.borderColor = 'var(--chatllm-primary, #3b82f6)';\n e.currentTarget.style.boxShadow = '0 4px 12px rgba(59, 130, 246, 0.1)';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.borderColor = 'var(--chatllm-border, #e5e7eb)';\n e.currentTarget.style.boxShadow = 'none';\n }}\n >\n <div\n style={{\n width: '44px',\n height: '44px',\n borderRadius: '12px',\n backgroundColor: 'var(--chatllm-primary-light, #dbeafe)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <IconSvg\n name={getActionIcon(action.icon)}\n size={22}\n color=\"var(--chatllm-primary, #3b82f6)\"\n />\n </div>\n <div>\n <div\n style={{\n fontSize: '14px',\n fontWeight: 500,\n color: 'var(--chatllm-text, #1f2937)',\n }}\n >\n {action.label}\n </div>\n </div>\n </button>\n ))}\n </div>\n )}\n\n {/* Templates */}\n {templates.length > 0 && (\n <div style={{ width: '100%', maxWidth: '600px' }}>\n <h3\n style={{\n fontSize: '14px',\n fontWeight: 500,\n color: 'var(--chatllm-text-muted, #6b7280)',\n marginBottom: '12px',\n textAlign: 'left',\n }}\n >\n 추천 프롬프트\n </h3>\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: '8px',\n }}\n >\n {templates.map((template) => (\n <button\n key={template.id}\n onClick={() => onTemplateClick(template)}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '12px',\n padding: '14px 16px',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '10px',\n cursor: 'pointer',\n textAlign: 'left',\n transition: 'all 0.2s',\n }}\n onMouseOver={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg-hover, #f9fafb)';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg, #ffffff)';\n }}\n >\n <div\n style={{\n width: '36px',\n height: '36px',\n borderRadius: '8px',\n backgroundColor: 'var(--chatllm-bg-secondary, #f3f4f6)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n }}\n >\n <IconSvg name=\"file-text-line\" size={18} color=\"var(--chatllm-text-muted, #6b7280)\" />\n </div>\n <div style={{ flex: 1, minWidth: 0 }}>\n <div\n style={{\n fontSize: '14px',\n fontWeight: 500,\n color: 'var(--chatllm-text, #1f2937)',\n }}\n >\n {template.title}\n </div>\n <div\n style={{\n fontSize: '13px',\n color: 'var(--chatllm-text-muted, #9ca3af)',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {template.description}\n </div>\n </div>\n <IconSvg name=\"arrow-right-line\" size={16} color=\"var(--chatllm-text-muted, #9ca3af)\" />\n </button>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n};\n\nexport default EmptyState;\n","/**\n * @description 메모리 패널 컴포넌트\n * 저장된 메모리, 컨텍스트 요약, 학습된 정보 조회\n */\n\nimport React, { useState } from 'react';\nimport { IconSvg } from './Icon';\n\nexport interface MemoryItem {\n id: string;\n key: string;\n value: string;\n category?: 'context' | 'preference' | 'skill' | 'fact';\n timestamp: number;\n}\n\nexport interface MemoryPanelProps {\n /** 메모리 아이템 목록 */\n items: MemoryItem[];\n /** 컨텍스트 요약 (압축된 대화) */\n contextSummary?: string;\n /** 삭제 핸들러 */\n onDelete?: (id: string) => void;\n /** 전체 삭제 핸들러 */\n onClearAll?: () => void;\n /** 패널 열림 상태 */\n isOpen: boolean;\n /** 패널 토글 */\n onToggle: () => void;\n}\n\nconst categoryLabels: Record<string, string> = {\n context: '대화 컨텍스트',\n preference: '사용자 선호',\n skill: '학습된 스킬',\n fact: '저장된 정보',\n};\n\nconst categoryColors: Record<string, string> = {\n context: '#3b82f6',\n preference: '#8b5cf6',\n skill: '#10b981',\n fact: '#f59e0b',\n};\n\nexport const MemoryPanel: React.FC<MemoryPanelProps> = ({\n items,\n contextSummary,\n onDelete,\n onClearAll,\n isOpen,\n onToggle,\n}) => {\n const [expandedId, setExpandedId] = useState<string | null>(null);\n const [activeTab, setActiveTab] = useState<'all' | 'context' | 'preference' | 'skill' | 'fact'>('all');\n\n const filteredItems = activeTab === 'all'\n ? items\n : items.filter(item => item.category === activeTab);\n\n const formatDate = (timestamp: number): string => {\n const date = new Date(timestamp);\n return date.toLocaleDateString('ko-KR', {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n };\n\n if (!isOpen) {\n return (\n <button\n onClick={onToggle}\n style={{\n position: 'fixed',\n right: '16px',\n bottom: '100px',\n width: '48px',\n height: '48px',\n borderRadius: '50%',\n backgroundColor: 'var(--chatllm-primary, #3b82f6)',\n border: 'none',\n boxShadow: '0 4px 12px rgba(59, 130, 246, 0.3)',\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex: 100,\n }}\n >\n <IconSvg name=\"robot-line\" size={24} color=\"#ffffff\" />\n </button>\n );\n }\n\n return (\n <div\n className=\"chatllm-memory-panel\"\n style={{\n position: 'fixed',\n right: '16px',\n bottom: '16px',\n width: '380px',\n maxHeight: '70vh',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n borderRadius: '16px',\n boxShadow: '0 8px 32px rgba(0, 0, 0, 0.12)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n display: 'flex',\n flexDirection: 'column',\n overflow: 'hidden',\n zIndex: 100,\n }}\n >\n {/* Header */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '16px',\n borderBottom: '1px solid var(--chatllm-border, #e5e7eb)',\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>\n <div\n style={{\n width: '32px',\n height: '32px',\n borderRadius: '8px',\n backgroundColor: 'var(--chatllm-primary-light, #dbeafe)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <IconSvg name=\"robot-line\" size={18} color=\"var(--chatllm-primary, #3b82f6)\" />\n </div>\n <div>\n <div style={{ fontSize: '15px', fontWeight: 600, color: 'var(--chatllm-text, #1f2937)' }}>\n AI 메모리\n </div>\n <div style={{ fontSize: '12px', color: 'var(--chatllm-text-muted, #9ca3af)' }}>\n {items.length}개 항목\n </div>\n </div>\n </div>\n <div style={{ display: 'flex', gap: '4px' }}>\n {onClearAll && items.length > 0 && (\n <button\n onClick={onClearAll}\n style={{\n padding: '8px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '8px',\n cursor: 'pointer',\n }}\n title=\"전체 삭제\"\n >\n <IconSvg name=\"delete-bin-line\" size={18} color=\"var(--chatllm-text-muted, #9ca3af)\" />\n </button>\n )}\n <button\n onClick={onToggle}\n style={{\n padding: '8px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '8px',\n cursor: 'pointer',\n }}\n >\n <IconSvg name=\"close-line\" size={18} color=\"var(--chatllm-text-muted, #9ca3af)\" />\n </button>\n </div>\n </div>\n\n {/* Tabs */}\n <div\n style={{\n display: 'flex',\n gap: '4px',\n padding: '12px 16px',\n borderBottom: '1px solid var(--chatllm-border-light, #f3f4f6)',\n overflowX: 'auto',\n }}\n >\n {(['all', 'context', 'preference', 'skill', 'fact'] as const).map((tab) => (\n <button\n key={tab}\n onClick={() => setActiveTab(tab)}\n style={{\n padding: '6px 12px',\n fontSize: '13px',\n fontWeight: activeTab === tab ? 500 : 400,\n backgroundColor: activeTab === tab\n ? 'var(--chatllm-primary-light, #dbeafe)'\n : 'transparent',\n color: activeTab === tab\n ? 'var(--chatllm-primary, #3b82f6)'\n : 'var(--chatllm-text-muted, #6b7280)',\n border: 'none',\n borderRadius: '6px',\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n }}\n >\n {tab === 'all' ? '전체' : categoryLabels[tab]}\n </button>\n ))}\n </div>\n\n {/* Content */}\n <div style={{ flex: 1, overflow: 'auto', padding: '12px' }}>\n {/* Context Summary */}\n {contextSummary && activeTab === 'all' && (\n <div\n style={{\n padding: '12px',\n marginBottom: '12px',\n backgroundColor: 'var(--chatllm-bg-secondary, #f9fafb)',\n borderRadius: '10px',\n borderLeft: '3px solid var(--chatllm-primary, #3b82f6)',\n }}\n >\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n marginBottom: '8px',\n }}\n >\n <IconSvg name=\"file-text-line\" size={14} color=\"var(--chatllm-primary, #3b82f6)\" />\n <span style={{ fontSize: '12px', fontWeight: 500, color: 'var(--chatllm-primary, #3b82f6)' }}>\n 대화 요약\n </span>\n </div>\n <p\n style={{\n fontSize: '13px',\n lineHeight: '1.6',\n color: 'var(--chatllm-text, #374151)',\n margin: 0,\n }}\n >\n {contextSummary}\n </p>\n </div>\n )}\n\n {/* Memory Items */}\n {filteredItems.length === 0 ? (\n <div\n style={{\n padding: '32px 16px',\n textAlign: 'center',\n color: 'var(--chatllm-text-muted, #9ca3af)',\n }}\n >\n <IconSvg name=\"robot-line\" size={32} color=\"var(--chatllm-text-muted, #d1d5db)\" />\n <p style={{ fontSize: '14px', marginTop: '12px' }}>저장된 메모리가 없습니다</p>\n </div>\n ) : (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n {filteredItems.map((item) => (\n <div\n key={item.id}\n style={{\n padding: '12px',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '10px',\n cursor: 'pointer',\n transition: 'all 0.2s',\n }}\n onClick={() => setExpandedId(expandedId === item.id ? null : item.id)}\n >\n {/* Item Header */}\n <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between' }}>\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '4px' }}>\n {item.category && (\n <span\n style={{\n fontSize: '11px',\n fontWeight: 500,\n padding: '2px 8px',\n backgroundColor: `${categoryColors[item.category]}15`,\n color: categoryColors[item.category],\n borderRadius: '4px',\n }}\n >\n {categoryLabels[item.category]}\n </span>\n )}\n <span style={{ fontSize: '11px', color: 'var(--chatllm-text-muted, #9ca3af)' }}>\n {formatDate(item.timestamp)}\n </span>\n </div>\n <div\n style={{\n fontSize: '13px',\n fontWeight: 500,\n color: 'var(--chatllm-text, #1f2937)',\n }}\n >\n {item.key}\n </div>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>\n {onDelete && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n onDelete(item.id);\n }}\n style={{\n padding: '4px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n opacity: 0.5,\n }}\n >\n <IconSvg name=\"delete-bin-line\" size={14} color=\"var(--chatllm-text-muted, #9ca3af)\" />\n </button>\n )}\n <IconSvg\n name={expandedId === item.id ? 'arrow-up-s-line' : 'arrow-down-s-line'}\n size={16}\n color=\"var(--chatllm-text-muted, #9ca3af)\"\n />\n </div>\n </div>\n\n {/* Expanded Content */}\n {expandedId === item.id && (\n <div\n style={{\n marginTop: '12px',\n paddingTop: '12px',\n borderTop: '1px solid var(--chatllm-border-light, #f3f4f6)',\n }}\n >\n <p\n style={{\n fontSize: '13px',\n lineHeight: '1.6',\n color: 'var(--chatllm-text, #374151)',\n margin: 0,\n whiteSpace: 'pre-wrap',\n }}\n >\n {item.value}\n </p>\n </div>\n )}\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default MemoryPanel;\n","/**\n * @description 설정 모달 컴포넌트\n * 일반/개인화/데이터 설정 탭 포함\n */\n\nimport React, { useState } from 'react';\nimport { IconSvg } from './Icon';\nimport type { PersonalizationConfig, SettingsTab } from '../types';\n\nexport interface SettingsModalProps {\n /** 모달 열림 상태 */\n isOpen: boolean;\n /** 모달 닫기 핸들러 */\n onClose: () => void;\n /** 개인화 설정 */\n personalization: PersonalizationConfig;\n /** 개인화 설정 변경 핸들러 */\n onPersonalizationChange: (config: PersonalizationConfig) => void;\n /** API 키 */\n apiKey?: string;\n /** API 키 변경 핸들러 */\n onApiKeyChange?: (key: string) => void;\n /** 전체 데이터 삭제 핸들러 */\n onClearAllData?: () => void;\n /** API 키 레이블 */\n apiKeyLabel?: string;\n /** API 키 설명 */\n apiKeyDescription?: string;\n}\n\nconst DEFAULT_PERSONALIZATION: PersonalizationConfig = {\n responseStyle: {\n warmth: 'medium',\n enthusiasm: 'medium',\n emojiUsage: 'low',\n formatting: 'default',\n verbosity: 'balanced',\n },\n userProfile: {},\n useMemory: true,\n language: 'auto',\n};\n\nexport const SettingsModal: React.FC<SettingsModalProps> = ({\n isOpen,\n onClose,\n personalization,\n onPersonalizationChange,\n apiKey = '',\n onApiKeyChange,\n onClearAllData,\n apiKeyLabel = 'API Key',\n apiKeyDescription = 'Cloud 모델 사용에 필요합니다',\n}) => {\n const [activeTab, setActiveTab] = useState<SettingsTab>('general');\n const [localApiKey, setLocalApiKey] = useState(apiKey);\n\n if (!isOpen) return null;\n\n const updateResponseStyle = (key: string, value: string) => {\n onPersonalizationChange({\n ...personalization,\n responseStyle: {\n ...personalization.responseStyle,\n [key]: value,\n },\n });\n };\n\n const updateUserProfile = (key: string, value: string) => {\n onPersonalizationChange({\n ...personalization,\n userProfile: {\n ...personalization.userProfile,\n [key]: value,\n },\n });\n };\n\n const handleApiKeyChange = (value: string) => {\n setLocalApiKey(value);\n onApiKeyChange?.(value);\n };\n\n return (\n <div\n className=\"chatllm-settings-overlay\"\n style={{\n position: 'fixed',\n inset: 0,\n backgroundColor: 'rgba(0, 0, 0, 0.3)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex: 1000,\n }}\n onClick={onClose}\n >\n <div\n className=\"chatllm-settings-modal\"\n style={{\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n borderRadius: '16px',\n width: '100%',\n maxWidth: '800px',\n height: '80vh',\n maxHeight: '600px',\n margin: '16px',\n boxShadow: '0 20px 60px rgba(0, 0, 0, 0.15)',\n display: 'flex',\n overflow: 'hidden',\n }}\n onClick={(e) => e.stopPropagation()}\n >\n {/* Sidebar */}\n <div\n style={{\n width: '200px',\n backgroundColor: 'var(--chatllm-bg-secondary, #f9fafb)',\n borderRight: '1px solid var(--chatllm-border, #e5e7eb)',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n {/* Close Button */}\n <div style={{ padding: '16px', borderBottom: '1px solid var(--chatllm-border, #e5e7eb)' }}>\n <button\n onClick={onClose}\n style={{\n padding: '8px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '8px',\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <IconSvg name=\"close-line\" size={20} color=\"var(--chatllm-text-muted, #6b7280)\" />\n </button>\n </div>\n\n {/* Tabs */}\n <nav style={{ flex: 1, padding: '8px' }}>\n <TabButton\n active={activeTab === 'general'}\n onClick={() => setActiveTab('general')}\n icon=\"settings-3-line\"\n label=\"일반\"\n />\n <TabButton\n active={activeTab === 'personalization'}\n onClick={() => setActiveTab('personalization')}\n icon=\"user-3-line\"\n label=\"개인 맞춤 설정\"\n />\n <TabButton\n active={activeTab === 'data'}\n onClick={() => setActiveTab('data')}\n icon=\"delete-bin-line\"\n label=\"데이터 제어\"\n />\n </nav>\n </div>\n\n {/* Content */}\n <div style={{ flex: 1, overflow: 'auto', padding: '24px' }}>\n {activeTab === 'general' && (\n <div>\n <h2 style={{ fontSize: '20px', fontWeight: 600, marginBottom: '24px', color: 'var(--chatllm-text, #1f2937)' }}>\n 일반\n </h2>\n\n {/* Language */}\n <SettingRow label=\"언어\">\n <select\n value={personalization.language}\n onChange={(e) => onPersonalizationChange({ ...personalization, language: e.target.value })}\n style={selectStyle}\n >\n <option value=\"auto\">자동 탐지</option>\n <option value=\"ko\">한국어</option>\n <option value=\"en\">English</option>\n <option value=\"ja\">日本語</option>\n </select>\n </SettingRow>\n\n {/* Reset */}\n <SettingRow label=\"기본값으로 초기화\" description=\"모든 설정을 초기 상태로 되돌립니다\">\n <button\n onClick={() => onPersonalizationChange(DEFAULT_PERSONALIZATION)}\n style={buttonSecondaryStyle}\n >\n 초기화\n </button>\n </SettingRow>\n\n {/* API Key */}\n {onApiKeyChange && (\n <div style={{ marginTop: '32px', paddingTop: '24px', borderTop: '1px solid var(--chatllm-border, #e5e7eb)' }}>\n <h3 style={{ fontSize: '16px', fontWeight: 500, marginBottom: '16px', color: 'var(--chatllm-text, #1f2937)' }}>\n API 설정\n </h3>\n <div>\n <label style={{ display: 'block', fontSize: '14px', marginBottom: '8px', color: 'var(--chatllm-text, #374151)' }}>\n {apiKeyLabel}\n </label>\n <input\n type=\"password\"\n value={localApiKey}\n onChange={(e) => handleApiKeyChange(e.target.value)}\n placeholder=\"API 키를 입력하세요\"\n style={inputStyle}\n />\n <p style={{ fontSize: '12px', color: 'var(--chatllm-text-muted, #9ca3af)', marginTop: '4px' }}>\n {apiKeyDescription}\n </p>\n </div>\n </div>\n )}\n </div>\n )}\n\n {activeTab === 'personalization' && (\n <div>\n <h2 style={{ fontSize: '20px', fontWeight: 600, marginBottom: '24px', color: 'var(--chatllm-text, #1f2937)' }}>\n 개인 맞춤 설정\n </h2>\n\n {/* User Profile */}\n <section style={{ marginBottom: '32px' }}>\n <h3 style={{ fontSize: '14px', fontWeight: 500, color: 'var(--chatllm-text-muted, #6b7280)', marginBottom: '16px' }}>\n 사용자 프로필\n </h3>\n <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <div>\n <label style={labelStyle}>닉네임</label>\n <input\n type=\"text\"\n value={personalization.userProfile.nickname || ''}\n onChange={(e) => updateUserProfile('nickname', e.target.value)}\n placeholder=\"어떻게 불러드릴까요?\"\n style={inputStyle}\n />\n </div>\n <div>\n <label style={labelStyle}>직업</label>\n <input\n type=\"text\"\n value={personalization.userProfile.occupation || ''}\n onChange={(e) => updateUserProfile('occupation', e.target.value)}\n placeholder=\"예: 소프트웨어 개발자\"\n style={inputStyle}\n />\n </div>\n <div>\n <label style={labelStyle}>추가 정보</label>\n <textarea\n value={personalization.userProfile.additionalInfo || ''}\n onChange={(e) => updateUserProfile('additionalInfo', e.target.value)}\n placeholder=\"관심사, 선호 사항 등\"\n rows={3}\n style={{ ...inputStyle, resize: 'none' }}\n />\n </div>\n </div>\n </section>\n\n {/* Response Style */}\n <section>\n <h3 style={{ fontSize: '14px', fontWeight: 500, color: 'var(--chatllm-text-muted, #6b7280)', marginBottom: '16px' }}>\n 응답 스타일\n </h3>\n\n <SettingRow label=\"따뜻함\">\n <select\n value={personalization.responseStyle.warmth}\n onChange={(e) => updateResponseStyle('warmth', e.target.value)}\n style={selectStyle}\n >\n <option value=\"high\">높음 - 친근하고 따뜻하게</option>\n <option value=\"medium\">기본값</option>\n <option value=\"low\">낮음 - 간결하고 사무적으로</option>\n </select>\n </SettingRow>\n\n <SettingRow label=\"열정적\">\n <select\n value={personalization.responseStyle.enthusiasm}\n onChange={(e) => updateResponseStyle('enthusiasm', e.target.value)}\n style={selectStyle}\n >\n <option value=\"high\">높음 - 적극적이고 활발하게</option>\n <option value=\"medium\">기본값</option>\n <option value=\"low\">낮음 - 차분하고 절제있게</option>\n </select>\n </SettingRow>\n\n <SettingRow label=\"이모지 사용\">\n <select\n value={personalization.responseStyle.emojiUsage}\n onChange={(e) => updateResponseStyle('emojiUsage', e.target.value)}\n style={selectStyle}\n >\n <option value=\"high\">높음 - 자주 사용</option>\n <option value=\"medium\">기본값</option>\n <option value=\"low\">낮음 - 거의 사용 안 함</option>\n </select>\n </SettingRow>\n\n <SettingRow label=\"응답 길이\">\n <select\n value={personalization.responseStyle.verbosity}\n onChange={(e) => updateResponseStyle('verbosity', e.target.value)}\n style={selectStyle}\n >\n <option value=\"detailed\">상세 - 자세하게 설명</option>\n <option value=\"balanced\">기본값</option>\n <option value=\"concise\">간결 - 핵심만 요약</option>\n </select>\n </SettingRow>\n </section>\n </div>\n )}\n\n {activeTab === 'data' && (\n <div>\n <h2 style={{ fontSize: '20px', fontWeight: 600, marginBottom: '24px', color: 'var(--chatllm-text, #1f2937)' }}>\n 데이터 제어\n </h2>\n\n {/* Memory Toggle */}\n <SettingRow label=\"메모리 사용\" description=\"대화 컨텍스트를 기억합니다\">\n <button\n onClick={() => onPersonalizationChange({ ...personalization, useMemory: !personalization.useMemory })}\n style={{\n width: '48px',\n height: '28px',\n borderRadius: '14px',\n backgroundColor: personalization.useMemory\n ? 'var(--chatllm-primary, #3b82f6)'\n : 'var(--chatllm-text-muted, #d1d5db)',\n border: 'none',\n cursor: 'pointer',\n position: 'relative',\n transition: 'background-color 0.2s',\n }}\n >\n <div\n style={{\n width: '22px',\n height: '22px',\n borderRadius: '50%',\n backgroundColor: '#ffffff',\n boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)',\n position: 'absolute',\n top: '3px',\n left: personalization.useMemory ? '23px' : '3px',\n transition: 'left 0.2s',\n }}\n />\n </button>\n </SettingRow>\n\n {/* Clear All Data */}\n {onClearAllData && (\n <SettingRow label=\"대화 기록 삭제\" description=\"모든 대화 기록을 삭제합니다\">\n <button\n onClick={() => {\n if (window.confirm('모든 대화 기록을 삭제하시겠습니까?')) {\n onClearAllData();\n }\n }}\n style={buttonDangerStyle}\n >\n 삭제\n </button>\n </SettingRow>\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n );\n};\n\n// Tab Button Component\nconst TabButton: React.FC<{\n active: boolean;\n onClick: () => void;\n icon: string;\n label: string;\n}> = ({ active, onClick, icon, label }) => (\n <button\n onClick={onClick}\n style={{\n width: '100%',\n display: 'flex',\n alignItems: 'center',\n gap: '12px',\n padding: '10px 12px',\n borderRadius: '10px',\n border: 'none',\n backgroundColor: active ? 'var(--chatllm-bg, #ffffff)' : 'transparent',\n boxShadow: active ? '0 1px 3px rgba(0, 0, 0, 0.08)' : 'none',\n color: active ? 'var(--chatllm-primary, #3b82f6)' : 'var(--chatllm-text-muted, #6b7280)',\n fontSize: '14px',\n cursor: 'pointer',\n textAlign: 'left',\n marginBottom: '4px',\n }}\n >\n <IconSvg name={icon as any} size={20} />\n {label}\n </button>\n);\n\n// Setting Row Component\nconst SettingRow: React.FC<{\n label: string;\n description?: string;\n children: React.ReactNode;\n}> = ({ label, description, children }) => (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '12px 0',\n borderBottom: '1px solid var(--chatllm-border-light, #f3f4f6)',\n }}\n >\n <div>\n <span style={{ fontSize: '14px', color: 'var(--chatllm-text, #374151)' }}>{label}</span>\n {description && (\n <p style={{ fontSize: '12px', color: 'var(--chatllm-text-muted, #9ca3af)', marginTop: '2px' }}>\n {description}\n </p>\n )}\n </div>\n {children}\n </div>\n);\n\n// Styles\nconst selectStyle: React.CSSProperties = {\n padding: '8px 12px',\n backgroundColor: 'var(--chatllm-bg-secondary, #f9fafb)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '8px',\n fontSize: '14px',\n color: 'var(--chatllm-text, #374151)',\n minWidth: '200px',\n cursor: 'pointer',\n};\n\nconst inputStyle: React.CSSProperties = {\n width: '100%',\n padding: '10px 12px',\n backgroundColor: 'var(--chatllm-bg-secondary, #f9fafb)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '8px',\n fontSize: '14px',\n color: 'var(--chatllm-text, #374151)',\n};\n\nconst labelStyle: React.CSSProperties = {\n display: 'block',\n fontSize: '12px',\n color: 'var(--chatllm-text-muted, #6b7280)',\n marginBottom: '6px',\n};\n\nconst buttonSecondaryStyle: React.CSSProperties = {\n padding: '8px 16px',\n backgroundColor: 'var(--chatllm-bg-secondary, #f3f4f6)',\n border: 'none',\n borderRadius: '8px',\n fontSize: '14px',\n color: 'var(--chatllm-text, #374151)',\n cursor: 'pointer',\n};\n\nconst buttonDangerStyle: React.CSSProperties = {\n padding: '8px 16px',\n backgroundColor: 'var(--chatllm-danger-bg, #fef2f2)',\n border: 'none',\n borderRadius: '8px',\n fontSize: '14px',\n color: 'var(--chatllm-danger, #dc2626)',\n cursor: 'pointer',\n};\n\nexport default SettingsModal;\n"],"mappings":"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","names":["import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_react","import_react","import_react","import_jsx_runtime","import_jsx_runtime","React","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","formatDate","import_react","import_jsx_runtime","DEFAULT_PERSONALIZATION","import_jsx_runtime","React"]}
1
+ {"version":3,"sources":["../../src/react/index.ts","../../src/react/ChatUI.tsx","../../src/react/hooks/useChatUI.ts","../../src/types.ts","../../src/react/components/Icon.tsx","../../src/react/components/ChatSidebar.tsx","../../src/react/components/ChatHeader.tsx","../../src/react/components/ChatInput.tsx","../../src/react/components/MessageList.tsx","../../src/react/components/MessageBubble.tsx","../../src/react/components/MarkdownRenderer.tsx","../../src/react/components/LinkChip.tsx","../../src/react/components/EmptyState.tsx","../../src/react/components/MemoryPanel.tsx","../../src/react/components/SettingsModal.tsx"],"sourcesContent":["/**\n * @description @gendive/chatllm/react - React UI 컴포넌트 패키지\n */\n\n// Main Component\nexport { ChatUI } from './ChatUI';\nexport type { ChatUIProps } from './types';\n\n// Headless Hook\nexport { useChatUI } from './hooks/useChatUI';\nexport type { UseChatUIOptions } from './hooks/useChatUI';\n\n// UseChatUIReturn is exported from types\n\n// Sub-components\nexport {\n Icon,\n IconSvg,\n ChatSidebar,\n ChatInput,\n ChatHeader,\n MessageBubble,\n MessageList,\n EmptyState,\n MemoryPanel,\n // Markdown & Link components\n MarkdownRenderer,\n LinkChip,\n // Settings\n SettingsModal,\n} from './components';\n\nexport type {\n MemoryItem,\n MemoryPanelProps,\n MarkdownRendererProps,\n LinkChipProps,\n SettingsModalProps,\n} from './components';\n\n// Types\nexport type {\n // Message Types\n ChatMessage,\n ChatSession,\n AlternativeResponse,\n // Action Types\n ActionItem,\n // Model Types\n ModelConfig,\n ProviderType,\n // Template Types\n PromptTemplate,\n // Settings Types\n SettingsTab,\n // Theme Types\n ThemeMode,\n ThemeConfig,\n // Component Props\n SendMessageParams,\n ChatUIComponents,\n SidebarProps,\n MessageListProps,\n MessageBubbleProps,\n InputProps,\n HeaderProps,\n EmptyStateProps,\n ActionMenuProps,\n ModelSelectorProps,\n // Personalization (re-export)\n PersonalizationConfig,\n ResponseStyle,\n UserProfile,\n // Hook return type\n UseChatUIReturn,\n} from './types';\n\nexport type { IconName, IconProps } from './components/Icon';\n","/**\n * @description ChatUI 메인 컴포넌트\n * 풀 기능 채팅 UI\n */\n\nimport React, { useState } from 'react';\nimport { useChatUI, UseChatUIOptions } from './hooks/useChatUI';\nimport { ChatSidebar } from './components/ChatSidebar';\nimport { ChatHeader } from './components/ChatHeader';\nimport { ChatInput } from './components/ChatInput';\nimport { MessageList } from './components/MessageList';\nimport { EmptyState } from './components/EmptyState';\nimport { MemoryPanel, MemoryItem } from './components/MemoryPanel';\nimport { SettingsModal } from './components/SettingsModal';\nimport type { ChatUIProps, ActionItem, PromptTemplate } from './types';\n\n// ============================================================================\n// Default Actions\n// ============================================================================\n\nconst DEFAULT_ACTIONS: ActionItem[] = [\n {\n id: 'webSearch',\n label: '웹 검색',\n icon: 'search',\n description: '웹에서 정보를 검색합니다',\n systemPrompt: '웹 검색 결과를 기반으로 답변해주세요.',\n },\n {\n id: 'imageGen',\n label: '이미지 생성',\n icon: 'image',\n description: '프롬프트로 이미지를 생성합니다',\n systemPrompt: '이미지 생성 요청입니다.',\n },\n {\n id: 'codeAnalysis',\n label: '코드 분석',\n icon: 'code',\n description: '코드를 분석하고 설명합니다',\n systemPrompt: '코드를 분석하고 자세히 설명해주세요.',\n },\n {\n id: 'summarize',\n label: '요약',\n icon: 'document',\n description: '긴 텍스트를 요약합니다',\n systemPrompt: '다음 내용을 핵심만 간결하게 요약해주세요.',\n },\n];\n\n// ============================================================================\n// Default Templates\n// ============================================================================\n\nconst DEFAULT_TEMPLATES: PromptTemplate[] = [\n {\n id: '1',\n title: 'AI 기반 글쓰기',\n description: '블로그, 이메일, 보고서 작성 도움',\n prompt: '다음 주제에 대해 블로그 글을 작성해주세요: ',\n category: '글쓰기',\n },\n {\n id: '2',\n title: '코드 리뷰',\n description: '코드 분석 및 개선점 제안',\n prompt: '다음 코드를 리뷰하고 개선점을 제안해주세요: ',\n category: '개발',\n },\n {\n id: '3',\n title: '번역 도우미',\n description: '자연스러운 번역 및 교정',\n prompt: '다음 텍스트를 자연스럽게 번역해주세요: ',\n category: '번역',\n },\n {\n id: '4',\n title: '요약 정리',\n description: '긴 문서를 핵심만 요약',\n prompt: '다음 내용을 핵심만 요약해주세요: ',\n category: '정리',\n },\n];\n\n// ============================================================================\n// CSS Styles (injected)\n// ============================================================================\n\nconst injectStyles = () => {\n if (typeof document === 'undefined') return;\n\n const styleId = 'chatllm-styles';\n if (document.getElementById(styleId)) return;\n\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = `\n @keyframes chatllm-typing {\n 0%, 80%, 100% {\n transform: scale(0);\n opacity: 0.5;\n }\n 40% {\n transform: scale(1);\n opacity: 1;\n }\n }\n\n .chatllm-root {\n --chatllm-primary: #3b82f6;\n --chatllm-primary-hover: #2563eb;\n --chatllm-primary-light: #dbeafe;\n --chatllm-bg: #ffffff;\n --chatllm-bg-secondary: #f9fafb;\n --chatllm-bg-tertiary: #f3f4f6;\n --chatllm-bg-hover: #f3f4f6;\n --chatllm-bg-active: #eff6ff;\n --chatllm-bg-disabled: #e5e7eb;\n --chatllm-sidebar-bg: #ffffff;\n --chatllm-input-bg: #f9fafb;\n --chatllm-text: #1f2937;\n --chatllm-text-muted: #6b7280;\n --chatllm-border: #e5e7eb;\n --chatllm-border-light: #f3f4f6;\n --chatllm-error: #ef4444;\n --chatllm-success: #22c55e;\n --chatllm-user-avatar: #e5e7eb;\n --chatllm-assistant-avatar: #dbeafe;\n }\n\n .chatllm-root.chatllm-dark {\n --chatllm-primary: #60a5fa;\n --chatllm-primary-hover: #3b82f6;\n --chatllm-primary-light: #1e3a5f;\n --chatllm-bg: #111827;\n --chatllm-bg-secondary: #1f2937;\n --chatllm-bg-tertiary: #374151;\n --chatllm-bg-hover: #374151;\n --chatllm-bg-active: #1e3a5f;\n --chatllm-bg-disabled: #374151;\n --chatllm-sidebar-bg: #111827;\n --chatllm-input-bg: #1f2937;\n --chatllm-text: #f9fafb;\n --chatllm-text-muted: #9ca3af;\n --chatllm-border: #374151;\n --chatllm-border-light: #1f2937;\n --chatllm-user-avatar: #374151;\n --chatllm-assistant-avatar: #1e3a5f;\n }\n\n .chatllm-root * {\n box-sizing: border-box;\n }\n\n .chatllm-root textarea::placeholder {\n color: var(--chatllm-text-muted);\n }\n\n .chatllm-root button:focus-visible {\n outline: 2px solid var(--chatllm-primary);\n outline-offset: 2px;\n }\n\n .chatllm-message-list::-webkit-scrollbar {\n width: 6px;\n }\n\n .chatllm-message-list::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .chatllm-message-list::-webkit-scrollbar-thumb {\n background-color: var(--chatllm-border);\n border-radius: 3px;\n }\n `;\n\n document.head.appendChild(style);\n};\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport const ChatUI: React.FC<ChatUIProps> = ({\n models,\n actions = DEFAULT_ACTIONS,\n templates = DEFAULT_TEMPLATES,\n personalization,\n apiKey,\n onApiKeyChange,\n apiEndpoint = '/api/chat',\n theme,\n showSidebar = true,\n showSettings = true,\n showModelSelector = true,\n systemPrompt,\n contextCompressionThreshold = 20,\n keepRecentMessages = 6,\n storageKey = 'chatllm_sessions',\n className = '',\n onSendMessage,\n onSessionChange,\n onError,\n}) => {\n // Inject styles on mount\n React.useEffect(() => {\n injectStyles();\n }, []);\n\n // Initialize hook\n const hookOptions: UseChatUIOptions = {\n models,\n actions,\n initialPersonalization: personalization,\n apiKey,\n apiEndpoint,\n initialModel: models[0]?.id,\n storageKey,\n contextCompressionThreshold,\n keepRecentMessages,\n onSendMessage,\n onSessionChange,\n onError,\n };\n\n const {\n sessions,\n currentSession,\n currentSessionId,\n messages,\n input,\n isLoading,\n selectedModel,\n sidebarOpen,\n settingsOpen,\n quotedText,\n selectedAction,\n copiedMessageId,\n editingMessageId,\n personalization: currentPersonalization,\n setInput,\n sendMessage,\n stopGeneration,\n newSession,\n selectSession,\n deleteSession,\n setModel,\n toggleSidebar,\n openSettings,\n closeSettings,\n setQuotedText,\n setSelectedAction,\n copyMessage,\n startEdit,\n cancelEdit,\n saveEdit,\n regenerate,\n askOtherModel,\n updatePersonalization,\n models: hookModels,\n } = useChatUI(hookOptions);\n\n // Generate greeting\n const greeting = currentPersonalization.userProfile.nickname\n ? `안녕하세요, ${currentPersonalization.userProfile.nickname}님`\n : '안녕하세요';\n\n // Handle template click\n const handleTemplateClick = (template: PromptTemplate) => {\n setInput(template.prompt);\n };\n\n // Handle action select from empty state\n const handleActionSelect = (action: ActionItem) => {\n setSelectedAction(action);\n };\n\n // Handle submit\n const handleSubmit = () => {\n sendMessage();\n };\n\n // Memory panel state\n const [memoryPanelOpen, setMemoryPanelOpen] = useState(false);\n\n // Build memory items from session context\n const memoryItems: MemoryItem[] = React.useMemo(() => {\n const items: MemoryItem[] = [];\n\n // Add context summary as memory item if exists\n if (currentSession?.contextSummary) {\n items.push({\n id: 'context_summary',\n key: '대화 컨텍스트 요약',\n value: currentSession.contextSummary,\n category: 'context',\n timestamp: currentSession.updatedAt,\n });\n }\n\n // Add personalization as preference items\n if (currentPersonalization.userProfile.nickname) {\n items.push({\n id: 'pref_nickname',\n key: '사용자 닉네임',\n value: currentPersonalization.userProfile.nickname,\n category: 'preference',\n timestamp: Date.now(),\n });\n }\n if (currentPersonalization.userProfile.occupation) {\n items.push({\n id: 'pref_occupation',\n key: '직업/역할',\n value: currentPersonalization.userProfile.occupation,\n category: 'preference',\n timestamp: Date.now(),\n });\n }\n if (currentPersonalization.userProfile.additionalInfo) {\n items.push({\n id: 'pref_info',\n key: '추가 정보',\n value: currentPersonalization.userProfile.additionalInfo,\n category: 'preference',\n timestamp: Date.now(),\n });\n }\n\n return items;\n }, [currentSession, currentPersonalization]);\n\n // Theme class\n const themeClass = theme?.mode === 'dark' ? 'chatllm-dark' : '';\n\n return (\n <div\n className={`chatllm-root ${themeClass} ${className}`}\n style={{\n display: 'flex',\n height: '100%',\n backgroundColor: 'var(--chatllm-bg-secondary)',\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif',\n }}\n >\n {/* Sidebar */}\n {showSidebar && (\n <ChatSidebar\n sessions={sessions}\n currentSessionId={currentSessionId}\n onSelectSession={selectSession}\n onNewSession={newSession}\n onDeleteSession={deleteSession}\n isOpen={sidebarOpen}\n onToggle={toggleSidebar}\n />\n )}\n\n {/* Main Content */}\n <main\n style={{\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n backgroundColor: 'var(--chatllm-bg)',\n minWidth: 0,\n }}\n >\n {/* Header */}\n <ChatHeader\n title={currentSession?.title || '새 대화'}\n model={selectedModel}\n models={models}\n onModelChange={setModel}\n onSettingsOpen={openSettings}\n onSidebarToggle={toggleSidebar}\n sidebarOpen={sidebarOpen}\n />\n\n {/* Messages or Empty State */}\n {messages.length === 0 ? (\n <EmptyState\n greeting={greeting}\n templates={templates}\n onTemplateClick={handleTemplateClick}\n actions={actions}\n onActionSelect={handleActionSelect}\n />\n ) : (\n <MessageList\n messages={messages}\n isLoading={isLoading}\n onCopy={copyMessage}\n onEdit={startEdit}\n onRegenerate={regenerate}\n onQuote={setQuotedText}\n onAskOtherModel={askOtherModel}\n models={hookModels}\n copiedId={copiedMessageId}\n editingId={editingMessageId}\n />\n )}\n\n {/* Input */}\n <ChatInput\n value={input}\n onChange={setInput}\n onSubmit={handleSubmit}\n onStop={stopGeneration}\n isLoading={isLoading}\n placeholder=\"메시지를 입력하세요...\"\n quotedText={quotedText}\n onClearQuote={() => setQuotedText(null)}\n selectedAction={selectedAction}\n onClearAction={() => setSelectedAction(null)}\n onActionSelect={setSelectedAction}\n actions={actions}\n />\n </main>\n\n {/* Memory Panel */}\n <MemoryPanel\n items={memoryItems}\n contextSummary={currentSession?.contextSummary}\n isOpen={memoryPanelOpen}\n onToggle={() => setMemoryPanelOpen(!memoryPanelOpen)}\n />\n\n {/* Settings Modal */}\n {showSettings && (\n <SettingsModal\n isOpen={settingsOpen}\n onClose={closeSettings}\n personalization={currentPersonalization}\n onPersonalizationChange={updatePersonalization}\n apiKey={apiKey}\n onApiKeyChange={onApiKeyChange}\n onClearAllData={() => {\n // 세션 전체 삭제\n sessions.forEach((s) => deleteSession(s.id));\n }}\n apiKeyLabel=\"API Key\"\n apiKeyDescription=\"Cloud 모델 사용에 필요합니다\"\n />\n )}\n </div>\n );\n};\n\nexport default ChatUI;\n","/**\n * @description Headless Chat UI Hook\n * 상태 관리와 로직만 제공, UI는 자유롭게 구현 가능\n */\n\nimport { useState, useRef, useCallback, useEffect } from 'react';\nimport type {\n ChatSession,\n ChatMessage,\n ActionItem,\n ModelConfig,\n PersonalizationConfig,\n UseChatUIReturn,\n SendMessageParams,\n ProviderType,\n} from '../types';\nimport { DEFAULT_PERSONALIZATION } from '../../types';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_STORAGE_KEY = 'chatllm_sessions';\nconst DEFAULT_PERSONALIZATION_KEY = 'chatllm_personalization';\nconst DEFAULT_COMPRESSION_THRESHOLD = 20;\nconst DEFAULT_KEEP_RECENT = 6;\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\nconst generateId = (prefix: string): string =>\n `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\nconst generateTitle = (messages: ChatMessage[]): string => {\n const firstUserMessage = messages.find((m) => m.role === 'user');\n if (!firstUserMessage) return '새 대화';\n const content = firstUserMessage.content;\n return content.length > 30 ? content.substring(0, 30) + '...' : content;\n};\n\n// ============================================================================\n// Hook Options\n// ============================================================================\n\nexport interface UseChatUIOptions {\n /** 사용 가능한 모델 목록 */\n models: ModelConfig[];\n /** 사용 가능한 Actions */\n actions?: ActionItem[];\n /** 초기 개인화 설정 */\n initialPersonalization?: Partial<PersonalizationConfig>;\n /** API 키 */\n apiKey?: string;\n /** API 엔드포인트 */\n apiEndpoint?: string;\n /** 초기 모델 */\n initialModel?: string;\n /** 스토리지 키 */\n storageKey?: string;\n /** 컨텍스트 압축 임계값 */\n contextCompressionThreshold?: number;\n /** 압축 후 유지할 메시지 수 */\n keepRecentMessages?: number;\n /** 커스텀 메시지 전송 핸들러 */\n onSendMessage?: (params: SendMessageParams) => Promise<ReadableStream<Uint8Array> | string>;\n /** 세션 변경 핸들러 */\n onSessionChange?: (session: ChatSession | null) => void;\n /** 에러 핸들러 */\n onError?: (error: Error) => void;\n}\n\n// ============================================================================\n// Main Hook\n// ============================================================================\n\nexport const useChatUI = (options: UseChatUIOptions): UseChatUIReturn => {\n const {\n models,\n actions = [],\n initialPersonalization,\n apiKey,\n apiEndpoint = '/api/chat',\n initialModel,\n storageKey = DEFAULT_STORAGE_KEY,\n contextCompressionThreshold = DEFAULT_COMPRESSION_THRESHOLD,\n keepRecentMessages = DEFAULT_KEEP_RECENT,\n onSendMessage,\n onSessionChange,\n onError,\n } = options;\n\n // ============================================================================\n // State\n // ============================================================================\n\n const [sessions, setSessions] = useState<ChatSession[]>([]);\n const [currentSessionId, setCurrentSessionId] = useState<string | null>(null);\n const [input, setInput] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [selectedModel, setSelectedModel] = useState(initialModel || models[0]?.id || '');\n const [sidebarOpen, setSidebarOpen] = useState(true);\n const [settingsOpen, setSettingsOpen] = useState(false);\n const [quotedText, setQuotedText] = useState<string | null>(null);\n const [selectedAction, setSelectedAction] = useState<ActionItem | null>(null);\n const [copiedMessageId, setCopiedMessageId] = useState<string | null>(null);\n const [editingMessageId, setEditingMessageId] = useState<string | null>(null);\n const [personalization, setPersonalization] = useState<PersonalizationConfig>({\n ...DEFAULT_PERSONALIZATION,\n ...initialPersonalization,\n });\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n // ============================================================================\n // Derived State\n // ============================================================================\n\n const currentSession = sessions.find((s) => s.id === currentSessionId) || null;\n const messages = currentSession?.messages || [];\n\n // ============================================================================\n // Persistence\n // ============================================================================\n\n useEffect(() => {\n if (typeof window === 'undefined') return;\n\n const saved = localStorage.getItem(storageKey);\n if (saved) {\n try {\n const parsed = JSON.parse(saved) as ChatSession[];\n setSessions(parsed);\n if (parsed.length > 0) {\n setCurrentSessionId(parsed[0].id);\n setSelectedModel(parsed[0].model);\n }\n } catch {\n // Ignore parse errors\n }\n }\n\n const savedPersonalization = localStorage.getItem(`${storageKey}_personalization`);\n if (savedPersonalization) {\n try {\n setPersonalization(JSON.parse(savedPersonalization));\n } catch {\n // Ignore parse errors\n }\n }\n }, [storageKey]);\n\n useEffect(() => {\n if (typeof window === 'undefined') return;\n\n if (sessions.length > 0) {\n localStorage.setItem(storageKey, JSON.stringify(sessions));\n }\n }, [sessions, storageKey]);\n\n useEffect(() => {\n if (typeof window === 'undefined') return;\n localStorage.setItem(`${storageKey}_personalization`, JSON.stringify(personalization));\n }, [personalization, storageKey]);\n\n // ============================================================================\n // Session Change Callback\n // ============================================================================\n\n useEffect(() => {\n onSessionChange?.(currentSession);\n }, [currentSession, onSessionChange]);\n\n // ============================================================================\n // System Prompt Builder\n // ============================================================================\n\n const buildSystemPrompt = useCallback((): string => {\n const parts: string[] = [];\n const { userProfile, responseStyle, language } = personalization;\n\n if (userProfile.nickname) {\n parts.push(`사용자의 이름/닉네임: ${userProfile.nickname}`);\n }\n if (userProfile.occupation) {\n parts.push(`사용자의 직업: ${userProfile.occupation}`);\n }\n if (userProfile.additionalInfo) {\n parts.push(`사용자 추가 정보: ${userProfile.additionalInfo}`);\n }\n\n const styleDescriptions: string[] = [];\n if (responseStyle.warmth === 'high') styleDescriptions.push('따뜻하고 친근하게');\n else if (responseStyle.warmth === 'low') styleDescriptions.push('간결하고 사무적으로');\n\n if (responseStyle.enthusiasm === 'high') styleDescriptions.push('열정적이고 적극적으로');\n else if (responseStyle.enthusiasm === 'low') styleDescriptions.push('차분하게');\n\n if (responseStyle.emojiUsage === 'high') styleDescriptions.push('이모지를 적극 활용해서');\n else if (responseStyle.emojiUsage === 'low') styleDescriptions.push('이모지 사용을 자제해서');\n\n if (responseStyle.verbosity === 'concise') styleDescriptions.push('핵심만 간결하게');\n else if (responseStyle.verbosity === 'detailed') styleDescriptions.push('상세하고 자세하게');\n\n if (styleDescriptions.length > 0) {\n parts.push(`응답 스타일: ${styleDescriptions.join(', ')} 응답해주세요.`);\n }\n\n if (language !== 'auto') {\n const languageNames: Record<string, string> = { ko: '한국어', en: '영어', ja: '일본어' };\n parts.push(`응답 언어: ${languageNames[language] || language}로 응답해주세요.`);\n }\n\n return parts.length > 0 ? parts.join('\\n') : '';\n }, [personalization]);\n\n // ============================================================================\n // Context Compression\n // ============================================================================\n\n const compressContext = useCallback(async (\n messagesToCompress: ChatMessage[],\n model: string\n ): Promise<string> => {\n const conversationText = messagesToCompress\n .map((m) => `${m.role === 'user' ? '사용자' : 'AI'}: ${m.content}`)\n .join('\\n\\n');\n\n const summaryPrompt = `다음 대화 내용을 핵심 정보만 유지하면서 간결하게 요약해주세요.\n중요한 결정사항, 사용자 요구사항, 맥락 정보를 보존하세요.\n\n대화:\n${conversationText}\n\n요약:`;\n\n try {\n const response = await fetch(apiEndpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n messages: [{ role: 'user', content: summaryPrompt }],\n model,\n }),\n });\n\n if (!response.ok) return '';\n\n const reader = response.body?.getReader();\n if (!reader) return '';\n\n const decoder = new TextDecoder();\n let buffer = '';\n let summary = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6);\n if (data === '[DONE]') continue;\n try {\n const parsed = JSON.parse(data);\n if (parsed.content) summary += parsed.content;\n } catch {\n // Ignore parse errors\n }\n }\n }\n }\n\n return summary;\n } catch {\n return '';\n }\n }, [apiEndpoint]);\n\n // ============================================================================\n // Actions\n // ============================================================================\n\n const newSession = useCallback(() => {\n const now = Date.now();\n const newSess: ChatSession = {\n id: generateId('session'),\n title: '새 대화',\n messages: [],\n model: selectedModel,\n createdAt: now,\n updatedAt: now,\n };\n setSessions((prev) => [newSess, ...prev]);\n setCurrentSessionId(newSess.id);\n }, [selectedModel]);\n\n const selectSession = useCallback((id: string) => {\n const session = sessions.find((s) => s.id === id);\n if (session) {\n setCurrentSessionId(id);\n setSelectedModel(session.model);\n }\n }, [sessions]);\n\n const deleteSession = useCallback((id: string) => {\n setSessions((prev) => {\n const filtered = prev.filter((s) => s.id !== id);\n if (currentSessionId === id) {\n setCurrentSessionId(filtered.length > 0 ? filtered[0].id : null);\n }\n if (filtered.length === 0 && typeof window !== 'undefined') {\n localStorage.removeItem(storageKey);\n }\n return filtered;\n });\n }, [currentSessionId, storageKey]);\n\n const setModel = useCallback((model: string) => {\n setSelectedModel(model);\n if (currentSessionId) {\n setSessions((prev) =>\n prev.map((s) => (s.id === currentSessionId ? { ...s, model } : s))\n );\n }\n }, [currentSessionId]);\n\n const toggleSidebar = useCallback(() => setSidebarOpen((prev) => !prev), []);\n const openSettings = useCallback(() => setSettingsOpen(true), []);\n const closeSettings = useCallback(() => setSettingsOpen(false), []);\n\n const copyMessage = useCallback((content: string, id: string) => {\n if (typeof navigator !== 'undefined') {\n navigator.clipboard.writeText(content).then(() => {\n setCopiedMessageId(id);\n setTimeout(() => setCopiedMessageId(null), 2000);\n });\n }\n }, []);\n\n const startEdit = useCallback((message: ChatMessage) => {\n if (message.role === 'user') {\n setEditingMessageId(message.id);\n }\n }, []);\n\n const cancelEdit = useCallback(() => {\n setEditingMessageId(null);\n }, []);\n\n const stopGeneration = useCallback(() => {\n abortControllerRef.current?.abort();\n }, []);\n\n const updatePersonalization = useCallback((config: Partial<PersonalizationConfig>) => {\n setPersonalization((prev) => ({ ...prev, ...config }));\n }, []);\n\n // ============================================================================\n // Send Message\n // ============================================================================\n\n const sendMessage = useCallback(async (content?: string) => {\n const messageContent = content || input;\n if (!messageContent.trim() || isLoading) return;\n\n let sessionId = currentSessionId;\n if (!sessionId) {\n const now = Date.now();\n const newSess: ChatSession = {\n id: generateId('session'),\n title: '새 대화',\n messages: [],\n model: selectedModel,\n createdAt: now,\n updatedAt: now,\n };\n setSessions((prev) => [newSess, ...prev]);\n sessionId = newSess.id;\n setCurrentSessionId(sessionId);\n }\n\n // 메시지 조합\n let finalContent = messageContent.trim();\n if (quotedText) {\n finalContent = `\"${quotedText}\"\\n\\n${finalContent}`;\n }\n if (selectedAction) {\n finalContent = `[${selectedAction.label}] ${finalContent}`;\n }\n\n const actionPrompt = selectedAction?.systemPrompt;\n const userMessage: ChatMessage = {\n id: generateId('msg'),\n role: 'user',\n content: finalContent,\n timestamp: Date.now(),\n };\n\n const assistantMessageId = generateId('msg');\n const assistantMessage: ChatMessage = {\n id: assistantMessageId,\n role: 'assistant',\n content: '',\n model: selectedModel,\n timestamp: Date.now(),\n };\n\n // Clear input state\n setInput('');\n setQuotedText(null);\n setSelectedAction(null);\n\n // Add messages to session\n const capturedSessionId = sessionId;\n setSessions((prev) =>\n prev.map((s) => {\n if (s.id === capturedSessionId) {\n const newMessages = [...s.messages, userMessage, assistantMessage];\n return {\n ...s,\n messages: newMessages,\n title: s.messages.length === 0 ? generateTitle([userMessage]) : s.title,\n updatedAt: Date.now(),\n };\n }\n return s;\n })\n );\n\n setIsLoading(true);\n abortControllerRef.current = new AbortController();\n\n try {\n const session = sessions.find((s) => s.id === capturedSessionId);\n const existingMessages = session?.messages || [];\n let messagesToSend = [...existingMessages, userMessage];\n\n // Context compression\n let contextSummary = session?.contextSummary;\n if (messagesToSend.length > contextCompressionThreshold && !contextSummary) {\n const toCompress = messagesToSend.slice(0, -keepRecentMessages);\n const summary = await compressContext(toCompress, selectedModel);\n if (summary) {\n contextSummary = summary;\n setSessions((prev) =>\n prev.map((s) =>\n s.id === capturedSessionId\n ? { ...s, contextSummary: summary, summaryAfterIndex: toCompress.length }\n : s\n )\n );\n }\n }\n\n // Build chat messages\n let chatMessages: { role: 'user' | 'assistant' | 'system'; content: string }[];\n if (contextSummary) {\n const recentMessages = messagesToSend.slice(-keepRecentMessages);\n chatMessages = [\n { role: 'system', content: `[이전 대화 요약]\\n${contextSummary}` },\n ...recentMessages.map((m) => ({ role: m.role, content: m.content })),\n ];\n } else {\n chatMessages = messagesToSend.map((m) => ({ role: m.role, content: m.content }));\n }\n\n // Build system prompt\n const baseSystemPrompt = buildSystemPrompt();\n const combinedSystemPrompt = [baseSystemPrompt, actionPrompt].filter(Boolean).join('\\n\\n');\n const messagesForApi = combinedSystemPrompt\n ? [{ role: 'system' as const, content: combinedSystemPrompt }, ...chatMessages]\n : chatMessages;\n\n // Get provider\n const modelConfig = models.find((m) => m.id === selectedModel);\n const provider = modelConfig?.provider || 'ollama';\n\n // Send request\n let response: Response;\n if (onSendMessage) {\n const result = await onSendMessage({\n messages: messagesForApi,\n model: selectedModel,\n provider,\n apiKey,\n systemPrompt: combinedSystemPrompt,\n });\n\n if (typeof result === 'string') {\n // Direct string response\n setSessions((prev) =>\n prev.map((s) => {\n if (s.id === capturedSessionId) {\n return {\n ...s,\n messages: s.messages.map((m) =>\n m.id === assistantMessageId ? { ...m, content: result } : m\n ),\n };\n }\n return s;\n })\n );\n return;\n }\n\n // Create fake response from stream\n response = new Response(result);\n } else {\n response = await fetch(apiEndpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n messages: messagesForApi,\n model: selectedModel,\n provider,\n apiKey: provider === 'devdive' ? apiKey : undefined,\n }),\n signal: abortControllerRef.current.signal,\n });\n }\n\n if (!response.ok) throw new Error('API error');\n\n const reader = response.body?.getReader();\n if (!reader) throw new Error('No reader');\n\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6);\n if (data === '[DONE]') continue;\n\n try {\n const parsed = JSON.parse(data);\n if (parsed.content) {\n setSessions((prev) =>\n prev.map((s) => {\n if (s.id === capturedSessionId) {\n return {\n ...s,\n messages: s.messages.map((m) =>\n m.id === assistantMessageId\n ? { ...m, content: m.content + parsed.content }\n : m\n ),\n };\n }\n return s;\n })\n );\n }\n } catch {\n // Ignore parse errors\n }\n }\n }\n }\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n return;\n }\n const err = error instanceof Error ? error : new Error('Unknown error');\n onError?.(err);\n\n setSessions((prev) =>\n prev.map((s) => {\n if (s.id === capturedSessionId) {\n return {\n ...s,\n messages: s.messages.map((m) =>\n m.id === assistantMessageId\n ? { ...m, content: '오류가 발생했습니다. 다시 시도해주세요.' }\n : m\n ),\n };\n }\n return s;\n })\n );\n } finally {\n setIsLoading(false);\n abortControllerRef.current = null;\n }\n }, [\n input,\n isLoading,\n currentSessionId,\n sessions,\n selectedModel,\n quotedText,\n selectedAction,\n apiEndpoint,\n apiKey,\n models,\n contextCompressionThreshold,\n keepRecentMessages,\n buildSystemPrompt,\n compressContext,\n onSendMessage,\n onError,\n ]);\n\n // ============================================================================\n // Edit & Regenerate\n // ============================================================================\n\n const saveEdit = useCallback(async (content: string) => {\n if (!editingMessageId || !currentSession || !currentSessionId) return;\n\n const messageIndex = currentSession.messages.findIndex((m) => m.id === editingMessageId);\n if (messageIndex === -1) return;\n\n const capturedSessionId = currentSessionId;\n setSessions((prev) =>\n prev.map((s) => {\n if (s.id === capturedSessionId) {\n const newMessages = s.messages.slice(0, messageIndex);\n return { ...s, messages: newMessages, updatedAt: Date.now() };\n }\n return s;\n })\n );\n\n setEditingMessageId(null);\n await sendMessage(content);\n }, [editingMessageId, currentSession, currentSessionId, sendMessage]);\n\n const regenerate = useCallback(async (messageId: string) => {\n if (!currentSession || !currentSessionId || isLoading) return;\n\n const assistantIndex = currentSession.messages.findIndex((m) => m.id === messageId);\n if (assistantIndex === -1) return;\n\n const userMessage = currentSession.messages[assistantIndex - 1];\n if (!userMessage || userMessage.role !== 'user') return;\n\n const capturedSessionId = currentSessionId;\n setSessions((prev) =>\n prev.map((s) => {\n if (s.id === capturedSessionId) {\n return {\n ...s,\n messages: s.messages.slice(0, assistantIndex),\n updatedAt: Date.now(),\n };\n }\n return s;\n })\n );\n\n // Re-send the user message\n setInput(userMessage.content);\n await sendMessage(userMessage.content);\n }, [currentSession, currentSessionId, isLoading, sendMessage]);\n\n // ============================================================================\n // Ask Other Model (Alternative Response)\n // ============================================================================\n\n const askOtherModel = useCallback(async (messageId: string, targetModel: string) => {\n if (!currentSession || !currentSessionId || isLoading) return;\n\n // Find the assistant message\n const assistantIndex = currentSession.messages.findIndex((m) => m.id === messageId);\n if (assistantIndex === -1) return;\n\n const assistantMessage = currentSession.messages[assistantIndex];\n if (assistantMessage.role !== 'assistant') return;\n\n // Find the user message before this assistant message\n const userMessage = currentSession.messages[assistantIndex - 1];\n if (!userMessage || userMessage.role !== 'user') return;\n\n setIsLoading(true);\n abortControllerRef.current = new AbortController();\n\n try {\n // Build messages to send (all messages up to and including user message)\n const messagesToSend = currentSession.messages.slice(0, assistantIndex);\n\n // Build chat messages\n let chatMessages: { role: 'user' | 'assistant' | 'system'; content: string }[];\n if (currentSession.contextSummary) {\n const recentMessages = messagesToSend.slice(-keepRecentMessages);\n chatMessages = [\n { role: 'system', content: `[이전 대화 요약]\\n${currentSession.contextSummary}` },\n ...recentMessages.map((m) => ({ role: m.role, content: m.content })),\n ];\n } else {\n chatMessages = messagesToSend.map((m) => ({ role: m.role, content: m.content }));\n }\n\n // Build system prompt\n const baseSystemPrompt = buildSystemPrompt();\n const messagesForApi = baseSystemPrompt\n ? [{ role: 'system' as const, content: baseSystemPrompt }, ...chatMessages]\n : chatMessages;\n\n // Get provider for target model\n const modelConfig = models.find((m) => m.id === targetModel);\n const provider = modelConfig?.provider || 'ollama';\n\n // Collect response content\n let responseContent = '';\n\n // Send request\n if (onSendMessage) {\n const result = await onSendMessage({\n messages: messagesForApi,\n model: targetModel,\n provider,\n apiKey,\n systemPrompt: baseSystemPrompt,\n });\n\n if (typeof result === 'string') {\n responseContent = result;\n } else {\n // Stream response\n const reader = result.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6);\n if (data === '[DONE]') continue;\n try {\n const parsed = JSON.parse(data);\n if (parsed.content) responseContent += parsed.content;\n } catch {\n // Ignore parse errors\n }\n }\n }\n }\n }\n } else {\n const response = await fetch(apiEndpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n messages: messagesForApi,\n model: targetModel,\n provider,\n apiKey: provider === 'devdive' ? apiKey : undefined,\n }),\n signal: abortControllerRef.current.signal,\n });\n\n if (!response.ok) throw new Error('API error');\n\n const reader = response.body?.getReader();\n if (!reader) throw new Error('No reader');\n\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6);\n if (data === '[DONE]') continue;\n try {\n const parsed = JSON.parse(data);\n if (parsed.content) responseContent += parsed.content;\n } catch {\n // Ignore parse errors\n }\n }\n }\n }\n }\n\n // Add alternative to the assistant message\n const alternative = {\n id: generateId('alt'),\n model: targetModel,\n content: responseContent,\n timestamp: Date.now(),\n };\n\n const capturedSessionId = currentSessionId;\n setSessions((prev) =>\n prev.map((s) => {\n if (s.id === capturedSessionId) {\n return {\n ...s,\n messages: s.messages.map((m) => {\n if (m.id === messageId) {\n const existingAlts = m.alternatives || [];\n return {\n ...m,\n alternatives: [...existingAlts, alternative],\n };\n }\n return m;\n }),\n updatedAt: Date.now(),\n };\n }\n return s;\n })\n );\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n return;\n }\n const err = error instanceof Error ? error : new Error('Unknown error');\n onError?.(err);\n } finally {\n setIsLoading(false);\n abortControllerRef.current = null;\n }\n }, [\n currentSession,\n currentSessionId,\n isLoading,\n keepRecentMessages,\n buildSystemPrompt,\n models,\n apiEndpoint,\n apiKey,\n onSendMessage,\n onError,\n ]);\n\n // ============================================================================\n // Return\n // ============================================================================\n\n return {\n // State\n sessions,\n currentSession,\n currentSessionId,\n messages,\n input,\n isLoading,\n selectedModel,\n sidebarOpen,\n settingsOpen,\n quotedText,\n selectedAction,\n copiedMessageId,\n editingMessageId,\n personalization,\n\n // Actions\n setInput,\n sendMessage,\n stopGeneration,\n newSession,\n selectSession,\n deleteSession,\n setModel,\n toggleSidebar,\n openSettings,\n closeSettings,\n setQuotedText,\n setSelectedAction,\n copyMessage,\n startEdit,\n cancelEdit,\n saveEdit,\n regenerate,\n askOtherModel,\n updatePersonalization,\n models,\n };\n};\n\nexport default useChatUI;\n","/**\n * Core types for devdive-chatLLM\n */\n\n// ============================================================================\n// Provider Types\n// ============================================================================\n\nexport type ProviderType = 'openai' | 'anthropic' | 'google' | 'naver' | 'ollama';\n\nexport interface ProviderConfigs {\n openai?: OpenAIConfig;\n anthropic?: AnthropicConfig;\n google?: GoogleConfig;\n naver?: NaverConfig;\n ollama?: OllamaConfig;\n}\n\nexport interface OpenAIConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\nexport interface AnthropicConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\nexport interface GoogleConfig {\n apiKey: string;\n}\n\nexport interface NaverConfig {\n apiKey: string;\n apiGatewayKey: string;\n baseUrl?: string;\n}\n\nexport interface OllamaConfig {\n baseUrl?: string; // default: http://localhost:11434\n}\n\n// ============================================================================\n// Message Types\n// ============================================================================\n\nexport type Role = 'system' | 'user' | 'assistant' | 'tool';\n\nexport interface Message {\n id: string;\n role: Role;\n content: string;\n provider?: ProviderType;\n model?: string;\n toolCalls?: ToolCall[];\n toolCallId?: string;\n timestamp: number;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ToolCall {\n id: string;\n name: string;\n arguments: Record<string, unknown>;\n}\n\nexport interface ToolResult {\n toolCallId: string;\n result: unknown;\n error?: string;\n}\n\n// ============================================================================\n// Tool/Function Types\n// ============================================================================\n\nexport interface ParameterSchema {\n type: 'string' | 'number' | 'boolean' | 'object' | 'array';\n description?: string;\n enum?: string[];\n items?: ParameterSchema;\n properties?: Record<string, ParameterSchema>;\n required?: string[];\n}\n\nexport interface ToolDefinition {\n name: string;\n description: string;\n parameters: {\n type: 'object';\n properties: Record<string, ParameterSchema>;\n required?: string[];\n };\n handler: (params: Record<string, unknown>) => Promise<unknown> | unknown;\n}\n\n// ============================================================================\n// Chat & Session Types\n// ============================================================================\n\nexport interface ChatConfig {\n id?: string;\n providers: ProviderConfigs;\n defaultProvider: ProviderType;\n defaultModel?: string;\n storagePath?: string;\n systemPrompt?: string;\n /** 개인화 설정 */\n personalization?: Partial<PersonalizationConfig>;\n}\n\nexport interface Chat {\n id: string;\n config: ChatConfig;\n messages: Message[];\n tools: Map<string, ToolDefinition>;\n memory: Map<string, MemoryEntry>;\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface SendOptions {\n provider?: ProviderType;\n model?: string;\n temperature?: number;\n maxTokens?: number;\n tools?: ToolDefinition[];\n systemPrompt?: string;\n}\n\n// ============================================================================\n// Streaming Types\n// ============================================================================\n\nexport type StreamEventType = 'text' | 'tool_call' | 'tool_result' | 'done' | 'error';\n\nexport interface StreamEvent {\n type: StreamEventType;\n content?: string;\n toolCall?: ToolCall;\n toolResult?: ToolResult;\n error?: Error;\n message?: Message;\n}\n\n// ============================================================================\n// Memory Types\n// ============================================================================\n\nexport interface MemoryEntry {\n key: string;\n value: unknown;\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface GlobalMemoryStore {\n entries: Map<string, MemoryEntry>;\n storagePath: string;\n}\n\n// ============================================================================\n// Acontext Types\n// ============================================================================\n\nexport type TaskStatus = 'pending' | 'in_progress' | 'completed' | 'failed';\n\nexport interface ObservedTask {\n id: string;\n description: string;\n status: TaskStatus;\n progress: number; // 0-100\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface UserPreference {\n key: string;\n value: unknown;\n confidence: number; // 0-1\n source: string; // which message extracted this\n}\n\nexport interface LearnedSkill {\n id: string;\n name: string;\n description: string;\n category: string;\n steps: SkillStep[];\n successRate: number;\n usageCount: number;\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface SkillStep {\n order: number;\n action: string;\n expectedInput?: string;\n expectedOutput?: string;\n}\n\nexport interface ObserverConfig {\n extractTasks: boolean;\n extractPreferences: boolean;\n autoLearn: boolean;\n}\n\nexport interface ObserverState {\n enabled: boolean;\n config: ObserverConfig;\n tasks: ObservedTask[];\n preferences: UserPreference[];\n}\n\n// ============================================================================\n// Personalization Types (ChatGPT-style settings)\n// ============================================================================\n\nexport type StyleLevel = 'low' | 'medium' | 'high';\nexport type FormattingStyle = 'minimal' | 'default' | 'rich';\n\n/**\n * 응답 스타일 설정\n */\nexport interface ResponseStyle {\n /** 따뜻함 수준 */\n warmth: StyleLevel;\n /** 열정/에너지 수준 */\n enthusiasm: StyleLevel;\n /** 이모지 사용 수준 */\n emojiUsage: StyleLevel;\n /** 포맷팅 스타일 (헤더, 목록 등) */\n formatting: FormattingStyle;\n /** 응답 길이 선호 */\n verbosity: 'concise' | 'balanced' | 'detailed';\n}\n\n/**\n * 사용자 프로필 정보\n */\nexport interface UserProfile {\n /** 사용자 닉네임/호칭 */\n nickname?: string;\n /** 직업/역할 */\n occupation?: string;\n /** 추가 정보 (관심사, 가치, 선호 사항) */\n additionalInfo?: string;\n /** 선호 언어 */\n preferredLanguage?: string;\n /** 전문 분야 */\n expertise?: string[];\n /** 커스텀 지시사항 */\n customInstructions?: string;\n}\n\n/**\n * 개인화 설정 전체\n */\nexport interface PersonalizationConfig {\n /** 응답 스타일 */\n responseStyle: ResponseStyle;\n /** 사용자 프로필 */\n userProfile: UserProfile;\n /** 메모리 참조 활성화 */\n useMemory: boolean;\n /** 언어 설정 ('auto' | 'ko' | 'en' | etc.) */\n language: string;\n}\n\n/**\n * 개인화 설정 기본값\n */\nexport const DEFAULT_PERSONALIZATION: PersonalizationConfig = {\n responseStyle: {\n warmth: 'medium',\n enthusiasm: 'medium',\n emojiUsage: 'low',\n formatting: 'default',\n verbosity: 'balanced',\n },\n userProfile: {},\n useMemory: true,\n language: 'auto',\n};\n\n// ============================================================================\n// LLM Chat Hook Integration Types\n// ============================================================================\n\n/**\n * @description Hook 결과 타입 (React Query UseMutationResult 호환)\n */\nexport interface MutationResult<TData = unknown, TError = Error, TVariables = unknown> {\n mutate: (variables: TVariables) => void;\n mutateAsync: (variables: TVariables) => Promise<TData>;\n isPending: boolean;\n isError: boolean;\n isSuccess: boolean;\n data?: TData;\n error?: TError;\n reset: () => void;\n}\n\n/**\n * @description Tool/Action Hook 타입\n */\nexport type ToolHook<TRequest = unknown, TResponse = unknown> = () => MutationResult<TResponse, Error, TRequest>;\n\n/**\n * @description AI가 자동으로 호출하는 Tool 설정\n * AI가 사용자 메시지를 분석해서 필요시 자동 호출\n */\nexport interface LLMToolConfig<TRequest = unknown, TResponse = unknown> {\n /** Tool hook */\n hook: ToolHook<TRequest, TResponse>;\n /** AI가 판단할 때 사용하는 설명 */\n description: string;\n /** JSON Schema 형태의 파라미터 정의 (선택) */\n parameters?: {\n type: 'object';\n properties: Record<string, {\n type: string;\n description?: string;\n enum?: string[];\n }>;\n required?: string[];\n };\n}\n\n/**\n * @description 사용자가 UI에서 직접 선택하는 Action 설정\n */\nexport interface LLMActionConfig<TRequest = unknown, TResponse = unknown> {\n /** Action hook */\n hook: ToolHook<TRequest, TResponse>;\n /** UI에 표시할 레이블 */\n label: string;\n /** 아이콘 이름 또는 컴포넌트 */\n icon?: string;\n /** 비활성화 여부 */\n disabled?: boolean;\n}\n\n/**\n * @description 기본 채팅(텍스트 생성) 설정\n */\nexport interface LLMChatHookConfig<TRequest = unknown, TResponse = unknown> {\n /** 텍스트 생성 hook */\n hook: ToolHook<TRequest, TResponse>;\n /** 기본 시스템 프롬프트 */\n systemPrompt?: string;\n}\n\n/**\n * @description LLM Chat 컴포넌트 Props\n */\nexport interface LLMChatComponentProps {\n /** AI가 자동 호출하는 Tools */\n tools?: Record<string, LLMToolConfig>;\n /** 사용자가 직접 선택하는 Actions */\n actions?: Record<string, LLMActionConfig>;\n /** 기본 채팅 설정 */\n chat: LLMChatHookConfig;\n /** 스타일 클래스 */\n className?: string;\n /** 개인화 설정 */\n personalization?: Partial<PersonalizationConfig>;\n}\n","/**\n * @description Remix Icons wrapper component\n * @see https://remixicon.com/\n * Using Remix Icons 4.6.0 via CDN or npm package\n */\n\nimport React from 'react';\n\nexport type IconName =\n // Navigation & UI\n | 'menu-line'\n | 'close-line'\n | 'arrow-left-line'\n | 'arrow-right-line'\n | 'arrow-down-s-line'\n | 'arrow-up-s-line'\n | 'more-line'\n | 'more-2-line'\n | 'settings-3-line'\n | 'settings-4-line'\n // Chat & Communication\n | 'chat-1-line'\n | 'chat-3-line'\n | 'chat-new-line'\n | 'message-2-line'\n | 'send-plane-line'\n | 'send-plane-fill'\n | 'question-answer-line'\n // Actions\n | 'add-line'\n | 'add-circle-line'\n | 'delete-bin-line'\n | 'delete-bin-6-line'\n | 'edit-line'\n | 'edit-2-line'\n | 'pencil-line'\n | 'check-line'\n | 'close-circle-line'\n | 'refresh-line'\n | 'loop-left-line'\n | 'stop-line'\n | 'stop-circle-line'\n | 'play-line'\n | 'pause-line'\n // Content\n | 'file-copy-line'\n | 'clipboard-line'\n | 'quote-text'\n | 'double-quotes-l'\n | 'double-quotes-r'\n // Search & Find\n | 'search-line'\n | 'search-2-line'\n | 'global-line'\n // Media\n | 'image-line'\n | 'image-add-line'\n | 'gallery-line'\n | 'video-line'\n | 'mic-line'\n // Code & Development\n | 'code-line'\n | 'code-s-slash-line'\n | 'terminal-box-line'\n | 'bug-line'\n | 'git-branch-line'\n // Document\n | 'file-text-line'\n | 'file-list-line'\n | 'article-line'\n | 'draft-line'\n | 'book-2-line'\n // AI & Magic\n | 'magic-line'\n | 'sparkling-line'\n | 'sparkling-2-line'\n | 'robot-line'\n | 'brain-line'\n // User\n | 'user-line'\n | 'user-3-line'\n | 'user-settings-line'\n | 'account-circle-line'\n // System\n | 'sun-line'\n | 'moon-line'\n | 'computer-line'\n | 'information-line'\n | 'error-warning-line'\n | 'checkbox-circle-line'\n | 'loader-4-line'\n // Misc\n | 'translate-2'\n | 'time-line'\n | 'history-line'\n | 'star-line'\n | 'star-fill'\n | 'heart-line'\n | 'thumb-up-line'\n | 'thumb-down-line'\n | 'attachment-line'\n | 'link'\n | 'links-line'\n | 'external-link-line'\n | 'download-line'\n | 'upload-line'\n | 'folder-line'\n | 'home-line'\n | 'dashboard-line'\n | 'list-check'\n | 'list-unordered'\n | 'key-line'\n | 'lock-line'\n | 'eye-line'\n | 'eye-off-line';\n\nexport interface IconProps {\n /** Icon name from Remix Icons */\n name: IconName;\n /** Size in pixels or CSS value */\n size?: number | string;\n /** CSS color value */\n color?: string;\n /** Additional CSS classes */\n className?: string;\n /** Additional inline styles */\n style?: React.CSSProperties;\n /** Click handler */\n onClick?: () => void;\n /** Accessibility label */\n 'aria-label'?: string;\n}\n\n/**\n * Remix Icons component\n * Uses CSS class-based icons (requires remixicon CSS)\n */\nexport const Icon: React.FC<IconProps> = ({\n name,\n size = 20,\n color,\n className = '',\n onClick,\n 'aria-label': ariaLabel,\n}) => {\n const sizeValue = typeof size === 'number' ? `${size}px` : size;\n\n return (\n <i\n className={`ri-${name} ${className}`}\n style={{\n fontSize: sizeValue,\n color,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n lineHeight: 1,\n }}\n onClick={onClick}\n aria-label={ariaLabel}\n role={onClick ? 'button' : undefined}\n tabIndex={onClick ? 0 : undefined}\n />\n );\n};\n\n/**\n * SVG-based Icon component (no external CSS required)\n * Icons are rendered inline as SVG\n */\nexport const IconSvg: React.FC<IconProps> = ({\n name,\n size = 20,\n color = 'currentColor',\n className = '',\n style,\n onClick,\n 'aria-label': ariaLabel,\n}) => {\n const sizeValue = typeof size === 'number' ? size : parseInt(size, 10) || 20;\n\n // Common SVG icons inline\n const icons: Partial<Record<IconName, React.ReactNode>> = {\n 'menu-line': (\n <path d=\"M3 4h18v2H3V4zm0 7h18v2H3v-2zm0 7h18v2H3v-2z\" />\n ),\n 'close-line': (\n <path d=\"M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z\" />\n ),\n 'add-line': (\n <path d=\"M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z\" />\n ),\n 'chat-1-line': (\n <path d=\"M10 3h4a8 8 0 1 1 0 16v3.5c-5-2-12-5-12-11.5a8 8 0 0 1 8-8zm2 14h2a6 6 0 0 0 0-12h-4a6 6 0 0 0-6 6c0 3.61 2.462 5.966 8 8.48V17z\" />\n ),\n 'send-plane-fill': (\n <path d=\"M1.946 9.315c-.522-.174-.527-.455.01-.634l19.087-6.362c.529-.176.832.12.684.638l-5.454 19.086c-.15.529-.455.547-.679.045L12 14l6-8-8 6-8.054-2.685z\" />\n ),\n 'send-plane-line': (\n <path d=\"M1.923 9.37c-.51-.205-.504-.51.034-.689l19.086-6.362c.529-.176.832.12.684.638l-5.454 19.086c-.15.529-.475.553-.717.07L12 14 3 10.5l8-4.25-9.077 3.12zM5.5 10.5l5.25 2.75 2.25 5.5 4-14-11.5 5.75z\" />\n ),\n 'search-line': (\n <path d=\"M18.031 16.617l4.283 4.282-1.415 1.415-4.282-4.283A8.96 8.96 0 0 1 11 20c-4.968 0-9-4.032-9-9s4.032-9 9-9 9 4.032 9 9a8.96 8.96 0 0 1-1.969 5.617zm-2.006-.742A6.977 6.977 0 0 0 18 11c0-3.868-3.133-7-7-7-3.868 0-7 3.132-7 7 0 3.867 3.132 7 7 7a6.977 6.977 0 0 0 4.875-1.975l.15-.15z\" />\n ),\n 'image-line': (\n <path d=\"M4.828 21l-.02.02-.021-.02H2.992A.993.993 0 0 1 2 20.007V3.993A1 1 0 0 1 2.992 3h18.016c.548 0 .992.445.992.993v16.014a1 1 0 0 1-.992.993H4.828zM20 15V5H4v14L14 9l6 6zm0 2.828l-6-6L6.828 19H20v-1.172zM8 11a2 2 0 1 1 0-4 2 2 0 0 1 0 4z\" />\n ),\n 'code-s-slash-line': (\n <path d=\"M24 12l-5.657 5.657-1.414-1.414L21.172 12l-4.243-4.243 1.414-1.414L24 12zM2.828 12l4.243 4.243-1.414 1.414L0 12l5.657-5.657L7.07 7.757 2.828 12zm6.96 9H7.66l6.552-18h2.128L9.788 21z\" />\n ),\n 'file-text-line': (\n <path d=\"M21 8v12.993A1 1 0 0 1 20.007 22H3.993A.993.993 0 0 1 3 21.008V2.992C3 2.455 3.449 2 4.002 2h10.995L21 8zm-2 1h-5V4H5v16h14V9zM8 7h3v2H8V7zm0 4h8v2H8v-2zm0 4h8v2H8v-2z\" />\n ),\n 'delete-bin-line': (\n <path d=\"M17 6h5v2h-2v13a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V8H2V6h5V3a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v3zm1 2H6v12h12V8zm-9 3h2v6H9v-6zm4 0h2v6h-2v-6zM9 4v2h6V4H9z\" />\n ),\n 'edit-line': (\n <path d=\"M6.414 16L16.556 5.858l-1.414-1.414L5 14.586V16h1.414zm.829 2H3v-4.243L14.435 2.322a1 1 0 0 1 1.414 0l2.829 2.829a1 1 0 0 1 0 1.414L7.243 18zM3 20h18v2H3v-2z\" />\n ),\n 'check-line': (\n <path d=\"M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414z\" />\n ),\n 'file-copy-line': (\n <path d=\"M7 6V3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1h-3v3c0 .552-.45 1-1.007 1H4.007A1.001 1.001 0 0 1 3 20l.003-14c0-.552.45-1 1.007-1H7zM5.003 8L5 20h10V8H5.003zM9 6h8v10h2V4H9v2z\" />\n ),\n 'refresh-line': (\n <path d=\"M5.463 4.433A9.961 9.961 0 0 1 12 2c5.523 0 10 4.477 10 10 0 2.136-.67 4.116-1.81 5.74L17 12h3a8 8 0 0 0-2.46-5.772A7.96 7.96 0 0 0 12 4a7.96 7.96 0 0 0-5.54 2.228l1.414 1.414A5.972 5.972 0 0 1 12 6a5.99 5.99 0 0 1 3.88 1.42l-1.42 1.42A4 4 0 0 0 8.54 12H6V7l.002-.002 1.461 1.435zM18.537 19.567A9.961 9.961 0 0 1 12 22C6.477 22 2 17.523 2 12c0-2.136.67-4.116 1.81-5.74L7 12H4a8 8 0 0 0 2.46 5.772A7.96 7.96 0 0 0 12 20a7.96 7.96 0 0 0 5.54-2.228l-1.414-1.414A5.972 5.972 0 0 1 12 18a5.99 5.99 0 0 1-3.88-1.42l1.42-1.42A4 4 0 0 0 15.46 12H18v5l-.002.002-1.461-1.435z\" />\n ),\n 'stop-circle-line': (\n <path d=\"M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm0-2a8 8 0 1 0 0-16 8 8 0 0 0 0 16zM9 9h6v6H9V9z\" />\n ),\n 'settings-3-line': (\n <path d=\"M3.34 17a10.018 10.018 0 0 1-.978-2.326 3 3 0 0 0 .002-5.347A9.99 9.99 0 0 1 4.865 4.99a3 3 0 0 0 4.631-2.674 9.99 9.99 0 0 1 5.007.002 3 3 0 0 0 4.632 2.672 10.018 10.018 0 0 1 2.525 4.337 3 3 0 0 0-.002 5.347 9.99 9.99 0 0 1-2.525 4.337 3 3 0 0 0-4.631 2.674 9.99 9.99 0 0 1-5.007-.002 3 3 0 0 0-4.632-2.672A10.018 10.018 0 0 1 3.34 17zm5.66.196a4.993 4.993 0 0 1 2.25 2.77c.499.047 1 .048 1.499.001A4.993 4.993 0 0 1 15 17.197a4.993 4.993 0 0 1 3.525-.565c.29-.408.54-.843.748-1.298A4.993 4.993 0 0 1 18 12c0-1.26.47-2.437 1.273-3.334a8.126 8.126 0 0 0-.75-1.298A4.993 4.993 0 0 1 15 6.804a4.993 4.993 0 0 1-2.25-2.77c-.499-.047-1-.048-1.499-.001A4.993 4.993 0 0 1 9 6.804a4.993 4.993 0 0 1-3.525.565 7.99 7.99 0 0 0-.748 1.298A4.993 4.993 0 0 1 6 12c0 1.26-.47 2.437-1.273 3.334a8.126 8.126 0 0 0 .75 1.298A4.993 4.993 0 0 1 9 17.196zM12 15a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2z\" />\n ),\n 'loader-4-line': (\n <path d=\"M12 3a9 9 0 0 1 9 9h-2a7 7 0 0 0-7-7V3z\" />\n ),\n 'sparkling-line': (\n <path d=\"M14 4.438A2 2 0 0 1 15.438 3l4.62.764a2 2 0 0 1 1.112.529l.152.152a2 2 0 0 1 .529 1.112L22.5 10a2 2 0 0 1-.436 1.559l-.095.11L21 10.5l-3.3-3.3L14 4.438zm-3 1.124l5.5 5.5-9.086 9.086a2 2 0 0 1-2.828 0l-.172-.172a2 2 0 0 1 0-2.828L13.5 8.062 11 5.562zm-8.657 14.95a1 1 0 0 0 1.414 0l9.9-9.9-1.414-1.413-9.9 9.9a1 1 0 0 0 0 1.414z\" />\n ),\n 'arrow-down-s-line': (\n <path d=\"M12 13.172l4.95-4.95 1.414 1.414L12 16 5.636 9.636 7.05 8.222z\" />\n ),\n 'arrow-up-s-line': (\n <path d=\"M12 10.828l-4.95 4.95-1.414-1.414L12 8l6.364 6.364-1.414 1.414z\" />\n ),\n 'double-quotes-l': (\n <path d=\"M4.583 17.321C3.553 16.227 3 15 3 13.011c0-3.5 2.457-6.637 6.03-8.188l.893 1.378c-3.335 1.804-3.987 4.145-4.247 5.621.537-.278 1.24-.375 1.929-.311 1.804.167 3.226 1.648 3.226 3.489a3.5 3.5 0 0 1-3.5 3.5c-1.073 0-2.099-.49-2.748-1.179zm10 0C13.553 16.227 13 15 13 13.011c0-3.5 2.457-6.637 6.03-8.188l.893 1.378c-3.335 1.804-3.987 4.145-4.247 5.621.537-.278 1.24-.375 1.929-.311 1.804.167 3.226 1.648 3.226 3.489a3.5 3.5 0 0 1-3.5 3.5c-1.073 0-2.099-.49-2.748-1.179z\" />\n ),\n 'robot-line': (\n <path d=\"M13 4.055c4.5.497 8 4.312 8 8.945v9H3v-9c0-4.633 3.5-8.448 8-8.945V1h2v3.055zM5 20h14v-7a7 7 0 1 0-14 0v7zm2-7a5 5 0 0 1 10 0v4H7v-4zm2 0v2h2v-2H9zm4 0v2h2v-2h-2z\" />\n ),\n 'user-3-line': (\n <path d=\"M20 22h-2v-2a3 3 0 0 0-3-3H9a3 3 0 0 0-3 3v2H4v-2a5 5 0 0 1 5-5h6a5 5 0 0 1 5 5v2zm-8-9a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8z\" />\n ),\n 'sun-line': (\n <path d=\"M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z\" />\n ),\n 'moon-line': (\n <path d=\"M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2h.1A6.979 6.979 0 0 0 10 7zm-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938 7.999 7.999 0 0 0 4 12z\" />\n ),\n 'key-line': (\n <path d=\"M12.917 13A6.002 6.002 0 0 1 1 12a6 6 0 0 1 11.917-1H23v6h-2v-4h-2v4h-2v-4h-4.083zM7 10a2 2 0 1 0 0 4 2 2 0 0 0 0-4z\" />\n ),\n 'links-line': (\n <path d=\"M17.657 14.828l-1.414-1.414L17.657 12A4 4 0 1 0 12 6.343l-1.414 1.414-1.414-1.414 1.414-1.414a6 6 0 0 1 8.485 8.485l-1.414 1.414zm-2.829 2.829l-1.414 1.414a6 6 0 1 1-8.485-8.485l1.414-1.414 1.414 1.414L6.343 12A4 4 0 1 0 12 17.657l1.414-1.414 1.414 1.414zm0-9.9l1.415 1.415-7.071 7.07-1.415-1.414 7.071-7.07z\" />\n ),\n 'external-link-line': (\n <path d=\"M10 6v2H5v11h11v-5h2v6a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h6zm11-3v8h-2V6.413l-7.793 7.794-1.414-1.414L17.585 5H13V3h8z\" />\n ),\n 'arrow-left-line': (\n <path d=\"M7.828 11H20v2H7.828l5.364 5.364-1.414 1.414L4 12l7.778-7.778 1.414 1.414z\" />\n ),\n 'arrow-right-line': (\n <path d=\"M16.172 11l-5.364-5.364 1.414-1.414L20 12l-7.778 7.778-1.414-1.414L16.172 13H4v-2z\" />\n ),\n };\n\n const iconPath = icons[name];\n\n return (\n <svg\n className={className}\n width={sizeValue}\n height={sizeValue}\n viewBox=\"0 0 24 24\"\n fill={color}\n onClick={onClick}\n aria-label={ariaLabel}\n role={onClick ? 'button' : 'img'}\n tabIndex={onClick ? 0 : undefined}\n style={{ display: 'inline-block', verticalAlign: 'middle', ...style }}\n >\n {iconPath || <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z\" />}\n </svg>\n );\n};\n\nexport default Icon;\n","/**\n * @description 채팅 사이드바 컴포넌트\n * 세션 목록, 새 대화 버튼\n */\n\nimport React from 'react';\nimport { IconSvg } from './Icon';\nimport type { SidebarProps } from '../types';\n\nconst formatDate = (timestamp: number): string => {\n const date = new Date(timestamp);\n const now = new Date();\n const diff = now.getTime() - date.getTime();\n const days = Math.floor(diff / (1000 * 60 * 60 * 24));\n\n if (days === 0) return '오늘';\n if (days === 1) return '어제';\n if (days < 7) return `${days}일 전`;\n return date.toLocaleDateString('ko-KR');\n};\n\nexport const ChatSidebar: React.FC<SidebarProps> = ({\n sessions,\n currentSessionId,\n onSelectSession,\n onNewSession,\n onDeleteSession,\n isOpen,\n onToggle,\n}) => {\n return (\n <aside\n className={`chatllm-sidebar ${isOpen ? 'chatllm-sidebar--open' : 'chatllm-sidebar--closed'}`}\n style={{\n width: isOpen ? '288px' : '0',\n flexShrink: 0,\n backgroundColor: 'var(--chatllm-sidebar-bg, #ffffff)',\n borderRight: '1px solid var(--chatllm-border, #e5e7eb)',\n transition: 'width 0.3s ease',\n overflow: 'hidden',\n }}\n >\n <div style={{ width: '288px', height: '100%', display: 'flex', flexDirection: 'column' }}>\n {/* Header */}\n <div\n style={{\n padding: '16px',\n borderBottom: '1px solid var(--chatllm-border-light, #f3f4f6)',\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '16px' }}>\n <div\n style={{\n width: '32px',\n height: '32px',\n borderRadius: '8px',\n background: 'linear-gradient(135deg, #3b82f6, #2563eb)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <IconSvg name=\"chat-1-line\" size={20} color=\"#ffffff\" />\n </div>\n <span style={{ fontWeight: 600, color: 'var(--chatllm-text, #1f2937)' }}>\n ChatLLM\n </span>\n </div>\n\n {/* New Chat Button */}\n <button\n onClick={onNewSession}\n style={{\n width: '100%',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '8px',\n padding: '10px 16px',\n backgroundColor: 'var(--chatllm-primary, #3b82f6)',\n color: '#ffffff',\n border: 'none',\n borderRadius: '8px',\n fontSize: '14px',\n fontWeight: 500,\n cursor: 'pointer',\n transition: 'background-color 0.2s',\n }}\n onMouseOver={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-primary-hover, #2563eb)';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-primary, #3b82f6)';\n }}\n >\n <IconSvg name=\"add-line\" size={18} color=\"#ffffff\" />\n 새 대화\n </button>\n </div>\n\n {/* Sessions List */}\n <div style={{ flex: 1, overflow: 'auto', padding: '8px' }}>\n {sessions.length === 0 ? (\n <div\n style={{\n padding: '24px 16px',\n textAlign: 'center',\n color: 'var(--chatllm-text-muted, #9ca3af)',\n fontSize: '14px',\n }}\n >\n 대화 기록이 없습니다\n </div>\n ) : (\n sessions.map((session) => (\n <div\n key={session.id}\n onClick={() => onSelectSession(session.id)}\n style={{\n padding: '12px',\n marginBottom: '4px',\n borderRadius: '8px',\n backgroundColor:\n session.id === currentSessionId\n ? 'var(--chatllm-bg-active, #eff6ff)'\n : 'transparent',\n cursor: 'pointer',\n transition: 'background-color 0.2s',\n }}\n onMouseOver={(e) => {\n if (session.id !== currentSessionId) {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg-hover, #f9fafb)';\n }\n }}\n onMouseOut={(e) => {\n if (session.id !== currentSessionId) {\n e.currentTarget.style.backgroundColor = 'transparent';\n }\n }}\n >\n <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>\n <div style={{ flex: 1, minWidth: 0 }}>\n <div\n style={{\n fontWeight: session.id === currentSessionId ? 500 : 400,\n color: 'var(--chatllm-text, #1f2937)',\n fontSize: '14px',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {session.title}\n </div>\n <div\n style={{\n fontSize: '12px',\n color: 'var(--chatllm-text-muted, #9ca3af)',\n marginTop: '4px',\n }}\n >\n {formatDate(session.updatedAt)}\n </div>\n </div>\n <button\n onClick={(e) => {\n e.stopPropagation();\n onDeleteSession(session.id);\n }}\n style={{\n padding: '4px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n opacity: 0.5,\n transition: 'opacity 0.2s',\n }}\n onMouseOver={(e) => {\n e.currentTarget.style.opacity = '1';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.opacity = '0.5';\n }}\n >\n <IconSvg name=\"delete-bin-line\" size={16} color=\"var(--chatllm-text-muted, #9ca3af)\" />\n </button>\n </div>\n </div>\n ))\n )}\n </div>\n\n {/* Toggle Button (Mobile) */}\n <button\n onClick={onToggle}\n style={{\n position: 'absolute',\n top: '16px',\n right: '-40px',\n width: '32px',\n height: '32px',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '8px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n cursor: 'pointer',\n }}\n >\n <IconSvg name={isOpen ? 'arrow-left-line' : 'menu-line'} size={18} />\n </button>\n </div>\n </aside>\n );\n};\n\nexport default ChatSidebar;\n","/**\n * @description 채팅 헤더 컴포넌트\n * 모델 선택, 설정 버튼\n */\n\nimport React, { useState } from 'react';\nimport { IconSvg } from './Icon';\nimport type { HeaderProps } from '../types';\n\nexport const ChatHeader: React.FC<HeaderProps> = ({\n title,\n model,\n models,\n onModelChange,\n onSettingsOpen,\n onSidebarToggle,\n sidebarOpen,\n}) => {\n const [modelDropdownOpen, setModelDropdownOpen] = useState(false);\n\n const currentModel = models.find((m) => m.id === model);\n\n return (\n <header\n className=\"chatllm-header\"\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '12px 24px',\n borderBottom: '1px solid var(--chatllm-border, #e5e7eb)',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n }}\n >\n {/* Left: Sidebar Toggle & Title */}\n <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>\n <button\n onClick={onSidebarToggle}\n style={{\n width: '36px',\n height: '36px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '8px',\n cursor: 'pointer',\n transition: 'background-color 0.2s',\n }}\n onMouseOver={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg-hover, #f3f4f6)';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent';\n }}\n >\n <IconSvg name=\"menu-line\" size={20} color=\"var(--chatllm-text, #1f2937)\" />\n </button>\n <h1\n style={{\n fontSize: '16px',\n fontWeight: 500,\n color: 'var(--chatllm-text, #1f2937)',\n margin: 0,\n }}\n >\n {title}\n </h1>\n </div>\n\n {/* Right: Model Selector & Settings */}\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>\n {/* Model Selector */}\n <div style={{ position: 'relative' }}>\n <button\n onClick={() => setModelDropdownOpen(!modelDropdownOpen)}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '8px 12px',\n backgroundColor: 'var(--chatllm-bg-secondary, #f9fafb)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '8px',\n cursor: 'pointer',\n transition: 'all 0.2s',\n }}\n onMouseOver={(e) => {\n e.currentTarget.style.borderColor = 'var(--chatllm-primary, #3b82f6)';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.borderColor = 'var(--chatllm-border, #e5e7eb)';\n }}\n >\n <IconSvg name=\"robot-line\" size={16} color=\"var(--chatllm-primary, #3b82f6)\" />\n <span style={{ fontSize: '14px', fontWeight: 500, color: 'var(--chatllm-text, #1f2937)' }}>\n {currentModel?.name || model}\n </span>\n <IconSvg\n name={modelDropdownOpen ? 'arrow-up-s-line' : 'arrow-down-s-line'}\n size={16}\n color=\"var(--chatllm-text-muted, #9ca3af)\"\n />\n </button>\n\n {/* Model Dropdown */}\n {modelDropdownOpen && (\n <>\n {/* Backdrop */}\n <div\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 99,\n }}\n onClick={() => setModelDropdownOpen(false)}\n />\n <div\n style={{\n position: 'absolute',\n top: '100%',\n right: 0,\n marginTop: '8px',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n borderRadius: '12px',\n boxShadow: '0 4px 24px rgba(0, 0, 0, 0.12)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n padding: '8px',\n minWidth: '220px',\n zIndex: 100,\n }}\n >\n {/* Group by provider */}\n {Array.from(new Set(models.map((m) => m.provider))).map((provider) => (\n <div key={provider}>\n <div\n style={{\n padding: '8px 12px',\n fontSize: '11px',\n fontWeight: 600,\n color: 'var(--chatllm-text-muted, #9ca3af)',\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n }}\n >\n {provider}\n </div>\n {models\n .filter((m) => m.provider === provider)\n .map((m) => (\n <button\n key={m.id}\n onClick={() => {\n onModelChange(m.id);\n setModelDropdownOpen(false);\n }}\n style={{\n width: '100%',\n display: 'flex',\n alignItems: 'center',\n gap: '10px',\n padding: '10px 12px',\n backgroundColor: m.id === model ? 'var(--chatllm-bg-active, #eff6ff)' : 'transparent',\n border: 'none',\n borderRadius: '8px',\n cursor: 'pointer',\n textAlign: 'left',\n transition: 'background-color 0.2s',\n }}\n onMouseOver={(e) => {\n if (m.id !== model) {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg-hover, #f9fafb)';\n }\n }}\n onMouseOut={(e) => {\n if (m.id !== model) {\n e.currentTarget.style.backgroundColor = 'transparent';\n }\n }}\n >\n <div\n style={{\n width: '28px',\n height: '28px',\n borderRadius: '6px',\n backgroundColor: m.id === model\n ? 'var(--chatllm-primary, #3b82f6)'\n : 'var(--chatllm-bg-secondary, #f3f4f6)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <IconSvg\n name=\"robot-line\"\n size={14}\n color={m.id === model ? '#ffffff' : 'var(--chatllm-text-muted, #9ca3af)'}\n />\n </div>\n <div>\n <div\n style={{\n fontSize: '14px',\n fontWeight: m.id === model ? 500 : 400,\n color: 'var(--chatllm-text, #1f2937)',\n }}\n >\n {m.name}\n </div>\n {m.description && (\n <div style={{ fontSize: '12px', color: 'var(--chatllm-text-muted, #9ca3af)' }}>\n {m.description}\n </div>\n )}\n </div>\n {m.id === model && (\n <IconSvg\n name=\"check-line\"\n size={16}\n color=\"var(--chatllm-primary, #3b82f6)\"\n className=\"ml-auto\"\n />\n )}\n </button>\n ))}\n </div>\n ))}\n </div>\n </>\n )}\n </div>\n\n {/* Settings Button */}\n <button\n onClick={onSettingsOpen}\n style={{\n width: '36px',\n height: '36px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '8px',\n cursor: 'pointer',\n transition: 'background-color 0.2s',\n }}\n onMouseOver={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg-hover, #f3f4f6)';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent';\n }}\n >\n <IconSvg name=\"settings-3-line\" size={20} color=\"var(--chatllm-text-muted, #6b7280)\" />\n </button>\n </div>\n </header>\n );\n};\n\nexport default ChatHeader;\n","/**\n * @description 채팅 입력창 컴포넌트\n * 텍스트 입력, 액션 메뉴, 인용문 칩\n */\n\nimport React, { useRef, useEffect, useState } from 'react';\nimport { IconSvg } from './Icon';\nimport type { InputProps, ActionItem } from '../types';\n\nexport const ChatInput: React.FC<InputProps> = ({\n value,\n onChange,\n onSubmit,\n onStop,\n isLoading,\n placeholder = '메시지를 입력하세요...',\n quotedText,\n onClearQuote,\n selectedAction,\n onClearAction,\n onActionSelect,\n actions = [],\n}) => {\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const [actionMenuOpen, setActionMenuOpen] = useState(false);\n\n // Auto-resize textarea\n useEffect(() => {\n if (textareaRef.current) {\n textareaRef.current.style.height = 'auto';\n textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 200)}px`;\n }\n }, [value]);\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n onSubmit();\n }\n };\n\n const handleActionSelect = (action: ActionItem) => {\n onActionSelect?.(action);\n setActionMenuOpen(false);\n };\n\n return (\n <div\n className=\"chatllm-input-container\"\n style={{\n padding: '16px 24px',\n borderTop: '1px solid var(--chatllm-border, #e5e7eb)',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n }}\n >\n {/* Quote & Action Chips */}\n {(quotedText || selectedAction) && (\n <div style={{ display: 'flex', gap: '8px', marginBottom: '12px', flexWrap: 'wrap' }}>\n {/* Quote Chip */}\n {quotedText && (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n padding: '8px 12px',\n backgroundColor: 'var(--chatllm-bg-secondary, #f9fafb)',\n borderRadius: '8px',\n borderLeft: '3px solid var(--chatllm-primary, #3b82f6)',\n maxWidth: '100%',\n }}\n >\n <IconSvg name=\"double-quotes-l\" size={14} color=\"var(--chatllm-primary, #3b82f6)\" />\n <span\n style={{\n fontSize: '13px',\n color: 'var(--chatllm-text, #1f2937)',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n maxWidth: '300px',\n }}\n >\n {quotedText}\n </span>\n <button\n onClick={onClearQuote}\n style={{\n padding: '2px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <IconSvg name=\"close-line\" size={14} color=\"var(--chatllm-text-muted, #9ca3af)\" />\n </button>\n </div>\n )}\n\n {/* Action Chip */}\n {selectedAction && (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n padding: '6px 12px',\n backgroundColor: 'var(--chatllm-primary-light, #dbeafe)',\n borderRadius: '16px',\n fontSize: '13px',\n fontWeight: 500,\n color: 'var(--chatllm-primary, #3b82f6)',\n }}\n >\n <IconSvg name=\"sparkling-line\" size={14} color=\"var(--chatllm-primary, #3b82f6)\" />\n {selectedAction.label}\n <button\n onClick={onClearAction}\n style={{\n padding: '2px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <IconSvg name=\"close-line\" size={14} color=\"var(--chatllm-primary, #3b82f6)\" />\n </button>\n </div>\n )}\n </div>\n )}\n\n {/* Input Area */}\n <div\n style={{\n display: 'flex',\n alignItems: 'flex-end',\n gap: '12px',\n padding: '12px 16px',\n backgroundColor: 'var(--chatllm-input-bg, #f9fafb)',\n borderRadius: '16px',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n transition: 'border-color 0.2s, box-shadow 0.2s',\n }}\n >\n {/* Action Menu Button */}\n {actions.length > 0 && (\n <div style={{ position: 'relative' }}>\n <button\n onClick={() => setActionMenuOpen(!actionMenuOpen)}\n style={{\n width: '36px',\n height: '36px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '8px',\n cursor: 'pointer',\n transition: 'background-color 0.2s',\n }}\n onMouseOver={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg-hover, #f3f4f6)';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg, #ffffff)';\n }}\n >\n <IconSvg name=\"add-line\" size={20} color=\"var(--chatllm-text, #1f2937)\" />\n </button>\n\n {/* Action Menu Dropdown */}\n {actionMenuOpen && (\n <div\n style={{\n position: 'absolute',\n bottom: '100%',\n left: 0,\n marginBottom: '8px',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n borderRadius: '12px',\n boxShadow: '0 4px 24px rgba(0, 0, 0, 0.12)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n padding: '8px',\n minWidth: '200px',\n zIndex: 100,\n }}\n >\n {actions.map((action) => (\n <button\n key={action.id}\n onClick={() => handleActionSelect(action)}\n style={{\n width: '100%',\n display: 'flex',\n alignItems: 'center',\n gap: '12px',\n padding: '10px 12px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '8px',\n cursor: 'pointer',\n textAlign: 'left',\n transition: 'background-color 0.2s',\n }}\n onMouseOver={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg-hover, #f3f4f6)';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent';\n }}\n >\n <div\n style={{\n width: '32px',\n height: '32px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'var(--chatllm-primary-light, #dbeafe)',\n borderRadius: '8px',\n }}\n >\n <IconSvg\n name={\n action.icon === 'search'\n ? 'search-line'\n : action.icon === 'image'\n ? 'image-line'\n : action.icon === 'code'\n ? 'code-s-slash-line'\n : 'file-text-line'\n }\n size={18}\n color=\"var(--chatllm-primary, #3b82f6)\"\n />\n </div>\n <div>\n <div style={{ fontSize: '14px', fontWeight: 500, color: 'var(--chatllm-text, #1f2937)' }}>\n {action.label}\n </div>\n <div style={{ fontSize: '12px', color: 'var(--chatllm-text-muted, #9ca3af)' }}>\n {action.description}\n </div>\n </div>\n </button>\n ))}\n </div>\n )}\n </div>\n )}\n\n {/* Textarea */}\n <textarea\n ref={textareaRef}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n rows={1}\n style={{\n flex: 1,\n minHeight: '24px',\n maxHeight: '200px',\n padding: '6px 0',\n backgroundColor: 'transparent',\n border: 'none',\n outline: 'none',\n fontSize: '15px',\n lineHeight: '1.5',\n resize: 'none',\n color: 'var(--chatllm-text, #1f2937)',\n }}\n />\n\n {/* Send / Stop Button */}\n {isLoading ? (\n <button\n onClick={onStop}\n style={{\n width: '36px',\n height: '36px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'var(--chatllm-error, #ef4444)',\n border: 'none',\n borderRadius: '8px',\n cursor: 'pointer',\n transition: 'background-color 0.2s',\n }}\n >\n <IconSvg name=\"stop-circle-line\" size={20} color=\"#ffffff\" />\n </button>\n ) : (\n <button\n onClick={onSubmit}\n disabled={!value.trim()}\n style={{\n width: '36px',\n height: '36px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: value.trim()\n ? 'var(--chatllm-primary, #3b82f6)'\n : 'var(--chatllm-bg-disabled, #e5e7eb)',\n border: 'none',\n borderRadius: '8px',\n cursor: value.trim() ? 'pointer' : 'not-allowed',\n transition: 'background-color 0.2s',\n }}\n >\n <IconSvg name=\"send-plane-fill\" size={18} color={value.trim() ? '#ffffff' : '#9ca3af'} />\n </button>\n )}\n </div>\n </div>\n );\n};\n\nexport default ChatInput;\n","/**\n * @description 메시지 목록 컴포넌트\n */\n\nimport React, { useRef, useEffect, useCallback, useState } from 'react';\nimport { MessageBubble } from './MessageBubble';\nimport { IconSvg } from './Icon';\nimport type { MessageListProps } from '../types';\n\nexport const MessageList: React.FC<MessageListProps> = ({\n messages,\n isLoading,\n onCopy,\n onEdit,\n onRegenerate,\n onQuote,\n onAskOtherModel,\n models,\n copiedId,\n editingId,\n}) => {\n const messagesEndRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const [selectedText, setSelectedText] = useState('');\n const [selectionPosition, setSelectionPosition] = useState<{ x: number; y: number } | null>(null);\n\n // Auto scroll to bottom\n useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n }, [messages]);\n\n // Handle text selection\n const handleMouseUp = useCallback(() => {\n const selection = window.getSelection();\n const text = selection?.toString().trim();\n\n if (text && text.length > 0) {\n const range = selection?.getRangeAt(0);\n const rect = range?.getBoundingClientRect();\n if (rect && containerRef.current) {\n const containerRect = containerRef.current.getBoundingClientRect();\n setSelectedText(text);\n setSelectionPosition({\n x: rect.left - containerRect.left + rect.width / 2,\n y: rect.top - containerRect.top - 10,\n });\n }\n } else {\n setTimeout(() => {\n const currentSelection = window.getSelection()?.toString().trim();\n if (!currentSelection) {\n setSelectionPosition(null);\n }\n }, 100);\n }\n }, []);\n\n // Handle quote\n const handleQuote = () => {\n if (selectedText && onQuote) {\n onQuote(selectedText);\n setSelectionPosition(null);\n setSelectedText('');\n window.getSelection()?.removeAllRanges();\n }\n };\n\n return (\n <div\n ref={containerRef}\n className=\"chatllm-message-list\"\n style={{\n flex: 1,\n overflow: 'auto',\n position: 'relative',\n }}\n onMouseUp={handleMouseUp}\n >\n {messages.map((message, index) => (\n <MessageBubble\n key={message.id}\n message={message}\n isLoading={isLoading && index === messages.length - 1 && message.role === 'assistant'}\n isCopied={copiedId === message.id}\n isEditing={editingId === message.id}\n onCopy={() => onCopy(message.content, message.id)}\n onEdit={() => onEdit(message)}\n onRegenerate={message.role === 'assistant' ? () => onRegenerate(message.id) : undefined}\n onQuote={onQuote}\n onAskOtherModel={\n message.role === 'assistant' && onAskOtherModel\n ? (targetModel) => onAskOtherModel(message.id, targetModel)\n : undefined\n }\n models={models}\n alternatives={message.alternatives}\n />\n ))}\n\n {/* Selection Popup */}\n {selectionPosition && (\n <div\n style={{\n position: 'absolute',\n left: selectionPosition.x,\n top: selectionPosition.y,\n transform: 'translate(-50%, -100%)',\n zIndex: 50,\n }}\n >\n <button\n onClick={handleQuote}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n padding: '8px 12px',\n backgroundColor: 'var(--chatllm-text, #1f2937)',\n color: '#ffffff',\n border: 'none',\n borderRadius: '8px',\n fontSize: '13px',\n fontWeight: 500,\n cursor: 'pointer',\n boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',\n }}\n >\n <IconSvg name=\"double-quotes-l\" size={14} color=\"#ffffff\" />\n 인용하기\n </button>\n {/* Arrow */}\n <div\n style={{\n position: 'absolute',\n left: '50%',\n bottom: '-6px',\n transform: 'translateX(-50%)',\n width: 0,\n height: 0,\n borderLeft: '6px solid transparent',\n borderRight: '6px solid transparent',\n borderTop: '6px solid var(--chatllm-text, #1f2937)',\n }}\n />\n </div>\n )}\n\n <div ref={messagesEndRef} />\n </div>\n );\n};\n\nexport default MessageList;\n","/**\n * @description 메시지 버블 컴포넌트\n * 사용자/AI 메시지 표시, 복사, 수정, 재생성\n * 마크다운 렌더링 및 출처 링크 칩 지원\n */\n\nimport React, { useState } from 'react';\nimport { IconSvg } from './Icon';\nimport { MarkdownRenderer } from './MarkdownRenderer';\nimport type { MessageBubbleProps } from '../types';\n\nexport const MessageBubble: React.FC<MessageBubbleProps> = ({\n message,\n isLoading,\n isCopied,\n isEditing,\n onCopy,\n onEdit,\n onRegenerate,\n onQuote,\n onAskOtherModel,\n models,\n alternatives,\n activeAlternativeIndex = 0,\n onAlternativeChange,\n}) => {\n const [showActions, setShowActions] = useState(false);\n const [showModelMenu, setShowModelMenu] = useState(false);\n const isUser = message.role === 'user';\n const isAssistant = message.role === 'assistant';\n\n // Get other available models (exclude current model)\n const otherModels = models?.filter((m) => m.id !== message.model) || [];\n\n // Get content to display (main or alternative)\n const displayContent =\n alternatives && alternatives.length > 0 && activeAlternativeIndex > 0\n ? alternatives[activeAlternativeIndex - 1]?.content || message.content\n : message.content;\n\n const displayModel =\n alternatives && alternatives.length > 0 && activeAlternativeIndex > 0\n ? alternatives[activeAlternativeIndex - 1]?.model\n : message.model;\n\n // Handle text selection for quote\n const handleMouseUp = () => {\n if (!onQuote) return;\n const selection = window.getSelection();\n const text = selection?.toString().trim();\n if (text && text.length > 0) {\n // Will be handled by parent component\n }\n };\n\n return (\n <div\n className={`chatllm-message chatllm-message--${message.role}`}\n style={{\n display: 'flex',\n gap: '12px',\n padding: '16px 24px',\n backgroundColor: isUser ? 'transparent' : 'var(--chatllm-bg-secondary, #f9fafb)',\n }}\n onMouseEnter={() => setShowActions(true)}\n onMouseLeave={() => setShowActions(false)}\n onMouseUp={handleMouseUp}\n >\n {/* Avatar */}\n <div\n style={{\n width: '32px',\n height: '32px',\n borderRadius: '8px',\n backgroundColor: isUser\n ? 'var(--chatllm-user-avatar, #e5e7eb)'\n : 'var(--chatllm-assistant-avatar, #dbeafe)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n }}\n >\n <IconSvg\n name={isUser ? 'user-3-line' : 'robot-line'}\n size={18}\n color={isUser ? 'var(--chatllm-text-muted, #6b7280)' : 'var(--chatllm-primary, #3b82f6)'}\n />\n </div>\n\n {/* Content */}\n <div style={{ flex: 1, minWidth: 0 }}>\n {/* Header */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n marginBottom: '8px',\n }}\n >\n <span\n style={{\n fontSize: '14px',\n fontWeight: 500,\n color: 'var(--chatllm-text, #1f2937)',\n }}\n >\n {isUser ? '나' : 'AI'}\n </span>\n {displayModel && (\n <span\n style={{\n fontSize: '12px',\n padding: '2px 8px',\n backgroundColor: 'var(--chatllm-bg-tertiary, #f3f4f6)',\n borderRadius: '4px',\n color: 'var(--chatllm-text-muted, #6b7280)',\n }}\n >\n {displayModel}\n </span>\n )}\n </div>\n\n {/* Message Content */}\n <div\n style={{\n wordBreak: 'break-word',\n }}\n >\n {isAssistant ? (\n // AI 메시지는 마크다운 렌더링\n <MarkdownRenderer content={displayContent} />\n ) : (\n // 사용자 메시지는 일반 텍스트\n <div\n style={{\n fontSize: '15px',\n lineHeight: '1.7',\n color: 'var(--chatllm-text, #374151)',\n whiteSpace: 'pre-wrap',\n }}\n >\n {displayContent}\n </div>\n )}\n {isLoading && isAssistant && !displayContent && (\n <span\n style={{\n display: 'inline-flex',\n gap: '4px',\n }}\n >\n <span className=\"chatllm-typing-dot\" style={dotStyle} />\n <span className=\"chatllm-typing-dot\" style={{ ...dotStyle, animationDelay: '0.2s' }} />\n <span className=\"chatllm-typing-dot\" style={{ ...dotStyle, animationDelay: '0.4s' }} />\n </span>\n )}\n </div>\n\n {/* Alternatives Navigation */}\n {alternatives && alternatives.length > 0 && (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n marginTop: '12px',\n paddingTop: '12px',\n borderTop: '1px solid var(--chatllm-border-light, #f3f4f6)',\n }}\n >\n <button\n onClick={() => onAlternativeChange?.(Math.max(0, activeAlternativeIndex - 1))}\n disabled={activeAlternativeIndex === 0}\n style={{\n ...navButtonStyle,\n opacity: activeAlternativeIndex === 0 ? 0.5 : 1,\n cursor: activeAlternativeIndex === 0 ? 'not-allowed' : 'pointer',\n }}\n >\n <IconSvg name=\"arrow-left-line\" size={14} />\n </button>\n <span style={{ fontSize: '12px', color: 'var(--chatllm-text-muted, #9ca3af)' }}>\n {activeAlternativeIndex + 1} / {alternatives.length + 1}\n </span>\n <button\n onClick={() =>\n onAlternativeChange?.(Math.min(alternatives.length, activeAlternativeIndex + 1))\n }\n disabled={activeAlternativeIndex === alternatives.length}\n style={{\n ...navButtonStyle,\n opacity: activeAlternativeIndex === alternatives.length ? 0.5 : 1,\n cursor: activeAlternativeIndex === alternatives.length ? 'not-allowed' : 'pointer',\n }}\n >\n <IconSvg name=\"arrow-right-line\" size={14} />\n </button>\n </div>\n )}\n\n {/* Action Buttons */}\n {showActions && !isLoading && (\n <div\n style={{\n display: 'flex',\n gap: '4px',\n marginTop: '12px',\n }}\n >\n {/* Copy */}\n <button onClick={onCopy} style={actionButtonStyle} title=\"복사\">\n <IconSvg\n name={isCopied ? 'check-line' : 'file-copy-line'}\n size={16}\n color={isCopied ? 'var(--chatllm-success, #22c55e)' : 'var(--chatllm-text-muted, #9ca3af)'}\n />\n </button>\n\n {/* Edit (User only) */}\n {isUser && (\n <button onClick={onEdit} style={actionButtonStyle} title=\"수정\">\n <IconSvg name=\"edit-line\" size={16} color=\"var(--chatllm-text-muted, #9ca3af)\" />\n </button>\n )}\n\n {/* Regenerate (Assistant only) */}\n {isAssistant && onRegenerate && (\n <button onClick={onRegenerate} style={actionButtonStyle} title=\"다시 생성\">\n <IconSvg name=\"refresh-line\" size={16} color=\"var(--chatllm-text-muted, #9ca3af)\" />\n </button>\n )}\n\n {/* Ask Other Model (Assistant only) */}\n {isAssistant && onAskOtherModel && otherModels.length > 0 && (\n <div style={{ position: 'relative' }}>\n <button\n onClick={() => setShowModelMenu(!showModelMenu)}\n style={actionButtonStyle}\n title=\"다른 모델에게 질문\"\n >\n <IconSvg name=\"robot-line\" size={16} color=\"var(--chatllm-text-muted, #9ca3af)\" />\n <IconSvg\n name=\"arrow-down-s-line\"\n size={12}\n color=\"var(--chatllm-text-muted, #9ca3af)\"\n style={{ marginLeft: '2px' }}\n />\n </button>\n\n {/* Model Dropdown Menu */}\n {showModelMenu && (\n <div\n style={{\n position: 'absolute',\n bottom: '100%',\n left: 0,\n marginBottom: '4px',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '8px',\n boxShadow: '0 4px 12px rgba(0, 0, 0, 0.1)',\n minWidth: '160px',\n zIndex: 100,\n overflow: 'hidden',\n }}\n onMouseLeave={() => setShowModelMenu(false)}\n >\n <div\n style={{\n padding: '8px 12px',\n fontSize: '11px',\n fontWeight: 600,\n color: 'var(--chatllm-text-muted, #9ca3af)',\n textTransform: 'uppercase',\n borderBottom: '1px solid var(--chatllm-border-light, #f3f4f6)',\n }}\n >\n 다른 모델에게 질문\n </div>\n {otherModels.map((model) => (\n <button\n key={model.id}\n onClick={() => {\n onAskOtherModel(model.id);\n setShowModelMenu(false);\n }}\n style={{\n width: '100%',\n padding: '10px 12px',\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n backgroundColor: 'transparent',\n border: 'none',\n cursor: 'pointer',\n fontSize: '13px',\n color: 'var(--chatllm-text, #1f2937)',\n textAlign: 'left',\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg-hover, #f3f4f6)';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent';\n }}\n >\n <IconSvg name=\"robot-line\" size={14} color=\"var(--chatllm-primary, #3b82f6)\" />\n <span style={{ flex: 1 }}>{model.name}</span>\n <span\n style={{\n fontSize: '10px',\n padding: '2px 6px',\n backgroundColor: 'var(--chatllm-bg-tertiary, #f3f4f6)',\n borderRadius: '4px',\n color: 'var(--chatllm-text-muted, #9ca3af)',\n }}\n >\n {model.provider}\n </span>\n </button>\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n};\n\nconst dotStyle: React.CSSProperties = {\n width: '8px',\n height: '8px',\n borderRadius: '50%',\n backgroundColor: 'var(--chatllm-primary, #3b82f6)',\n animation: 'chatllm-typing 1.4s infinite ease-in-out both',\n};\n\nconst actionButtonStyle: React.CSSProperties = {\n padding: '6px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '6px',\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n transition: 'background-color 0.2s',\n};\n\nconst navButtonStyle: React.CSSProperties = {\n width: '24px',\n height: '24px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '6px',\n};\n\nexport default MessageBubble;\n","/**\n * @description 마크다운 렌더러 컴포넌트\n * 외부 의존성 없이 기본 마크다운 파싱 지원\n */\n\nimport React, { useMemo } from 'react';\nimport { LinkChip } from './LinkChip';\n\nexport interface MarkdownRendererProps {\n /** 마크다운 텍스트 */\n content: string;\n /** 커스텀 클래스 */\n className?: string;\n}\n\n// 링크 정규식 - [text](url) 패턴\nconst LINK_REGEX = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n// 출처 링크 패턴 - 연속된 링크들 (예: [`1. brave`](url) [`2. brave`](url))\nconst SOURCE_LINKS_REGEX = /(\\*{0,2}출처:?\\*{0,2}\\s*)?((?:\\[`?[^\\]]+`?\\]\\([^)]+\\)\\s*)+)/gi;\n// 코드 블록 패턴\nconst CODE_BLOCK_REGEX = /```(\\w*)\\n?([\\s\\S]*?)```/g;\n// 인라인 코드 패턴\nconst INLINE_CODE_REGEX = /`([^`]+)`/g;\n// 굵게 패턴\nconst BOLD_REGEX = /\\*\\*([^*]+)\\*\\*/g;\n// 기울임 패턴 (굵게가 아닌 경우만)\nconst ITALIC_REGEX = /(?<!\\*)\\*([^*]+)\\*(?!\\*)/g;\n// 헤딩 패턴\nconst HEADING_REGEX = /^(#{1,6})\\s+(.+)$/gm;\n// 리스트 아이템 패턴\nconst LIST_ITEM_REGEX = /^[\\-\\*]\\s+(.+)$/gm;\n// 번호 리스트 패턴\nconst NUMBERED_LIST_REGEX = /^(\\d+)\\.\\s+(.+)$/gm;\n// 인용 패턴\nconst BLOCKQUOTE_REGEX = /^>\\s+(.+)$/gm;\n// 수평선 패턴\nconst HR_REGEX = /^---+$/gm;\n\ninterface ParsedLink {\n text: string;\n url: string;\n}\n\n/**\n * 출처 링크들을 파싱하여 배열로 반환\n */\nconst parseSourceLinks = (text: string): ParsedLink[] => {\n const links: ParsedLink[] = [];\n let match;\n const linkRegex = /\\[`?([^\\]`]+)`?\\]\\(([^)]+)\\)/g;\n\n while ((match = linkRegex.exec(text)) !== null) {\n links.push({\n text: match[1],\n url: match[2],\n });\n }\n\n return links;\n};\n\n/**\n * 텍스트에서 인라인 요소 파싱 (굵게, 기울임, 코드, 링크)\n */\nconst parseInlineElements = (text: string, key: string): React.ReactNode[] => {\n const elements: React.ReactNode[] = [];\n let lastIndex = 0;\n let currentText = text;\n\n // 인라인 코드 처리\n currentText = currentText.replace(INLINE_CODE_REGEX, '§CODE§$1§/CODE§');\n // 굵게 처리\n currentText = currentText.replace(BOLD_REGEX, '§BOLD§$1§/BOLD§');\n // 기울임 처리\n currentText = currentText.replace(ITALIC_REGEX, '§ITALIC§$1§/ITALIC§');\n // 일반 링크 처리 (출처 링크가 아닌 것)\n currentText = currentText.replace(LINK_REGEX, '§LINK§$1§URL§$2§/LINK§');\n\n // 파싱된 마커를 React 요소로 변환\n const parts = currentText.split(/(§CODE§.*?§\\/CODE§|§BOLD§.*?§\\/BOLD§|§ITALIC§.*?§\\/ITALIC§|§LINK§.*?§\\/LINK§)/);\n\n parts.forEach((part, index) => {\n if (part.startsWith('§CODE§')) {\n const content = part.replace('§CODE§', '').replace('§/CODE§', '');\n elements.push(\n <code\n key={`${key}-code-${index}`}\n style={{\n backgroundColor: 'var(--chatllm-code-bg, #f3f4f6)',\n padding: '2px 6px',\n borderRadius: '4px',\n fontSize: '0.9em',\n fontFamily: 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace',\n color: 'var(--chatllm-code-text, #e11d48)',\n }}\n >\n {content}\n </code>\n );\n } else if (part.startsWith('§BOLD§')) {\n const content = part.replace('§BOLD§', '').replace('§/BOLD§', '');\n elements.push(<strong key={`${key}-bold-${index}`}>{content}</strong>);\n } else if (part.startsWith('§ITALIC§')) {\n const content = part.replace('§ITALIC§', '').replace('§/ITALIC§', '');\n elements.push(<em key={`${key}-italic-${index}`}>{content}</em>);\n } else if (part.startsWith('§LINK§')) {\n const match = part.match(/§LINK§(.+?)§URL§(.+?)§\\/LINK§/);\n if (match) {\n elements.push(\n <a\n key={`${key}-link-${index}`}\n href={match[2]}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{\n color: 'var(--chatllm-link, #3b82f6)',\n textDecoration: 'none',\n }}\n >\n {match[1]}\n </a>\n );\n }\n } else if (part) {\n elements.push(part);\n }\n });\n\n return elements;\n};\n\n/**\n * 코드 블록 렌더링\n */\nconst CodeBlock: React.FC<{ language?: string; code: string }> = ({ language, code }) => {\n const [copied, setCopied] = React.useState(false);\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(code);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch (e) {\n console.error('Failed to copy');\n }\n };\n\n return (\n <div\n style={{\n position: 'relative',\n margin: '12px 0',\n borderRadius: '8px',\n overflow: 'hidden',\n backgroundColor: 'var(--chatllm-code-block-bg, #1f2937)',\n }}\n >\n {/* Header */}\n <div\n style={{\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: '8px 12px',\n backgroundColor: 'var(--chatllm-code-block-header, #374151)',\n borderBottom: '1px solid var(--chatllm-code-block-border, #4b5563)',\n }}\n >\n <span\n style={{\n fontSize: '12px',\n color: 'var(--chatllm-code-block-lang, #9ca3af)',\n textTransform: 'lowercase',\n }}\n >\n {language || 'code'}\n </span>\n <button\n onClick={handleCopy}\n style={{\n padding: '4px 8px',\n fontSize: '12px',\n backgroundColor: 'transparent',\n border: '1px solid var(--chatllm-code-block-border, #4b5563)',\n borderRadius: '4px',\n color: 'var(--chatllm-code-block-text, #e5e7eb)',\n cursor: 'pointer',\n }}\n >\n {copied ? '복사됨!' : '복사'}\n </button>\n </div>\n {/* Code */}\n <pre\n style={{\n margin: 0,\n padding: '16px',\n overflow: 'auto',\n fontSize: '13px',\n lineHeight: '1.6',\n fontFamily: 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace',\n color: 'var(--chatllm-code-block-text, #e5e7eb)',\n }}\n >\n <code>{code.trim()}</code>\n </pre>\n </div>\n );\n};\n\n/**\n * 출처 링크 섹션 렌더링\n */\nconst SourceLinksSection: React.FC<{ links: ParsedLink[]; label?: string }> = ({ links, label }) => {\n return (\n <div\n style={{\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n gap: '8px',\n margin: '12px 0',\n padding: '12px',\n backgroundColor: 'var(--chatllm-source-bg, #f8fafc)',\n borderRadius: '8px',\n border: '1px solid var(--chatllm-border-light, #e2e8f0)',\n }}\n >\n {label && (\n <span\n style={{\n fontSize: '13px',\n fontWeight: 500,\n color: 'var(--chatllm-text-muted, #64748b)',\n marginRight: '4px',\n }}\n >\n {label}\n </span>\n )}\n {links.map((link, index) => (\n <LinkChip key={index} text={link.text} url={link.url} />\n ))}\n </div>\n );\n};\n\nexport const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({ content, className }) => {\n const rendered = useMemo(() => {\n const elements: React.ReactNode[] = [];\n let processedContent = content;\n\n // 1. 코드 블록 추출 및 치환\n const codeBlocks: { language: string; code: string }[] = [];\n processedContent = processedContent.replace(CODE_BLOCK_REGEX, (_, lang, code) => {\n codeBlocks.push({ language: lang || '', code });\n return `§CODEBLOCK§${codeBlocks.length - 1}§/CODEBLOCK§`;\n });\n\n // 2. 출처 링크 섹션 추출 및 치환\n const sourceSections: { label: string; links: ParsedLink[] }[] = [];\n processedContent = processedContent.replace(SOURCE_LINKS_REGEX, (match, label, linksText) => {\n const links = parseSourceLinks(linksText);\n if (links.length > 0) {\n sourceSections.push({ label: label?.replace(/\\*+/g, '').trim() || '출처', links });\n return `§SOURCES§${sourceSections.length - 1}§/SOURCES§`;\n }\n return match;\n });\n\n // 3. 줄 단위로 파싱\n const lines = processedContent.split('\\n');\n let currentList: { type: 'ul' | 'ol'; items: React.ReactNode[] } | null = null;\n let blockquoteLines: string[] = [];\n\n const flushList = () => {\n if (currentList) {\n if (currentList.type === 'ul') {\n elements.push(\n <ul key={`ul-${elements.length}`} style={{ margin: '8px 0', paddingLeft: '24px' }}>\n {currentList.items}\n </ul>\n );\n } else {\n elements.push(\n <ol key={`ol-${elements.length}`} style={{ margin: '8px 0', paddingLeft: '24px' }}>\n {currentList.items}\n </ol>\n );\n }\n currentList = null;\n }\n };\n\n const flushBlockquote = () => {\n if (blockquoteLines.length > 0) {\n elements.push(\n <blockquote\n key={`bq-${elements.length}`}\n style={{\n margin: '12px 0',\n padding: '12px 16px',\n borderLeft: '4px solid var(--chatllm-primary, #3b82f6)',\n backgroundColor: 'var(--chatllm-bg-secondary, #f9fafb)',\n borderRadius: '0 8px 8px 0',\n color: 'var(--chatllm-text, #374151)',\n }}\n >\n {blockquoteLines.map((line, i) => (\n <React.Fragment key={i}>\n {parseInlineElements(line, `bq-line-${i}`)}\n {i < blockquoteLines.length - 1 && <br />}\n </React.Fragment>\n ))}\n </blockquote>\n );\n blockquoteLines = [];\n }\n };\n\n lines.forEach((line, lineIndex) => {\n // 코드 블록 마커 처리\n const codeBlockMatch = line.match(/§CODEBLOCK§(\\d+)§\\/CODEBLOCK§/);\n if (codeBlockMatch) {\n flushList();\n flushBlockquote();\n const index = parseInt(codeBlockMatch[1]);\n elements.push(\n <CodeBlock key={`codeblock-${lineIndex}`} {...codeBlocks[index]} />\n );\n return;\n }\n\n // 출처 링크 마커 처리\n const sourcesMatch = line.match(/§SOURCES§(\\d+)§\\/SOURCES§/);\n if (sourcesMatch) {\n flushList();\n flushBlockquote();\n const index = parseInt(sourcesMatch[1]);\n elements.push(\n <SourceLinksSection key={`sources-${lineIndex}`} {...sourceSections[index]} />\n );\n return;\n }\n\n // 수평선\n if (HR_REGEX.test(line)) {\n flushList();\n flushBlockquote();\n elements.push(\n <hr\n key={`hr-${lineIndex}`}\n style={{\n margin: '16px 0',\n border: 'none',\n borderTop: '1px solid var(--chatllm-border, #e5e7eb)',\n }}\n />\n );\n return;\n }\n\n // 헤딩\n const headingMatch = line.match(/^(#{1,6})\\s+(.+)$/);\n if (headingMatch) {\n flushList();\n flushBlockquote();\n const level = headingMatch[1].length;\n const text = headingMatch[2];\n const HeadingTag = `h${level}` as keyof JSX.IntrinsicElements;\n const sizes: Record<number, string> = {\n 1: '1.5em',\n 2: '1.3em',\n 3: '1.15em',\n 4: '1.05em',\n 5: '1em',\n 6: '0.95em',\n };\n elements.push(\n <HeadingTag\n key={`heading-${lineIndex}`}\n style={{\n fontSize: sizes[level],\n fontWeight: level <= 2 ? 600 : 500,\n margin: '16px 0 8px',\n color: 'var(--chatllm-text, #1f2937)',\n }}\n >\n {parseInlineElements(text, `heading-${lineIndex}`)}\n </HeadingTag>\n );\n return;\n }\n\n // 인용문\n const blockquoteMatch = line.match(/^>\\s*(.*)$/);\n if (blockquoteMatch) {\n flushList();\n blockquoteLines.push(blockquoteMatch[1]);\n return;\n } else {\n flushBlockquote();\n }\n\n // 비순서 리스트\n const ulMatch = line.match(/^[\\-\\*]\\s+(.+)$/);\n if (ulMatch) {\n flushBlockquote();\n if (!currentList || currentList.type !== 'ul') {\n flushList();\n currentList = { type: 'ul', items: [] };\n }\n currentList.items.push(\n <li key={`li-${lineIndex}`} style={{ margin: '4px 0' }}>\n {parseInlineElements(ulMatch[1], `li-${lineIndex}`)}\n </li>\n );\n return;\n }\n\n // 순서 리스트\n const olMatch = line.match(/^(\\d+)\\.\\s+(.+)$/);\n if (olMatch) {\n flushBlockquote();\n if (!currentList || currentList.type !== 'ol') {\n flushList();\n currentList = { type: 'ol', items: [] };\n }\n currentList.items.push(\n <li key={`li-${lineIndex}`} style={{ margin: '4px 0' }}>\n {parseInlineElements(olMatch[2], `li-${lineIndex}`)}\n </li>\n );\n return;\n }\n\n // 리스트 종료\n flushList();\n\n // 빈 줄\n if (!line.trim()) {\n elements.push(<br key={`br-${lineIndex}`} />);\n return;\n }\n\n // 일반 텍스트\n elements.push(\n <p key={`p-${lineIndex}`} style={{ margin: '4px 0' }}>\n {parseInlineElements(line, `p-${lineIndex}`)}\n </p>\n );\n });\n\n // 남은 리스트/인용문 처리\n flushList();\n flushBlockquote();\n\n return elements;\n }, [content]);\n\n return (\n <div\n className={`chatllm-markdown ${className || ''}`}\n style={{\n fontSize: '15px',\n lineHeight: '1.7',\n color: 'var(--chatllm-text, #374151)',\n }}\n >\n {rendered}\n </div>\n );\n};\n\nexport default MarkdownRenderer;\n","/**\n * @description 링크 칩 컴포넌트\n * 출처 링크를 칩 형태로 표시\n */\n\nimport React, { useState } from 'react';\nimport { IconSvg } from './Icon';\n\nexport interface LinkChipProps {\n /** 링크 텍스트 */\n text: string;\n /** 링크 URL */\n url: string;\n /** 파비콘 표시 여부 */\n showFavicon?: boolean;\n /** 번호 표시 */\n index?: number;\n /** 커스텀 스타일 */\n style?: React.CSSProperties;\n}\n\n/**\n * URL에서 도메인 추출\n */\nconst getDomain = (url: string): string => {\n try {\n const urlObj = new URL(url);\n return urlObj.hostname.replace('www.', '');\n } catch {\n return url;\n }\n};\n\n/**\n * 도메인에서 짧은 이름 추출\n */\nconst getShortName = (domain: string): string => {\n const parts = domain.split('.');\n if (parts.length >= 2) {\n return parts[parts.length - 2];\n }\n return domain;\n};\n\n/**\n * 도메인별 색상 매핑\n */\nconst getDomainColor = (domain: string): string => {\n const lowerDomain = domain.toLowerCase();\n\n // 주요 사이트 색상\n const colorMap: Record<string, string> = {\n 'google': '#4285f4',\n 'wikipedia': '#000000',\n 'github': '#24292e',\n 'stackoverflow': '#f48024',\n 'medium': '#00ab6c',\n 'youtube': '#ff0000',\n 'twitter': '#1da1f2',\n 'naver': '#03c75a',\n 'namu': '#00a495',\n 'tistory': '#eb531f',\n 'velog': '#20c997',\n 'brave': '#fb542b',\n 'mk': '#0066cc',\n 'ko': '#3366cc',\n };\n\n for (const [key, color] of Object.entries(colorMap)) {\n if (lowerDomain.includes(key)) {\n return color;\n }\n }\n\n // 기본 색상 (해시 기반)\n let hash = 0;\n for (let i = 0; i < domain.length; i++) {\n hash = domain.charCodeAt(i) + ((hash << 5) - hash);\n }\n const hue = hash % 360;\n return `hsl(${hue}, 60%, 45%)`;\n};\n\nexport const LinkChip: React.FC<LinkChipProps> = ({\n text,\n url,\n showFavicon = true,\n index,\n style,\n}) => {\n const [isHovered, setIsHovered] = useState(false);\n const domain = getDomain(url);\n const shortName = getShortName(domain);\n const domainColor = getDomainColor(domain);\n\n // 텍스트에서 번호 추출 (예: \"1. brave\" -> { number: 1, label: \"brave\" })\n const parseText = (t: string): { number?: string; label: string } => {\n const match = t.match(/^(\\d+)\\.\\s*(.+)$/);\n if (match) {\n return { number: match[1], label: match[2] };\n }\n return { label: t };\n };\n\n const parsed = parseText(text);\n const displayNumber = index !== undefined ? String(index + 1) : parsed.number;\n const displayLabel = parsed.label;\n\n return (\n <a\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: '6px',\n padding: '4px 10px',\n backgroundColor: isHovered\n ? 'var(--chatllm-chip-bg-hover, #e2e8f0)'\n : 'var(--chatllm-chip-bg, #f1f5f9)',\n border: '1px solid var(--chatllm-chip-border, #e2e8f0)',\n borderRadius: '16px',\n textDecoration: 'none',\n fontSize: '13px',\n fontWeight: 500,\n color: 'var(--chatllm-chip-text, #475569)',\n transition: 'all 0.15s ease',\n cursor: 'pointer',\n maxWidth: '180px',\n ...style,\n }}\n title={`${displayLabel} - ${domain}`}\n >\n {/* 번호 배지 */}\n {displayNumber && (\n <span\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '18px',\n height: '18px',\n borderRadius: '50%',\n backgroundColor: domainColor,\n color: '#ffffff',\n fontSize: '11px',\n fontWeight: 600,\n flexShrink: 0,\n }}\n >\n {displayNumber}\n </span>\n )}\n\n {/* 파비콘 또는 링크 아이콘 */}\n {showFavicon && !displayNumber && (\n <span\n style={{\n width: '16px',\n height: '16px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n }}\n >\n <IconSvg\n name=\"links-line\"\n size={14}\n color={domainColor}\n />\n </span>\n )}\n\n {/* 텍스트 */}\n <span\n style={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {displayLabel}\n </span>\n\n {/* 외부 링크 아이콘 */}\n <IconSvg\n name=\"external-link-line\"\n size={12}\n color=\"var(--chatllm-text-muted, #94a3b8)\"\n style={{\n opacity: isHovered ? 1 : 0.6,\n flexShrink: 0,\n }}\n />\n </a>\n );\n};\n\nexport default LinkChip;\n","/**\n * @description 빈 상태 컴포넌트\n * 대화가 없을 때 표시되는 시작 화면\n */\n\nimport React from 'react';\nimport { IconSvg, IconName } from './Icon';\nimport type { EmptyStateProps, ActionItem } from '../types';\n\nexport const EmptyState: React.FC<EmptyStateProps> = ({\n greeting,\n templates = [],\n onTemplateClick,\n actions = [],\n onActionSelect,\n}) => {\n const getActionIcon = (icon: string): IconName => {\n const iconMap: Record<string, IconName> = {\n search: 'search-line',\n image: 'image-line',\n code: 'code-s-slash-line',\n document: 'file-text-line',\n };\n return iconMap[icon] || 'sparkling-line';\n };\n\n return (\n <div\n className=\"chatllm-empty-state\"\n style={{\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '48px 24px',\n textAlign: 'center',\n }}\n >\n {/* Logo */}\n <div\n style={{\n width: '64px',\n height: '64px',\n borderRadius: '16px',\n background: 'linear-gradient(135deg, #3b82f6, #8b5cf6)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n marginBottom: '24px',\n boxShadow: '0 8px 32px rgba(59, 130, 246, 0.25)',\n }}\n >\n <IconSvg name=\"sparkling-line\" size={32} color=\"#ffffff\" />\n </div>\n\n {/* Greeting */}\n <h1\n style={{\n fontSize: '28px',\n fontWeight: 600,\n color: 'var(--chatllm-text, #1f2937)',\n marginBottom: '8px',\n }}\n >\n {greeting}\n </h1>\n <p\n style={{\n fontSize: '16px',\n color: 'var(--chatllm-text-muted, #6b7280)',\n marginBottom: '32px',\n }}\n >\n 무엇을 도와드릴까요?\n </p>\n\n {/* Actions Grid */}\n {actions.length > 0 && (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fit, minmax(140px, 1fr))',\n gap: '12px',\n width: '100%',\n maxWidth: '600px',\n marginBottom: '32px',\n }}\n >\n {actions.map((action) => (\n <button\n key={action.id}\n onClick={() => onActionSelect?.(action)}\n style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n gap: '12px',\n padding: '20px 16px',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '12px',\n cursor: 'pointer',\n transition: 'all 0.2s',\n }}\n onMouseOver={(e) => {\n e.currentTarget.style.borderColor = 'var(--chatllm-primary, #3b82f6)';\n e.currentTarget.style.boxShadow = '0 4px 12px rgba(59, 130, 246, 0.1)';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.borderColor = 'var(--chatllm-border, #e5e7eb)';\n e.currentTarget.style.boxShadow = 'none';\n }}\n >\n <div\n style={{\n width: '44px',\n height: '44px',\n borderRadius: '12px',\n backgroundColor: 'var(--chatllm-primary-light, #dbeafe)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <IconSvg\n name={getActionIcon(action.icon)}\n size={22}\n color=\"var(--chatllm-primary, #3b82f6)\"\n />\n </div>\n <div>\n <div\n style={{\n fontSize: '14px',\n fontWeight: 500,\n color: 'var(--chatllm-text, #1f2937)',\n }}\n >\n {action.label}\n </div>\n </div>\n </button>\n ))}\n </div>\n )}\n\n {/* Templates */}\n {templates.length > 0 && (\n <div style={{ width: '100%', maxWidth: '600px' }}>\n <h3\n style={{\n fontSize: '14px',\n fontWeight: 500,\n color: 'var(--chatllm-text-muted, #6b7280)',\n marginBottom: '12px',\n textAlign: 'left',\n }}\n >\n 추천 프롬프트\n </h3>\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: '8px',\n }}\n >\n {templates.map((template) => (\n <button\n key={template.id}\n onClick={() => onTemplateClick(template)}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '12px',\n padding: '14px 16px',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '10px',\n cursor: 'pointer',\n textAlign: 'left',\n transition: 'all 0.2s',\n }}\n onMouseOver={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg-hover, #f9fafb)';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--chatllm-bg, #ffffff)';\n }}\n >\n <div\n style={{\n width: '36px',\n height: '36px',\n borderRadius: '8px',\n backgroundColor: 'var(--chatllm-bg-secondary, #f3f4f6)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n }}\n >\n <IconSvg name=\"file-text-line\" size={18} color=\"var(--chatllm-text-muted, #6b7280)\" />\n </div>\n <div style={{ flex: 1, minWidth: 0 }}>\n <div\n style={{\n fontSize: '14px',\n fontWeight: 500,\n color: 'var(--chatllm-text, #1f2937)',\n }}\n >\n {template.title}\n </div>\n <div\n style={{\n fontSize: '13px',\n color: 'var(--chatllm-text-muted, #9ca3af)',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {template.description}\n </div>\n </div>\n <IconSvg name=\"arrow-right-line\" size={16} color=\"var(--chatllm-text-muted, #9ca3af)\" />\n </button>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n};\n\nexport default EmptyState;\n","/**\n * @description 메모리 패널 컴포넌트\n * 저장된 메모리, 컨텍스트 요약, 학습된 정보 조회\n */\n\nimport React, { useState } from 'react';\nimport { IconSvg } from './Icon';\n\nexport interface MemoryItem {\n id: string;\n key: string;\n value: string;\n category?: 'context' | 'preference' | 'skill' | 'fact';\n timestamp: number;\n}\n\nexport interface MemoryPanelProps {\n /** 메모리 아이템 목록 */\n items: MemoryItem[];\n /** 컨텍스트 요약 (압축된 대화) */\n contextSummary?: string;\n /** 삭제 핸들러 */\n onDelete?: (id: string) => void;\n /** 전체 삭제 핸들러 */\n onClearAll?: () => void;\n /** 패널 열림 상태 */\n isOpen: boolean;\n /** 패널 토글 */\n onToggle: () => void;\n}\n\nconst categoryLabels: Record<string, string> = {\n context: '대화 컨텍스트',\n preference: '사용자 선호',\n skill: '학습된 스킬',\n fact: '저장된 정보',\n};\n\nconst categoryColors: Record<string, string> = {\n context: '#3b82f6',\n preference: '#8b5cf6',\n skill: '#10b981',\n fact: '#f59e0b',\n};\n\nexport const MemoryPanel: React.FC<MemoryPanelProps> = ({\n items,\n contextSummary,\n onDelete,\n onClearAll,\n isOpen,\n onToggle,\n}) => {\n const [expandedId, setExpandedId] = useState<string | null>(null);\n const [activeTab, setActiveTab] = useState<'all' | 'context' | 'preference' | 'skill' | 'fact'>('all');\n\n const filteredItems = activeTab === 'all'\n ? items\n : items.filter(item => item.category === activeTab);\n\n const formatDate = (timestamp: number): string => {\n const date = new Date(timestamp);\n return date.toLocaleDateString('ko-KR', {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n };\n\n if (!isOpen) {\n return (\n <button\n onClick={onToggle}\n style={{\n position: 'fixed',\n right: '16px',\n bottom: '100px',\n width: '48px',\n height: '48px',\n borderRadius: '50%',\n backgroundColor: 'var(--chatllm-primary, #3b82f6)',\n border: 'none',\n boxShadow: '0 4px 12px rgba(59, 130, 246, 0.3)',\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex: 100,\n }}\n >\n <IconSvg name=\"robot-line\" size={24} color=\"#ffffff\" />\n </button>\n );\n }\n\n return (\n <div\n className=\"chatllm-memory-panel\"\n style={{\n position: 'fixed',\n right: '16px',\n bottom: '16px',\n width: '380px',\n maxHeight: '70vh',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n borderRadius: '16px',\n boxShadow: '0 8px 32px rgba(0, 0, 0, 0.12)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n display: 'flex',\n flexDirection: 'column',\n overflow: 'hidden',\n zIndex: 100,\n }}\n >\n {/* Header */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '16px',\n borderBottom: '1px solid var(--chatllm-border, #e5e7eb)',\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>\n <div\n style={{\n width: '32px',\n height: '32px',\n borderRadius: '8px',\n backgroundColor: 'var(--chatllm-primary-light, #dbeafe)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <IconSvg name=\"robot-line\" size={18} color=\"var(--chatllm-primary, #3b82f6)\" />\n </div>\n <div>\n <div style={{ fontSize: '15px', fontWeight: 600, color: 'var(--chatllm-text, #1f2937)' }}>\n AI 메모리\n </div>\n <div style={{ fontSize: '12px', color: 'var(--chatllm-text-muted, #9ca3af)' }}>\n {items.length}개 항목\n </div>\n </div>\n </div>\n <div style={{ display: 'flex', gap: '4px' }}>\n {onClearAll && items.length > 0 && (\n <button\n onClick={onClearAll}\n style={{\n padding: '8px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '8px',\n cursor: 'pointer',\n }}\n title=\"전체 삭제\"\n >\n <IconSvg name=\"delete-bin-line\" size={18} color=\"var(--chatllm-text-muted, #9ca3af)\" />\n </button>\n )}\n <button\n onClick={onToggle}\n style={{\n padding: '8px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '8px',\n cursor: 'pointer',\n }}\n >\n <IconSvg name=\"close-line\" size={18} color=\"var(--chatllm-text-muted, #9ca3af)\" />\n </button>\n </div>\n </div>\n\n {/* Tabs */}\n <div\n style={{\n display: 'flex',\n gap: '4px',\n padding: '12px 16px',\n borderBottom: '1px solid var(--chatllm-border-light, #f3f4f6)',\n overflowX: 'auto',\n }}\n >\n {(['all', 'context', 'preference', 'skill', 'fact'] as const).map((tab) => (\n <button\n key={tab}\n onClick={() => setActiveTab(tab)}\n style={{\n padding: '6px 12px',\n fontSize: '13px',\n fontWeight: activeTab === tab ? 500 : 400,\n backgroundColor: activeTab === tab\n ? 'var(--chatllm-primary-light, #dbeafe)'\n : 'transparent',\n color: activeTab === tab\n ? 'var(--chatllm-primary, #3b82f6)'\n : 'var(--chatllm-text-muted, #6b7280)',\n border: 'none',\n borderRadius: '6px',\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n }}\n >\n {tab === 'all' ? '전체' : categoryLabels[tab]}\n </button>\n ))}\n </div>\n\n {/* Content */}\n <div style={{ flex: 1, overflow: 'auto', padding: '12px' }}>\n {/* Context Summary */}\n {contextSummary && activeTab === 'all' && (\n <div\n style={{\n padding: '12px',\n marginBottom: '12px',\n backgroundColor: 'var(--chatllm-bg-secondary, #f9fafb)',\n borderRadius: '10px',\n borderLeft: '3px solid var(--chatllm-primary, #3b82f6)',\n }}\n >\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n marginBottom: '8px',\n }}\n >\n <IconSvg name=\"file-text-line\" size={14} color=\"var(--chatllm-primary, #3b82f6)\" />\n <span style={{ fontSize: '12px', fontWeight: 500, color: 'var(--chatllm-primary, #3b82f6)' }}>\n 대화 요약\n </span>\n </div>\n <p\n style={{\n fontSize: '13px',\n lineHeight: '1.6',\n color: 'var(--chatllm-text, #374151)',\n margin: 0,\n }}\n >\n {contextSummary}\n </p>\n </div>\n )}\n\n {/* Memory Items */}\n {filteredItems.length === 0 ? (\n <div\n style={{\n padding: '32px 16px',\n textAlign: 'center',\n color: 'var(--chatllm-text-muted, #9ca3af)',\n }}\n >\n <IconSvg name=\"robot-line\" size={32} color=\"var(--chatllm-text-muted, #d1d5db)\" />\n <p style={{ fontSize: '14px', marginTop: '12px' }}>저장된 메모리가 없습니다</p>\n </div>\n ) : (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n {filteredItems.map((item) => (\n <div\n key={item.id}\n style={{\n padding: '12px',\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '10px',\n cursor: 'pointer',\n transition: 'all 0.2s',\n }}\n onClick={() => setExpandedId(expandedId === item.id ? null : item.id)}\n >\n {/* Item Header */}\n <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between' }}>\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '4px' }}>\n {item.category && (\n <span\n style={{\n fontSize: '11px',\n fontWeight: 500,\n padding: '2px 8px',\n backgroundColor: `${categoryColors[item.category]}15`,\n color: categoryColors[item.category],\n borderRadius: '4px',\n }}\n >\n {categoryLabels[item.category]}\n </span>\n )}\n <span style={{ fontSize: '11px', color: 'var(--chatllm-text-muted, #9ca3af)' }}>\n {formatDate(item.timestamp)}\n </span>\n </div>\n <div\n style={{\n fontSize: '13px',\n fontWeight: 500,\n color: 'var(--chatllm-text, #1f2937)',\n }}\n >\n {item.key}\n </div>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: '4px' }}>\n {onDelete && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n onDelete(item.id);\n }}\n style={{\n padding: '4px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '4px',\n cursor: 'pointer',\n opacity: 0.5,\n }}\n >\n <IconSvg name=\"delete-bin-line\" size={14} color=\"var(--chatllm-text-muted, #9ca3af)\" />\n </button>\n )}\n <IconSvg\n name={expandedId === item.id ? 'arrow-up-s-line' : 'arrow-down-s-line'}\n size={16}\n color=\"var(--chatllm-text-muted, #9ca3af)\"\n />\n </div>\n </div>\n\n {/* Expanded Content */}\n {expandedId === item.id && (\n <div\n style={{\n marginTop: '12px',\n paddingTop: '12px',\n borderTop: '1px solid var(--chatllm-border-light, #f3f4f6)',\n }}\n >\n <p\n style={{\n fontSize: '13px',\n lineHeight: '1.6',\n color: 'var(--chatllm-text, #374151)',\n margin: 0,\n whiteSpace: 'pre-wrap',\n }}\n >\n {item.value}\n </p>\n </div>\n )}\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default MemoryPanel;\n","/**\n * @description 설정 모달 컴포넌트\n * 일반/개인화/데이터 설정 탭 포함\n */\n\nimport React, { useState } from 'react';\nimport { IconSvg } from './Icon';\nimport type { PersonalizationConfig, SettingsTab } from '../types';\n\nexport interface SettingsModalProps {\n /** 모달 열림 상태 */\n isOpen: boolean;\n /** 모달 닫기 핸들러 */\n onClose: () => void;\n /** 개인화 설정 */\n personalization: PersonalizationConfig;\n /** 개인화 설정 변경 핸들러 */\n onPersonalizationChange: (config: PersonalizationConfig) => void;\n /** API 키 */\n apiKey?: string;\n /** API 키 변경 핸들러 */\n onApiKeyChange?: (key: string) => void;\n /** 전체 데이터 삭제 핸들러 */\n onClearAllData?: () => void;\n /** API 키 레이블 */\n apiKeyLabel?: string;\n /** API 키 설명 */\n apiKeyDescription?: string;\n}\n\nconst DEFAULT_PERSONALIZATION: PersonalizationConfig = {\n responseStyle: {\n warmth: 'medium',\n enthusiasm: 'medium',\n emojiUsage: 'low',\n formatting: 'default',\n verbosity: 'balanced',\n },\n userProfile: {},\n useMemory: true,\n language: 'auto',\n};\n\nexport const SettingsModal: React.FC<SettingsModalProps> = ({\n isOpen,\n onClose,\n personalization,\n onPersonalizationChange,\n apiKey = '',\n onApiKeyChange,\n onClearAllData,\n apiKeyLabel = 'API Key',\n apiKeyDescription = 'Cloud 모델 사용에 필요합니다',\n}) => {\n const [activeTab, setActiveTab] = useState<SettingsTab>('general');\n const [localApiKey, setLocalApiKey] = useState(apiKey);\n\n if (!isOpen) return null;\n\n const updateResponseStyle = (key: string, value: string) => {\n onPersonalizationChange({\n ...personalization,\n responseStyle: {\n ...personalization.responseStyle,\n [key]: value,\n },\n });\n };\n\n const updateUserProfile = (key: string, value: string) => {\n onPersonalizationChange({\n ...personalization,\n userProfile: {\n ...personalization.userProfile,\n [key]: value,\n },\n });\n };\n\n const handleApiKeyChange = (value: string) => {\n setLocalApiKey(value);\n onApiKeyChange?.(value);\n };\n\n return (\n <div\n className=\"chatllm-settings-overlay\"\n style={{\n position: 'fixed',\n inset: 0,\n backgroundColor: 'rgba(0, 0, 0, 0.3)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex: 1000,\n }}\n onClick={onClose}\n >\n <div\n className=\"chatllm-settings-modal\"\n style={{\n backgroundColor: 'var(--chatllm-bg, #ffffff)',\n borderRadius: '16px',\n width: '100%',\n maxWidth: '800px',\n height: '80vh',\n maxHeight: '600px',\n margin: '16px',\n boxShadow: '0 20px 60px rgba(0, 0, 0, 0.15)',\n display: 'flex',\n overflow: 'hidden',\n }}\n onClick={(e) => e.stopPropagation()}\n >\n {/* Sidebar */}\n <div\n style={{\n width: '200px',\n backgroundColor: 'var(--chatllm-bg-secondary, #f9fafb)',\n borderRight: '1px solid var(--chatllm-border, #e5e7eb)',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n {/* Close Button */}\n <div style={{ padding: '16px', borderBottom: '1px solid var(--chatllm-border, #e5e7eb)' }}>\n <button\n onClick={onClose}\n style={{\n padding: '8px',\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '8px',\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <IconSvg name=\"close-line\" size={20} color=\"var(--chatllm-text-muted, #6b7280)\" />\n </button>\n </div>\n\n {/* Tabs */}\n <nav style={{ flex: 1, padding: '8px' }}>\n <TabButton\n active={activeTab === 'general'}\n onClick={() => setActiveTab('general')}\n icon=\"settings-3-line\"\n label=\"일반\"\n />\n <TabButton\n active={activeTab === 'personalization'}\n onClick={() => setActiveTab('personalization')}\n icon=\"user-3-line\"\n label=\"개인 맞춤 설정\"\n />\n <TabButton\n active={activeTab === 'data'}\n onClick={() => setActiveTab('data')}\n icon=\"delete-bin-line\"\n label=\"데이터 제어\"\n />\n </nav>\n </div>\n\n {/* Content */}\n <div style={{ flex: 1, overflow: 'auto', padding: '24px' }}>\n {activeTab === 'general' && (\n <div>\n <h2 style={{ fontSize: '20px', fontWeight: 600, marginBottom: '24px', color: 'var(--chatllm-text, #1f2937)' }}>\n 일반\n </h2>\n\n {/* Language */}\n <SettingRow label=\"언어\">\n <select\n value={personalization.language}\n onChange={(e) => onPersonalizationChange({ ...personalization, language: e.target.value })}\n style={selectStyle}\n >\n <option value=\"auto\">자동 탐지</option>\n <option value=\"ko\">한국어</option>\n <option value=\"en\">English</option>\n <option value=\"ja\">日本語</option>\n </select>\n </SettingRow>\n\n {/* Reset */}\n <SettingRow label=\"기본값으로 초기화\" description=\"모든 설정을 초기 상태로 되돌립니다\">\n <button\n onClick={() => onPersonalizationChange(DEFAULT_PERSONALIZATION)}\n style={buttonSecondaryStyle}\n >\n 초기화\n </button>\n </SettingRow>\n\n {/* API Key */}\n {onApiKeyChange && (\n <div style={{ marginTop: '32px', paddingTop: '24px', borderTop: '1px solid var(--chatllm-border, #e5e7eb)' }}>\n <h3 style={{ fontSize: '16px', fontWeight: 500, marginBottom: '16px', color: 'var(--chatllm-text, #1f2937)' }}>\n API 설정\n </h3>\n <div>\n <label style={{ display: 'block', fontSize: '14px', marginBottom: '8px', color: 'var(--chatllm-text, #374151)' }}>\n {apiKeyLabel}\n </label>\n <input\n type=\"password\"\n value={localApiKey}\n onChange={(e) => handleApiKeyChange(e.target.value)}\n placeholder=\"API 키를 입력하세요\"\n style={inputStyle}\n />\n <p style={{ fontSize: '12px', color: 'var(--chatllm-text-muted, #9ca3af)', marginTop: '4px' }}>\n {apiKeyDescription}\n </p>\n </div>\n </div>\n )}\n </div>\n )}\n\n {activeTab === 'personalization' && (\n <div>\n <h2 style={{ fontSize: '20px', fontWeight: 600, marginBottom: '24px', color: 'var(--chatllm-text, #1f2937)' }}>\n 개인 맞춤 설정\n </h2>\n\n {/* User Profile */}\n <section style={{ marginBottom: '32px' }}>\n <h3 style={{ fontSize: '14px', fontWeight: 500, color: 'var(--chatllm-text-muted, #6b7280)', marginBottom: '16px' }}>\n 사용자 프로필\n </h3>\n <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>\n <div>\n <label style={labelStyle}>닉네임</label>\n <input\n type=\"text\"\n value={personalization.userProfile.nickname || ''}\n onChange={(e) => updateUserProfile('nickname', e.target.value)}\n placeholder=\"어떻게 불러드릴까요?\"\n style={inputStyle}\n />\n </div>\n <div>\n <label style={labelStyle}>직업</label>\n <input\n type=\"text\"\n value={personalization.userProfile.occupation || ''}\n onChange={(e) => updateUserProfile('occupation', e.target.value)}\n placeholder=\"예: 소프트웨어 개발자\"\n style={inputStyle}\n />\n </div>\n <div>\n <label style={labelStyle}>추가 정보</label>\n <textarea\n value={personalization.userProfile.additionalInfo || ''}\n onChange={(e) => updateUserProfile('additionalInfo', e.target.value)}\n placeholder=\"관심사, 선호 사항 등\"\n rows={3}\n style={{ ...inputStyle, resize: 'none' }}\n />\n </div>\n </div>\n </section>\n\n {/* Response Style */}\n <section>\n <h3 style={{ fontSize: '14px', fontWeight: 500, color: 'var(--chatllm-text-muted, #6b7280)', marginBottom: '16px' }}>\n 응답 스타일\n </h3>\n\n <SettingRow label=\"따뜻함\">\n <select\n value={personalization.responseStyle.warmth}\n onChange={(e) => updateResponseStyle('warmth', e.target.value)}\n style={selectStyle}\n >\n <option value=\"high\">높음 - 친근하고 따뜻하게</option>\n <option value=\"medium\">기본값</option>\n <option value=\"low\">낮음 - 간결하고 사무적으로</option>\n </select>\n </SettingRow>\n\n <SettingRow label=\"열정적\">\n <select\n value={personalization.responseStyle.enthusiasm}\n onChange={(e) => updateResponseStyle('enthusiasm', e.target.value)}\n style={selectStyle}\n >\n <option value=\"high\">높음 - 적극적이고 활발하게</option>\n <option value=\"medium\">기본값</option>\n <option value=\"low\">낮음 - 차분하고 절제있게</option>\n </select>\n </SettingRow>\n\n <SettingRow label=\"이모지 사용\">\n <select\n value={personalization.responseStyle.emojiUsage}\n onChange={(e) => updateResponseStyle('emojiUsage', e.target.value)}\n style={selectStyle}\n >\n <option value=\"high\">높음 - 자주 사용</option>\n <option value=\"medium\">기본값</option>\n <option value=\"low\">낮음 - 거의 사용 안 함</option>\n </select>\n </SettingRow>\n\n <SettingRow label=\"응답 길이\">\n <select\n value={personalization.responseStyle.verbosity}\n onChange={(e) => updateResponseStyle('verbosity', e.target.value)}\n style={selectStyle}\n >\n <option value=\"detailed\">상세 - 자세하게 설명</option>\n <option value=\"balanced\">기본값</option>\n <option value=\"concise\">간결 - 핵심만 요약</option>\n </select>\n </SettingRow>\n </section>\n </div>\n )}\n\n {activeTab === 'data' && (\n <div>\n <h2 style={{ fontSize: '20px', fontWeight: 600, marginBottom: '24px', color: 'var(--chatllm-text, #1f2937)' }}>\n 데이터 제어\n </h2>\n\n {/* Memory Toggle */}\n <SettingRow label=\"메모리 사용\" description=\"대화 컨텍스트를 기억합니다\">\n <button\n onClick={() => onPersonalizationChange({ ...personalization, useMemory: !personalization.useMemory })}\n style={{\n width: '48px',\n height: '28px',\n borderRadius: '14px',\n backgroundColor: personalization.useMemory\n ? 'var(--chatllm-primary, #3b82f6)'\n : 'var(--chatllm-text-muted, #d1d5db)',\n border: 'none',\n cursor: 'pointer',\n position: 'relative',\n transition: 'background-color 0.2s',\n }}\n >\n <div\n style={{\n width: '22px',\n height: '22px',\n borderRadius: '50%',\n backgroundColor: '#ffffff',\n boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)',\n position: 'absolute',\n top: '3px',\n left: personalization.useMemory ? '23px' : '3px',\n transition: 'left 0.2s',\n }}\n />\n </button>\n </SettingRow>\n\n {/* Clear All Data */}\n {onClearAllData && (\n <SettingRow label=\"대화 기록 삭제\" description=\"모든 대화 기록을 삭제합니다\">\n <button\n onClick={() => {\n if (window.confirm('모든 대화 기록을 삭제하시겠습니까?')) {\n onClearAllData();\n }\n }}\n style={buttonDangerStyle}\n >\n 삭제\n </button>\n </SettingRow>\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n );\n};\n\n// Tab Button Component\nconst TabButton: React.FC<{\n active: boolean;\n onClick: () => void;\n icon: string;\n label: string;\n}> = ({ active, onClick, icon, label }) => (\n <button\n onClick={onClick}\n style={{\n width: '100%',\n display: 'flex',\n alignItems: 'center',\n gap: '12px',\n padding: '10px 12px',\n borderRadius: '10px',\n border: 'none',\n backgroundColor: active ? 'var(--chatllm-bg, #ffffff)' : 'transparent',\n boxShadow: active ? '0 1px 3px rgba(0, 0, 0, 0.08)' : 'none',\n color: active ? 'var(--chatllm-primary, #3b82f6)' : 'var(--chatllm-text-muted, #6b7280)',\n fontSize: '14px',\n cursor: 'pointer',\n textAlign: 'left',\n marginBottom: '4px',\n }}\n >\n <IconSvg name={icon as any} size={20} />\n {label}\n </button>\n);\n\n// Setting Row Component\nconst SettingRow: React.FC<{\n label: string;\n description?: string;\n children: React.ReactNode;\n}> = ({ label, description, children }) => (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '12px 0',\n borderBottom: '1px solid var(--chatllm-border-light, #f3f4f6)',\n }}\n >\n <div>\n <span style={{ fontSize: '14px', color: 'var(--chatllm-text, #374151)' }}>{label}</span>\n {description && (\n <p style={{ fontSize: '12px', color: 'var(--chatllm-text-muted, #9ca3af)', marginTop: '2px' }}>\n {description}\n </p>\n )}\n </div>\n {children}\n </div>\n);\n\n// Styles\nconst selectStyle: React.CSSProperties = {\n padding: '8px 12px',\n backgroundColor: 'var(--chatllm-bg-secondary, #f9fafb)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '8px',\n fontSize: '14px',\n color: 'var(--chatllm-text, #374151)',\n minWidth: '200px',\n cursor: 'pointer',\n};\n\nconst inputStyle: React.CSSProperties = {\n width: '100%',\n padding: '10px 12px',\n backgroundColor: 'var(--chatllm-bg-secondary, #f9fafb)',\n border: '1px solid var(--chatllm-border, #e5e7eb)',\n borderRadius: '8px',\n fontSize: '14px',\n color: 'var(--chatllm-text, #374151)',\n};\n\nconst labelStyle: React.CSSProperties = {\n display: 'block',\n fontSize: '12px',\n color: 'var(--chatllm-text-muted, #6b7280)',\n marginBottom: '6px',\n};\n\nconst buttonSecondaryStyle: React.CSSProperties = {\n padding: '8px 16px',\n backgroundColor: 'var(--chatllm-bg-secondary, #f3f4f6)',\n border: 'none',\n borderRadius: '8px',\n fontSize: '14px',\n color: 'var(--chatllm-text, #374151)',\n cursor: 'pointer',\n};\n\nconst buttonDangerStyle: React.CSSProperties = {\n padding: '8px 16px',\n backgroundColor: 'var(--chatllm-danger-bg, #fef2f2)',\n border: 'none',\n borderRadius: '8px',\n fontSize: '14px',\n color: 'var(--chatllm-danger, #dc2626)',\n cursor: 'pointer',\n};\n\nexport default SettingsModal;\n"],"mappings":"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","names":["import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_react","import_react","import_react","import_jsx_runtime","import_jsx_runtime","React","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","formatDate","import_react","import_jsx_runtime","DEFAULT_PERSONALIZATION","import_jsx_runtime","React"]}