@things-factory/ai-assistant 10.1.123 โ†’ 10.1.125

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,"file":"assistant-chat.js","sourceRoot":"","sources":["../../client/components/assistant-chat.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * <ox-assistant-chat> โ€” AI ๋„์šฐ๋ฏธ ์ฑ„ํŒ… ์ปดํฌ๋„ŒํŠธ (Lit).\n *\n * ์ž…๋ ฅ:\n * - sessionId: ์˜์† ChatSession ์‹๋ณ„์ž (์—†์œผ๋ฉด ad-hoc ๋ชจ๋“œ, ๋ฉ”์‹œ์ง€ ์˜์† ์•ˆ ๋จ)\n * - currentBoard: ํ˜„์žฌ BoardModel JSON (ํ˜ธ์ŠคํŠธ๊ฐ€ ๋™๊ธฐํ™”)\n * - scopes / knownTypes / categories: ๋„๋ฉ”์ธ ์ปจํ…์ŠคํŠธ\n *\n * ์ถœ๋ ฅ (์ด๋ฒคํŠธ):\n * - `scene-edit-patch` { detail: { patch, summary, confidence, patchId } }\n * ํ˜ธ์ŠคํŠธ๊ฐ€ ๋ฐ›์•„์„œ ๋ณด๋“œ ๋ชจ๋ธ์— ์ ์šฉ (applyScenePatch from @operato/scene-ops).\n * - `chat-followup` { detail: { question } }\n *\n * ๋ชจ๋“œ ์ „ํ™˜์€ ์ปจํ…Œ์ด๋„ˆ (์›Œํฌ์ŠคํŽ˜์ด์Šค) ์˜ ์ฑ…์ž„. ์ด ์ปดํฌ๋„ŒํŠธ๋Š” ์ž์ฒด๋กœ ํ’€ ์ฑ„ํŒ… UX.\n */\nimport '@material/web/icon/icon.js'\nimport './assistant-session-toolbar.js'\nimport { assistantAutoAskKey, assistantDraftDecision, assistantModelFingerprint, type AssistantRequestContext } from '../utils/assistant-request-context.js'\n\nimport { LitElement, css, html, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js'\nimport { client } from '@operato/graphql'\nimport { auth } from '@things-factory/auth-base/dist-client/index.js'\nimport { i18next, localize } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\nimport gql from 'graphql-tag'\n\nimport {\n renderMarkdown,\n injectMentionRefids,\n injectMentionUserIds,\n stripMentionRefids\n} from './markdown.js'\nimport { acceptOf, chatAttachmentUrl, refuseAttachments, textCharsOf } from '../utils/attachment-policy.js'\nimport { pastedTableFile } from '../utils/pasted-table.js'\nimport { appendWords, composerHeight, composerKeyAction, sendShortcut, tableAsWords } from '../utils/composer-frame.js'\nimport { readSpreadsheet, spreadsheetKindOf, type SpreadsheetRefusal } from '../utils/spreadsheet-text.js'\nimport { entryReviewAddress, offersWorkspaceReview } from '../utils/entry-workspace.js'\nimport { buildAssistantChatInput, buildChatMutationInput } from './chat-input-builder.js'\nimport { receiveRemoteMessage, reconcileSentLine, remoteMessageToLine } from './chat-echo-dedup.js'\nimport './mention-popup.js'\nimport {\n buildMentionCandidates,\n buildCatalogCandidates,\n buildSlashCandidates,\n buildUserCandidates,\n extractMentionContext,\n filterMentionCandidates,\n applyMentionSelection,\n resolveMentionToken,\n type MentionCandidate,\n type FilterResult\n} from './mention-popup.js'\n/*\n * ๊ธฐ๋ณธ ์นดํƒˆ๋กœ๊ทธยท์Šฌ๋ž˜์‹œ ๋ชฉ๋ก์€ **ํ˜ธ์ŠคํŠธ๊ฐ€ ๋„ฃ๋Š”๋‹ค** (2026-09-10).\n *\n * ์—ฌ๊ธฐ์„œ `./default-catalog-entries.js` ๋ฅผ ์ง์ ‘ import ํ•˜๊ณ  ์žˆ์—ˆ๋‹ค. ๊ทธ ๋‘ ํŒŒ์ผ์€ ๋ณด๋“œ ์ €์ž‘์˜\n * ๋ชฉ๋ก์ด๊ณ , ๊ทธ๋ž˜์„œ ์ด ๋Œ€ํ™”๋ฉด์ด ๋ณด๋“œ ํŽธ์ง‘๊ธฐ ์—†์ด๋Š” ์„ค ์ˆ˜ ์—†์—ˆ๋‹ค โ€” ์ด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ค‘๋ฆฝ ํŒจํ‚ค์ง€๋กœ\n * ์˜ค์ง€ ๋ชปํ•œ ์œ ์ผํ•œ ์ด์œ ๊ฐ€ ๊ทธ ๋‘ ์ค„์ด์—ˆ๋‹ค.\n *\n * ๋“ฑ๋กํ•˜๋Š” ์ชฝ์ด ์ฃผ์ธ์ด๋ผ๋Š” ๊ทœ์•ฝ์„ ๋”ฐ๋ฅธ๋‹ค(`registerToolCategory` ์™€ ๊ฐ™์€ ๋ชจ์–‘): `board-ai` ๋ฅผ\n * import ํ•˜๋ฉด ๊ทธ ํŒจํ‚ค์ง€๊ฐ€ ์ž๊ธฐ ๊ธฐ๋ณธ๊ฐ’์„ ๋„ฃ๊ณ , ์•ˆ ํ•˜๋ฉด ๋น„์–ด ์žˆ๋‹ค. ๋ณด๋“œ๊ฐ€ ์—†๋Š” ์ œํ’ˆ์— ๋ณด๋“œ ๋ชฉ๋ก์ด\n * ๋œจ์ง€ ์•Š๋Š” ๊ฒƒ์ด ๋งž๋‹ค.\n */\nimport { chatDefaults } from './chat-defaults.js'\nimport { isDifferentConversation, resolveConversation, type AssistantMode, type AssistantModeView, pickInitialMode } from './assistant-mode.js'\nimport { parseProposalOutcomeLine, parseProposalRequestLine, proposalCardState, type ParsedProposalOutcome } from './proposal-outcome-line.js'\nimport { availableTriggers, type TriggerChip } from './chat-triggers.js'\nimport './entry-review.js'\nimport { entryGroupOf, entryReadyCount, entryTitle, isChangeProposal, isEntryProposal, latestEntryKeys } from '../utils/entry-proposal.js'\nimport { isWorkspaceProposal, versionOfCard, workspaceAddress } from '../utils/workspace.js'\nimport { isOpenPageProposal, openPageNote } from '../utils/open-page.js'\n\ninterface ChatLine {\n role: 'user' | 'assistant' | 'system'\n /** ์„œ๋ฒ„ ChatMessage.id โ€” ์‹ค์‹œ๊ฐ„ ๋ฐฉ์†ก ์—์ฝ” dedup ์˜ ํ‚ค (์žˆ์„ ๋•Œ๋งŒ). */\n id?: string\n /** ํด๋ผ ์ž„์‹œ ํ•ธ๋“ค โ€” ์˜์† id ๋ถ€์—ฌ ์ „ optimistic ๋ผ์ธ์„ index ๋น„์˜์กด์œผ๋กœ ์‹๋ณ„/reconcile. */\n _localId?: string\n /** ๋ณด๋‚ธ ์‚ฌ์šฉ์ž email/name โ€” ๊ทธ๋ฃน์ฑ— ๋ฐœ์‹ ์ž ํ‘œ์‹œ + ์ž๊ธฐ ์—ฌ๋ถ€ ํŒ์ •.\n * **email ๋กœ ํŒ์ •ํ•œ๋‹ค**: ๋กœ๊ทธ์ธ ์‹๋ณ„์ž๋ผ ๋น„์–ด ์žˆ์ง€ ์•Š๊ณ , ์‹œ์Šคํ…œ ๋‚ด๋ถ€ ๊ด€๋ฆฌํ‚ค(User.id)๋ฅผ\n * ํด๋ผ์ด์–ธํŠธ ํŒ์ •์— ๋Œ์–ด๋“ค์ด์ง€ ์•Š๋Š”๋‹ค(๊ด€๋ฆฌํ‚ค ๋…ธ์ถœ์ด ๊ณ„์•ฝ์ฒ˜๋Ÿผ ๊ตณ๋Š” ๊ฒƒ์„ ํ”ผํ•œ๋‹ค). */\n senderEmail?: string\n senderName?: string\n /** ๋ฉ”์‹œ์ง€ ๋ณธ๋ฌธ. `#token{refid:N}` inline marker ๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ์Œ (์˜์†๋œ ๋ฉ”์‹œ์ง€ / ์‚ฌ์šฉ์ž\n * popup pick / AI resolved mention). ๋ Œ๋”๋ง ์‹œ ์ถ”์ถœํ•ด์„œ `<span data-refid=\"N\">` ์œผ๋กœ ๋ณ€ํ™˜. */\n content: string\n patchSummary?: string\n followUp?: string\n patchId?: string\n pending?: boolean\n /**\n * ์„œ๋ฒ„๊ฐ€ ์ด ์‚ฌ๋žŒ์—๊ฒŒ ๊ฐ’์„ ์•ˆ ๋‚ด์ค€ ์ค„ โ€” ADR-0073 ํŒ์ • 1.\n *\n * `content` ์— ์˜จ ๊ฒƒ์€ ใ€Œ์ด ๋‹ต์€ <๋ฌธ> ๊ถŒํ•œ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹คใ€ ํ•œ ์ค„์ด๋‹ค. ์ค„์„ ์ง€์šฐ์ง€ ์•Š๋Š” ์ด์œ ๋Š”, ๋ฐฉ์—\n * ๋ฌด์Šจ ์ผ์ด ์žˆ์—ˆ๋Š”์ง€๋Š” ์•Œ ์ˆ˜ ์žˆ์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ฐ’๋งŒ ์•ˆ ๋ณด์ธ๋‹ค.\n */\n redacted?: boolean\n /** AI ๊ฐ€ ์‘๋‹ต์„ ๋งŒ๋“œ๋Š” ๋™์•ˆ ํ˜ธ์ถœํ•œ ๋„๊ตฌ trace โ€” fold-able ๋ฐ•์Šค์—์„œ ๋…ธ์ถœ. */\n toolUsages?: Array<{\n name: string\n arguments: any\n result: any\n kind: 'read' | 'write' | 'unknown'\n /** ๋ช‡ ๋ฒˆ์งธ LLM ํ„ด โ€” ๋‹จ๊ณ„๋กœ ์ฝ๊ธฐ ์œ„ํ•œ ๊ฐ’. */\n iter?: number\n /** ์ด ํ˜ธ์ถœ์ด ์–ด๋–ป๊ฒŒ ๋๋‚ฌ๋Š”๊ฐ€ โ€” ๋ฐฐ์ง€. */\n outcome?: 'ok' | 'rejected' | 'queued' | 'proposed' | 'folded' | 'error'\n }>\n /** UI ์ƒํƒœ: tool usage ๋ฐ•์Šค ํŽผ์นจ ์—ฌ๋ถ€ (assistant ๋ฉ”์‹œ์ง€๋งˆ๋‹ค ๋…๋ฆฝ). */\n toolUsagesOpen?: boolean\n /** UI ์ƒํƒœ: ์ ‘ํžŒ ์‹œ์Šคํ…œ ๊ธฐ๋ก์„ ํŽผ์ณค๋Š”๊ฐ€(๊ณ์ค„์ด ๋Œ€ํ™”๋ฅผ ๊ฐ€๋ฆฌ์ง€ ์•Š๊ฒŒ ๊ธฐ๋ณธ์€ 3์ค„ ์ ‘๊ธฐ). */\n systemOpen?: boolean\n /**\n * ์กฐ์น˜ ์ œ์•ˆ โ€” AI ๊ฐ€ **์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ ** ์ œ์•ˆํ•œ ๊ฒƒ๋“ค. ์‚ฌ์šฉ์ž๊ฐ€ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ์•ผ ์‹คํ–‰๋œ๋‹ค.\n *\n * ์˜์†ํ•˜์ง€ ์•Š๋Š”๋‹ค(์ด๋ฒˆ ์‘๋‹ต์—๋งŒ ๋ถ™๋Š”๋‹ค): ์Šน์ธ์€ **์ง€๊ธˆ** ํ•˜๋Š” ํŒ๋‹จ์ด๊ณ , ๋˜๋Œ๋ฆด ์ˆ˜ ์—†๋Š” ์กฐ์น˜๋ฅผ\n * ์ง€๋‚œ ๋งฅ๋ฝ์œผ๋กœ ๋‹ค์‹œ ๊ถŒํ•˜๋Š” ๊ฒƒ์€ ์œ„ํ—˜ํ•˜๋‹ค. ๋‹ค์‹œ ํ•„์š”ํ•˜๋ฉด ๋‹ค์‹œ ๋ฌผ์–ด๋ณด๋ฉด ๋œ๋‹ค.\n */\n proposals?: any[]\n /**\n * ์ ‘์ง€ ๊ฒฝ๊ณ  โ€” ์ด ๋‹ต์ด ์–ธ๊ธ‰ํ–ˆ์œผ๋‚˜ ๋ชจ๋ธ์ด ๋ฐ›์€ ๊ทผ๊ฑฐ(ํ”„๋กฌํ”„ํŠธยท๋ณด๋“œ ๋ฌธ๋งฅยท์ด๋ ฅยท๋„๊ตฌ ๊ฒฐ๊ณผ)์— ์—†๋˜ ์‹๋ณ„์ž.\n * ์žˆ์œผ๋ฉด ๊ทธ ๋Œ€์ƒ์€ ๋งŒ๋“ค์–ด ๋‚ธ ๊ฒƒ์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ฃผ์˜๋ฅผ ๋‹ต ์•„๋ž˜์— ํ‘œ์‹œํ•œ๋‹ค(๋‹ต ์ž์ฒด๋Š” ๊ทธ๋Œ€๋กœ ๋ณด์—ฌ์ค€๋‹ค).\n */\n groundingWarnings?: string[]\n attachments?: Array<{\n /** A stored file of the conversation (shared dock ยง9) - opened by its route, not carried inline. */\n id?: string\n name: string\n size: number\n type: string\n url?: string\n base64?: string\n }>\n}\n\nexport interface ChatAttachment {\n id: string\n file: File\n name: string\n size: number\n type: string\n url: string\n base64?: string\n /** A table pasted into the composer - its shape for the chip, its rows for the preview, its words to give back. */\n table?: { rows: string[][]; columns: number; text?: string }\n}\n\nfunction formatFileSize(bytes: number): string {\n if (!bytes || bytes < 1024) return `${bytes || 0} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nconst BOARD_AI_CHAT_MUTATION = gql`\n mutation BoardAIChat($input: BoardAIChatInput!) {\n boardAIChat(input: $input) {\n reply\n patch\n followUp\n clientId\n sessionId\n userMessageId\n assistantMessageId\n patchId\n toolUsages\n actions\n proposals\n groundingWarnings\n historyFolded\n }\n }\n`\n\n/*\n * The neutral door. Selected by `chatEndpoint`, and it asks for fewer fields because there is\n * less to ask for: no patch, no scene actions, no patch id โ€” this surface has no document.\n *\n * `offeredTools` has no counterpart on the board side. It is what the server actually put in\n * front of the model this turn, so a surface that granted a category and sees it missing knows\n * the registration never happened, instead of reading a vague answer as a refusal.\n */\n/* Files go to the conversation first; the turn then names them (design/ai/shared-dock.md ยง9). */\nconst ATTACH_TO_CONVERSATION_MUTATION = gql`\n mutation AttachToConversation($sessionId: String!, $files: [Upload!]!, $kind: String) {\n attachToConversation(sessionId: $sessionId, files: $files, kind: $kind) {\n id\n name\n mimetype\n size\n }\n }\n`\n\nconst ASSISTANT_CHAT_MUTATION = gql`\n mutation AssistantChat($input: AssistantChatInput!) {\n assistantChat(input: $input) {\n reply\n clientId\n sessionId\n userMessageId\n assistantMessageId\n toolUsages\n offeredTools\n proposals\n groundingWarnings\n historyFolded\n }\n }\n`\n\n/*\n * What this conversation offers on screen, in this person's language.\n *\n * The `/` sentences, the `@` catalog and the two notices are declared with the mode on the server\n * (ADR-0061 decision 7) and translated there, so the panel and the door cannot describe different\n * conversations, and a host does not carry a second copy of the words.\n */\n/*\n * ์ด ํ™”๋ฉด์— ์„ค ์ˆ˜ ์žˆ๋Š” ๋Œ€ํ™”๋“ค โ€” ADR-0072 A17 โ‘ .\n *\n * ํ™”๋ฉด์€ ์ž๊ธฐ๊ฐ€ ๋ฌด์—‡์„ ๋ณด์—ฌ ์ฃผ๋Š”์ง€๋งŒ ๋งํ•˜๊ณ , ๊ทธ ์œ„์— ์–ด๋А ๋Œ€ํ™”๊ฐ€ ์„œ๋Š”์ง€๋Š” ์•ฑ ์„œ๋ฒ„๊ฐ€ ๋‹ตํ•œ๋‹ค.\n */\nconst ASSISTANT_MODES_QUERY = gql`\n query AssistantModes($subject: String!) {\n assistantModes(subject: $subject) {\n kind\n label\n isDefault\n }\n }\n`\n\nconst ASSISTANT_MODE_QUERY = gql`\n query AssistantMode($kind: String!) {\n assistantMode(kind: $kind) {\n kind\n slashTemplates {\n name\n description\n template\n }\n catalogEntries\n proposalChoices\n placeholder\n intro\n examples\n footerNotice\n stagedNotice\n attachments\n }\n }\n`\n\n/*\n * ๋ฐฉ์— ๋งํ•˜๋Š” ๋ฌธ โ€” ์‚ฌ๋žŒ์—๊ฒŒ ํ•˜๋Š” ๋ง์ด๊ณ  ๋ชจ๋ธ์„ ๋ถ€๋ฅด์ง€ ์•Š๋Š”๋‹ค(ADR-0070 A15).\n *\n * ์ด ๋ฌธ์ด ์„œ๊ธฐ ์ „์—๋Š” ํ™”๋ฉด์—์„œ ๋‚˜๊ฐ€๋Š” ๋ชจ๋“  ๋ง์ด ์–ด์‹œ์Šคํ„ดํŠธ๋ฅผ ํ–ฅํ–ˆ๋‹ค. ์˜† ์‚ฌ๋žŒ์—๊ฒŒ ํ•œ๋งˆ๋”” ํ•˜๋ ค๋ฉด\n * ์–ด์‹œ์Šคํ„ดํŠธ๊ฐ€ ๋ฐ˜๋“œ์‹œ ๋Œ€๋‹ตํ–ˆ๊ณ , ๊ทธ ๋Œ€๋‹ต์ด ๋‹ค์‹œ ๋Œ€ํ™”์— ๋‚จ์•˜๋‹ค.\n */\n/*\n * `@` ๊ฐ€ ๊ณ ๋ฅผ ์ˆ˜ ์žˆ๋Š” ์‚ฌ๋žŒ๋“ค โ€” ์ด ๋„๋ฉ”์ธ์˜ ์‚ฌ์šฉ์ž.\n *\n * ํ˜ธ์ŠคํŠธ๊ฐ€ `userProvider` ๋ฅผ ์ฃผ์ง€ ์•Š์œผ๋ฉด ์—ฌ๊ธฐ์„œ ์ง์ ‘ ๋ฌป๋Š”๋‹ค. ์ฃผ์ง€ ์•Š๋Š” ๊ฒƒ์ด ๊ธฐ๋ณธ์ด์—ˆ๊ณ , ๊ทธ๋ž˜์„œ ์•ฑ ์…‹\n * ์–ด๋””์—์„œ๋„ `@์ด๋ฆ„` ์„ **๊ณ ๋ฅผ ์ˆ˜๊ฐ€ ์—†์—ˆ๋‹ค** โ€” ๋ฉ˜์…˜์ด ์‚ฌ๋žŒ์„ ๋ถˆ๋Ÿฌ๋“ค์ด๋Š” ๊ธฐ์ „(ADR-0071 ๊ฒฐ์ • 1)์„ ์„ธ์›Œ\n * ๋†“๊ณ  ๋ถ€๋ฅด๋Š” ์ž๋ฆฌ๊ฐ€ ์—†๋Š” ์ƒํƒœ์˜€๋‹ค. ์ด ๋ฌธ์€ `ai-assistant` ์˜ ๊ฒƒ์ด๊ณ  ๋Œ€ํ™”์ฐฝ์ด ๊ทธ ๋ฌธ์˜ ํ™”๋ฉด์ด๋‹ค.\n */\nconst DOMAIN_USERS_FOR_MENTION_QUERY = gql`\n query DomainUsersForMention($query: String) {\n domainUsersForMention(query: $query) {\n id\n name\n email\n }\n }\n`\n\nconst SAY_TO_ROOM_MUTATION = gql`\n mutation SayToRoom($sessionId: String!, $content: String!) {\n sayToRoom(sessionId: $sessionId, content: $content)\n }\n`\n\nconst CHAT_MESSAGES_QUERY = gql`\n query ChatMessages($sessionId: String!, $limit: Int, $offset: Int) {\n chatMessages(sessionId: $sessionId, limit: $limit, offset: $offset) {\n id\n role\n content\n relatedPatchId\n toolUsagesJson\n proposalsJson\n groundingWarningsJson\n attachmentsJson\n createdAt\n redacted\n creator {\n name\n email\n }\n }\n }\n`\n\n// C4 ๊ทธ๋ฃน์ฑ— โ€” ๊ฐ™์€ ์„ธ์…˜์˜ ๋ฉ”์‹œ์ง€(์‚ฌ์šฉ์ž/AI/system) ์‹ค์‹œ๊ฐ„ ๋ฐฉ์†ก ๊ตฌ๋….\n// ์ž๊ธฐ ๋ฐœ์‹  ์—์ฝ”๋Š” message.id ๋กœ dedup (mutation ์‘๋‹ต์œผ๋กœ ์ด๋ฏธ ๋ Œ๋”).\nconst CHAT_MESSAGE_SUBSCRIPTION = gql`\n subscription ChatMessageActivity($sessionId: String!) {\n chatMessageActivity(sessionId: $sessionId) {\n id\n role\n content\n relatedPatchId\n toolUsagesJson\n proposalsJson\n groundingWarningsJson\n attachmentsJson\n createdAt\n redacted\n creator {\n name\n email\n }\n }\n }\n`\n\n// C4 presence/roster โ€” ์„ธ์…˜ ์ฐธ์—ฌ์ž ๋ชฉ๋ก + ๋งˆ์ง€๋ง‰ ์ ‘์†(online ํŒ์ •์šฉ).\nconst CHAT_PARTICIPANTS_QUERY = gql`\n query ChatSessionParticipants($sessionId: String!) {\n chatSessionParticipants(sessionId: $sessionId) {\n id\n role\n lastSeenAt\n user {\n id\n name\n }\n }\n }\n`\nconst TOUCH_PRESENCE_MUTATION = gql`\n mutation TouchPresence($sessionId: String!) {\n touchPresence(sessionId: $sessionId)\n }\n`\n// heartbeat ์ฃผ๊ธฐ(ms) โ€” ์„œ๋ฒ„ PRESENCE_TTL_MS(75s)์˜ ~1/2.5. ๋กœ์ปฌ online ํŒ์ •๋„ ๋™์ผ TTL.\nconst PRESENCE_HEARTBEAT_MS = 30_000\nconst PRESENCE_TTL_MS = 75_000\n\n/** ์ด๋ฆ„ โ†’ roster chip ์ด๋‹ˆ์…œ (ํ•œ๊ธ€ 1์ž / ์˜๋ฌธ ์ตœ๋Œ€ 2์ž). */\nfunction initials(name: string): string {\n const n = (name || '?').trim()\n if (!n) return '?'\n const parts = n.split(/\\s+/)\n if (parts.length >= 2) return (parts[0][0] + parts[1][0]).toUpperCase()\n return /[a-zA-Z]/.test(n) ? n.slice(0, 2).toUpperCase() : n.slice(0, 1)\n}\n\n@customElement('ox-assistant-chat')\nexport class OxAssistantChat extends LitElement {\n /** ์˜์† ์„ธ์…˜ id. ์—†์œผ๋ฉด ad-hoc (๋ฉ”์‹œ์ง€ ์˜์† ์•ˆ ๋จ). */\n @property({ type: String, attribute: 'session-id' })\n sessionId?: string\n @property({ attribute: false }) prepareSession?: (adopt: (id: string) => void) => Promise<string | undefined>\n private adoptingSession = false\n\n /**\n * ๋ณด๋“œ์˜ ๋ชจ๋“  ChatSession ๋ฆฌ์ŠคํŠธ โ€” ๋‹ค์ค‘ ์„ธ์…˜ ํ™œ์„ฑํ™” ์‹œ ํƒญ UI ๋กœ ํ‘œ์‹œ.\n *\n * ๋นˆ ๋ฐฐ์—ด / ๋ฏธ์ง€์ • โ†’ ๋‹จ์ผ ์„ธ์…˜ UX (ํƒญ ์•ˆ ๋ณด์ž„). ํ•œ ๋ณด๋“œ = ํ•œ ์„ธ์…˜ ๊ฐ€์ •์˜ ๊ธฐ์กด ํ˜ธ์ถœ์ž\n * ํ˜ธํ™˜. host (board-modeller-page) ๊ฐ€ chatSessionsByBoard query ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌ.\n *\n * ์ด ์ปดํฌ๋„ŒํŠธ๋Š” list ์ž์ฒด๋ฅผ fetch ํ•˜์ง€ ์•Š์Œ โ€” ์˜์† ๋ชจ๋ธ / ๊ถŒํ•œ / ํŽ˜์ด์ง€๋„ค์ด์…˜ ์ •์ฑ…์€\n * host ์ฑ…์ž„. ๋ณธ ์ปดํฌ๋„ŒํŠธ๋Š” ํ‘œ์‹œ + ์ด๋ฒคํŠธ emission ๋งŒ.\n */\n @property({ type: Array, attribute: false })\n sessions: Array<{ id: string; name?: string; createdAt?: string }> = []\n\n /**\n * ํ˜„์žฌ BoardModel โ€” chat() ์ž…๋ ฅ์œผ๋กœ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌ.\n *\n * ์ฃผ์˜: ํ˜ธ์ŠคํŠธ๊ฐ€ ๋ผ์ด๋ธŒ ํŽธ์ง‘ ๊ฐ€๋Šฅํ•œ ์บ”๋ฒ„์Šค(things-scene)๋ฅผ ๊ฐ–๊ณ  ์žˆ๋‹ค๋ฉด, ์บ”๋ฒ„์Šค ์•ˆ์—์„œ\n * ์ผ์–ด๋‚˜๋Š” ์ˆ˜์ž‘์—… ํŽธ์ง‘์ด ์ด property ์—๋Š” ์ž๋™ ๋ฐ˜์˜๋˜์ง€ ์•Š๋Š”๋‹ค. ์ด ๊ฒฝ์šฐ `boardProvider`\n * ์ฝœ๋ฐฑ์„ ๊ฐ™์ด ๋„˜๊ธฐ๋ฉด send() ์‹œ์ ์— ๋ผ์ด๋ธŒ ๋ณด๋“œ๋ฅผ pull ํ•œ๋‹ค.\n */\n @property({ type: Object })\n currentBoard?: any\n\n /**\n * ๋ผ์ด๋ธŒ ๋ณด๋“œ ๋ชจ๋ธ ๊ณต๊ธ‰์ž (์„ ํƒ).\n *\n * ํ˜ธ์ŠคํŠธ๊ฐ€ things-scene ๊ฐ™์€ ์บ”๋ฒ„์Šค๋ฅผ ์‚ฌ์šฉ ์ค‘์ด๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ์บ”๋ฒ„์Šค์—์„œ ์ˆ˜์ž‘์—… ํŽธ์ง‘ํ•œ\n * ๋‚ด์šฉ์€ `currentBoard` property ์— ์ž๋™ ๋ฐ˜์˜๋˜์ง€ ์•Š๋Š”๋‹ค. ์ด ์ฝœ๋ฐฑ์„ ๋“ฑ๋กํ•˜๋ฉด `send()`\n * ์ง์ „์— ํ˜ธ์ถœํ•ด ๊ฐ€์žฅ ์ตœ์‹  ๋ณด๋“œ๋ฅผ pull โ†’ AI ๊ฐ€ ํ•ญ์ƒ ๋ผ์ด๋ธŒ ์ƒํƒœ๋ฅผ ๋ณธ๋‹ค.\n *\n * ์šฐ์„ ์ˆœ์œ„: boardProvider() ?? currentBoard.\n */\n @property({ attribute: false })\n boardProvider?: () => any\n\n /**\n * `#` mention ๊ฒ€์ƒ‰ ๊ณต๊ธ‰์ž (์„ ํƒ). ํ˜ธ์ŠคํŠธ๊ฐ€ things-scene ์˜ SceneSearchEngine ์œผ๋กœ wrap.\n *\n * ํ˜ธ์ŠคํŠธ๋Š” query ๋ฅผ ๋ฐ›์•„ popup ์— ํ‘œ์‹œํ•  FilterResult[] ๋ฅผ ๋Œ๋ ค์ค€๋‹ค โ€” chat ์ž์ฒด๋Š”\n * things-scene ์˜์กด์„ฑ์„ ๊ฐ–์ง€ ์•Š๊ณ  popup ํ‘œ์‹œ ๋กœ์ง๋งŒ ๋‹ด๋‹น. ๊ฒ€์ƒ‰ ์šฐ์„ ์ˆœ์œ„ / ๋งค์นญ ๋ฃฐ์€\n * SceneSearchEngine (F-Finder ์™€ ๊ณต์œ ) ์— ์œ„์ž„ โ†’ ์ผ๊ด€์„ฑ ๋ณด์žฅ.\n *\n * ๋ฏธ์„ค์ • ์‹œ `currentBoard.components` ์—์„œ ๋‹จ์ˆœ substring ๋งค์นญ (legacy fallback).\n * ๋นˆ query ์—์„œ๋Š” ํ˜ธ์ถœ๋˜์ง€ ์•Š์Œ โ€” ๋นˆ query ๋Š” ์ „์ฒด ํ›„๋ณด enumeration ์ด์ง€ ๊ฒ€์ƒ‰์ด ์•„๋‹˜.\n */\n @property({ attribute: false })\n searchProvider?: (query: string) => FilterResult[]\n\n /**\n * `@` mention ๋„๋ฉ”์ธ ์‚ฌ์šฉ์ž ๊ณต๊ธ‰์ž (์„ ํƒ). ํ˜ธ์ŠคํŠธ๊ฐ€ `domainUsersForMention` query ๋กœ wrap.\n *\n * ํ˜ธ์ŠคํŠธ๋Š” query ๋ฌธ์ž์—ด์„ ๋ฐ›์•„ ๋„๋ฉ”์ธ ์‚ฌ์šฉ์ž ํ›„๋ณด (id/name/email) ๋ฐฐ์—ด์„ ๋Œ๋ ค์ค€๋‹ค.\n *\n * **๋ฏธ์„ค์ •์ด๋ฉด ๋Œ€ํ™”์ฐฝ์ด ์ด ํŒจํ‚ค์ง€์˜ ๋ฌธ(`domainUsersForMention`)์— ์ง์ ‘ ๋ฌป๋Š”๋‹ค.** ์˜ˆ์ „์—๋Š” ๋นˆ\n * ๊ฒฐ๊ณผ์˜€๊ณ , ๊ทธ๋ž˜์„œ ์•ฑ ์…‹์—์„œ๋Š” `@์ด๋ฆ„` ์„ ๊ณ ๋ฅผ ์ˆ˜ ์—†์—ˆ๋‹ค โ€” ๋ฉ˜์…˜์ด ์‚ฌ๋žŒ์„ ๋ถˆ๋Ÿฌ๋“ค์ด๋Š” ๊ธธ์„ ์„ธ์›Œ๋„\n * ๋ถ€๋ฅด๋Š” ์ž๋ฆฌ๊ฐ€ ์—†์—ˆ๋‹ค. ์ž๊ธฐ ๋ชฉ๋ก์„ ๋”ฐ๋กœ ์“ฐ๋Š” ํ˜ธ์ŠคํŠธ๋งŒ ์ด๊ฒƒ์„ ์ค€๋‹ค.\n */\n @property({ attribute: false })\n userProvider?: (\n query: string\n ) =>\n | Promise<Array<{ id: string; name?: string | null; email?: string | null }>>\n | Array<{ id: string; name?: string | null; email?: string | null }>\n\n /**\n * ๋ชจ๋ธ๋Ÿฌ์—์„œ ํ˜„์žฌ ์„ ํƒ๋œ ์ปดํฌ๋„ŒํŠธ์˜ `refid` ๋ชฉ๋ก.\n *\n * refid ๋Š” things-scene ์ด ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ์— ์ž๋™ ๋ฐœ๊ธ‰ํ•˜๋Š” universal numeric handle.\n * ํ˜ธ์ŠคํŠธ๊ฐ€ ๋งค render ๋งˆ๋‹ค `.selectedRefids=${...}` ๋กœ ๊ฐฑ์‹ . AI ํ•œํ…Œ selection ์ •๋ณด๋กœ\n * ๊ทธ๋Œ€๋กœ ์ „๋‹ฌ๋˜์–ด \"์„ ํƒํ•œ\" / \"selected\" / \"this\" ๋ฅ˜ ์ง€์‹œ์–ด ํ•ด์„์— ์‚ฌ์šฉ.\n */\n @property({ type: Array, attribute: false })\n selectedRefids: number[] = []\n\n /**\n * ์ด ๋Œ€ํ™”๋ฉด์ด ์“ธ ์ˆ˜ ์žˆ๋Š” **์™ธ๋ถ€ ๋„๊ตฌ ์นดํ…Œ๊ณ ๋ฆฌ** ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ(registerToolCategory ์ด๋ฆ„).\n * ๋ฏธ์ง€์ •์ด๋ฉด ๋“ฑ๋ก๋œ ์ „๋ถ€(ํ˜„ํ–‰ ๋™์ž‘) โ€” ๋ณด๋“œ ๋ชจ๋ธ๋Ÿฌ๋Š” ์ง€์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค.\n * ์„ฑ๊ฒฉ์ด ๋‹ค๋ฅธ ๋Œ€ํ™”๋ฉด(์˜ˆ: ํŠธ์œˆ ์šด์˜ ๋„ํฌ)์ด ์„œ๋กœ์˜ ๋Šฅ๋ ฅ์„ ๊ฐ–์ง€ ์•Š๊ฒŒ ํ•˜๋Š” ๊ฒฝ๊ณ„.\n */\n @property({ type: Array, attribute: false })\n toolCategories?: string[]\n\n /**\n * ์ด ๋Œ€ํ™”๋ฉด์ด ๋ฌด์—‡์„ ๋ณด๊ณ  ์žˆ๋Š”์ง€ โ€” ์„œ๋ฒ„ ๋„๊ตฌ๊ฐ€ `ctx.state.host` ๋กœ ์ฝ๋Š”๋‹ค(์˜ˆ: `{ spaceId }`).\n * ์—†์œผ๋ฉด ๋„๊ตฌ๊ฐ€ ๋Œ€์ƒ์„ ๋ชฐ๋ผ ๋ชจ๋ธ์ด ์‚ฌ์šฉ์ž์—๊ฒŒ ์‹๋ณ„์ž๋ฅผ ๋˜๋ฌป๋Š”๋‹ค.\n */\n @property({ type: Object, attribute: false })\n hostContext?: any\n\n /** ์ฝ”์–ด ๋ณด๋“œ ํŽธ์ง‘ ๋„๊ตฌ ์‚ฌ์šฉ ์—ฌ๋ถ€. ๊ธฐ๋ณธ true. ๋ณด๋“œ๋ฅผ ๊ณ ์น  ์ด์œ ๊ฐ€ ์—†๋Š” ๋ฉด์—์„œ false. */\n @property({ type: Boolean, attribute: 'board-tools' })\n boardTools = true\n\n /*\n * Which server operation this surface talks to. A closed set of two, named after the operations\n * themselves so a reader can grep either way.\n *\n * boardAIChat board authoring โ€” lives in @things-factory/board-ai, carries the board model,\n * returns patches and scene actions\n * assistantChat a surface with no document of its own โ€” lives here, runs registered tools only\n *\n * **There is no default** (ADR-0061 decision 7). It was `boardAIChat`, which meant a surface that\n * said nothing talked to a package it may not even load โ€” operato-figure got\n * `Cannot query field \"boardAIChat\" on type \"Mutation\"` that way (2026-09-11). A surface that\n * declares a mode talks to `assistantChat`; one that declares no mode names this itself.\n */\n @property({ type: String, attribute: 'chat-endpoint' })\n chatEndpoint?: 'boardAIChat' | 'assistantChat'\n\n /**\n * What this conversation is โ€” see `AssistantMode`.\n *\n * A host that sets this sets nothing else about the conversation: the persona, the tool\n * categories, the model and the limits belong to the mode its app server registered, and what\n * `@` and `/` offer comes from that same declaration, translated. They cannot disagree because\n * there is one of them.\n *\n * When `kind` or `target` changes the conversation on screen is closed and a new one begins.\n */\n @property({ attribute: false })\n mode?: AssistantMode\n\n /**\n * ์ด ํ™”๋ฉด์ด ๋ณด์—ฌ ์ฃผ๋Š” ๊ฒƒ์˜ **์ข…๋ฅ˜** โ€” `'board'`, `'space'`, `'station'`, `'figure'` (ADR-0072 A17 โ‘ ).\n *\n * `mode` ๊ฐ€ ใ€Œ์ง€๊ธˆ ์–ด๋А ๋Œ€ํ™”์ธ๊ฐ€ใ€๋ผ๋ฉด ์ด๊ฒƒ์€ ใ€Œ๊ทธ ์ž๋ฆฌ์— ์–ด๋–ค ๋Œ€ํ™”๋“ค์ด ์„ค ์ˆ˜ ์žˆ๋‚˜ใ€์ด๋‹ค. ์„œ๋ฒ„๊ฐ€\n * `assistantModes(subject)` ๋กœ ๋‹ตํ•˜๊ณ , ๋‘˜ ์ด์ƒ์ด๋ฉด ๊ณ ๋ฅด๊ฐœ๊ฐ€ ๋œฌ๋‹ค. ํ•˜๋‚˜๋ฉด ๊ณ ๋ฅด๊ฐœ๋ฅผ ๋‚ด์ง€ ์•Š๋Š”๋‹ค โ€”\n * ๊ณ ๋ฅผ ๊ฒƒ์ด ์—†๋Š” ๊ณ ๋ฅด๊ฐœ๋Š” ์ž๋ฆฌ๋งŒ ์ฐจ์ง€ํ•œ๋‹ค.\n *\n * ํ™”๋ฉด์ด ์ด๊ฒƒ์„ ์•ˆ ์ฃผ๋ฉด ๊ณ ๋ฅด๊ฐœ๋Š” ์—†๊ณ  host ๊ฐ€ ์ •ํ•œ ๋Œ€ํ™” ํ•˜๋‚˜๋งŒ ์‚ฐ๋‹ค. ๊ทธ๊ฒƒ์ด ์˜ค๋Š˜๊นŒ์ง€์˜ ๋ชจ์–‘์ด๋‹ค.\n */\n @property({ type: String })\n subject?: string\n\n /**\n * ๋ผ์ด๋ธŒ ์ƒํƒœ๋ฅผ ๋‹ค๋ฃจ๋Š” ๋Œ€ํ™”๋ฉด์ธ๊ฐ€ โ€” true ๋ฉด **์ฒซ ํ„ด์— ๋„๊ตฌ ํ˜ธ์ถœ์„ ๊ฐ•์ œ**ํ•œ๋‹ค.\n *\n * ์ ‘์ง€ ๊ฐ€๋“œ๋Š” ์ง€์–ด๋‚ธ ์‹๋ณ„์ž๋ฅผ ์žก์ง€๋งŒ ์‹๋ณ„์ž ์—†๋Š” ์ƒํ™ฉ ์„œ์ˆ (\"๋ฐ”์˜๊ฒŒ ์›€์ง์ด๊ณ  ์žˆ๋‹ค\")์€ ์žก์ง€ ๋ชปํ•œ๋‹ค.\n * ๊ทธ๊ฑด ๋„๊ตฌ๋ฅผ ๋ถ€๋ฅด์ง€ ์•Š๊ณ  ๋‹ตํ•œ ๊ฒฝ์šฐ์ด๋ฏ€๋กœ, ์กฐํšŒ๋ฅผ ๋จผ์ € ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด ์›์ฒœ์„ ๋ง‰๋Š”๋‹ค.\n */\n @property({ type: Boolean, attribute: 'require-grounding-tools' })\n requireGroundingTools = false\n\n /** board-import registry scopes. */\n @property({ type: Array })\n scopes?: string[]\n\n @property({ type: Array, attribute: 'known-types' })\n knownTypes?: string[]\n\n @property({ type: Array })\n categories?: string[]\n\n /**\n * ์ปดํฌ๋„ŒํŠธ type ๋ณ„ ์œ ํšจ ์†์„ฑ ์Šคํ‚ด.\n * ํ˜•ํƒœ: [{ type, description?, group?, properties? }]\n * LLM ์ด ์ •ํ™•ํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค๋„๋ก mutation input ์œผ๋กœ forwarding.\n */\n @property({ type: Array, attribute: false })\n componentSchemas?: Array<{ type: string; description?: string; group?: string; properties?: Record<string, any> }>\n\n /* No default here โ€” the render falls back to `ai-assistant.text.input-placeholder`, which every locale has.\n * A literal default is one language for every reader, and it hid the key that already existed. */\n @property({ type: String })\n placeholder?: string\n\n @state()\n private lines: ChatLine[] = []\n\n @state()\n private input = ''\n\n /**\n * ๋ฐ–์—์„œ ์งˆ๋ฌธ์„ ๋„ฃ์–ด **์ž๋™์œผ๋กœ ๋ณด๋‚ด๊ฒŒ** ํ•˜๋Š” ์ง„์ž…์ .\n *\n * ์˜ค๋ฅ˜ ํ† ์ŠคํŠธ์˜ \"AI์—๊ฒŒ ๋ฌป๊ธฐ\" ์ฒ˜๋Ÿผ, ์‚ฌ์šฉ์ž๊ฐ€ ํƒ€์ดํ•‘ํ•˜์ง€ ์•Š๊ณ  ๊ณง๋ฐ”๋กœ ๋‹ต์„ ๋ฐ›์•„์•ผ ํ•˜๋Š” ๊ฒฝ๋กœ๊ฐ€ ์žˆ๋‹ค.\n * ๊ฐ’์ด ๋“ค์–ด์˜ค๋ฉด ๊ทธ ๋ฌธ์žฅ์„ ์ž…๋ ฅ์œผ๋กœ ์‚ผ์•„ ํ•œ ๋ฒˆ ์ „์†กํ•˜๊ณ  ๋น„์šด๋‹ค(๊ฐ™์€ ์งˆ๋ฌธ์ด ๋ฐ˜๋ณต ์ „์†ก๋˜์ง€ ์•Š๊ฒŒ).\n */\n @property({ attribute: false })\n autoAsk?: string\n @property() autoAskRequestId?: string\n\n /**\n * A sentence to place in the input **without sending it** โ€” the pair of `autoAsk`.\n *\n * Some paths hand the person a starting sentence to edit and send themselves (twin's \"new twin โ†’\n * AI\"). Filled once per `draftRequestId`, with focus on the input; never over text the person is\n * typing; and when `autoAsk` arrives for the same request, `autoAsk` wins\n * (`assistantDraftDecision`).\n */\n @property({ attribute: false })\n draft?: string\n @property() draftRequestId?: string\n @property({ attribute: false }) contextProvider?: () => AssistantRequestContext\n\n /**\n * ๋นˆ ํ™”๋ฉด์˜ ์ œ๋ชฉยท๋ถ€์ œ โ€” **ํ˜ธ์ŠคํŠธ๊ฐ€ ์ž๊ธฐ ๋ง๋กœ ์ค€๋‹ค.**\n *\n * โ”€โ”€ ์™œ ์—ด์—ˆ๋‚˜ (2026-09-11) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ์ด ๊ฐ’์ด `board-ai.text.empty-title` ๋กœ ๊ณ ์ •๋ผ ์žˆ์—ˆ๋‹ค. ๊ทธ๋ž˜์„œ figure ์ €์ž‘๋ฉด์—์„œ ๋„ํฌ๋ฅผ ์—ด๋ฉด\n * ๋„ํ˜•์„ ํŽธ์ง‘ํ•˜๋Š” ์‚ฌ๋žŒ์—๊ฒŒ **ใ€Œ๋ณด๋“œ๋ฅผ ๋งŒ๋“ค๋ผใ€๊ณ  ๊ฐ€๋ฅด์ณค๋‹ค** โ€” ใ€ŒMonitoring dashboard with 3\n * gaugesใ€ ๊ฐ™์€ ์˜ˆ์‹œ๊นŒ์ง€ ํ•จ๊ป˜.\n *\n * ๋นˆ ํ™”๋ฉด์€ ๊ทธ ํ™”๋ฉด์ด ๋ฌด์—‡์ธ์ง€ ๊ฐ€๋ฅด์น˜๋Š” ์ž๋ฆฌ๋‹ค. ๊ฑฐ๊ธฐ์„œ ํ‹€๋ฆฌ๋ฉด ์ฒ˜์Œ ์—ฌ๋Š” ์‚ฌ๋žŒ์ด ์ด ๋„๊ตฌ๋ฅผ\n * ์˜คํ•ดํ•œ๋‹ค. ๋„๊ตฌ ์ชฝ(`toolCategories`ยท`boardTools`)์€ ์ด๋ฏธ ์ค‘๋ฆฝ์ด์—ˆ๊ณ  **๊ธ€๋งŒ ์•ˆ ์—ด๋ ค ์žˆ์—ˆ๋‹ค.**\n *\n * โš  **ํ‚ค๊ฐ€ ์•„๋‹ˆ๋ผ ๋ฒˆ์—ญ๋œ ๊ธ€์„ ๋ฐ›๋Š”๋‹ค.** ํ˜ธ์ŠคํŠธ๋งˆ๋‹ค ์ž๊ธฐ ์ ‘๋‘ ์•„๋ž˜ ํ‚ค๋ฅผ ๋‘๋ฏ€๋กœ(figure ๋Š”\n * `figure.text.โ€ฆ`), ํ‚ค๋ฅผ ๋ฐ›์œผ๋ฉด ์ด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋‚จ์˜ ์ ‘๋‘๋ฅผ ์•Œ์•„์•ผ ํ•œ๋‹ค.\n *\n * โš  ์•ˆ ์ฃผ๋ฉด **์ง€๊ธˆ๊นŒ์ง€์˜ ๋ณด๋“œ ๋ฌธ๊ตฌ**๊ฐ€ ๋‚˜์˜จ๋‹ค โ€” ๊ฑฐ๋™์„ ๋ฐ”๊พธ์ง€ ์•Š์œผ๋ ค๊ณ  ๊ทธ๋ ‡๊ฒŒ ๋’€๋‹ค. ์ฆ‰ ๋ณด๋“œ๊ฐ€\n * ์•„๋‹Œ ํ˜ธ์ŠคํŠธ๊ฐ€ ์ด ๊ฐ’์„ ์žŠ์œผ๋ฉด ํ‹€๋ฆฐ ๊ธ€์ด ์กฐ์šฉํžˆ ๋œฌ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์„ ์ค‘๋ฆฝ์œผ๋กœ ๋ฐ”๊พธ๋Š” ๊ฒƒ์€\n * board-uiยทtwin ์ด ์ž๊ธฐ ๊ธ€์„ ๋„˜๊ธฐ๊ฒŒ ํ•˜๋Š” ๋ณ„ ๊ฑด์ด๋‹ค(๊ทธ๋•Œ ์ด ์ฃผ์„์„ ์ง€์šด๋‹ค).\n */\n @property({ type: Object, attribute: false }) intro?: { title: string; subtitle: string }\n\n /**\n * ๋นˆ ํ™”๋ฉด์˜ ์˜ˆ์‹œ โ€” ํ˜ธ์ŠคํŠธ๊ฐ€ ์ž๊ธฐ ๊ฒƒ์„ ์ค€๋‹ค. ์•ˆ ์ฃผ๋ฉด ๋ณด๋“œ ์˜ˆ์‹œ๊ฐ€ ๋‚˜์˜จ๋‹ค(์œ„ โš  ์™€ ๊ฐ™์€ ์ด์œ ).\n *\n * ์˜ˆ์‹œ๋Š” **๊ทธ ๋„๊ตฌ๋กœ ์‹ค์ œ๋กœ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ง**์ด์–ด์•ผ ํ•œ๋‹ค. ํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ์„ ์˜ˆ์‹œ๋กœ ๋‘๋ฉด ๋นˆ ํ™”๋ฉด์ด\n * ๊ฑฐ์ง“์„ ๊ฐ€๋ฅด์นœ๋‹ค.\n */\n @property({ type: Array, attribute: false }) examples?: Array<{ label: string; items: string[] }>\n\n /** autoAsk ๋ฅผ ์ด๋ฏธ ๋ณด๋ƒˆ๋Š”์ง€ โ€” ์žฌ๋ Œ๋”๋งˆ๋‹ค ๋‹ค์‹œ ๋ณด๋‚ด์ง€ ์•Š๊ธฐ ์œ„ํ•œ ํ‘œ์‹. */\n private _autoAsked?: string\n /** The draft already placed (or deliberately skipped) โ€” so a re-render does not place it again. */\n private _drafted?: string\n\n /** ๋งˆ์ง€๋ง‰ send ์‹คํŒจ ์‹œ ๋ณด์กด โ€” ๋‹ค์‹œ ์‹œ๋„ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ์‚ฌ์šฉ */\n @state()\n private lastFailedInput?: string\n\n /** ๋˜๋Œ๋ ค์ง„ patch id ๋“ค โ€” ํ•œ ๋ฒˆ revert ํ•œ patch ๋Š” ๋ฒ„ํŠผ ๋น„ํ™œ์„ฑ */\n @state()\n private revertedPatchIds = new Set<string>()\n\n /** ์ฒจ๋ถ€๋œ ํŒŒ์ผ/์ด๋ฏธ์ง€ ๋ชฉ๋ก */\n @state()\n private attachments: ChatAttachment[] = []\n\n /** ๋“œ๋ž˜๊ทธ ์˜ค๋ฒ„ ์ƒํƒœ (์‹œ๊ฐ ํ”ผ๋“œ๋ฐฑ์šฉ) */\n @state()\n private dragOver = false\n\n /** The wide box (๋„“๊ฒŒ ์“ฐ๊ธฐ) covers the conversation inside the dock - shared-dock.md ยง10. */\n @state()\n private composerWide = false\n\n /** The pasted table whose rows cover the conversation, or null. */\n @state()\n private previewAttachmentId: string | null = null\n\n /*\n * โ”€โ”€ ์™œ ์ด๋ฏธ์ง€๋งŒ ๋ฐ›๋‚˜ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * `.json` ยท `.txt` ยท `.csv` ๋„ ๋ฐ›๊ณ  ์žˆ์—ˆ๋‹ค. ๊ทธ ํŒŒ์ผ๋“ค์€ `hostContext.attachments` ๋กœ ์‹ค๋ ค ๊ฐ”๊ณ \n * **๊ทธ๊ฒƒ์„ ์ฝ์–ด ๋ชจ๋ธ์— ๋ถ™์ด๋Š” ์ฝ”๋“œ๊ฐ€ ์—†์—ˆ๋‹ค.** ์‚ฌ๋žŒ์ด CSV ๋ฅผ ๋ถ™์ด๊ณ  ใ€Œ์ด ํ‘œ ์ข€ ๋ด์ค˜ใ€๋ผ๊ณ  ํ•˜๋ฉด ํ™”๋ฉด์—\n * ํŒŒ์ผ ์นฉ์ด ๋œจ๊ณ  ๋‹ต๋„ ์™”๋‹ค. ๊ทธ ๋‹ต์€ ํŒŒ์ผ์„ ๋ณธ ์ ์ด ์—†๊ณ , ์˜ค๋ฅ˜๋„ ์•ˆ ๋‚ฌ๋‹ค(2026-09-18 ํ‘œ๋ฉด ์กฐ์‚ฌ).\n *\n * ์ด๋ฏธ์ง€๋Š” ๊ธธ์ด ์žˆ๋‹ค โ€” `assistant-chat-resolver.ts` ๊ฐ€ `hostContext.image` ๋ฅผ ๋งˆ์ง€๋ง‰ ์‚ฌ๋žŒ ํ„ด์—\n * ๋ถ™์ธ๋‹ค. ๊ทธ๋ž˜์„œ ๋˜๋Š” ๊ฒƒ๋งŒ ๋‚จ๊ธฐ๊ณ  ์ขํ˜”๋‹ค. ๋ชป ํ•˜๋Š” ์ผ์„ ํ™”๋ฉด์ด ๊ถŒํ•˜์ง€ ์•Š๋Š”๋‹ค.\n *\n * โ”€โ”€ ๊ธ€ ํŒŒ์ผ์„ ์ฒญํ•˜๋Š” ์ œํ’ˆ์ด ์„ค ๋•Œ์˜ ๋ชจ์–‘ (์ˆ˜์„ ์•„ํ‚คํ…ํŠธ, ADR-0071 ๋ณดํƒฌ) โ”€โ”€โ”€\n * ์ด๋ฏธ์ง€์™€ **๊ฐ™์€ ์ž๋ฆฌ**(์‚ฌ๋žŒ ํ„ด)์— ๋ถ™์ธ๋‹ค. ํฌ๊ธฐ ์ƒํ•œ์€ ๋ชจ๋“œ๊ฐ€ ์„ ์–ธํ•˜๊ณ , ๋„˜์œผ๋ฉด ๋ณด๋‚ด๊ธฐ ์ „์— ์‚ฌ์‹ค ํ•œ\n * ์ค„๋กœ ๊ฑฐ์ ˆํ•œ๋‹ค โ€” ์กฐ์šฉํžˆ ์ž๋ฅด์ง€ ์•Š๋Š”๋‹ค. ๋น„์šฉ์€ ์‚ฌ์šฉ๋Ÿ‰์˜ ์ถ•์ด๋‹ค(ADR-0061 ๊ฒฐ์ • 6).\n *\n * `attachments` ์ง ์ž์ฒด๋Š” ๊ทธ๋Œ€๋กœ ๋‘”๋‹ค: figure ์˜ ๋„๊ตฌ๊ฐ€ ๊ฑฐ๊ธฐ์„œ ์ด๋ฏธ์ง€๋ฅผ ์ฐพ๋Š”๋‹ค\n * (`figure-tools.ts` โ€” `ctx.host.image` ๊ฐ€ ์—†์„ ๋•Œ์˜ ๊ฐˆ๋ž˜).\n */\n /** This conversation talks to the neutral door - its attachments follow the mode's policy (ยง9). */\n private get usesAttachmentPolicy(): boolean {\n return this.conversation.chatEndpoint === 'assistantChat'\n }\n\n /** Whether the attach button stands: a mode that declares nothing takes nothing (the board door keeps its images). */\n private get acceptsAttachments(): boolean {\n return !this.usesAttachmentPolicy || !!this.modeView?.attachments?.kinds?.length\n }\n\n /** A refusal in the reader's words - the same keys the door uses. */\n private attachmentRefusalText(refusal: NonNullable<ReturnType<typeof refuseAttachments>>): string {\n const params: any = { ...refusal }\n if (refusal.code === 'attachment-too-large') params.max = Math.round(refusal.maxBytes / 1024 / 1024)\n if (refusal.code === 'too-many-attachments') params.max = refusal.maxFiles\n if (refusal.code === 'attachment-kind-not-accepted') params.kinds = refusal.kinds.join(', ')\n return String(i18next.t(`ai-assistant.text.${refusal.code}`, { ...params, defaultValue: refusal.code }))\n }\n\n private async onAttachFiles(files: FileList | File[] | null | undefined, table?: ChatAttachment['table']) {\n if (!files || files.length === 0) return\n let list = Array.from(files)\n if (this.usesAttachmentPolicy && this.modeView?.attachments?.kinds?.includes('spreadsheet')) {\n /* A spreadsheet travels as the text of its sheets (ยง9-5) - read here, refused by name when it cannot be. */\n const read = await this.readSpreadsheets(list)\n if ('refusal' in read) {\n this.errorMessage = String(i18next.t(`ai-assistant.text.${read.refusal.code}`, { ...(read.refusal as any), defaultValue: read.refusal.code }))\n return\n }\n list = read.files\n }\n if (this.usesAttachmentPolicy) {\n /* Said before anything is sent - never cut silently (ยง9-1). */\n const refusal = refuseAttachments(this.modeView?.attachments, [...this.attachments, ...list].map(f => ({ name: f.name, type: f.type, size: f.size })))\n if (refusal) {\n this.errorMessage = this.attachmentRefusalText(refusal)\n return\n }\n }\n const newAttachments: ChatAttachment[] = []\n\n for (const file of list) {\n const id = 'att-' + Math.random().toString(36).substring(2, 9)\n const url = URL.createObjectURL(file)\n let base64: string | undefined\n try {\n base64 = await this.readFileAsBase64(file)\n } catch (err) {\n console.warn('Failed to read file as base64', err)\n }\n newAttachments.push({\n id,\n file,\n name: file.name,\n size: file.size,\n type: file.type || 'application/octet-stream',\n url,\n base64,\n table\n })\n }\n\n this.attachments = [...this.attachments, ...newAttachments]\n }\n\n /** Each .xlsx replaced by one CSV file per sheet; any other file passes as it is. */\n private async readSpreadsheets(list: File[]): Promise<{ files: File[] } | { refusal: SpreadsheetRefusal }> {\n const out: File[] = []\n let Workbook: any\n for (const file of list) {\n const kind = spreadsheetKindOf(file)\n if (!kind) {\n out.push(file)\n continue\n }\n if (kind === 'xls') return { refusal: { code: 'attachment-xls-not-read', name: file.name } }\n if (!Workbook) {\n const mod: any = await import('exceljs')\n Workbook = (mod.default ?? mod).Workbook\n }\n const read = await readSpreadsheet(await file.arrayBuffer(), file.name, textCharsOf(this.modeView?.attachments), Workbook)\n if ('refusal' in read) return read\n for (const sheet of read.files) out.push(new File([sheet.text], sheet.name, { type: 'text/csv' }))\n }\n return { files: out }\n }\n\n private readFileAsBase64(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => resolve(reader.result as string)\n reader.onerror = reject\n reader.readAsDataURL(file)\n })\n }\n\n private removeAttachment(id: string) {\n const target = this.attachments.find(a => a.id === id)\n if (target?.url) {\n URL.revokeObjectURL(target.url)\n }\n this.attachments = this.attachments.filter(a => a.id !== id)\n if (this.previewAttachmentId === id) this.previewAttachmentId = null\n }\n\n /** A pasted table goes back into the box as the words it was copied as - the conversion was not the person's choice. */\n private tableToWords(id: string) {\n const target = this.attachments.find(a => a.id === id)\n if (!target?.table) return\n this.input = appendWords(this.input, tableAsWords(target.table))\n this.removeAttachment(id)\n this.updateComplete.then(() => (this.renderRoot.querySelector('textarea') as HTMLTextAreaElement | null)?.focus())\n }\n\n /** The small box stands as tall as its text, up to 40% of the chat; the wide box fills what it covers. */\n private fitComposer() {\n const ta = this.renderRoot.querySelector('.input-row textarea') as HTMLTextAreaElement | null\n if (!ta) return\n if (this.composerWide) {\n ta.style.height = ''\n ta.style.overflowY = ''\n return\n }\n ta.style.height = '0px'\n const border = ta.offsetHeight - ta.clientHeight\n const resting = parseFloat(getComputedStyle(ta).minHeight) || 0\n const { height, scrolls } = composerHeight(ta.scrollHeight + border, this.clientHeight, resting)\n ta.style.height = `${height}px`\n ta.style.overflowY = scrolls ? 'auto' : 'hidden'\n }\n\n private setComposerWide(wide: boolean) {\n this.composerWide = wide\n if (wide) this.previewAttachmentId = null\n this.updateComplete.then(() => (this.renderRoot.querySelector('.input-row textarea') as HTMLTextAreaElement | null)?.focus())\n }\n\n private onComposerPaste(e: ClipboardEvent) {\n const items = e.clipboardData?.items\n if (!items || items.length === 0) return\n\n /*\n Rows copied from a spreadsheet or a web page travel as a file, so the entry card can check each row against\n its line. A spreadsheet also puts a picture of the cells on the clipboard - with the table taken, it is left.\n */\n if (this.usesAttachmentPolicy) {\n const pasted = pastedTableFile(\n { html: e.clipboardData?.getData('text/html'), text: e.clipboardData?.getData('text/plain') },\n this.modeView?.attachments,\n rows => String(i18next.t('ai-assistant.text.pasted-table-name', { rows, defaultValue: 'pasted table ({rows} rows)' }))\n )\n if (pasted) {\n e.preventDefault()\n if ('refusal' in pasted) {\n this.errorMessage = String(i18next.t(`ai-assistant.text.${pasted.refusal.code}`, { ...pasted.refusal, defaultValue: pasted.refusal.code }))\n return\n }\n const words = e.clipboardData?.getData('text/plain')\n this.onAttachFiles([new File([pasted.text], pasted.name, { type: 'text/csv' })], { ...pasted.table, text: words })\n return\n }\n }\n\n const files: File[] = []\n for (let i = 0; i < items.length; i++) {\n const item = items[i]\n if (item.kind === 'file') {\n const file = item.getAsFile()\n if (file) files.push(file)\n }\n }\n\n if (files.length > 0) {\n this.onAttachFiles(files)\n }\n }\n\n private onComposerDragOver(e: DragEvent) {\n e.preventDefault()\n e.stopPropagation()\n if (!this.dragOver) this.dragOver = true\n }\n\n private onComposerDragLeave(e: DragEvent) {\n e.preventDefault()\n e.stopPropagation()\n const currentTarget = e.currentTarget as HTMLElement\n const relatedTarget = e.relatedTarget as Node | null\n if (!currentTarget.contains(relatedTarget)) {\n this.dragOver = false\n }\n }\n\n private onComposerDrop(e: DragEvent) {\n e.preventDefault()\n e.stopPropagation()\n this.dragOver = false\n if (e.dataTransfer?.files?.length) {\n this.onAttachFiles(e.dataTransfer.files)\n }\n }\n\n /** mini action โ€” ์ธ๋ผ์ธ ์˜ˆ์‹œ ํ† ๊ธ€ */\n @state()\n private examplesOpen = false\n\n /** ๋ณต์‚ฌ toast ํ‘œ์‹œ ์ƒํƒœ */\n @state()\n private toastMessage?: string\n\n /** ๋ณต์‚ฌ confirmation feedback (๋ฉ”์‹œ์ง€ idx โ†’ ์งง์€ ์‹œ๊ฐ„ ๋™์•ˆ โœ“ ํ‘œ์‹œ) */\n @state()\n private copiedIdx?: number\n\n /** ์›๋ณธ JSON ์„ ํŽผ์นœ ๋‹จ๊ณ„(๋ผ์ธ:๋‹จ๊ณ„) โ€” ๋ชฉ๋ก์€ ํ•œ ์ค„ ์š”์•ฝ์œผ๋กœ ํ›‘๊ณ  ํ•„์š”ํ•œ ๊ฒƒ๋งŒ ํŽผ์นœ๋‹ค. */\n @state()\n private openToolSteps = new Set<string>()\n\n /** ์ด๋ฏธ ์‹คํ–‰์„ ์š”์ฒญํ•œ ์ œ์•ˆ ํ‚ค โ€” ๊ฐ™์€ ์นด๋“œ๋ฅผ ๋‘ ๋ฒˆ ๋ˆŒ๋Ÿฌ ๋˜๋Œ๋ฆด ์ˆ˜ ์—†๋Š” ๋ช…๋ น์ด ๋‘ ๋ฒˆ ๋‚˜๊ฐ€์ง€ ์•Š๊ฒŒ. */\n @state()\n private sentProposals = new Set<string>()\n\n /** Proposal keys the host has reported staged. Only the host knows; see `acknowledgeProposalStaged`. */\n @state()\n private stagedProposals = new Set<string>()\n\n /**\n * The host reports that it put this candidate somewhere the person can look at it.\n *\n * Staging happens outside this component โ€” a dock catches `assistant-proposal-preview`, hands\n * the candidate to a viewer, and only that host knows whether it worked, or whether it has a\n * viewer at all. So the card says nothing until the host calls this, and it then says it in the\n * words the host registered (`chatDefaults.stagedNoticeKey`).\n *\n * Safe to call for a candidate the card never showed; the key simply never matches.\n */\n acknowledgeProposalStaged(proposal: any): void {\n /*\n Silence has two meanings and they are not the same defect. A host that never calls this is\n telling us it does not know, and drawing nothing is right. A host that calls it without\n registering `stagedNoticeKey` meant to say something and left out the words -- staying quiet\n about that reads to whoever wired it as \"the badge just doesn't appear here\".\n\n The screen still shows nothing either way. There is no sentence to show, and inventing one is\n what this whole correction removed.\n */\n if (!this.conversation.stagedNotice && !OxAssistantChat.warnedMissingStagedNotice) {\n OxAssistantChat.warnedMissingStagedNotice = true\n console.warn(\n '[assistant-chat] a host reported a proposal staged but declared no staged notice, so the card can ' +\n 'say nothing. Declare `stagedNoticeKey` on the mode (the server translates it), or pass one to ' +\n '`registerChatDefaults` from a host with no mode.'\n )\n }\n\n this.stagedProposals = new Set(this.stagedProposals).add(this.proposalKey(proposal))\n }\n\n /** Once per page: the miss is a wiring mistake, and repeating it per candidate buries it. */\n private static warnedMissingStagedNotice = false\n\n /**\n * ์ด ๋Œ€ํ™”๊ฐ€ ๊ธธ์–ด์ ธ ์•ž๋ถ€๋ถ„์ด ํ”„๋กฌํ”„ํŠธ์—์„œ ์ ‘ํ˜”๋‹ค๋Š” **์‚ฌ์‹ค**(์„œ๋ฒ„ ๋ณด๊ณ ). ์ฃผ์ œ ์ดํƒˆ์„ ํŒ์ •ํ•œ ๊ฒƒ์ด\n * ์•„๋‹ˆ๋‹ค โ€” ํŒ์ •ํ•˜๋ฉด ์˜คํƒ์ด ์ƒ๊ธฐ๊ณ , ์˜คํƒ์ด ์ƒ๊ธฐ๋ฉด ์‚ฌ์šฉ์ž๋Š” ์•ˆ๋‚ด ์ž์ฒด๋ฅผ ๋ฌด์‹œํ•œ๋‹ค.\n * ์‚ฌ์‹ค๋งŒ ์•Œ๋ฆฌ๊ณ  \"์ƒˆ ๋Œ€ํ™”๋กœ ์‹œ์ž‘ํ• ์ง€\" ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ •ํ•œ๋‹ค.\n */\n @state()\n private historyFolded?: { omitted: number; summarized: boolean }\n\n /** ์•ˆ๋‚ด๋ฅผ ๋‹ซ์•˜๋Š”๊ฐ€ โ€” ํ•œ ๋ฒˆ ๋‹ซ์œผ๋ฉด ์ด ์„ธ์…˜์—์„œ๋Š” ๋‹ค์‹œ ๋„์šฐ์ง€ ์•Š๋Š”๋‹ค(์ž”์†Œ๋ฆฌ ๊ธˆ์ง€). */\n @state()\n private foldNoticeDismissed = false\n\n @state()\n private busy = false\n\n /** Host navigation may retain a conversation for reading while its subject is off screen. */\n @property() sendBlocked = ''\n\n /** The host may inspect navigation risk without reading or copying the person's input. */\n get navigationState(): { busy: boolean; draft: boolean } {\n return { busy: this.busy, draft: !!this.input.trim() || this.attachments.length > 0 }\n }\n\n @state()\n private errorMessage?: string\n\n /** C4 presence/roster โ€” ์„ธ์…˜ ์ฐธ์—ฌ์ž ๋ชฉ๋ก. lastSeenAt ์œผ๋กœ online ํŒ์ •. */\n @state()\n private participants: Array<{ id: string; role: string; lastSeenAt?: string; user?: { id: string; name?: string } }> = []\n\n /** roster online ์žฌํ‰๊ฐ€ ํŠธ๋ฆฌ๊ฑฐ โ€” heartbeat tick ๋งˆ๋‹ค ๊ฐฑ์‹ (์‹œ๊ฐ„ ๊ฒฝ๊ณผ ๋ฐ˜์˜). */\n @state()\n private _presenceTick = 0\n\n private _heartbeatTimer?: ReturnType<typeof setInterval>\n\n /** C4 ๊ทธ๋ฃน์ฑ— โ€” ๋ฉ”์‹œ์ง€ ์‹ค์‹œ๊ฐ„ ๋ฐฉ์†ก ๊ตฌ๋… ํ•ธ๋“ค + ์—์ฝ” dedup. */\n private _messageSub?: { unsubscribe: () => void }\n /** ์ด๋ฏธ transcript ์— ๋ฐ˜์˜๋œ ์„œ๋ฒ„ ๋ฉ”์‹œ์ง€ id ์ง‘ํ•ฉ โ€” ์ž๊ธฐ ์—์ฝ”ยท์ค‘๋ณต ๋ฐฉ์†ก ์ฐจ๋‹จ. */\n private _seenMessageIds = new Set<string>()\n /** optimistic ๋ผ์ธ ์ž„์‹œ ํ•ธ๋“ค ์‹œํ€€์Šค (index ๋น„์˜์กด reconcile ์šฉ). */\n private _localSeq = 0\n\n /** ํ˜„์žฌ ๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž email โ€” ๊ทธ๋ฃน์ฑ—์—์„œ ๋‚ด ๋ฉ”์‹œ์ง€ vs ํƒ€์ธ ๋ฉ”์‹œ์ง€ ๊ตฌ๋ถ„.\n * email ์„ ์“ฐ๋Š” ์ด์œ : /auth/profile ์ด ํ•ญ์ƒ ๋‚ด๋ ค์ฃผ๋Š” ๋กœ๊ทธ์ธ ์‹๋ณ„์ž์ด๊ณ (๋น„์–ด ์žˆ์ง€ ์•Š๋‹ค),\n * ๋‚ด๋ถ€ ๊ด€๋ฆฌํ‚ค(User.id)๋ฅผ ํด๋ผ์ด์–ธํŠธ ํŒ์ •์— ์˜์กดํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•จ. */\n private get _myEmail(): string | undefined {\n return (auth.credential as any)?.email\n }\n\n private get _myUserId(): string | undefined {\n return (auth.credential as any)?.id\n }\n\n /** Mention popup โ€” `#` (์ปดํฌ๋„ŒํŠธ) / `@` (์นดํƒˆ๋กœ๊ทธ) / `/` (slash) ํŠธ๋ฆฌ๊ฑฐ ์‹œ ํ™œ์„ฑ.\n * ๋‹จ์ผ popup ์žฌ์‚ฌ์šฉ โ€” mentionTrigger ๋กœ ํ™œ์„ฑ trigger ์ถ”์ . */\n @state()\n private mentionOpen = false\n\n /** popup ํ‘œ์‹œ์šฉ โ€” F-Finder ์ฒ˜๋Ÿผ matchType + matchValue ๋™๋ด‰๋œ ๊ฒฐ๊ณผ */\n @state()\n private mentionResults: FilterResult[] = []\n\n @state()\n private mentionActiveIndex = 0\n\n /** filter cap (50) ์œผ๋กœ ์ž˜๋ผ๋‚ธ ์ถ”๊ฐ€ ๋งค์นญ ์ˆ˜ โ€” popup ์˜ 'N more' ํ‘œ์‹œ์šฉ */\n @state()\n private mentionOverflow = 0\n\n /** ํ˜„์žฌ ํ™œ์„ฑ mention ์˜ textarea ๋‚ด trigger ์œ„์น˜ */\n private mentionHashPos = -1\n\n /** ํ˜„์žฌ ํ™œ์„ฑ trigger char โ€” '#' / '@' / '/'. popup ๋น„ํ™œ์„ฑ ์‹œ ์˜๋ฏธ ์—†์Œ. */\n private mentionTrigger: '#' | '@' | '/' = '#'\n\n /** popup ์—ด๊ธฐ ์ง์ „ ์‚ฌ์šฉ์ž selection ์Šค๋ƒ…์ƒท โ€” Esc/blur close ์‹œ ์›๋ณต์šฉ */\n private originalSelectedRefids: number[] = []\n\n /** popup ์—์„œ ๋ช…์‹œ ์„ ํƒ๋œ #mention ๋งคํ•‘ โ€” {token: refid}.\n * ์‚ฌ์šฉ์ž textarea ์—๋Š” #token ๋งŒ ๋ณด์ด์ง€๋งŒ server ํ•œํ…Œ๋Š” ์ •ํ™•ํ•œ refid ์ „๋‹ฌ.\n * send ์‹œ mutation input.mentions ๋กœ ํ•จ๊ป˜ ์ „์†ก. ์‚ฌ์šฉ์ž๊ฐ€ textarea ๋น„์šฐ๊ฑฐ๋‚˜\n * ์ƒˆ ์ฑ„ํŒ… ์‹œ์ž‘ํ•˜๋ฉด ์ •๋ฆฌ. */\n private pickedMentions: Map<string, number> = new Map()\n\n /** popup ์—์„œ ๋ช…์‹œ ์„ ํƒ๋œ @user ๋ฉ˜์…˜ ๋งคํ•‘ โ€” {token: userId}.\n * textarea ์—๋Š” @username ๋งŒ ๋ณด์ด์ง€๋งŒ server ํ•œํ…Œ๋Š” ์ •ํ™•ํ•œ userId ์ „๋‹ฌ.\n * send ์‹œ mutation input.userMentions ๋กœ ํ•จ๊ป˜ ์ „์†ก. */\n private pickedUserMentions: Map<string, string> = new Map()\n\n /** input ๋””๋ฐ”์šด์Šค timer โ€” 150ms ํ›„ refreshMentionPopup ์‹คํ–‰ (F-Finder ์™€ ๋™์ผ) */\n private inputDebounceTimer?: ReturnType<typeof setTimeout>\n\n /** centerTo ๋””๋ฐ”์šด์Šค timer โ€” arrow nav / hover ๋น ๋ฅผ ๋•Œ ์นด๋ฉ”๋ผ ์• ๋‹ˆ๋ฉ”์ด์…˜ race ๋ฐฉ์ง€ */\n private centerDebounceTimer?: ReturnType<typeof setTimeout>\n\n /*\n * โ”€โ”€ What this conversation is, resolved โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n *\n * A host that declares a mode gets the mode and nothing else โ€” a field it leaves out is empty,\n * never filled from these properties or the registered defaults. A host that has not declared\n * one keeps the separate properties and the global defaults it had before.\n */\n private get conversation() {\n return resolveConversation(\n this.mode,\n {\n hostContext: this.hostContext,\n chatEndpoint: this.chatEndpoint,\n /* A host with no mode still registers its wording as keys; it is translated here. */\n footerNotice: chatDefaults.footerNoticeKey ? i18next.t(chatDefaults.footerNoticeKey) : undefined,\n stagedNotice: chatDefaults.stagedNoticeKey ? i18next.t(chatDefaults.stagedNoticeKey) : undefined\n } as any,\n chatDefaults as any,\n this.modeView\n )\n }\n\n /**\n * What the server said this mode offers, in this person's language.\n *\n * Fetched when the mode changes and kept until the next one answers. Until it arrives the panel\n * offers nothing rather than the list some other package registered globally.\n */\n @state() private modeView?: AssistantModeView\n\n private modeViewToken = 0\n\n /** ์ด subject ์— ์„ค ์ˆ˜ ์žˆ๋Š” ๋Œ€ํ™”๋“ค โ€” ๊ธฐ๋ณธ์ด ๋จผ์ €. ํ•˜๋‚˜๋ฟ์ด๋ฉด ๊ณ ๋ฅด๊ฐœ๋ฅผ ๊ทธ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค. */\n @state() private modeChoices: { kind: string; label: string; isDefault: boolean }[] = []\n\n private modeChoicesToken = 0\n\n /**\n * ์ด ํ™”๋ฉด์— ์„ค ์ˆ˜ ์žˆ๋Š” ๋Œ€ํ™”๋ฅผ ์„œ๋ฒ„์— ๋ฌป๋Š”๋‹ค.\n *\n * ํ™”๋ฉด์ด ์ข…๋ฅ˜ ๋ชฉ๋ก์„ ์†์— ๋“ค๊ณ  ์žˆ์œผ๋ฉด, ๋Œ€ํ™”๋ฅผ ํ•˜๋‚˜ ๋” ์„ธ์šด ๋‚  ๊ทธ ํ™”๋ฉด๋งŒ ๋ชจ๋ฅธ ์ฑ„๋กœ ๋‚จ๋Š”๋‹ค. ๋ชฉ๋ก์€\n * ์•ฑ ์„œ๋ฒ„์˜ ์„ ์–ธ์—์„œ ๋‚˜์˜จ๋‹ค(ADR-0072 A17 โ‘ ).\n */\n private async loadModeChoices() {\n const subject = this.subject\n if (!subject) {\n this.modeChoices = []\n return\n }\n const token = ++this.modeChoicesToken\n try {\n const result = await client.query({\n query: ASSISTANT_MODES_QUERY,\n variables: { subject },\n fetchPolicy: 'cache-first'\n })\n if (token !== this.modeChoicesToken) return\n this.modeChoices = result.data?.assistantModes ?? []\n } catch {\n /*\n * ๋ชป ๋ฌผ์–ด๋ดค๋‹ค๊ณ  ํ™”๋ฉด์„ ๋ง‰์ง€ ์•Š๋Š”๋‹ค โ€” host ๊ฐ€ ์ค€ ๋Œ€ํ™”๋Š” ๊ทธ๋Œ€๋กœ ์‚ฐ๋‹ค. ๊ณ ๋ฅด๊ฐœ๋งŒ ์•ˆ ๋‚˜์˜จ๋‹ค.\n * ์—ฌ๊ธฐ์„œ ์˜ค๋ฅ˜ ๋ฌธ๊ตฌ๋ฅผ ๋„์šฐ๋ฉด ๊ณ ๋ฅผ ๊ฒƒ์ด ํ•˜๋‚˜๋ฟ์ธ ํ™”๋ฉด์—์„œ๋„ ๋นจ๊ฐ„ ์ค„์ด ๋œฌ๋‹ค.\n */\n if (token !== this.modeChoicesToken) return\n this.modeChoices = []\n }\n }\n\n /**\n * ์‚ฌ๋žŒ์ด ๋‹ค๋ฅธ ๋Œ€ํ™”๋ฅผ ๊ณจ๋ž๋‹ค.\n *\n * ๊ณ ๋ฅธ ๊ฒƒ์€ **์ด subject ์ข…๋ฅ˜์— ๋Œ€ํ•ด** ๊ธฐ์–ตํ•œ๋‹ค โ€” ๋ณด๋“œ๋ฅผ ์—ด ๋•Œ๋งˆ๋‹ค ์ €์ž‘ ๋Œ€ํ™”๋กœ ๋Œ์•„๊ฐ€๋ฉด, ํ˜„์žฅ์„\n * ๋ฌผ์œผ๋ ค๋˜ ์‚ฌ๋žŒ์€ ํ™”๋ฉด์„ ์—ด ๋•Œ๋งˆ๋‹ค ๊ฐ™์€ ์†์งˆ์„ ๋‹ค์‹œ ํ•ด์•ผ ํ•œ๋‹ค. ๊ธฐ์–ต์€ ์ด ๋ธŒ๋ผ์šฐ์ €์—๋งŒ ๋‚จ๋Š”๋‹ค\n * (์„œ๋ฒ„์— ์นธ์„ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค โ€” A17 โ‘ ). ์„ธ์…˜ ์ž์ฒด๋Š” ์ž๊ธฐ๊ฐ€ ์–ด๋А ๋Œ€ํ™”์˜€๋Š”์ง€ ์ด๋ฏธ ์•ˆ๋‹ค.\n */\n private onModePick(kind: string) {\n if (!this.mode || kind === this.mode.kind) return\n try {\n if (this.subject) localStorage.setItem(`assistant-mode:${this.subject}`, kind)\n } catch {\n /* ์ €์žฅ์ด ๋ง‰ํžŒ ๋ธŒ๋ผ์šฐ์ €์—์„œ๋„ ๊ณ ๋ฅด๊ธฐ ์ž์ฒด๋Š” ๋œ๋‹ค โ€” ๋‹ค์Œ์— ๋‹ค์‹œ ๊ณ ๋ฅด๋ฉด ๋  ๋ฟ์ด๋‹ค. */\n }\n this.askHostForMode(kind)\n }\n\n /**\n * **๊ณ ๋ฅด๋Š” ๊ฒƒ์€ ์ฒญํ•˜๋Š” ์ผ์ด๋‹ค** โ€” `mode` ๋ฅผ ์—ฌ๊ธฐ์„œ ๋ฐ”๊พธ์ง€ ์•Š๋Š”๋‹ค.\n *\n * host ๋Š” ๋ Œ๋”๋งˆ๋‹ค `mode` ๋ฅผ ๋‹ค์‹œ ๋‚ด๋ ค ์ค€๋‹ค. ํŒจ๋„์ด ์ž๊ธฐ ์†์œผ๋กœ ๊ณ ์ณ ๋‘๋ฉด ๋‹ค์Œ ๋ Œ๋”๊ฐ€ ๊ทธ๊ฒƒ์„ ๋ฎ๊ณ ,\n * ๋” ๋‚˜์œ ๊ฒƒ์€ host ๊ฐ€ **์ž๊ธฐ๊ฐ€ ๋ฌด์—‡์„ ์—ด์—ˆ๋Š”์ง€ ๋ชจ๋ฅด๋Š” ์ฑ„๋กœ ๋‚จ๋Š”๋‹ค**๋Š” ๊ฒƒ์ด๋‹ค. host ๋Š” ๋Œ€ํ™”์˜ ์„ธ์…˜์„\n * ๋Œ€์ƒ๋ณ„๋กœ ๋“ค๊ณ  ์žˆ์œผ๋ฏ€๋กœ, ๋Œ€ํ™”๊ฐ€ ๋ฐ”๋€ ๊ฒƒ์„ ๋ชจ๋ฅด๋ฉด ์•ž ๋Œ€ํ™”์˜ ์„ธ์…˜์„ ๊ทธ๋Œ€๋กœ ๋„˜๊ธด๋‹ค โ€” ๊ทธ๋Ÿฌ๋ฉด ์ƒˆ ๋ง์ด ์•ž\n * ๋Œ€ํ™”์— ๋ถ™๋Š”๋‹ค(2026-09-18 Figure ๋ ˆ์ธ์ด :3300 ์—์„œ ๋ณธ ๊ฒƒ์ด ์ด๊ฒƒ์ด๋‹ค).\n *\n * ๊ทธ๋ž˜์„œ ์ฃผ์ธ์€ ํ•˜๋‚˜๋‹ค: host ๊ฐ€ `mode` ๋ฅผ ๊ฐ–๊ณ , ํŒจ๋„์€ ใ€Œ์ด๊ฒƒ์œผ๋กœ ๋ฐ”๊ฟ” ๋‹ฌ๋ผใ€๊ณ  ๋งํ•œ๋‹ค. ๊ธฐ์–ต์€ ํŒจ๋„์ด\n * ์ง„๋‹ค(๋ธŒ๋ผ์šฐ์ €๋งˆ๋‹ค ๋‹ค๋ฅธ ๊ฐ’์ด๋ผ host ๊ฐ€ ์งˆ ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค) โ€” ๊ธฐ์–ตํ•œ ๊ฒƒ์„ ๋˜์‚ด๋ฆด ๋•Œ๋„ ๊ฐ™์€ ์ฒญ์œผ๋กœ ๋‚˜๊ฐ„๋‹ค.\n */\n private askHostForMode(kind: string) {\n this.dispatchEvent(\n new CustomEvent('assistant-mode-change', { detail: { kind, subject: this.subject }, bubbles: true, composed: true })\n )\n }\n\n /** ์ด subject ์—์„œ ์ง€๋‚œ๋ฒˆ์— ๊ณ ๋ฅธ ๋Œ€ํ™” โ€” ์—†์œผ๋ฉด undefined. */\n private rememberedMode(subject: string): string | undefined {\n try {\n return localStorage.getItem(`assistant-mode:${subject}`) ?? undefined\n } catch {\n return undefined\n }\n }\n\n private async loadModeView() {\n const mode = this.mode\n if (!mode?.kind) {\n this.modeView = undefined\n return\n }\n const token = ++this.modeViewToken\n try {\n const result = await client.query({ query: ASSISTANT_MODE_QUERY, variables: { kind: mode.kind }, fetchPolicy: 'cache-first' })\n /* A late answer for a conversation the person has already left is dropped. */\n if (token !== this.modeViewToken) return\n this.modeView = result.data?.assistantMode\n this.rebuildMentionCaches()\n } catch (error) {\n if (token !== this.modeViewToken) return\n this.modeView = undefined\n /*\n * A kind this server does not have is a mismatched deployment, and the person should read it\n * rather than watch an empty `/` list.\n */\n this.errorMessage = error instanceof Error ? error.message : String(error)\n }\n }\n\n /*\n * The `@` and `/` candidates, built once per mode.\n *\n * These were built at field initialisation, which meant a host could not change what the\n * panel offers without replacing the element. A mode change rebuilds them below.\n */\n private cachedCatalogCandidates: MentionCandidate[] = buildCatalogCandidates(chatDefaults.catalogEntries)\n\n private cachedSlashCandidates: MentionCandidate[] = buildSlashCandidates(chatDefaults.slashTemplates)\n\n private rebuildMentionCaches() {\n this.cachedCatalogCandidates = buildCatalogCandidates(this.conversation.catalogEntries)\n this.cachedSlashCandidates = buildSlashCandidates(this.conversation.slashTemplates)\n }\n\n /** `@` ๋งˆ์ง€๋ง‰ query ์˜ ๋„๋ฉ”์ธ ์‚ฌ์šฉ์ž ํ›„๋ณด ์บ์‹œ โ€” userProvider ์‘๋‹ต ๋„์ฐฉ ์‹œ ๊ฐฑ์‹ .\n * query ๋ณ„ ์บ์‹œ๊ฐ€ ์•„๋‹ˆ๋ผ ๋‹จ์ˆœ \"์ตœ๊ทผ ๊ฒฐ๊ณผ\" โ€” async race ํšŒํ”ผ. */\n private cachedUserCandidates: MentionCandidate[] = []\n\n /** ์ง„ํ–‰ ์ค‘์ธ userProvider fetch token โ€” ๋Šฆ๊ฒŒ ๋„์ฐฉํ•œ ์‘๋‹ต์ด ์ตœ์‹ ์„ ๋ฎ์–ด์“ฐ์ง€ ์•Š๋„๋ก ์‹๋ณ„. */\n private userFetchToken = 0\n\n static styles = [\n // ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ‘œ์ค€ ์Šคํฌ๋กค๋ฐ” (--scrollbar-width / --scrollbar-thumb-color ๋“ฑ ํ˜ธ์ŠคํŠธ ๋ณ€์ˆ˜ ๋”ฐ๋ฆ„)\n ScrollbarStyles,\n css`\n /*\n Material Design 3 ํ† ํฐ ์‚ฌ์šฉ โ€” ์‚ฌ์šฉ์ž ํ…Œ๋งˆ (๋ผ์ดํŠธ/๋‹คํฌ/๋ธŒ๋žœ๋“œ) ์ž๋™ ๋ฐ˜์˜.\n ๊ฐ var() ์˜ ๋‘ ๋ฒˆ์งธ ์ธ์ž๋Š” ํ† ํฐ ๋ฏธ์ •์˜ ์‹œ fallback (ํ˜„ ๋””์ž์ธ ํ†ค).\n */\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 240px;\n position: relative;\n font:\n 400 11px / 1.55 -apple-system,\n BlinkMacSystemFont,\n 'Inter',\n 'Pretendard',\n 'Segoe UI',\n Roboto,\n sans-serif;\n letter-spacing: -0.005em;\n color: var(--md-sys-color-on-surface, #0f172a);\n background: var(--md-sys-color-surface, #ffffff);\n }\n\n /* โ”€โ”€ C4 Roster (participants + presence) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n /* ์ด ๋Œ€ํ™”์˜ ์ฃผ์–ด โ€” ๊ฐ™์€ ํ™”๋ฉด ์œ„์— ๋‘ ๋Œ€ํ™”๊ฐ€ ์„ค ๋•Œ๋งŒ ๋‚˜์˜จ๋‹ค(ADR-0072 A17 โ‘ ).\n ์ง€๊ธˆ ๋Œ€ํ™”๊ฐ€ ์ œ๋ชฉ ๊ตต๊ธฐ๋กœ ์„œ๊ณ , ๋ฐ”๊ฟ€ ์ž๋ฆฌ๊ฐ€ ๊ทธ ์˜†์— ๋ถ™๋Š”๋‹ค. ์„ธ์…˜ ํƒญ๊ณผ ๊ฐ™์€ ๋ฌด๊ฒŒ๋กœ ๊ทธ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค\n (UX ๋ ˆ์ธ, 2026-09-18) โ€” ํ•œ์ชฝ์€ ํ™”์ œ๋ฅผ ๋ฐ”๊พธ๊ณ  ํ•œ์ชฝ์€ ์‹คํƒ€๋ž˜๋ฅผ ๋ฐ”๊พผ๋‹ค. */\n .mode-subject {\n display: flex;\n align-items: baseline;\n gap: 8px;\n padding: 6px 12px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n }\n .mode-now {\n /* ๊ณ ๋ฅธ ์ƒํƒœ์˜ ์ƒ‰์€ ์„ธ์…˜ ํƒญ๊ณผ ๊ฐ™์€ ๊ณ„์—ด์ด๋‹ค โ€” ํ•œ ํŒจ๋„ ์•ˆ์—์„œ ใ€Œ๊ณจ๋ž๋‹คใ€๊ฐ€ ๋‘ ์ƒ‰์œผ๋กœ ๋‚˜์˜ค๋ฉด ์ฝ๋Š”\n ์‚ฌ๋žŒ์€ ๋‘ ์ƒ‰์ด ์„œ๋กœ ๋‹ค๋ฅธ ๋œป์ธ ์ค„ ์•ˆ๋‹ค.\n\n 12px ์ด์—ˆ๋‹ค๊ฐ€ ํ•œ ๋‹จ ๋‚ด๋ ธ๋‹ค. ๋„ํฌ ์ œ๋ชฉ(figure ์˜ .scope-title ์ด 12.5px / 650)๊ณผ 0.5px ยท\n ๊ตต๊ธฐ 50 ์ฐจ์ด๋Š” ๋ˆˆ์— ๋‹ฟ์ง€ ์•Š์•„์„œ, ๊ฑฐ์˜ ๊ฐ™์€ ์ œ๋ชฉ ์ค„์ด ๋‘˜ ํฌ๊ฐœ์กŒ๋‹ค. ๋„ํฌ ์ œ๋ชฉ์€ ๊ทธ ๋„ํฌ ์ „์ฒด๋ฅผ\n ๊ฑฐ๋А๋ฆฌ๊ณ  ์ด ์ค„์€ ๊ทธ ์•ˆ ๋Œ€ํ™” ํ•˜๋‚˜์˜ ์„ฑ์งˆ์ด๋‹ค โ€” 11px ์ด๋ฉด ์ด ํŒจ๋„์˜ ๋‹ค๋ฅธ ์กฐ์ž‘๋ถ€์™€ ๊ฐ™์€ ๋‹จ์ด๊ณ ,\n ใ€Œ์ด๊ฒƒ์ด ์ฃผ์–ด๋‹คใ€๋Š” ์ƒ‰์ด ๊ณ„์† ์ง„๋‹ค(UX ๋ ˆ์ธ, 2026-09-18). */\n color: var(--primary-color, #007f87);\n font-size: 11px;\n font-weight: 600;\n }\n .mode-switch,\n .mode-select {\n appearance: none;\n background: transparent;\n border: 1px solid var(--md-sys-color-outline-variant, #cbd5e1);\n border-radius: 999px;\n color: var(--md-sys-color-on-surface-variant, #475569);\n cursor: pointer;\n font: inherit;\n font-size: 11px;\n padding: 2px 10px;\n white-space: nowrap;\n }\n .mode-switch:hover:not([disabled]) {\n background: color-mix(in srgb, var(--primary-color, #007f87) 7%, transparent);\n color: var(--primary-color, #007f87);\n }\n /* ๋‹ตํ•˜๋Š” ๋™์•ˆ์—๋„ ใ€Œ๋‚ด๊ฐ€ ์ง€๊ธˆ ๋ฌด์—‡์— ๋Œ€ํ•ด ๋งํ•˜๊ณ  ์žˆ๋‚˜ใ€๋Š” ๋˜๋ ทํ•ด์•ผ ํ•œ๋‹ค โ€” ํ๋ ค์ง€๋Š” ๊ฒƒ์€ ๋ฐ”๊ฟ€\n ์ž๋ฆฌ๋ฟ์ด๋‹ค. ์ง€๊ธˆ ๋Œ€ํ™”๊นŒ์ง€ ํ๋ฆฌ๋ฉด ๊ทธ ํ•œ ์ค„์ด ๊ฐ€์žฅ ์•ˆ ๋ณด์ธ๋‹ค. */\n .mode-subject [disabled] {\n cursor: default;\n opacity: 0.5;\n }\n\n .roster {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 4px;\n padding: 4px 8px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n }\n .roster-count {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n font-size: 10px;\n opacity: 0.7;\n margin-right: 2px;\n }\n .roster-count md-icon {\n font-size: 13px;\n width: 13px;\n height: 13px;\n }\n .roster-chip {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 1px 6px 1px 4px;\n border-radius: 9px;\n font-size: 10px;\n background: var(--md-sys-color-surface-variant, #f1f5f9);\n }\n .roster-chip.offline {\n opacity: 0.45;\n }\n .roster-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #cbd5e1;\n }\n .roster-chip.online .roster-dot {\n background: #22c55e;\n }\n\n /* โ”€โ”€ Session tabs โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .session-tabs {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 4px 6px 0 6px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n background: var(--md-sys-color-surface-container-low, #fafbfc);\n overflow-x: auto;\n scrollbar-width: thin;\n flex-shrink: 0;\n }\n .session-tab {\n flex-shrink: 0;\n padding: 4px 10px;\n font-size: 11px;\n line-height: 1.4;\n color: var(--md-sys-color-on-surface-variant, #64748b);\n background: transparent;\n border: 1px solid transparent;\n border-bottom: 0;\n border-top-left-radius: 5px;\n border-top-right-radius: 5px;\n cursor: pointer;\n max-width: 160px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n .session-tab:hover {\n background: var(--md-sys-color-surface-container, #f1f5f9);\n }\n .session-tab.active {\n background: var(--md-sys-color-surface, #ffffff);\n color: var(--md-sys-color-on-surface, #0f172a);\n border-color: var(--md-sys-color-outline-variant, #e2e8f0);\n font-weight: 500;\n position: relative;\n }\n .session-tab.active::after {\n content: '';\n position: absolute;\n left: 0;\n right: 0;\n bottom: -1px;\n height: 1px;\n background: var(--md-sys-color-surface, #ffffff);\n }\n .session-tab-new {\n flex-shrink: 0;\n padding: 4px 8px 4px 6px;\n background: transparent;\n border: 0;\n cursor: pointer;\n color: var(--md-sys-color-on-surface-variant, #64748b);\n display: inline-flex;\n align-items: center;\n gap: 2px;\n font-size: 11px;\n line-height: 1.4;\n border-radius: 5px;\n white-space: nowrap;\n }\n .session-tab-new:hover {\n color: var(--md-sys-color-primary, #2563eb);\n background: var(--md-sys-color-surface-container, #f1f5f9);\n }\n .session-tab-new md-icon {\n --md-icon-size: 14px;\n font-size: 14px;\n }\n\n /* โ”€โ”€ Messages โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n /* ์Šคํฌ๋กค๋ฐ”๋Š” ScrollbarStyles (์œ„์ชฝ styles ๋ฐฐ์—ด) ๊ฐ€ ์ฒ˜๋ฆฌ โ€” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ‘œ์ค€ ๋”ฐ๋ฆ„ */\n .messages {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden; /* ๊ฐ€๋กœ ์Šคํฌ๋กค ์ฐจ๋‹จ โ€” ์ž์‹ (empty / msg) ๋‚ด๋ถ€์—์„œ wrap ์ฒ˜๋ฆฌ */\n padding: 10px 16px 4px;\n display: flex;\n flex-direction: column;\n gap: 4px; /* ๋‹จ์ผ spacing source โ€” .msg-wrap ์˜ ์ž์ฒด margin ์€ 0 */\n scroll-behavior: smooth;\n min-width: 0; /* flex item ์˜ ๊ธฐ๋ณธ min-content ๋ฌด์‹œ โ€” ์ž์‹ ellipsis/wrap ๋™์ž‘ */\n }\n\n /* โ”€โ”€ Empty state โ€” onboarding ๊ฐ€์ด๋“œ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .empty {\n margin: auto;\n text-align: left;\n width: 100%;\n max-width: 360px;\n box-sizing: border-box;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 16px;\n word-break: break-word; /* ๊ธด ํ•œ๊ธ€ / URL ๋„ ์ค„๋ฐ”๊ฟˆํ•ด ๊ฐ€๋กœ overflow ๋ฐฉ์ง€ */\n overflow-wrap: anywhere;\n }\n .empty .header {\n text-align: center;\n padding: 8px 0 4px;\n }\n .empty .icon {\n font-size: 22px;\n opacity: 0.4;\n margin-bottom: 8px;\n color: var(--md-sys-color-primary, currentColor);\n display: block;\n }\n .empty .title {\n color: var(--md-sys-color-on-surface, #0f172a);\n font-size: 12.5px;\n font-weight: 600;\n margin-bottom: 4px;\n letter-spacing: -0.01em;\n }\n .empty .subtitle {\n color: var(--md-sys-color-on-surface-variant, #475569);\n font-size: 10.5px;\n line-height: 1.5;\n }\n\n .empty .group {\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n .empty .group-label {\n font-size: 9.5px;\n color: var(--md-sys-color-outline, #94a3b8);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n font-weight: 600;\n padding: 0 2px;\n }\n .empty .example {\n all: unset;\n display: block;\n cursor: pointer;\n padding: 7px 10px;\n font-size: 11px;\n color: var(--md-sys-color-on-surface, #0f172a);\n background: var(--md-sys-color-surface-container, #f8fafc);\n border: 1px solid var(--md-sys-color-outline-variant, #eef2f6);\n border-radius: 8px;\n line-height: 1.5;\n box-sizing: border-box;\n width: 100%;\n max-width: 100%;\n word-break: break-word;\n overflow-wrap: anywhere;\n transition:\n background 0.15s,\n border-color 0.15s,\n transform 0.1s;\n }\n .empty .example:hover {\n background: var(--md-sys-color-surface-container-high, #f1f5f9);\n border-color: var(--md-sys-color-outline, #cbd5e1);\n }\n .empty .example:active {\n transform: scale(0.99);\n }\n .empty .example .arrow {\n float: right;\n opacity: 0.4;\n margin-left: 8px;\n font-size: 11px;\n }\n\n .empty .footer {\n margin-top: 4px;\n padding: 8px 4px 0;\n border-top: 1px solid var(--md-sys-color-outline-variant, #eef2f6);\n color: var(--md-sys-color-outline, #94a3b8);\n font-size: 10px;\n line-height: 1.6;\n text-align: center;\n }\n .empty .footer .badge {\n display: inline-block;\n margin: 0 4px;\n padding: 1px 7px;\n background: var(--md-sys-color-surface-container, #f8fafc);\n border-radius: 8px;\n font-size: 9.5px;\n color: var(--md-sys-color-on-surface-variant, #64748b);\n }\n /* โ”€โ”€ Trigger chip row (empty state) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .empty .trigger-row {\n margin: 12px 0 4px;\n padding: 10px 12px;\n background: var(--md-sys-color-surface-container-low, #f8fafc);\n border: 1px solid var(--md-sys-color-outline-variant, #eef2f6);\n border-radius: 10px;\n }\n .empty .trigger-row-label {\n font-size: 10px;\n color: var(--md-sys-color-on-surface-variant, #64748b);\n margin-bottom: 6px;\n text-align: center;\n letter-spacing: 0.02em;\n }\n .empty .trigger-chips {\n display: flex;\n gap: 6px;\n justify-content: center;\n flex-wrap: wrap;\n }\n .empty .trigger-chip {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 10px;\n background: var(--md-sys-color-surface, #ffffff);\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n border-radius: 18px;\n cursor: pointer;\n font-size: 11.5px;\n color: var(--md-sys-color-on-surface, #0f172a);\n transition:\n border-color 0.15s,\n background 0.15s,\n color 0.15s;\n }\n .empty .trigger-chip:hover {\n border-color: var(--md-sys-color-primary, #2563eb);\n background: var(--md-sys-color-primary-container, #dbeafe);\n color: var(--md-sys-color-on-primary-container, #1e3a8a);\n }\n .empty .trigger-chip .trigger-char {\n font-family:\n 'SF Mono',\n Menlo,\n Monaco,\n Consolas,\n monospace;\n font-size: 13px;\n font-weight: 600;\n color: var(--md-sys-color-primary, #2563eb);\n min-width: 12px;\n text-align: center;\n }\n .empty .trigger-chip:hover .trigger-char {\n color: var(--md-sys-color-on-primary-container, #1e3a8a);\n }\n .empty .trigger-chip .trigger-desc {\n font-weight: 500;\n }\n\n /* โ”€โ”€ Message label (sender hint) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .msg-label {\n font-size: 9.5px;\n color: var(--md-sys-color-outline, #94a3b8);\n letter-spacing: 0.05em;\n font-weight: 500;\n text-transform: uppercase;\n margin: 4px 0 1px 4px;\n align-self: flex-start;\n }\n .msg-label:first-child {\n margin-top: 0;\n }\n\n /* โ”€โ”€ Message wrapper (๋ฉ”์‹œ์ง€ + hover ์•ก์…˜) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .msg-wrap {\n display: flex;\n flex-direction: column;\n width: fit-content;\n max-width: min(92%, 420px);\n /* margin 0 โ€” spacing ์€ .messages gap ๋‹จ์ผ source */\n }\n .msg-wrap.user {\n align-self: flex-end;\n align-items: flex-end;\n }\n .msg-wrap.assistant {\n align-self: flex-start;\n align-items: flex-start;\n }\n .msg-wrap.system {\n align-self: center;\n align-items: center;\n max-width: 100%;\n }\n\n /* โ”€โ”€ Message bubble โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .msg {\n display: inline-block;\n width: fit-content;\n max-width: 100%;\n padding: 5px 9px;\n border-radius: 10px;\n white-space: normal;\n overflow-wrap: anywhere;\n font-size: 11px;\n line-height: 1.45;\n }\n\n .msg.user {\n align-self: flex-end;\n background: var(--md-sys-color-primary, #1e293b);\n color: var(--md-sys-color-on-primary, #f8fafc);\n border-radius: 12px 12px 3px 12px;\n /* margin-top 0 โ€” .messages gap ์œผ๋กœ๋งŒ spacing */\n }\n\n /* ๊ทธ๋ฃน์ฑ— โ€” ๋‹ค๋ฅธ ์ฐธ์—ฌ์ž์˜ ๋ฉ”์‹œ์ง€. ๋‚ด ๋ฉ”์‹œ์ง€(์šฐ์ธก primary)์™€ ๊ตฌ๋ถ„: ์ขŒ์ธก ์ •๋ ฌ + ๋ณด์กฐ ์ƒ‰. */\n .msg-wrap.user.other {\n align-self: flex-start;\n align-items: flex-start;\n }\n .msg.user.other {\n align-self: flex-start;\n background: var(--md-sys-color-secondary-container, #e2e8f0);\n color: var(--md-sys-color-on-secondary-container, #0f172a);\n border-radius: 12px 12px 12px 3px;\n }\n /* ๋ฐœ์‹ ์ž ์ด๋ฆ„ ๋ผ๋ฒจ โ€” AI ๋ผ๋ฒจ(๋Œ€๋ฌธ์ž)๊ณผ ๋‹ฌ๋ฆฌ ์‚ฌ๋žŒ ์ด๋ฆ„์€ ๊ทธ๋Œ€๋กœ. */\n .msg-label.sender {\n text-transform: none;\n letter-spacing: 0;\n color: var(--md-sys-color-primary, #475569);\n }\n\n .msg.assistant {\n align-self: flex-start;\n background: var(--md-sys-color-surface-container, #f8fafc);\n color: var(--md-sys-color-on-surface, #0f172a);\n border: 1px solid var(--md-sys-color-outline-variant, #eef2f6);\n border-radius: 12px 12px 12px 3px;\n }\n\n /* โ”€โ”€ Markdown ๋ Œ๋” (AI ์‘๋‹ต) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .md-body {\n display: block;\n }\n .md-body > :first-child {\n margin-top: 0;\n }\n .md-body > :last-child {\n margin-bottom: 0;\n }\n .md-body p {\n margin: 0 0 4px;\n line-height: 1.45;\n }\n .md-body ul,\n .md-body ol {\n margin: 2px 0 4px;\n padding-left: 16px;\n }\n .md-body li {\n margin: 0;\n line-height: 1.45;\n }\n .md-body li > p {\n margin: 0;\n }\n .md-body strong {\n font-weight: 600;\n }\n .md-body em {\n font-style: italic;\n }\n /* '#token' mention โ€” popup ์˜ match-badge ํ†ค๊ณผ ๋งž์ถค. ์ฑ„ํŒ… ๋ฒ„๋ธ”์—์„œ ์ปดํฌ๋„ŒํŠธ\n ์ฐธ์กฐ์ž„์„ ์‹œ๊ฐ์ ์œผ๋กœ ๊ตฌ๋ถ„ (์‚ฌ์šฉ์ž/AI ๋ฉ”์‹œ์ง€ ์–‘์ชฝ). */\n .md-body .mention {\n display: inline-block;\n padding: 0 5px;\n border-radius: 4px;\n background: var(--md-sys-color-primary-container, rgba(37, 99, 235, 0.12));\n color: var(--md-sys-color-on-primary-container, #1e40af);\n font-weight: 500;\n white-space: nowrap;\n cursor: pointer;\n transition: background 0.12s;\n }\n .md-body .mention:hover {\n background: var(--md-sys-color-primary, rgba(37, 99, 235, 0.25));\n color: var(--md-sys-color-on-primary, #ffffff);\n }\n .msg.user .md-body .mention {\n background: rgba(255, 255, 255, 0.22);\n color: inherit;\n }\n .msg.user .md-body .mention:hover {\n background: rgba(255, 255, 255, 0.40);\n }\n .md-body code {\n font-family:\n 'SF Mono',\n Menlo,\n Monaco,\n Consolas,\n monospace;\n font-size: 10px;\n padding: 1px 4px;\n background: var(--md-sys-color-surface-container-high, rgba(15, 23, 42, 0.06));\n border-radius: 3px;\n }\n .md-body pre {\n margin: 5px 0;\n padding: 6px 8px;\n background: var(--md-sys-color-surface-container-high, rgba(15, 23, 42, 0.06));\n border-radius: 5px;\n overflow-x: auto;\n font-size: 10px;\n line-height: 1.5;\n }\n /* user ๋ฉ”์‹œ์ง€(์–ด๋‘์šด ๋ฐฐ๊ฒฝ) ์œ„์—์„œ๋Š” code/pre ์˜ contrast ๋ณด์ • */\n .msg.user .md-body code,\n .msg.user .md-body pre {\n background: rgba(255, 255, 255, 0.15);\n }\n .msg.user .md-body a {\n color: inherit;\n text-decoration: underline;\n text-underline-offset: 2px;\n }\n .msg.user .md-body blockquote {\n border-left-color: rgba(255, 255, 255, 0.3);\n color: rgba(255, 255, 255, 0.85);\n }\n .msg.user .md-body hr {\n border-top-color: rgba(255, 255, 255, 0.2);\n }\n .md-body pre code {\n padding: 0;\n background: transparent;\n font-size: inherit;\n }\n .md-body a {\n color: var(--md-sys-color-primary, #1e293b);\n text-decoration: underline;\n text-underline-offset: 2px;\n }\n .md-body a:hover {\n text-decoration: none;\n }\n .md-body h1,\n .md-body h2,\n .md-body h3,\n .md-body h4 {\n margin: 4px 0 2px;\n font-weight: 600;\n line-height: 1.35;\n }\n .md-body h1 { font-size: 13px; }\n .md-body h2 { font-size: 12px; }\n .md-body h3,\n .md-body h4 { font-size: 11.5px; }\n .md-body blockquote {\n margin: 4px 0;\n padding: 1px 8px;\n border-left: 2px solid var(--md-sys-color-outline-variant, #cbd5e1);\n color: var(--md-sys-color-on-surface-variant, #64748b);\n }\n .md-body hr {\n border: 0;\n border-top: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n margin: 6px 0;\n }\n .md-body table {\n border-collapse: collapse;\n margin: 4px 0;\n font-size: 10px;\n }\n .md-body th,\n .md-body td {\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n padding: 2px 6px;\n }\n .md-body th {\n background: var(--md-sys-color-surface-container, #f8fafc);\n font-weight: 600;\n }\n\n .msg.system {\n align-self: center;\n background: transparent;\n color: var(--md-sys-color-outline, #94a3b8);\n font-size: 10px;\n font-style: italic;\n max-width: 100%;\n padding: 2px 8px;\n margin: 0;\n border: 0;\n }\n /* ์‹œ์Šคํ…œ ๊ธฐ๋ก์€ **๊ณ์ค„**์ด๋‹ค โ€” ๊ธธ๋ฉด ํ™”๋ฉด์„ ์žก์•„๋จน์–ด ๋Œ€ํ™”๊ฐ€ ์•ˆ ๋ณด์ธ๋‹ค(์˜ฎ๊ฒจ์˜จ ๋Œ€ํ™”๋ฅผ ํ•œ ๋ฉ์–ด๋ฆฌ๋กœ\n ๋„ฃ์—ˆ์„ ๋•Œ ์‹ค์ œ๋กœ ๊ทธ๋žฌ๋‹ค). ์„ธ ์ค„๋กœ ์ ‘๊ณ  ๋ˆŒ๋Ÿฌ์„œ ํŽผ์นœ๋‹ค. */\n .msg.system .sys-text {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 3;\n overflow: hidden;\n white-space: pre-wrap;\n cursor: pointer;\n }\n .msg.system.open .sys-text {\n display: block;\n -webkit-line-clamp: unset;\n overflow: visible;\n }\n\n /* ๊ฐ’์ด ์•ˆ ์˜จ ์ค„ โ€” ADR-0073 ํŒ์ • 1.\n ๋งํ’์„ ์˜ ์ž๋ฆฌ์™€ ใ€ŒAIใ€ ๋”ฑ์ง€๋Š” ์ง€ํ‚จ๋‹ค โ€” ๊ทธ ์ค„์€ ์–ด์‹œ์Šคํ„ดํŠธ์˜ ๋‹ต์ด ๋งž๊ณ , ์ฝ๋Š” ์‚ฌ๋žŒ์ด ๋ชป ์ง€๋‚˜๊ฐ„\n ๊ฒƒ์ด๋‹ค. ์ ์„  ํ…Œ๋‘๋ฆฌ์™€ ํ๋ฆฐ ์ƒ‰์ด ใ€Œ์ด๊ฒƒ์€ ๊ทธ๊ฐ€ ์“ด ๋ฌธ์žฅ์ด ์•„๋‹ˆ๋‹คใ€๋ฅผ ๋งํ•œ๋‹ค.\n\n ๊ธฐ์šธ์ž„์€ ์“ฐ์ง€ ์•Š๋Š”๋‹ค. ์ด ์•ฑ์˜ ๊ธ€๊ผด ๋ฌถ์Œ์— ํ•œ๊ธ€ ์ดํƒค๋ฆญ ์ž์†Œ๊ฐ€ ์—†์–ด ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ•ฉ์„ฑ์œผ๋กœ ๊ธฐ์šธ์ด๊ณ ,\n ํš ๊ท ํ˜•์ด ๋ฌด๋„ˆ์ ธ ์ž‘์€ ๊ธ€์ž๊ฐ€ ๋จผ์ € ์•ˆ ์ฝํžŒ๋‹ค. UX ๋ ˆ์ธ์ด :4000 ์—์„œ ์žฌ ๋ณด์•˜๋‹ค โ€” ใ€Œ๊ถŒํ•œใ€์˜ ์ง„ํ–‰\n ํญ์ด normalยทitalic ๋‘˜ ๋‹ค 27.6875px ๋กœ ๊ฐ™๋‹ค(2026-09-18). */\n .msg.redacted {\n background: transparent;\n border: 1px dashed var(--md-sys-color-outline-variant, #cbd5e1);\n color: var(--md-sys-color-outline, #94a3b8);\n }\n .redacted-body {\n align-items: center;\n display: flex;\n gap: 6px;\n }\n .redacted-body md-icon {\n /* md-icon ์€ ์ž๊ธฐ ํฌ๊ธฐ๋ฅผ ์ด ๋ณ€์ˆ˜๋กœ ์žก๋Š”๋‹ค โ€” width/height ๋งŒ ์ฃผ๋ฉด ์•„๋ฌด ์ผ๋„ ์•ˆ ์ผ์–ด๋‚œ๋‹ค. */\n --md-icon-size: 14px;\n font-size: 14px;\n }\n\n .msg.pending {\n opacity: 0.5;\n }\n .typing-dots {\n display: inline-flex;\n gap: 4px;\n align-items: center;\n vertical-align: middle;\n }\n .typing-dots > span {\n display: inline-block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: currentColor;\n opacity: 0.4;\n animation: pulse 1.2s ease-in-out infinite;\n }\n .typing-dots > span:nth-child(2) { animation-delay: 0.2s; }\n .typing-dots > span:nth-child(3) { animation-delay: 0.4s; }\n @keyframes pulse {\n 0%, 100% { opacity: 0.2; transform: scale(0.85); }\n 50% { opacity: 0.7; transform: scale(1.1); }\n }\n\n /* โ”€โ”€ Patch indicator + ์ธ๋ผ์ธ ๋˜๋Œ๋ฆฌ๊ธฐ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .summary {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n margin-top: 4px;\n padding: 3px 4px 3px 8px;\n background: var(--md-sys-color-surface-container-high, #f1f5f9);\n border-radius: 6px;\n font-size: 10px;\n color: var(--md-sys-color-on-surface-variant, #475569);\n line-height: 1;\n }\n .summary md-icon {\n --md-icon-size: 13px;\n color: var(--md-sys-color-tertiary, #10b981);\n }\n .summary.reverted {\n opacity: 0.6;\n }\n .summary.reverted md-icon {\n color: var(--md-sys-color-outline, #94a3b8);\n }\n .summary .summary-text {\n letter-spacing: 0.01em;\n }\n .summary .revert-btn {\n height: 20px;\n padding: 0 8px;\n background: transparent;\n border: 0;\n border-radius: 4px;\n cursor: pointer;\n font-family: inherit;\n letter-spacing: inherit;\n font-size: 10px;\n color: var(--md-sys-color-on-surface-variant, #475569);\n line-height: 1;\n transition: background 0.12s, color 0.12s;\n width: auto;\n }\n .summary .revert-btn:hover:not(:disabled) {\n background: var(--md-sys-color-surface, #ffffff);\n color: var(--md-sys-color-on-surface, #0f172a);\n }\n .summary.reverted .revert-btn,\n .summary .revert-btn:disabled {\n display: none;\n }\n\n /* โ”€โ”€ Follow-up question โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .followup {\n font-size: 10.5px;\n color: var(--md-sys-color-on-secondary-container, #92400e);\n background: var(--md-sys-color-secondary-container, #fffbeb);\n border-left: 2px solid var(--md-sys-color-secondary, #f59e0b);\n padding: 5px 8px;\n border-radius: 0 5px 5px 0;\n margin-top: 4px;\n line-height: 1.45;\n }\n\n /* โ”€โ”€ \"๋Œ€ํ™”๊ฐ€ ๊ธธ์–ด์กŒ์Šต๋‹ˆ๋‹ค\" ์•ˆ๋‚ด โ€” ์กฐ์šฉํ•œ ํ•œ ์ค„, ๊ฐ•์กฐํ•˜์ง€ ์•Š๋Š”๋‹ค โ”€โ”€โ”€โ”€โ”€ */\n .fold-notice {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 0 0 4px;\n padding: 5px 8px;\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n border-radius: 8px;\n background: var(--md-sys-color-surface-container-low, #f8fafc);\n color: var(--md-sys-color-on-surface-variant, #475569);\n font-size: 10.5px;\n line-height: 1.45;\n }\n .fold-notice md-icon {\n --md-icon-size: 14px;\n flex-shrink: 0;\n }\n .fold-notice .fn-text {\n flex: 1;\n min-width: 0;\n }\n /* ์ƒˆ ๋Œ€ํ™” โ€” ๊ถŒ์œ ์ด๋ฏ€๋กœ ๊ฐ•์กฐ์ƒ‰ ๊ธ€์ž๋งŒ(์ฑ„์šด ๋ฒ„ํŠผ์€ ์ง€์‹œ์ฒ˜๋Ÿผ ์ฝํžŒ๋‹ค). */\n .fold-notice .fn-new {\n flex-shrink: 0;\n border: 0;\n background: none;\n color: var(--md-sys-color-primary, #0f766e);\n font-family: inherit;\n font-size: 10.5px;\n font-weight: 650;\n cursor: pointer;\n padding: 2px 4px;\n border-radius: 5px;\n white-space: nowrap;\n }\n .fold-notice .fn-new:hover {\n background: var(--md-sys-color-surface-container-high, #e2e8f0);\n }\n .fold-notice .fn-close {\n flex-shrink: 0;\n border: 0;\n background: none;\n color: var(--md-sys-color-outline, #94a3b8);\n cursor: pointer;\n padding: 0;\n display: inline-flex;\n }\n .fold-notice .fn-close md-icon {\n --md-icon-size: 13px;\n }\n\n /* โ”€โ”€ ์กฐ์น˜ ์ œ์•ˆ โ€” AI ๋Š” ์ œ์•ˆ๊นŒ์ง€, ์‹คํ–‰์€ ์‚ฌ์šฉ์ž โ”€โ”€โ”€โ”€โ”€ */\n .proposals {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin-top: 6px;\n }\n .proposal {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n padding: 6px 8px 6px 7px;\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n /* ์™ผ์ชฝ ๊ฐ•์กฐ์„  โ€” ๋˜๋Œ๋ฆด ์ˆ˜ ์—†๋Š” ํ–‰๋™์ž„์„ ์กฐ์šฉํžˆ ๊ตฌ๋ถ„ํ•œ๋‹ค(์ƒ‰๋งŒ์œผ๋กœ ์†Œ๋ฆฌ์น˜์ง€ ์•Š๋Š”๋‹ค). */\n border-left: 3px solid var(--md-sys-color-primary, #0f766e);\n border-radius: 8px;\n background: var(--md-sys-color-surface-container-low, #f8fafc);\n }\n .proposal md-icon {\n --md-icon-size: 16px;\n color: var(--md-sys-color-primary, #0f766e);\n flex-shrink: 0;\n }\n .proposal .pbody {\n display: flex;\n flex-direction: column;\n gap: 1px;\n min-width: 0;\n /* ์ƒํƒœ ๋ฌธ๊ตฌ๊ฐ€ ๊ธธ์–ด์ ธ๋„ ์ œ๋ชฉ ์˜์—ญ์„ 0px๊นŒ์ง€ ๋ฐ€์–ด ํ•œ ๊ธ€์ž์”ฉ ์„ธ๋กœ๋กœ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค. */\n flex: 1 1 132px;\n }\n .proposal .plabel {\n font-size: 11.5px;\n font-weight: 650;\n color: var(--md-sys-color-on-surface, #0f172a);\n overflow-wrap: anywhere;\n }\n .proposal .preason {\n font-size: 10.5px;\n color: var(--md-sys-color-on-surface-variant, #475569);\n overflow-wrap: anywhere;\n }\n /* ์‹คํ–‰ ๋ฒ„ํŠผ โ€” ์ด ๋Œ€ํ™”์˜ ์œ ์ผํ•œ \"๋˜๋Œ๋ฆด ์ˆ˜ ์—†๋Š”\" ํ–‰๋™์ด๋ฏ€๋กœ ์ฑ„์šด ๋ฒ„ํŠผ ํ•˜๋‚˜๋กœ ๋ถ„๋ช…ํ•˜๊ฒŒ. */\n .proposal .run {\n /* ๋ณด๋‚ด๋Š” ์ค‘ n์ดˆ์ฒ˜๋Ÿผ ๊ธด ์ƒํƒœ๋„ ์ข์€ ๋„ํฌ์—์„œ ์นด๋“œ ํญ์„ ๋…์ ํ•˜์ง€ ์•Š๋Š”๋‹ค. */\n min-width: 0;\n max-width: 100%;\n overflow-wrap: anywhere;\n white-space: normal;\n line-height: 1.3;\n flex-shrink: 0;\n padding: 4px 12px;\n border: 0;\n border-radius: 999px;\n background: var(--md-sys-color-primary, #0f766e);\n color: var(--md-sys-color-on-primary, #ffffff);\n font-family: inherit;\n font-size: 11px;\n font-weight: 650;\n letter-spacing: 0.01em;\n cursor: pointer;\n transition: filter 0.12s;\n }\n .proposal .run:hover:not(:disabled) {\n filter: brightness(1.08);\n }\n .proposal .run:disabled {\n background: var(--md-sys-color-surface-container-high, #e2e8f0);\n color: var(--md-sys-color-on-surface-variant, #475569);\n cursor: default;\n }\n .proposal.sent {\n border-left-color: var(--md-sys-color-outline, #94a3b8);\n }\n .proposal .staged-badge {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 3px 8px;\n border-radius: 999px;\n background: rgba(15, 118, 110, 0.1);\n color: var(--md-sys-color-primary, #0f766e);\n font-size: 11px;\n font-weight: 600;\n flex-shrink: 0;\n }\n .proposal .staged-badge md-icon {\n --md-icon-size: 13px;\n color: inherit;\n }\n\n .proposal-choices {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-top: 6px;\n padding: 6px 8px;\n background: var(--md-sys-color-surface-container-lowest, #ffffff);\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n border-radius: 8px;\n }\n .proposal-choices .choice-chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 9px;\n border-radius: 999px;\n border: 1px solid var(--md-sys-color-outline-variant, #cbd5e1);\n background: var(--md-sys-color-surface-container-low, #f8fafc);\n color: var(--md-sys-color-on-surface, #1e293b);\n font-family: inherit;\n font-size: 11px;\n font-weight: 550;\n cursor: pointer;\n transition: all 0.14s ease-in-out;\n }\n .proposal-choices .choice-chip:hover {\n background: var(--md-sys-color-surface-container-high, #e2e8f0);\n border-color: var(--md-sys-color-primary, #0f766e);\n color: var(--md-sys-color-primary, #0f766e);\n }\n .proposal-choices .choice-chip.primary {\n background: var(--md-sys-color-primary-container, #ccfbf1);\n color: var(--md-sys-color-on-primary-container, #0f766e);\n border-color: var(--md-sys-color-primary, #0f766e);\n font-weight: 650;\n }\n .proposal-choices .choice-chip md-icon {\n --md-icon-size: 13px;\n color: inherit;\n }\n\n /* The entry card's way to the large review - a quiet action under its table, never a second run button. */\n .workspace-review {\n display: flex;\n align-items: center;\n gap: 5px;\n margin: 6px 0 0 auto;\n padding: 5px 11px 5px 9px;\n border: 1px solid transparent;\n border-radius: 999px;\n background: transparent;\n color: var(--md-sys-color-primary, #0f766e);\n font-family: inherit;\n font-size: 12px;\n font-weight: 600;\n letter-spacing: 0.01em;\n cursor: pointer;\n transition:\n background-color 0.14s ease-in-out,\n border-color 0.14s ease-in-out;\n }\n .workspace-review md-icon {\n --md-icon-size: 15px;\n color: inherit;\n }\n .workspace-review:hover {\n background: color-mix(in srgb, var(--md-sys-color-primary, #0f766e) 8%, transparent);\n border-color: color-mix(in srgb, var(--md-sys-color-primary, #0f766e) 24%, transparent);\n }\n .workspace-review:active {\n background: color-mix(in srgb, var(--md-sys-color-primary, #0f766e) 14%, transparent);\n }\n .workspace-review:focus-visible {\n outline: 2px solid var(--md-sys-color-primary, #0f766e);\n outline-offset: 1px;\n }\n\n /* โ”€โ”€ ์ ‘์ง€ ๊ฒฝ๊ณ  โ€” ๊ทผ๊ฑฐ์— ์—†๋Š” ๋Œ€์ƒ์„ ์ง€๋ชฉํ•œ ๋‹ต โ”€โ”€โ”€โ”€โ”€ */\n .grounding-warning {\n display: flex;\n align-items: flex-start;\n gap: 6px;\n margin-top: 4px;\n padding: 5px 8px;\n border-radius: 6px;\n border: 1px solid var(--md-sys-color-error, #dc2626);\n background: var(--md-sys-color-error-container, #fef2f2);\n color: var(--md-sys-color-on-error-container, #7f1d1d);\n font-size: 10.5px;\n line-height: 1.45;\n }\n .grounding-warning md-icon {\n --md-icon-size: 14px;\n flex-shrink: 0;\n }\n .grounding-warning .ids {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-weight: 600;\n word-break: break-all;\n }\n\n /* โ”€โ”€ Tool usages fold-able ๋ฐ•์Šค โ€” AI ๋„๊ตฌ ํ˜ธ์ถœ trace โ”€โ”€โ”€โ”€โ”€ */\n .tool-usages {\n margin-top: 4px;\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n border-radius: 6px;\n background: var(--md-sys-color-surface-container-low, #f8fafc);\n overflow: hidden;\n font-size: 10.5px;\n }\n .tool-usages-header {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n padding: 5px 8px;\n background: transparent;\n border: 0;\n cursor: pointer;\n color: var(--md-sys-color-on-surface-variant, #475569);\n font-family: inherit;\n font-size: inherit;\n letter-spacing: inherit;\n text-align: left;\n }\n .tool-usages-header:hover {\n background: var(--md-sys-color-surface-container, #f1f5f9);\n }\n .tool-usages-icon,\n .tool-usages-chevron {\n --md-icon-size: 14px;\n flex-shrink: 0;\n }\n .tool-usages-summary {\n flex: 1;\n font-weight: 500;\n }\n .tool-usages-counts {\n color: var(--md-sys-color-outline, #94a3b8);\n font-weight: 400;\n font-size: 10px;\n }\n .tool-usages-list {\n list-style: none;\n margin: 0;\n padding: 0 8px 8px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n .tool-usage-item {\n border-left: 2px solid var(--md-sys-color-outline-variant, #cbd5e1);\n padding: 4px 8px 4px 8px;\n background: var(--md-sys-color-surface, #ffffff);\n border-radius: 0 4px 4px 0;\n }\n .tool-usage-item.kind-read {\n border-left-color: var(--md-sys-color-tertiary, #10b981);\n }\n .tool-usage-item.kind-write {\n border-left-color: var(--md-sys-color-primary, #1e293b);\n }\n .tool-usage-item.kind-unknown {\n border-left-color: var(--md-sys-color-error, #b91c1c);\n }\n .tool-usage-head {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 3px;\n }\n .tool-usage-step {\n color: var(--md-sys-color-outline, #94a3b8);\n font-size: 10px;\n }\n .tool-usage-name {\n font-weight: 600;\n color: var(--md-sys-color-on-surface, #0f172a);\n font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace;\n font-size: 10.5px;\n }\n .tool-usage-kind {\n font-size: 9.5px;\n padding: 1px 5px;\n border-radius: 3px;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-weight: 600;\n }\n .tool-usage-kind.kind-read {\n color: var(--md-sys-color-on-tertiary, #ffffff);\n background: var(--md-sys-color-tertiary, #10b981);\n }\n .tool-usage-kind.kind-write {\n color: var(--md-sys-color-on-primary, #ffffff);\n background: var(--md-sys-color-primary, #1e293b);\n }\n .tool-usage-kind.kind-unknown {\n color: var(--md-sys-color-on-error, #ffffff);\n background: var(--md-sys-color-error, #b91c1c);\n }\n /* ํŒ๋‹จ ํŒŒ์ดํ”„๋ผ์ธ โ€” ํ›‘์–ด ์ฝ๋Š” ๋ชฉ๋ก. ๋ฐฐ์ง€๋กœ ๊ฒฐ๊ณผ๋ฅผ ๊ตฌ๋ถ„ํ•˜๊ณ  ์›๋ณธ์€ ๋ˆŒ๋Ÿฌ์„œ ๋ณธ๋‹ค. */\n .tool-usages.has-problem {\n border-color: var(--md-sys-color-error, #dc2626);\n }\n .tool-usages-counts .tu-flag {\n font-weight: 650;\n }\n .tool-usages-counts .tu-flag.bad {\n color: var(--md-sys-color-error, #dc2626);\n }\n .tu-turn {\n list-style: none;\n margin: 4px 0 2px;\n padding: 0 8px;\n font-size: 9.5px;\n font-weight: 650;\n letter-spacing: 0.04em;\n color: var(--md-sys-color-outline, #94a3b8);\n text-transform: uppercase;\n }\n .tool-usage-head {\n cursor: pointer;\n align-items: center;\n }\n .tool-usage-item.outcome-rejected,\n .tool-usage-item.outcome-error {\n border-left-color: var(--md-sys-color-error, #dc2626);\n }\n .tool-usage-item.outcome-proposed {\n border-left-color: var(--md-sys-color-primary, #0f766e);\n }\n .tool-usage-item.outcome-folded {\n opacity: 0.7;\n }\n .tu-badge {\n flex-shrink: 0;\n padding: 0 5px;\n border-radius: 999px;\n font-size: 9px;\n font-weight: 700;\n line-height: 15px;\n background: var(--md-sys-color-surface-container-high, #e2e8f0);\n color: var(--md-sys-color-on-surface-variant, #475569);\n }\n .tu-badge.rejected,\n .tu-badge.error {\n background: var(--md-sys-color-error-container, #fef2f2);\n color: var(--md-sys-color-error, #dc2626);\n }\n .tu-badge.proposed {\n background: var(--md-sys-color-primary, #0f766e);\n color: var(--md-sys-color-on-primary, #fff);\n }\n /* ํ•œ ์ค„ ์š”์•ฝ โ€” ๋„˜์น˜๋ฉด ์ž๋ฅธ๋‹ค. ๋ชฉ๋ก์€ ํ›‘๋Š” ๊ณณ์ด๊ณ  ์ฝ๋Š” ๊ณณ์ด ์•„๋‹ˆ๋‹ค. */\n .tu-line {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--md-sys-color-on-surface-variant, #475569);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 9.5px;\n }\n .tu-more {\n --md-icon-size: 13px;\n flex-shrink: 0;\n color: var(--md-sys-color-outline, #94a3b8);\n }\n\n .tool-usage-args,\n .tool-usage-result {\n margin: 2px 0 0;\n padding: 4px 6px;\n background: var(--md-sys-color-surface-container-high, rgba(15, 23, 42, 0.04));\n border-radius: 3px;\n font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace;\n font-size: 10px;\n line-height: 1.4;\n white-space: pre-wrap;\n overflow-x: auto;\n color: var(--md-sys-color-on-surface, #0f172a);\n max-height: 180px;\n overflow-y: auto;\n }\n .tool-usage-args {\n border-left: 2px solid var(--md-sys-color-outline-variant, #cbd5e1);\n }\n .tool-usage-result {\n border-left: 2px solid var(--md-sys-color-outline, #94a3b8);\n }\n\n /* โ”€โ”€ Hover actions (assistant ๋ฉ”์‹œ์ง€๋งŒ, Material icon button) โ”€โ”€ */\n .msg-actions {\n display: flex;\n gap: 2px;\n margin-top: 2px;\n padding: 0;\n opacity: 0;\n transition: opacity 0.15s;\n pointer-events: none;\n }\n .msg-wrap:hover .msg-actions,\n .msg-wrap:focus-within .msg-actions {\n opacity: 1;\n pointer-events: auto;\n }\n .msg-actions .msg-action {\n width: 22px;\n height: 22px;\n padding: 0;\n background: transparent;\n border: 0;\n border-radius: 5px;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--md-sys-color-outline, #94a3b8);\n transition:\n background 0.12s,\n color 0.12s;\n }\n .msg-actions .msg-action:hover:not(:disabled) {\n background: var(--md-sys-color-surface-container-high, #e2e8f0);\n color: var(--md-sys-color-on-surface, #0f172a);\n }\n .msg-actions .msg-action:disabled {\n opacity: 0.4;\n cursor: default;\n }\n .msg-actions .msg-action.confirmed {\n color: var(--md-sys-color-tertiary, #10b981);\n }\n .msg-actions .msg-action md-icon {\n --md-icon-size: 14px;\n }\n\n /* โ”€โ”€ Error banner โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .error {\n color: var(--md-sys-color-on-error-container, #b91c1c);\n padding: 7px 11px;\n background: var(--md-sys-color-error-container, #fef2f2);\n border: 1px solid var(--md-sys-color-error, #fee2e2);\n border-radius: 8px;\n margin: 0 16px 8px;\n font-size: 10.5px;\n line-height: 1.5;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n }\n .error .error-text {\n flex: 1;\n }\n .error .retry-btn {\n flex-shrink: 0;\n padding: 3px 8px;\n font-size: 10px;\n font-family: inherit;\n letter-spacing: inherit;\n background: var(--md-sys-color-error, #b91c1c);\n color: var(--md-sys-color-on-error, #ffffff);\n border: 0;\n border-radius: 6px;\n cursor: pointer;\n transition: opacity 0.15s;\n width: auto;\n height: auto;\n }\n .error .retry-btn:hover {\n opacity: 0.88;\n }\n\n /* โ”€โ”€ Composer (actions + input ํ†ตํ•ฉ ์˜์—ญ) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .composer {\n position: relative;\n border-top: 1px solid var(--md-sys-color-outline-variant, #f1f5f9);\n background: var(--md-sys-color-surface, #ffffff);\n display: flex;\n flex-direction: column;\n transition: background 0.15s, border-color 0.15s;\n }\n /* The wide box and a table's rows cover the conversation, inside the dock - the page beside it stays. */\n .messages.covered {\n flex: 0 0 0;\n padding: 0;\n overflow: hidden;\n visibility: hidden;\n }\n .composer.wide,\n .composer.previewing {\n flex: 1 1 auto;\n min-height: 0;\n }\n .composer.wide .input-row {\n flex: 1;\n min-height: 0;\n align-items: stretch;\n }\n .composer.wide .input-row > :not(.textarea-wrap) {\n align-self: flex-end;\n }\n .composer.wide textarea {\n min-height: 0;\n }\n .composer-size {\n margin-left: auto;\n }\n /* Named above the send button, out of the row - it takes no width from the box. */\n .composer.wide .input-row {\n position: relative;\n }\n .send-shortcut {\n position: absolute;\n right: 14px;\n bottom: 48px;\n font-size: 10px;\n color: var(--md-sys-color-outline, #64748b);\n white-space: nowrap;\n pointer-events: none;\n }\n /* A finger has no Ctrl or โŒ˜ - the send button is the way. */\n @media (pointer: coarse) {\n .send-shortcut {\n display: none;\n }\n }\n .table-preview {\n flex: 1;\n min-height: 0;\n display: flex;\n flex-direction: column;\n margin: 4px 14px;\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n border-radius: 8px;\n background: var(--md-sys-color-surface, #ffffff);\n overflow: hidden;\n }\n .table-preview-head {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 8px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n flex-wrap: wrap;\n }\n .table-preview-head > md-icon {\n --md-icon-size: 18px;\n color: var(--md-sys-color-primary, #0284c7);\n }\n .table-preview-name {\n font-weight: 500;\n color: var(--md-sys-color-on-surface, #0f172a);\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .table-preview-shape {\n color: var(--md-sys-color-on-surface-variant, #475569);\n margin-right: auto;\n }\n .table-preview-body {\n flex: 1;\n min-height: 0;\n overflow: auto;\n }\n .table-preview-body table {\n border-collapse: collapse;\n font-size: 11px;\n }\n .table-preview-body th,\n .table-preview-body td {\n border-bottom: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n padding: 4px 8px;\n text-align: left;\n white-space: nowrap;\n color: var(--md-sys-color-on-surface, #0f172a);\n }\n .table-preview-body th {\n position: sticky;\n left: 0;\n font-weight: 400;\n text-align: right;\n color: var(--md-sys-color-on-surface-variant, #475569);\n background: var(--md-sys-color-surface-container, #f1f5f9);\n }\n .attachment-open {\n all: unset;\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n flex: 1;\n cursor: pointer;\n border-radius: 6px;\n }\n .attachment-open:focus-visible {\n outline: 2px solid var(--md-sys-color-primary, #0284c7);\n outline-offset: 2px;\n }\n .attachment-chip.open {\n border-color: var(--md-sys-color-primary, #0284c7);\n }\n .composer.drag-over {\n background: var(--md-sys-color-surface-container, #f1f5f9);\n border-top-color: var(--md-sys-color-primary, #0284c7);\n }\n .drag-drop-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(255, 255, 255, 0.94);\n backdrop-filter: blur(2px);\n z-index: 10;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 6px;\n border: 2px dashed var(--md-sys-color-primary, #0284c7);\n border-radius: 4px;\n color: var(--md-sys-color-primary, #0284c7);\n font-size: 13px;\n font-weight: 500;\n pointer-events: none;\n }\n .drag-drop-overlay md-icon {\n --md-icon-size: 28px;\n }\n .attachment-strip {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 6px 14px 2px;\n max-height: 120px;\n overflow-y: auto;\n }\n .attachment-chip {\n display: flex;\n align-items: center;\n gap: 6px;\n background: var(--md-sys-color-surface-container, #f1f5f9);\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n border-radius: 8px;\n padding: 3px 6px 3px 4px;\n max-width: 220px;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n }\n .attachment-thumb {\n width: 28px;\n height: 28px;\n object-fit: cover;\n border-radius: 4px;\n flex: none;\n }\n .attachment-icon {\n --md-icon-size: 20px;\n color: var(--md-sys-color-primary, #0284c7);\n flex: none;\n }\n .attachment-meta {\n display: flex;\n flex-direction: column;\n min-width: 0;\n flex: 1;\n }\n .attachment-name {\n font-size: 11px;\n font-weight: 500;\n color: var(--md-sys-color-on-surface, #0f172a);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .attachment-size {\n font-size: 9px;\n color: var(--md-sys-color-outline, #64748b);\n }\n .attachment-remove {\n all: unset;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n cursor: pointer;\n color: var(--md-sys-color-outline, #64748b);\n transition: background 0.15s, color 0.15s;\n flex: none;\n }\n .attachment-remove:hover {\n background: var(--md-sys-color-surface-container-highest, #cbd5e1);\n color: var(--md-sys-color-error, #ef4444);\n }\n .attachment-remove md-icon {\n --md-icon-size: 14px;\n }\n .msg-attachments {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-top: 8px;\n }\n .msg-attachment-img-wrap {\n border-radius: 8px;\n overflow: hidden;\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n background: var(--md-sys-color-surface-container-lowest, #ffffff);\n max-width: 240px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n display: flex;\n flex-direction: column;\n }\n .msg-attachment-img-wrap img {\n max-width: 100%;\n max-height: 160px;\n object-fit: cover;\n display: block;\n }\n .msg-attachment-label {\n padding: 4px 8px;\n font-size: 10px;\n color: var(--md-sys-color-on-surface-variant, #64748b);\n background: var(--md-sys-color-surface-container, #f8fafc);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n border-top: 1px solid var(--md-sys-color-outline-variant, #f1f5f9);\n }\n .msg-attachment-file-chip {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 10px;\n border-radius: 8px;\n background: var(--md-sys-color-surface-container, #f8fafc);\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n font-size: 11px;\n color: var(--md-sys-color-on-surface, #0f172a);\n }\n .msg-attachment-file-chip md-icon {\n --md-icon-size: 18px;\n color: var(--md-sys-color-primary, #0284c7);\n }\n\n /* โ”€โ”€ Mini action row (๋ฉ”์‹œ์ง€ ์‹œ์ž‘ ํ›„) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .actions-row {\n display: flex;\n gap: 6px;\n padding: 6px 14px 4px;\n flex-wrap: wrap;\n align-items: center;\n }\n /* Material 3 assist-chip ํ†ค โ€” height 24, font label-small */\n .action {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 5px;\n height: 24px;\n padding: 0 10px;\n font-size: 11px;\n font-family: inherit;\n letter-spacing: inherit;\n line-height: 1;\n color: var(--md-sys-color-on-surface-variant, #475569);\n background: transparent;\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n border-radius: 8px;\n cursor: pointer;\n transition:\n background 0.15s,\n border-color 0.15s,\n color 0.15s;\n width: auto;\n vertical-align: middle;\n }\n .action:hover {\n background: var(--md-sys-color-surface-container, #f8fafc);\n border-color: var(--md-sys-color-outline, #cbd5e1);\n color: var(--md-sys-color-on-surface, #0f172a);\n }\n .action:active {\n transform: scale(0.97);\n }\n .action md-icon {\n --md-icon-size: 14px;\n opacity: 0.7;\n }\n\n /* โ”€โ”€ Inline examples (action row ์˜ \"์˜ˆ์‹œ\" ํ† ๊ธ€ ์‹œ) โ”€โ”€โ”€โ”€ */\n .inline-examples {\n padding: 4px 16px 0;\n display: flex;\n flex-direction: column;\n gap: 3px;\n }\n .inline-examples .ex-row {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n }\n .inline-examples .ex-row .ex-label {\n font-size: 9px;\n color: var(--md-sys-color-outline, #94a3b8);\n letter-spacing: 0.05em;\n text-transform: uppercase;\n margin-right: 2px;\n align-self: center;\n font-weight: 600;\n }\n .inline-examples .ex {\n all: unset;\n cursor: pointer;\n padding: 2px 8px;\n font-size: 10px;\n color: var(--md-sys-color-on-surface, #0f172a);\n background: var(--md-sys-color-surface-container, #f8fafc);\n border: 1px solid var(--md-sys-color-outline-variant, #eef2f6);\n border-radius: 10px;\n transition: background 0.15s;\n }\n .inline-examples .ex:hover {\n background: var(--md-sys-color-surface-container-high, #f1f5f9);\n }\n\n /* โ”€โ”€ Input area โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n /* border-top ์€ .composer ๊ฐ€ ๋‹ด๋‹น (actions-row ๊ฐ€ ๊ฐ™์€ wrapper ์•ˆ) */\n .input-row {\n display: flex;\n gap: 8px;\n padding: 6px 14px 10px;\n background: transparent;\n align-items: flex-end;\n }\n /* ๋ฉ”์‹œ์ง€ ์‹œ์ž‘ ์ „ โ€” actions-row ๊ฐ€ ์—†์„ ๋•Œ๋Š” input-row ๊ฐ€ ์ง์ ‘ border-top */\n .composer.no-actions .input-row {\n padding-top: 10px;\n }\n\n /* mention popup โ€” textarea wrapper ๊ฐ€ relative ์ปจํ…์ŠคํŠธ, popup ์ด textarea\n ์™€ ์ •ํ™•ํžˆ ๊ฐ™์€ ํญ/์ขŒํ‘œ (์ขŒ์šฐ ๋ ์ •๋ ฌ). send ๋ฒ„ํŠผ ์˜์—ญ์€ ์ œ์™ธ. */\n .textarea-wrap {\n flex: 1;\n position: relative;\n display: flex;\n min-width: 0;\n }\n .textarea-wrap textarea {\n flex: 1;\n width: 100%;\n }\n .mention-popup {\n bottom: calc(100% + 4px);\n left: 0;\n right: 0;\n }\n\n textarea {\n flex: 1;\n padding: 8px 12px;\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n border-radius: 12px;\n font: inherit;\n letter-spacing: inherit;\n resize: none;\n /* The resting height of one line as it stood; the box grows from here by composerHeight (shared-dock.md ยง10). */\n box-sizing: border-box;\n min-height: 54px;\n outline: none;\n transition:\n border-color 0.2s,\n box-shadow 0.2s;\n background: var(--md-sys-color-surface, #ffffff);\n color: var(--md-sys-color-on-surface, #0f172a);\n }\n textarea::placeholder {\n color: var(--md-sys-color-outline, #94a3b8);\n }\n textarea:focus {\n border-color: var(--md-sys-color-outline, #cbd5e1);\n box-shadow: 0 0 0 3px var(--md-sys-color-primary-container, rgba(15, 23, 42, 0.08));\n }\n textarea:disabled {\n background: var(--md-sys-color-surface-container, #f8fafc);\n color: var(--md-sys-color-outline, #94a3b8);\n cursor: not-allowed;\n }\n\n /* ๋ณด๋‚ด๊ธฐ ์ „์— ๋ณด์ด๋Š” ์ดˆ๋Œ€ ์•ˆ๋‚ด โ€” ๋ˆ„๋ฅด๊ธฐ ์ „์— ์•Œ์•„์•ผ ํ•˜๋Š” ์‚ฌ์‹ค์ด๋‹ค. */\n .invite-notice {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 0 2px 4px;\n color: var(--md-sys-color-on-surface-variant, #475569);\n font-size: 11.5px;\n }\n\n .invite-notice md-icon {\n --md-icon-size: 15px;\n }\n\n /* โ”€โ”€ Send button โ€” ChatGPT ์Šคํƒ€์ผ ์›ํ˜• โ†‘ (.input-row ์•ˆ์˜ button ๋งŒ) โ”€โ”€โ”€ */\n .input-row > button {\n width: 32px;\n height: 32px;\n padding: 0;\n background: var(--md-sys-color-primary, #1e293b);\n color: var(--md-sys-color-on-primary, #ffffff);\n border: 0;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition:\n background 0.15s,\n transform 0.1s,\n opacity 0.15s;\n flex-shrink: 0;\n align-self: flex-end;\n margin-bottom: 2px;\n }\n /*\n ๋ฐฉ์— ๋งํ•˜๋Š” ์ž๋ฆฌ๋Š” **๋‘ ๋ฒˆ์งธ ํ–‰๋™**์ด๋‹ค โ€” ์ด ํ™”๋ฉด์˜ ์ฒซ ํ–‰๋™์€ ์–ด์‹œ์Šคํ„ดํŠธ์—๊ฒŒ ๋ฌป๋Š” ๊ฒƒ์ด๋‹ค.\n ๊ฐ™์€ ๋ฌด๊ฒŒ๋กœ ๋‘๋ฉด ๋ฌด์—‡์ด ๊ธฐ๋ณธ์ธ์ง€ ํ™”๋ฉด์ด ๋งํ•˜์ง€ ์•Š๊ฒŒ ๋œ๋‹ค(ADR-0070 A15 ์˜ ์ž๋ฆฌ ๋‘˜).\n */\n .input-row > button.say-to-room {\n background: var(--md-sys-color-surface-container-highest, #e2e8f0);\n color: var(--md-sys-color-on-surface-variant, #475569);\n }\n\n .input-row > button:disabled {\n background: var(--md-sys-color-surface-container-highest, #e2e8f0);\n color: var(--md-sys-color-outline, #94a3b8);\n cursor: not-allowed;\n }\n .input-row > button:hover:not(:disabled) {\n opacity: 0.88;\n }\n .input-row > button:active:not(:disabled) {\n transform: scale(0.94);\n }\n .input-row > button md-icon {\n --md-icon-size: 18px;\n }\n .input-row > button .spinner {\n width: 12px;\n height: 12px;\n border: 1.8px solid currentColor;\n border-right-color: transparent;\n border-radius: 50%;\n animation: spin 0.7s linear infinite;\n }\n @keyframes spin {\n to {\n transform: rotate(360deg);\n }\n }\n `\n ]\n\n connectedCallback() {\n super.connectedCallback()\n // ์ฒซ ๋งˆ์šดํŠธ ์‹œ sessionId ๊ฐ€ ์ด๋ฏธ set ๋ผ์žˆ์–ด๋„ loadHistory ๋Š” ์ฒซ render ํ›„ updated()\n // ๊ฐ€ ์ฒ˜๋ฆฌ โ€” ๋‹จ์ผ ์ง„์ž…์ ์œผ๋กœ ์ผ๊ด€ (์ด์ „์—” connectedCallback ๊ณผ updated ์–‘์ชฝ์ด ํ˜ธ์ถœ โ†’\n // ๋™์‹œ fetch race ๋ฐœ์ƒ).\n /* ๋ชจ๋“œ๊ฐ€ ์ด๋ฏธ ๋ถ™์–ด ์žˆ์œผ๋ฉด ๋ฌด์—‡์„ ์ฃผ๋Š”์ง€ ๋จผ์ € ๋ฌป๋Š”๋‹ค โ€” ๋ฐ”๋€” ๋•Œ๋Š” updated ๊ฐ€ ๋‹ค์‹œ ๋ฌป๋Š”๋‹ค. */\n if (this.mode?.kind) this.loadModeView()\n if (this.subject) this.onSubjectChanged()\n /*\n * Put back after the dock was closed: what is being written stays, the conversation is read again and its\n * broadcast and presence start again - they were stopped when it was taken out.\n */\n if (this.hasUpdated && this.sessionId) {\n this.loadHistory()\n this._startPresence()\n this._startMessageSubscription()\n }\n }\n\n /**\n * ํ™”๋ฉด์ด ๋ณด์—ฌ ์ฃผ๋Š” ๊ฒƒ์˜ ์ข…๋ฅ˜๊ฐ€ ๋ฐ”๋€Œ์—ˆ๋‹ค โ€” ์„ค ์ˆ˜ ์žˆ๋Š” ๋Œ€ํ™”๋ฅผ ๋‹ค์‹œ ๋ฌป๊ณ , ์ง€๋‚œ๋ฒˆ ๊ณ ๋ฅธ ๊ฒƒ์„ ๋˜์‚ด๋ฆฐ๋‹ค.\n *\n * ๋˜์‚ด๋ฆฌ๋Š” ๊ฒƒ์€ **๊ณ ๋ฅธ ๋Œ€ํ™”**์ด์ง€ ์„ธ์…˜์ด ์•„๋‹ˆ๋‹ค. ์„ธ์…˜์€ ์ž๊ธฐ๊ฐ€ ์–ด๋А ๋Œ€ํ™”์˜€๋Š”์ง€ ์ด๋ฏธ ์•Œ๊ณ , ๋‹ค๋ฅธ\n * ๋Œ€ํ™”๋กœ ๊ฐ€๋ฉด ๊ทธ๋•Œ ์ƒˆ๋กœ ๋‚œ๋‹ค(ADR-0072 A17 โ‘ ).\n */\n private async onSubjectChanged() {\n await this.loadModeChoices()\n if (this.modeChoices.length < 2 || !this.subject || !this.mode) return\n\n const kind = pickInitialMode(this.mode.kind, this.modeChoices, this.rememberedMode(this.subject))\n if (kind && kind !== this.mode.kind) this.askHostForMode(kind)\n }\n\n updated(changed: Map<string, any>) {\n if (changed.has('input') || changed.has('composerWide') || changed.has('previewAttachmentId') || changed.has('attachments')) this.fitComposer()\n\n /*\n * ๋ฐ–์—์„œ ๋„ฃ์–ด ์ค€ ์งˆ๋ฌธ์„ ์ž๋™ ์ „์†กํ•œ๋‹ค(์˜ค๋ฅ˜ ํ† ์ŠคํŠธ์˜ \"AI์—๊ฒŒ ๋ฌป๊ธฐ\" ๋“ฑ).\n *\n * sessionId ๊ฐ€ ๋ถ™๊ธฐ ์ „์— ๋ณด๋‚ด๋ฉด ๋Œ€ํ™”์— ๋‚จ์ง€ ์•Š์œผ๋ฏ€๋กœ ์„ธ์…˜์ด ์ค€๋น„๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.\n * ๊ฐ™์€ ๋ฌธ์žฅ์„ ๋‘ ๋ฒˆ ๋ณด๋‚ด์ง€ ์•Š๋„๋ก ๋ณด๋‚ธ ๊ฐ’์„ ๊ธฐ์–ตํ•œ๋‹ค โ€” ์žฌ๋ Œ๋”๋งˆ๋‹ค updated ๊ฐ€ ๋‹ค์‹œ ๋Œ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.\n */\n if (this.autoAsk && assistantAutoAskKey(this.autoAsk, this.autoAskRequestId) !== this._autoAsked && (this.sessionId || this.prepareSession) && !this.busy) {\n this._autoAsked = assistantAutoAskKey(this.autoAsk, this.autoAskRequestId)\n this.input = this.autoAsk\n this.send()\n }\n\n /* A draft fills the input and waits for the person โ€” it is never sent from here. */\n const draft = assistantDraftDecision({\n draft: this.draft,\n draftRequestId: this.draftRequestId,\n drafted: this._drafted,\n typed: this.input,\n autoAsk: this.autoAsk,\n autoAskRequestId: this.autoAskRequestId\n })\n if (draft.consumed) this._drafted = draft.consumed\n if (draft.fill) {\n this.input = this.draft!\n this.updateComplete.then(() => (this.renderRoot.querySelector('textarea') as HTMLTextAreaElement | null)?.focus())\n }\n\n /*\n * The subject changed, so the conversation is over.\n *\n * A conversation about station 3 is not a conversation about station 7. Leaving the old one\n * on screen means the user reads an answer about a screen they are no longer looking at,\n * and every host that met this wrote its own guard: plant re-checked the context on each\n * send and threw when it had moved, twin closed its session when the anchor changed. The\n * mode carries an id, so the component can do it once, here.\n *\n * The host still owns `sessionId`; it hears `assistant-mode-changed` and decides whether\n * this subject gets a stored session of its own.\n */\n /* ๋ณด๋Š” ๊ฒƒ์˜ ์ข…๋ฅ˜๊ฐ€ ๋ฐ”๋€Œ๋ฉด ์„ค ์ˆ˜ ์žˆ๋Š” ๋Œ€ํ™”๋„ ๋‹ฌ๋ผ์ง„๋‹ค โ€” ๋ณด๋“œ์—์„œ ํ˜„์žฅ์œผ๋กœ ๋„˜์–ด๊ฐ„ ์ž๋ฆฌ. */\n if (changed.has('subject')) this.onSubjectChanged()\n\n if (changed.has('mode') && isDifferentConversation(changed.get('mode'), this.mode)) {\n /* What this conversation offers is the new mode's; ask before drawing the panel again. */\n this.modeView = undefined\n this.rebuildMentionCaches()\n this.loadModeView()\n this.lines = []\n this.pickedMentions.clear()\n this.pickedUserMentions.clear()\n this.cachedUserCandidates = []\n this.errorMessage = undefined\n this.input = ''\n this._seenMessageIds.clear()\n this.dispatchEvent(\n new CustomEvent('assistant-mode-changed', {\n detail: { mode: this.mode },\n bubbles: true,\n composed: true\n })\n )\n }\n\n if (changed.has('sessionId') && this.adoptingSession) {\n this.adoptingSession = false\n this._startPresence()\n this._startMessageSubscription()\n } else if (changed.has('sessionId')) {\n // sessionId ๊ฐ€ ๋ฐ”๋€Œ๋ฉด (set / unset / ๋‹ค๋ฅธ ๋ณด๋“œ ์ „ํ™˜) ์ด์ „ ์„ธ์…˜์˜ ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ\n // ์ปจํ…์ŠคํŠธ ์ •๋ฆฌ โ€” lines / pickedMentions / errorMessage / input ๋ชจ๋‘ ์ƒˆ์ง€ ์•Š๋„๋ก.\n // ๋ณด๋“œ ๋‹จ์œ„ ๊ฒฉ๋ฆฌ (ChatSession 1:1 boardId) ๊ฐ€ ๊นจ์ง€๋Š” ํšŒ๊ท€ ๋ฐฉ์ง€.\n this.lines = []\n this.pickedMentions.clear()\n this.pickedUserMentions.clear()\n this.cachedUserCandidates = []\n this.errorMessage = undefined\n this.input = ''\n this.participants = []\n this._seenMessageIds.clear() // ์„ธ์…˜ ์ „ํ™˜ โ€” ์—์ฝ” dedup ์ปจํ…์ŠคํŠธ ๋ฆฌ์…‹\n if (this.sessionId) {\n this.loadHistory()\n this._startPresence() // C4: roster ๋กœ๋“œ + heartbeat ์‹œ์ž‘\n this._startMessageSubscription() // C4: ๋ฉ”์‹œ์ง€ ์‹ค์‹œ๊ฐ„ ๋ฐฉ์†ก ๊ตฌ๋…\n } else {\n this._stopPresence()\n this._stopMessageSubscription()\n }\n }\n // ์ž๋™ ์Šคํฌ๋กค\n const ms = this.renderRoot.querySelector('.messages') as HTMLElement | null\n if (ms) ms.scrollTop = ms.scrollHeight\n }\n\n disconnectedCallback() {\n this._stopPresence()\n this._stopMessageSubscription()\n if (this.elapsedTimer) {\n clearInterval(this.elapsedTimer)\n this.elapsedTimer = undefined\n }\n super.disconnectedCallback()\n }\n\n // โ”€โ”€ C4 presence/roster โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n private _startPresence() {\n this._stopPresence()\n this._loadParticipants()\n this._touchPresence() // ์ฆ‰์‹œ 1ํšŒ โ€” ๋‚ด online ์ฆ‰์‹œ ๋ฐ˜์˜\n this._heartbeatTimer = setInterval(() => {\n this._touchPresence()\n this._loadParticipants()\n this._presenceTick++ // online ํŒ์ • ์žฌํ‰๊ฐ€(์‹œ๊ฐ„ ๊ฒฝ๊ณผ)\n }, PRESENCE_HEARTBEAT_MS)\n }\n\n private _stopPresence() {\n if (this._heartbeatTimer) {\n clearInterval(this._heartbeatTimer)\n this._heartbeatTimer = undefined\n }\n }\n\n // โ”€โ”€ C4 ๊ทธ๋ฃน์ฑ— โ€” ๋ฉ”์‹œ์ง€ ์‹ค์‹œ๊ฐ„ ๋ฐฉ์†ก ๊ตฌ๋… โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n private _startMessageSubscription() {\n this._stopMessageSubscription()\n if (!this.sessionId) return\n try {\n this._messageSub = client\n .subscribe({ query: CHAT_MESSAGE_SUBSCRIPTION, variables: { sessionId: this.sessionId } })\n .subscribe({\n next: ({ data }: any) => this._onRemoteMessage(data?.chatMessageActivity),\n error: () => {\n /* ๊ตฌ๋… ์—๋Ÿฌ๋Š” ์ฑ„ํŒ… ๋ณธ ๊ธฐ๋Šฅ ๋ฌด์˜ํ–ฅ โ€” ํžˆ์Šคํ† ๋ฆฌ ์ฟผ๋ฆฌ๋กœ ํด๋ฐฑ */\n }\n })\n } catch {\n /* ๊ตฌ๋… ๋ฏธ์ง€์› ํ™˜๊ฒฝ โ€” ์กฐ์šฉํžˆ ์Šคํ‚ต */\n }\n }\n\n private _stopMessageSubscription() {\n if (this._messageSub) {\n try {\n this._messageSub.unsubscribe()\n } catch {\n /* ์ด๋ฏธ ๋‹ซํž˜ */\n }\n this._messageSub = undefined\n }\n }\n\n /** ์„œ๋ฒ„ ChatMessage โ†’ ChatLine. */\n private _msgToLine(m: any): ChatLine {\n return remoteMessageToLine(m) as ChatLine\n }\n\n /**\n * ์›๊ฒฉ(๋ฐฉ์†ก) ๋ฉ”์‹œ์ง€ ์ˆ˜์‹  โ€” ์—์ฝ”ยท์ค‘๋ณต์€ id ๋กœ ์ฐจ๋‹จ, ์‹ ๊ทœ๋Š” transcript ์— append.\n * ์ž๊ธฐ ๋ฐœ์‹  ๋ฉ”์‹œ์ง€์˜ id ๋Š” ์ „์†ก reconcile ์—์„œ ์ด๋ฏธ _seenMessageIds ์— ๋“ฑ๋ก๋จ.\n */\n private _onRemoteMessage(m: any) {\n const next = receiveRemoteMessage(this.lines as any, this._seenMessageIds, m)\n if (!next) return\n this._seenMessageIds = next.seen\n this.lines = next.lines as ChatLine[]\n }\n\n /**\n * ์ „์†กํ•œ optimistic ๋ผ์ธ์„ ์„œ๋ฒ„ id ๋กœ reconcile (index ๋น„์˜์กด โ€” _localId ๋กœ ํƒ์ƒ‰).\n * ์—์ฝ”๊ฐ€ ์‘๋‹ต๋ณด๋‹ค ๋จผ์ € ๋„์ฐฉํ•ด ์ด๋ฏธ append ๋์œผ๋ฉด optimistic ์ค‘๋ณต ๋ผ์ธ์„ ์ œ๊ฑฐํ•œ๋‹ค.\n */\n private _reconcileSentLine(localId: string, serverId: string | undefined, patch: Partial<ChatLine>) {\n const next = reconcileSentLine(this.lines as any, this._seenMessageIds, localId, serverId, patch as any)\n this._seenMessageIds = next.seen\n this.lines = next.lines as ChatLine[]\n }\n\n private async _loadParticipants() {\n if (!this.sessionId) return\n try {\n const result = await client.query({\n query: CHAT_PARTICIPANTS_QUERY,\n variables: { sessionId: this.sessionId },\n fetchPolicy: 'network-only'\n })\n this.participants = result.data?.chatSessionParticipants ?? []\n } catch {\n /* roster ๋กœ๋“œ ์‹คํŒจ๋Š” ์ฑ„ํŒ… ๋ณธ ๊ธฐ๋Šฅ ๋ฌด์˜ํ–ฅ โ€” ์กฐ์šฉํžˆ ๋ฌด์‹œ */\n }\n }\n\n private async _touchPresence() {\n if (!this.sessionId) return\n try {\n await client.mutate({ mutation: TOUCH_PRESENCE_MUTATION, variables: { sessionId: this.sessionId } })\n } catch {\n /* heartbeat ์‹คํŒจ ๋ฌด์‹œ */\n }\n }\n\n /** lastSeenAt ์ด TTL ์ด๋‚ด๋ฉด online. (_presenceTick ์˜์กด์œผ๋กœ ์ฃผ๊ธฐ ์žฌํ‰๊ฐ€.) */\n private _isOnline(lastSeenAt?: string): boolean {\n void this._presenceTick\n if (!lastSeenAt) return false\n const t = new Date(lastSeenAt).getTime()\n if (!Number.isFinite(t)) return false\n const age = Date.now() - t\n return age >= 0 ? age <= PRESENCE_TTL_MS : true\n }\n\n private async loadHistory() {\n if (!this.sessionId) return\n try {\n const result = await client.query({\n query: CHAT_MESSAGES_QUERY,\n variables: { sessionId: this.sessionId, limit: 200, offset: 0 },\n fetchPolicy: 'network-only'\n })\n const msgs = result.data?.chatMessages ?? []\n /* ์„œ๋ฒ„ ์ด๋ ฅ์„ ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์˜ค๋ฉด ํ™”๋ฉด์— ์ „๋ถ€ ๋ณด์ธ๋‹ค โ†’ ์ ‘์€ ์ง€์  ํ•ด์ œ(์•ˆ ํ•˜๋ฉด ํ™”๋ฉด๊ณผ ์—์ด์ „ํŠธ ๋ฌธ๋งฅ์ด\n * ์–ด๊ธ‹๋‚œ ์ฑ„ ๋‚จ๋Š”๋‹ค). ์ „์†ก ํ›„์—๋Š” ํ•ด์ œํ•˜์ง€ ์•Š๋Š”๋‹ค โ€” ์ ‘ํžŒ ํ™”๋ฉด์ด ๊ทธ๋Œ€๋กœ์ด๋ฏ€๋กœ ๊ณ„์† ์ˆจ๊ฒจ์•ผ ํ•œ๋‹ค. */\n this._truncateAfterId = undefined\n this.lines = msgs.map((m: any) => this._msgToLine(m))\n // ๋กœ๋“œ๋œ ๋ฉ”์‹œ์ง€ id ๋ฅผ seen ์— ๋“ฑ๋ก โ€” ์ดํ›„ ๋ฐฉ์†ก ์—์ฝ” dedup ๊ธฐ์ค€.\n this._seenMessageIds = new Set<string>(msgs.map((m: any) => m.id).filter(Boolean))\n } catch (e: any) {\n this.errorMessage = `${i18next.t('ai-assistant.text.failed-to-load-history')}: ${e.message ?? e}`\n }\n }\n\n render() {\n const hasMessages = this.lines.length > 0\n return html`\n ${this.toastMessage\n ? html`<div class=\"toast show\">${this.toastMessage}</div>`\n : nothing}\n ${this.renderModeSubject()}\n ${this.renderSessionTabs()}\n ${this.renderRoster()}\n <div class=\"messages ${this.composerWide || this.previewedTable ? 'covered' : ''}\" @click=${this.onBubbleClick}>\n ${!hasMessages ? this.renderEmpty() : nothing}\n ${(() => {\n const myEmail = this._myEmail\n return this.lines.map((line, idx) => {\n const prev = this.lines[idx - 1]\n const showLabel = line.role === 'assistant' && (!prev || prev.role !== 'assistant')\n /* ๊ทธ๋ฃน์ฑ—: ๋‹ค๋ฅธ ์ฐธ์—ฌ์ž์˜ user ๋ฉ”์‹œ์ง€๋Š” ์ขŒ์ธก + ๋ณด๋‚ธ์ด ์ด๋ฆ„ ํ‘œ์‹œ(์—ฐ์† ๋™์ผ ๋ฐœ์‹ ์ž๋Š” 1ํšŒ๋งŒ).\n * ํŒ์ •์€ email ๋น„๊ต. **๋‚ด email ์„ ๋ชจ๋ฅผ ๋•Œ๋Š” '๋‚จ'์œผ๋กœ ๋‹จ์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค** โ€” ๋‚ด ๋ฐœํ™”๋ฅผ ๋‚จ์˜ ๊ฒƒ์œผ๋กœ\n * ์ž˜๋ชป ๋ณด์—ฌ์ฃผ๋Š” ์ชฝ์ด ๋” ํ•ด๋กญ๋‹ค(๋กœ๊ทธ์ธ ์ •๋ณด๊ฐ€ ์•„์ง ์•ˆ ์˜จ ์ˆœ๊ฐ„ ๋“ฑ). ๋‚ด email ์„ ์•„๋Š” ์ƒํƒœ์—์„œ\n * ๋ฐœ์‹ ์ž email ์ด ๋‹ค๋ฅด๊ฑฐ๋‚˜ ๋น„์–ด ์žˆ์œผ๋ฉด ๋‹ค๋ฅธ ๊ณ„์ •์œผ๋กœ ๋ณธ๋‹ค. */\n const isOther = line.role === 'user' && !!myEmail && line.senderEmail !== myEmail\n const prevSameSender = !!prev && prev.role === 'user' && prev.senderEmail === line.senderEmail\n const showSenderLabel = isOther && !prevSameSender\n const content = (line.content ?? '').trim()\n /* A \"requested\" row is the card's state, shown on the card - as a line it would only be the machine's key. */\n if (line.role === 'system' && parseProposalRequestLine(content)) return nothing\n /*\n * ๊ฐ€๋ ค์ง„ ์ค„์€ ์–ด์‹œ์Šคํ„ดํŠธ์˜ ๋ง์ด ์•„๋‹ˆ๋‹ค โ€” ๋งˆํฌ๋‹ค์šด์œผ๋กœ ๊ทธ๋ฆฌ์ง€ ์•Š๊ณ , ๋ณต์‚ฌยท์žฌ์‹คํ–‰ ๊ฐ™์€ ์†์žก์ด๋„\n * ๋‹ฌ์ง€ ์•Š๋Š”๋‹ค(ADR-0073 ํŒ์ • 1). ๊ทธ ์†์žก์ด๋“ค์€ ์žˆ์ง€๋„ ์•Š์€ ๋‹ต์„ ๋‹ค๋ฃฌ๋‹ค.\n */\n const isMarkdown = line.role !== 'system' && content.length > 0 && !line.redacted\n const showActions = line.role !== 'system' && !line.pending && content.length > 0 && !line.redacted\n return html`\n ${showLabel\n ? html`<div class=\"msg-label\">${i18next.t('ai-assistant.label.ai')}</div>`\n : showSenderLabel\n ? html`<div class=\"msg-label sender\">${line.senderName || i18next.t('ai-assistant.label.participant')}</div>`\n : nothing}\n <div class=\"msg-wrap ${line.role} ${isOther ? 'other' : ''}\">\n <div\n class=\"msg ${line.role} ${isOther ? 'other' : ''} ${line.pending ? 'pending' : ''} ${line.systemOpen\n ? 'open'\n : ''} ${line.redacted ? 'redacted' : ''}\">\n ${line.pending\n ? html`<span class=\"typing-dots\"><span></span><span></span><span></span></span>`\n : line.redacted\n ? html`<div class=\"redacted-body\"><md-icon>lock</md-icon><span>${content}</span></div>`\n : isMarkdown\n ? html`<div class=\"md-body\">${unsafeHTML(renderMarkdown(content))}</div>`\n : line.role === 'system'\n ? html`<span\n class=\"sys-text\"\n title=${i18next.t('ai-assistant.text.toggle-system-note', { defaultValue: 'click to expand' })}\n @click=${() => this.toggleSystemNote(idx)}\n >${content}</span\n >`\n : content}\n ${line.attachments && line.attachments.length > 0\n ? html`\n <div class=\"msg-attachments\">\n ${line.attachments.map(att => {\n /* A stored file opens through the conversation's own route (ยง9-3); a fresh one shows its local copy. */\n const href = att.url || att.base64 || (att.id && this.sessionId ? chatAttachmentUrl(this.sessionId, att.id) : '')\n /* By type - a text file carries base64 too, and drew as a broken image (found on :3700). */\n return att.type?.startsWith('image/') || att.url?.startsWith('data:image/') || att.base64?.startsWith('data:image/')\n ? html`\n <a class=\"msg-attachment-img-wrap\" title=${att.name} href=${href} target=\"_blank\" rel=\"noopener\">\n <img src=${href} alt=${att.name} />\n <span class=\"msg-attachment-label\">${att.name}</span>\n </a>\n `\n : html`\n <a class=\"msg-attachment-file-chip\" title=${att.name} href=${href || nothing} target=\"_blank\" rel=\"noopener\">\n <md-icon>description</md-icon>\n <span>${att.name}</span>\n </a>\n `\n })}\n </div>\n `\n : nothing}\n ${line.patchId\n ? html`\n <div class=\"summary ${this.revertedPatchIds.has(line.patchId) ? 'reverted' : ''}\">\n <md-icon>check_circle</md-icon>\n <span class=\"summary-text\">\n ${this.revertedPatchIds.has(line.patchId)\n ? i18next.t('ai-assistant.text.reverted')\n : i18next.t('ai-assistant.text.applied-changes')}\n </span>\n <button\n class=\"revert-btn\"\n ?disabled=${this.revertedPatchIds.has(line.patchId)}\n @click=${() => line.patchId && this.onRevertClick(line.patchId)}>\n ${i18next.t('ai-assistant.button.revert')}\n </button>\n </div>\n `\n : nothing}\n ${line.followUp\n ? html`<div class=\"followup\">${unsafeHTML(renderMarkdown(line.followUp.trim()))}</div>`\n : nothing}\n ${line.proposals && line.proposals.length > 0 ? this.renderProposals(line) : nothing}\n ${line.groundingWarnings && line.groundingWarnings.length > 0\n ? this.renderGroundingWarning(line)\n : nothing}\n ${line.toolUsages && line.toolUsages.length > 0\n ? this.renderToolUsages(idx, line)\n : nothing}\n </div>\n ${showActions ? this.renderMessageActions(idx, line, content) : nothing}\n </div>\n `\n })\n })()}\n </div>\n ${this.errorMessage\n ? html`\n <div class=\"error\">\n <span class=\"error-text\">${this.errorMessage}</span>\n ${this.lastFailedInput\n ? html`\n <button class=\"retry-btn\" @click=${this.retryLastSend}>\n ${i18next.t('ai-assistant.button.retry')}\n </button>\n `\n : nothing}\n </div>\n `\n : nothing}\n ${this.renderFoldNotice()}\n <div\n class=\"composer ${this.dragOver ? 'drag-over' : ''} ${this.composerWide ? 'wide' : ''} ${this.previewedTable ? 'previewing' : ''}\"\n @dragover=${(e: DragEvent) => this.onComposerDragOver(e)}\n @dragleave=${(e: DragEvent) => this.onComposerDragLeave(e)}\n @drop=${(e: DragEvent) => this.onComposerDrop(e)}\n @paste=${(e: ClipboardEvent) => this.onComposerPaste(e)}>\n ${this.dragOver\n ? html`\n <div class=\"drag-drop-overlay\">\n <md-icon>cloud_upload</md-icon>\n <span>${i18next.t('ai-assistant.text.drop-files-here', { defaultValue: 'Drop images or files here' })}</span>\n </div>\n `\n : nothing}\n <div class=\"actions-row\">\n <input\n id=\"chat-file-input\"\n type=\"file\"\n multiple\n accept=${this.usesAttachmentPolicy ? acceptOf(this.modeView?.attachments) : 'image/*'}\n style=\"display: none\"\n @change=${(e: Event) => {\n const input = e.target as HTMLInputElement\n if (input.files?.length) {\n this.onAttachFiles(input.files)\n input.value = ''\n }\n }}\n />\n ${this.acceptsAttachments\n ? html`<button\n type=\"button\"\n class=\"action\"\n @click=${() => this.renderRoot.querySelector<HTMLInputElement>('#chat-file-input')?.click()}\n title=${i18next.t('ai-assistant.tooltip.attach-file', { defaultValue: 'attach an image (drag & drop or paste supported)' })}>\n <md-icon>attach_file</md-icon>\n ${i18next.t('ai-assistant.button.attach', { defaultValue: 'Attach' })}\n </button>`\n : nothing}\n ${hasMessages\n ? html`\n <button\n type=\"button\"\n class=\"action\"\n @click=${() => (this.examplesOpen = !this.examplesOpen)}\n title=${i18next.t('ai-assistant.text.show-examples-tooltip')}>\n <md-icon>${this.examplesOpen ? 'close' : 'lightbulb'}</md-icon>\n ${this.examplesOpen\n ? i18next.t('ai-assistant.button.close')\n : i18next.t('ai-assistant.button.examples')}\n </button>\n `\n : nothing}\n <button\n type=\"button\"\n class=\"action composer-size\"\n aria-pressed=${this.composerWide ? 'true' : 'false'}\n @click=${() => this.setComposerWide(!this.composerWide)}>\n <md-icon>${this.composerWide ? 'close_fullscreen' : 'open_in_full'}</md-icon>\n ${this.composerWide\n ? i18next.t('ai-assistant.button.write-narrow', { defaultValue: 'Narrow' })\n : i18next.t('ai-assistant.button.write-wide', { defaultValue: 'Write wide' })}\n </button>\n </div>\n ${this.renderTablePreview()}\n ${this.examplesOpen ? this.renderInlineExamples() : nothing}\n ${this.attachments.length > 0\n ? html`\n <div class=\"attachment-strip\">\n ${this.attachments.map(\n att => html`\n <div class=\"attachment-chip ${att.id === this.previewAttachmentId ? 'open' : ''}\" title=${att.name}>\n ${att.table\n ? html`<button\n type=\"button\"\n class=\"attachment-open\"\n aria-expanded=${att.id === this.previewAttachmentId ? 'true' : 'false'}\n @click=${() => (this.previewAttachmentId = att.id === this.previewAttachmentId ? null : att.id)}>\n <md-icon class=\"attachment-icon\">table_chart</md-icon>\n <span class=\"attachment-meta\">\n <span class=\"attachment-name\">${att.name}</span>\n <span class=\"attachment-size\">${this.tableShape(att.table)}</span>\n </span>\n </button>`\n : html`${att.type.startsWith('image/')\n ? html`<img class=\"attachment-thumb\" src=${att.url} alt=${att.name} />`\n : html`<md-icon class=\"attachment-icon\">description</md-icon>`}\n <div class=\"attachment-meta\">\n <span class=\"attachment-name\">${att.name}</span>\n <span class=\"attachment-size\">${formatFileSize(att.size)}</span>\n </div>`}\n <button\n type=\"button\"\n class=\"attachment-remove\"\n title=${i18next.t('ai-assistant.button.remove-attachment', { defaultValue: 'Remove attachment' })}\n @click=${() => this.removeAttachment(att.id)}>\n <md-icon>close</md-icon>\n </button>\n </div>\n `\n )}\n </div>\n `\n : nothing}\n ${this.renderInviteNotice()}\n <div class=\"input-row\">\n <div class=\"textarea-wrap\">\n <textarea\n .value=${this.input}\n @input=${(e: Event) => this.onTextareaInput(e)}\n @keydown=${(e: KeyboardEvent) => this.onKeyDown(e)}\n @blur=${() => {\n // ํฌ์ปค์Šค๋ฅผ popup item ์œผ๋กœ ์˜ฎ๊ธฐ๋Š” click ๋ณด๋‹ค blur ๊ฐ€ ๋จผ์ € โ€” popup item ์˜\n // mousedown.preventDefault() ๊ฐ€ ์ฒ˜๋ฆฌํ•˜์ง€๋งŒ ์•ˆ์ „๋ง์œผ๋กœ ์งง์€ ์ง€์—ฐ ํ›„ ๋‹ซ๊ธฐ.\n setTimeout(() => this.closeMentionPopup(), 150)\n }}\n ?disabled=${this.busy}\n rows=\"1\"\n placeholder=${this.conversation.placeholder ??\n this.placeholder ??\n i18next.t('ai-assistant.text.input-placeholder')}></textarea>\n ${this.mentionOpen\n ? html`\n <ox-mention-popup\n class=\"mention-popup\"\n .results=${this.mentionResults}\n .activeIndex=${this.mentionActiveIndex}\n .overflow=${this.mentionOverflow}\n @mention-active-change=${(e: CustomEvent) => {\n // ๋งˆ์šฐ์Šค hover โ€” keyboard nav ์™€ ๋™์ผํ•˜๊ฒŒ select + centerTo\n const idx = e.detail?.index\n if (typeof idx === 'number' && idx >= 0 && idx < this.mentionResults.length) {\n this.mentionActiveIndex = idx\n this.previewActiveCandidate()\n }\n }}\n @mention-select=${(e: CustomEvent) =>\n this.applyMention(e.detail.candidate)}></ox-mention-popup>\n `\n : nothing}\n </div>\n ${/*\n ๋‘ ์ž๋ฆฌ๋‹ค โ€” ์–ด์‹œ์Šคํ„ดํŠธ์—๊ฒŒ ๋ฌป๋Š” ์ž๋ฆฌ์™€ **๋ฐฉ์— ๋งํ•˜๋Š” ์ž๋ฆฌ**. ๋ˆ„๋ฅธ ์ž๋ฆฌ๊ฐ€ ๊ทธ ๋ง์˜ ๋Œ€์ƒ์„\n ์ •ํ•˜๊ณ , ์„œ๋ฒ„๋Š” ์–ด๋А ๋ฌธ์ด ๋ถˆ๋ ธ๋Š”์ง€๋กœ ๊ทธ ์‚ฌ์‹ค์„ ์ €์žฅํ•œ๋‹ค(ADR-0070 A15 ๊ฒฐ์ • โ‘ ).\n\n **๋ฐฉ์— ์‚ฌ๋žŒ์ด ์žˆ์„ ๋•Œ๋งŒ ๋ณด์ธ๋‹ค.** ํ˜ผ์ž ์“ฐ๋Š” ๋Œ€ํ™”์—์„œ ใ€Œ๋ฐฉ์— ๋งํ•˜๊ธฐใ€๋Š” ์•„๋ฌด์—๊ฒŒ๋„ ํ•˜์ง€ ์•Š๋Š”\n ๋ง์ด๊ณ , ๋ˆ„๋ฅผ ์ผ์ด ์—†๋Š” ๋‹จ์ถ”๋Š” ๋ฌด์—‡์ด ๊ธฐ๋ณธ์ธ์ง€ ํ๋ฆฐ๋‹ค. ์กฐ๊ฑด์€ ์ฐธ์—ฌ์ž ๋ชฉ๋ก๊ณผ ๊ฐ™๋‹ค(๋‘˜ ์ด์ƒ) โ€”\n ๋‘˜์งธ ์‚ฌ๋žŒ์€ ๋ฉ˜์…˜์œผ๋กœ ๋“ค์–ด์˜ค๊ณ , ๊ทธ ์ˆœ๊ฐ„ ์ด ์ž๋ฆฌ๋„ ํ•จ๊ป˜ ์„ ๋‹ค.\n */ ''}\n ${this.sessionId && this.participants.length >= 2\n ? html`\n <button\n class=\"say-to-room\"\n ?disabled=${this.busy || !this.input.trim()}\n @click=${() => this.sayToRoom()}\n title=${i18next.t('ai-assistant.text.say-to-room-tooltip', {\n defaultValue: 'say this to the people here โ€” the assistant does not answer'\n })}>\n <md-icon>forum</md-icon>\n </button>\n `\n : nothing}\n ${this.composerWide\n ? html`<span class=\"send-shortcut\">${i18next.t('ai-assistant.text.send-shortcut', { key: sendShortcut(navigator.platform), defaultValue: '{key} to send' })}</span>`\n : nothing}\n <button\n ?disabled=${this.busy || !!this.sendBlocked || (!this.input.trim() && this.attachments.length === 0)}\n @click=${this.send}\n title=${this.sendBlocked ||\n (this.composerWide\n ? i18next.t('ai-assistant.text.send-tooltip-wide', { key: sendShortcut(navigator.platform), defaultValue: 'Send ({key})' })\n : i18next.t('ai-assistant.text.send-tooltip'))}>\n ${this.busy\n ? html`<span class=\"spinner\"></span>`\n : html`<md-icon>arrow_upward</md-icon>`}\n </button>\n </div>\n </div>\n `\n }\n\n /**\n * ๋ฐฉ์— ๋งํ•œ๋‹ค โ€” ์–ด์‹œ์Šคํ„ดํŠธ๋Š” ๋‹ตํ•˜์ง€ ์•Š๋Š”๋‹ค.\n *\n * ์ €์žฅ๋˜๋Š” ๋Œ€ํ™”๊ฐ€ ์žˆ์„ ๋•Œ๋งŒ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์„ธ์…˜์ด ์—†๋Š” ์ฆ‰์„ ์งˆ๋ฌธ์—๋Š” ใ€Œ๋ฐฉใ€์ด ์—†๋‹ค โ€” ๊ทธ ์ž๋ฆฌ์—์„œ\n * ํ•œ ๋ง์€ ๋ˆ„๊ตฌ์—๊ฒŒ๋„ ๋‚จ์ง€ ์•Š๋Š”๋‹ค.\n */\n private async sayToRoom() {\n const body = this.input.trim()\n if (!body || this.busy) return\n if (!this.sessionId) {\n /* ๋งํ•  ๋ฐฉ์ด ์—†๋‹ค๋Š” ์‚ฌ์‹ค์„ ๋งํ•œ๋‹ค โ€” ์กฐ์šฉํžˆ ๋ฒ„๋ฆฌ๋ฉด ์‚ฌ๋žŒ์€ ๋งํ–ˆ๋‹ค๊ณ  ๋ฏฟ๋Š”๋‹ค. */\n this.errorMessage = i18next.t('ai-assistant.text.no-room-yet', {\n defaultValue: 'this conversation is not saved yet, so there is nobody else in it to talk to'\n })\n return\n }\n\n const localId = `local-${++this._localSeq}-r`\n this.lines = [...this.lines, { role: 'user', content: body, _localId: localId, senderEmail: this._myEmail }]\n this.input = ''\n this.busy = true\n try {\n const result = await client.mutate({\n mutation: SAY_TO_ROOM_MUTATION,\n variables: { sessionId: this.sessionId, content: body }\n })\n /* ๋ฐฉ์†ก ์—์ฝ”์™€ ๊ฒน์น˜์ง€ ์•Š๊ฒŒ ์„œ๋ฒ„ id ๋กœ ๋งž์ถ˜๋‹ค โ€” ๋ณด๋‚ธ ๋ง์ด ๋‘ ์ค„๋กœ ๋ณด์ด์ง€ ์•Š๊ฒŒ. */\n this._reconcileSentLine(localId, result.data?.sayToRoom ?? undefined, {})\n } catch (error) {\n this.lines = this.lines.filter(line => line._localId !== localId)\n this.input = body\n this.errorMessage = error instanceof Error ? error.message : String(error)\n } finally {\n this.busy = false\n }\n }\n\n /**\n * ๋ณด๋‚ด๊ธฐ ์ „์— ๋งํ•œ๋‹ค โ€” ใ€Œ์ด ์‚ฌ๋žŒ์€ ์ด ๋Œ€ํ™”์— ๋“ค์–ด์˜ต๋‹ˆ๋‹คใ€(ADR-0071 ๊ฒฐ์ • 1 โ‘ฃ).\n *\n * ๋ฉ˜์…˜์€ ์‚ฌ๋žŒ์„ ๋ถˆ๋Ÿฌ๋“ค์ธ๋‹ค. ๋ˆ„๋ฅธ ๋’ค์— ์•Œ๋ฉด ์ด๋ฏธ ๋“ค์–ด์™€ ์žˆ๊ณ , ํ˜‘์˜์˜ ๊ณต๊ฐœ ๋ฒ”์œ„๋Š” ๋˜๋Œ๋ฆฌ๊ธฐ ์–ด๋ ค์šด\n * ์ข…๋ฅ˜์˜ ์ผ์ด๋‹ค. ๊ทธ๋ž˜์„œ **์•„์ง ๋ณด๋‚ด์ง€ ์•Š์€ ์ƒํƒœ์—์„œ** ๋ˆ„๊ฐ€ ๋“ค์–ด์˜ค๊ฒŒ ๋˜๋Š”์ง€ ๋ณด์ธ๋‹ค.\n *\n * ์ดˆ๋Œ€ํ•  ์ˆ˜ ์—†๋Š” ์ž๋ฆฌ(๋ณด๊ธฐ ๊ถŒํ•œ ยท ์•„์ง ์ฐธ์—ฌ์ž๊ฐ€ ์•„๋‹˜)๋ผ๋ฉด ๊ทธ ์‚ฌ์‹ค์„ ๋งํ•œ๋‹ค โ€” ๋ˆŒ๋ €๋Š”๋ฐ ์•„๋ฌด ์ผ๋„\n * ์ผ์–ด๋‚˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ๋‚˜์˜๋‹ค.\n */\n private renderInviteNotice() {\n if (!this.sessionId) return nothing\n\n const here = new Set(this.participants.map(p => p.user?.id).filter(Boolean) as string[])\n const incoming = [...this.pickedUserMentions.entries()]\n .filter(([token, userId]) => this.input.includes(`@${token}`) && !here.has(userId))\n .map(([token]) => token)\n if (incoming.length === 0) return nothing\n\n const myRole = this.participants.find(p => p.user?.id && p.user.id === this._myUserId)?.role\n const mayInvite = myRole === 'owner' || myRole === 'member'\n const names = incoming.map(token => `@${token}`).join(', ')\n\n return html`\n <div class=\"invite-notice\">\n <md-icon>person_add</md-icon>\n <span>\n ${mayInvite\n ? i18next.t('ai-assistant.text.will-be-invited', {\n names,\n defaultValue: '{names} will join this conversation when you send'\n })\n : i18next.t('ai-assistant.text.cannot-invite', {\n names,\n defaultValue: '{names} will not join โ€” only the people already in this conversation can bring someone in'\n })}\n </span>\n </div>\n `\n }\n\n private get previewedTable(): ChatAttachment | undefined {\n return this.previewAttachmentId ? this.attachments.find(a => a.id === this.previewAttachmentId && a.table) : undefined\n }\n\n private tableShape(table: NonNullable<ChatAttachment['table']>) {\n return i18next.t('ai-assistant.text.table-shape', { rows: table.rows.length, columns: table.columns, defaultValue: '{rows} rows ร— {columns} columns' })\n }\n\n /*\n The rows of a pasted table, over the conversation - numbered as the file numbers them, which is the number the\n entry card names. Every row: the paste is held under the mode's limit already.\n */\n private renderTablePreview() {\n const att = this.previewedTable\n if (!att?.table) return nothing\n const { rows, columns } = att.table\n return html`\n <div\n class=\"table-preview\"\n role=\"region\"\n aria-label=${att.name}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.stopPropagation()\n this.previewAttachmentId = null\n }\n }}>\n <div class=\"table-preview-head\">\n <md-icon>table_chart</md-icon>\n <span class=\"table-preview-name\">${att.name}</span>\n <span class=\"table-preview-shape\">${this.tableShape(att.table)}</span>\n <button type=\"button\" class=\"action\" @click=${() => this.tableToWords(att.id)}>\n <md-icon>notes</md-icon>\n ${i18next.t('ai-assistant.button.table-to-words', { defaultValue: 'Put in as words' })}\n </button>\n <button type=\"button\" class=\"action\" @click=${() => (this.previewAttachmentId = null)}>\n <md-icon>close</md-icon>\n ${i18next.t('ai-assistant.button.close')}\n </button>\n </div>\n <div class=\"table-preview-body\">\n <table>\n ${rows.map(\n (row, i) => html`<tr>\n <th scope=\"row\">${i + 1}</th>\n ${Array.from({ length: columns }, (_, c) => html`<td>${row[c] ?? ''}</td>`)}\n </tr>`\n )}\n </table>\n </div>\n </div>\n `\n }\n\n private onKeyDown(e: KeyboardEvent) {\n /*\n The Enter that ends a Korean (or Japanese, Chinese) syllable belongs to the input method - sending on it\n sends the line without its last syllable, which then lands in the emptied box.\n */\n if (e.isComposing || e.keyCode === 229) return\n // Mention popup ํ™œ์„ฑ ์‹œ โ€” ํ™”์‚ดํ‘œ/Enter/Tab/Esc ๊ฐ€๋กœ์ฑ„์„œ popup ๋„ค๋น„๊ฒŒ์ด์…˜\n if (this.mentionOpen) {\n if (e.key === 'ArrowDown') {\n e.preventDefault()\n if (this.mentionResults.length > 0) {\n this.mentionActiveIndex =\n (this.mentionActiveIndex + 1) % this.mentionResults.length\n this.previewActiveCandidate()\n }\n return\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault()\n if (this.mentionResults.length > 0) {\n this.mentionActiveIndex =\n (this.mentionActiveIndex - 1 + this.mentionResults.length) %\n this.mentionResults.length\n this.previewActiveCandidate()\n }\n return\n }\n if (e.key === 'Enter' || e.key === 'Tab') {\n if (this.mentionResults.length > 0) {\n e.preventDefault()\n this.applyMention(this.mentionResults[this.mentionActiveIndex].candidate)\n return\n }\n // ๋งค์นญ 0๊ฐœ๋ฉด popup ๋‹ซ๊ณ  ์ผ๋ฐ˜ ๋™์ž‘ fall through\n this.closeMentionPopup()\n }\n if (e.key === 'Escape') {\n e.preventDefault()\n this.closeMentionPopup()\n return\n }\n }\n const action = composerKeyAction(e, this.composerWide)\n if (action === 'narrow') {\n /* The Escape that narrows the box is spent here - the floating dock closes on the next one. */\n e.preventDefault()\n e.stopPropagation()\n this.setComposerWide(false)\n } else if (action === 'send') {\n e.preventDefault()\n if (!this.busy) this.send()\n }\n }\n\n /** input ์ด๋ฒคํŠธ โ€” value ์ฆ‰์‹œ ๋ฐ˜์˜ + popup ๊ฐฑ์‹ ์€ 150ms ๋””๋ฐ”์šด์Šค (F-Finder ์™€ ๋™์ผ).\n * big board ์—์„œ ๋งค keystroke filter ๋น„์šฉ ์ ˆ๊ฐ + ํ•œ๊ตญ์–ด IME ์กฐํ•ฉ ์ค‘ ๊นœ๋นก์ž„ ์™„ํ™”. */\n private onTextareaInput(e: Event) {\n const ta = e.target as HTMLTextAreaElement\n this.input = ta.value\n if (this.inputDebounceTimer) clearTimeout(this.inputDebounceTimer)\n this.inputDebounceTimer = setTimeout(() => {\n this.refreshMentionPopup(ta)\n }, 150)\n }\n\n /** ํ˜„์žฌ cursor ์œ„์น˜๋ฅผ ๋ณด๊ณ  mention popup ํ™œ์„ฑ/๋น„ํ™œ์„ฑ + ํ›„๋ณด ๊ฐฑ์‹ .\n * `#` (์ปดํฌ๋„ŒํŠธ) / `@` (์นดํƒˆ๋กœ๊ทธ) / `/` (slash ํ…œํ”Œ๋ฆฟ) ํ•œ ๋ฒˆ์— ํ•˜๋‚˜๋งŒ ํ™œ์„ฑ. */\n private refreshMentionPopup(ta: HTMLTextAreaElement) {\n const cursor = ta.selectionStart ?? ta.value.length\n\n const triggers: Array<'#' | '@' | '/'> = ['#', '@', '/']\n let chosen: { hashPos: number; query: string; trigger: '#' | '@' | '/' } | null =\n null\n for (const t of triggers) {\n const ctx = extractMentionContext(ta.value, cursor, t)\n if (!ctx) continue\n if (!chosen || ctx.hashPos > chosen.hashPos) {\n chosen = { ...ctx, trigger: t }\n }\n }\n\n if (!chosen) {\n if (this.mentionOpen) this.closeMentionPopup()\n return\n }\n\n const wasOpen = this.mentionOpen\n const cap = 50\n let results: FilterResult[]\n if (chosen.trigger === '#' && this.searchProvider && chosen.query) {\n // ํ˜ธ์ŠคํŠธ์˜ SceneSearchEngine ์œ„์ž„ โ€” F-Finder ์™€ ๋™์ผ ๊ฒ€์ƒ‰ ๋ฃฐ. cap ๋งŒ chat ์ธก์—์„œ ์ ์šฉ.\n results = this.searchProvider(chosen.query).slice(0, cap)\n } else if (chosen.trigger === '@') {\n // `@` = ๋„๋ฉ”์ธ ์‚ฌ์šฉ์ž ๋ฉ˜์…˜. host ๊ฐ€ userProvider set ํ–ˆ์œผ๋ฉด query โ†’ users ๋น„๋™๊ธฐ fetch.\n // userProvider ๋ฏธ์„ค์ • / ๊ฒฐ๊ณผ ์—†์Œ โ†’ ๋นˆ popup (๋ฉ€ํ‹ฐ์œ ์ € ๋ฏธ์‚ฌ์šฉ ํ™˜๊ฒฝ).\n // async ๋ผ ์ฆ‰์‹œ ๋ฐ˜ํ™˜์€ ๋นˆ ๊ฒฐ๊ณผ; await ํ›„ ๋‹ค์‹œ set ํ•˜๋Š” ํŒจํ„ด.\n results = this.cachedUserCandidates\n ? filterMentionCandidates(this.cachedUserCandidates, chosen.query, cap)\n : []\n // ๋น„๋™๊ธฐ ๊ฐฑ์‹  โ€” ๊ฒฐ๊ณผ ๋„์ฐฉํ•˜๋ฉด popup ๋‹ค์‹œ ๊ฐฑ์‹ \n this.refreshUserCandidatesAsync(chosen.query, chosen.hashPos)\n } else {\n let all: MentionCandidate[]\n if (chosen.trigger === '#') {\n // ๋นˆ query ์˜ # ๋˜๋Š” searchProvider ๋ฏธ์„ค์ • โ€” ๋กœ์ปฌ enumeration ์œผ๋กœ ์ „์ฒด ํ›„๋ณด ํ‘œ์‹œ\n const liveBoard = this.boardProvider ? this.boardProvider() : this.currentBoard\n all = buildMentionCandidates(liveBoard?.components ?? [])\n } else {\n // `/` = ์นดํƒˆ๋กœ๊ทธ + slash ํ…œํ”Œ๋ฆฟ ํ†ตํ•ฉ (Notion `/` ํŒจํ„ด). ๋‘˜ ๋‹ค \"์‚ฝ์ž… ๊ฐ€๋Šฅ ํ•ญ๋ชฉ\".\n all = [...this.cachedCatalogCandidates, ...this.cachedSlashCandidates]\n }\n results = filterMentionCandidates(all, chosen.query, cap)\n }\n // overflow ๊ณ„์‚ฐ โ€” ์ „์ฒด ๋งค์นญ ์ค‘ cap ์œผ๋กœ ์ž˜๋ ค๋‚˜๊ฐ„ ์ˆ˜ (popup 'N more' ํ‘œ๊ธฐ)\n // (cap ์ž˜๋ผ์„œ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ, ์ „์ฒด ์นด์šดํŠธ๋Š” ์ž์œ  ๊ฒ€์ƒ‰ ์‹œ ์•Œ๊ธฐ ์–ด๋ ค์›€.\n // ์—„๊ฒฉํ•œ overflow ์ถ”์  ๋Œ€์‹  results.length === cap ์ด๋ฉด ์ถ”์ • ํ‘œ์‹œ)\n const overflow = results.length === cap ? 0 : 0\n this.mentionResults = results\n this.mentionOverflow = overflow\n this.mentionActiveIndex = 0\n this.mentionHashPos = chosen.hashPos\n this.mentionTrigger = chosen.trigger\n this.mentionOpen = true\n\n // ์ฒซ open ์‹œ โ€” ์‚ฌ์šฉ์ž selection ์Šค๋ƒ…์ƒท (์ทจ์†Œ ์‹œ ์›๋ณต์šฉ)\n if (!wasOpen && chosen.trigger === '#') {\n this.originalSelectedRefids = (this.selectedRefids ?? []).slice()\n }\n // ๋งค์นญ๋œ ํ›„๋ณด outline ๋งŒ ๊ฐฑ์‹  โ€” ์นด๋ฉ”๋ผ/์„ ํƒ ๋ณ€๊ฒฝ์€ commit (Enter/click) ์‹œ์ ์—๋งŒ.\n this.highlightMatchedCandidates()\n }\n\n /**\n * ํ˜ธ์ŠคํŠธ๊ฐ€ ๋ชฉ๋ก์„ ์ฃผ์ง€ ์•Š์„ ๋•Œ ์ด ๋„๋ฉ”์ธ์˜ ์‚ฌ์šฉ์ž๋ฅผ ์ง์ ‘ ๋ฌป๋Š”๋‹ค.\n *\n * ์‹คํŒจ๋Š” ๋นˆ ๋ชฉ๋ก์ด๋‹ค โ€” ๋ฉ˜์…˜์„ ๋ชป ๊ณ ๋ฅด๋Š” ๊ฒƒ์ด์ง€ ๋Œ€ํ™”๊ฐ€ ๋ง‰ํž ์ผ์€ ์•„๋‹ˆ๋‹ค.\n */\n private async fetchDomainUsers(query: string): Promise<Array<{ id: string; name?: string | null; email?: string | null }>> {\n try {\n const result = await client.query({\n query: DOMAIN_USERS_FOR_MENTION_QUERY,\n variables: { query },\n fetchPolicy: 'network-only'\n })\n return result.data?.domainUsersForMention ?? []\n } catch {\n return []\n }\n }\n\n /** `@` query ์— ๋Œ€ํ•œ userProvider ๋น„๋™๊ธฐ ํ˜ธ์ถœ โ€” ์‘๋‹ต ๋„์ฐฉ ์‹œ popup ๊ฒฐ๊ณผ ๊ฐฑ์‹ .\n * race ๋ฐฉ์ง€: token ์œผ๋กœ ์ตœ์‹  ํ˜ธ์ถœ ์‹๋ณ„ (๋Šฆ๊ฒŒ ๋„์ฐฉํ•œ ์‘๋‹ต ๋ฌด์‹œ). */\n private async refreshUserCandidatesAsync(query: string, hashPos: number) {\n const token = ++this.userFetchToken\n try {\n const users = this.userProvider\n ? await Promise.resolve(this.userProvider(query))\n : await this.fetchDomainUsers(query)\n if (token !== this.userFetchToken) return // ๋” ์ตœ์‹  ํ˜ธ์ถœ์ด ์žˆ์Œ\n // popup ์ด ๋‹ซํ˜”๊ฑฐ๋‚˜ trigger / hashPos ๊ฐ€ ๋ฐ”๋€Œ๋ฉด ๋ฌด์‹œ\n if (!this.mentionOpen || this.mentionTrigger !== '@' || this.mentionHashPos !== hashPos) {\n return\n }\n this.cachedUserCandidates = buildUserCandidates(users)\n this.mentionResults = filterMentionCandidates(\n this.cachedUserCandidates,\n query,\n 50\n )\n this.mentionActiveIndex = 0\n } catch (e) {\n // ์กฐ์šฉํžˆ ๋ฌด์‹œ โ€” ์‚ฌ์šฉ์ž ์ž…๋ ฅ ํ๋ฆ„ ๋ฐฉํ•ด X. ๋””๋ฒ„๊ทธ ์‹œ console ํ™•์ธ ๊ฐ€๋Šฅ.\n console.warn('[board-ai-chat] userProvider failed:', e)\n }\n }\n\n /** popup ํ›„๋ณด๋“ค outline highlight โ€” ์นด๋ฉ”๋ผ/์„ ํƒ ๋ณ€๊ฒฝ ์—†์Œ.\n * ํƒ€์ดํ•‘ ์งํ›„ (refreshMentionPopup) ์—์„œ ํ˜ธ์ถœ โ€” ์‚ฌ์šฉ์ž๊ฐ€ active ๋ฅผ ๋ช…์‹œ ์ด๋™ํ•˜์ง€\n * ์•Š์€ ์ƒํƒœ์ด๋ฏ€๋กœ ์ž„์˜์˜ ์ฒซ ํ•ญ๋ชฉ์„ ์„ ํƒํ•˜๊ฑฐ๋‚˜ ์นด๋ฉ”๋ผ ์ด๋™์‹œํ‚ค์ง€ ์•Š์Œ.\n * # trigger ์ผ ๋•Œ๋งŒ ํ™œ์„ฑ. */\n private highlightMatchedCandidates() {\n if (this.mentionTrigger !== '#') return\n const allRefids: number[] = []\n for (const r of this.mentionResults) {\n if (typeof r.candidate.refid === 'number') allRefids.push(r.candidate.refid)\n }\n this.dispatchActions([{ action: 'highlightComponents', refids: allRefids }])\n }\n\n /** active ํ›„๋ณด live preview โ€” ์‚ฌ์šฉ์ž๊ฐ€ โ†‘โ†“ ํ‚ค / popup ๋งˆ์šฐ์Šค hover ๋กœ ๋ช…์‹œ์ ์œผ๋กœ\n * active ๋ฅผ ์˜ฎ๊ธด ์‹œ์ ์— ํ˜ธ์ถœ. F-Finder ๋™๊ธ‰ 3-action: highlight + select + centerTo.\n * centerTo ๋Š” 150ms ๋””๋ฐ”์šด์Šค โ€” ๋น ๋ฅธ nav ์‹œ ์นด๋ฉ”๋ผ ์• ๋‹ˆ๋ฉ”์ด์…˜ race ๋ฐฉ์ง€.\n * # trigger ์ผ ๋•Œ๋งŒ ํ™œ์„ฑ. */\n private previewActiveCandidate() {\n if (this.mentionTrigger !== '#') return\n const allRefids: number[] = []\n for (const r of this.mentionResults) {\n if (typeof r.candidate.refid === 'number') allRefids.push(r.candidate.refid)\n }\n const active = this.mentionResults[this.mentionActiveIndex]\n const activeRefid =\n active && typeof active.candidate.refid === 'number'\n ? active.candidate.refid\n : undefined\n\n const actions: any[] = [{ action: 'highlightComponents', refids: allRefids }]\n if (typeof activeRefid === 'number') {\n actions.push({ action: 'selectComponents', refids: [activeRefid] })\n }\n this.dispatchActions(actions)\n\n if (this.centerDebounceTimer) clearTimeout(this.centerDebounceTimer)\n if (typeof activeRefid === 'number') {\n this.centerDebounceTimer = setTimeout(() => {\n this.dispatchActions([\n { action: 'centerToComponent', refid: activeRefid, animated: true }\n ])\n }, 150)\n }\n }\n\n private dispatchActions(actions: any[]) {\n this.dispatchEvent(\n new CustomEvent('scene-action-execute', {\n detail: { actions, sessionId: this.sessionId },\n bubbles: true,\n composed: true\n })\n )\n }\n\n /** ๋ฉ”์‹œ์ง€ ๋ฒ„๋ธ”์˜ `<span class=\"mention\">#token</span>` ํด๋ฆญ โ€” ์ปดํฌ๋„ŒํŠธ๋กœ select + centerTo.\n * resolve ๋ฃฐ์€ pure helper `resolveMentionToken` ์— ์œ„์ž„ (๋‹จ์œ„ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ). */\n private onBubbleClick = (e: Event) => {\n const target = e.target as HTMLElement | null\n if (!target?.classList?.contains('mention')) return\n e.preventDefault()\n const text = (target.textContent || '').trim()\n const token = text.startsWith('#') ? text.slice(1) : text\n if (!token) return\n\n const refid = resolveMentionToken(token, {\n persistedRefid: target.getAttribute('data-refid'),\n searchProvider: this.searchProvider,\n board: this.boardProvider ? this.boardProvider() : this.currentBoard\n })\n\n if (typeof refid === 'number') {\n this.dispatchActions([\n { action: 'selectComponents', refids: [refid] },\n { action: 'centerToComponent', refid, animated: true }\n ])\n } else {\n this.showToast(\n i18next.t('ai-assistant.text.mention-not-found', {\n token,\n defaultValue: `#${token} not found`\n })\n )\n }\n }\n\n /** popup ๋‹ซ๊ธฐ. commit=false (์ทจ์†Œ) ๋ฉด # ์˜ ๊ฒฝ์šฐ:\n * - highlight ์ •๋ฆฌ (highlightComponents [])\n * - ์›๋ž˜ selection ์œผ๋กœ ์›๋ณต\n * commit=true (ํ™•์ •) ๋ฉด ํ˜„์žฌ preview ์ƒํƒœ ์œ ์ง€ + highlight ๋งŒ ์ •๋ฆฌ. */\n private closeMentionPopup(commit = false) {\n if (!this.mentionOpen) return\n const wasHashTrigger = this.mentionTrigger === '#'\n this.mentionOpen = false\n this.mentionResults = []\n this.mentionOverflow = 0\n this.mentionActiveIndex = 0\n this.mentionHashPos = -1\n\n if (wasHashTrigger) {\n // popup ๋‹ซํž˜ โ†’ highlight ํ•ญ์ƒ ์ •๋ฆฌ (ํ™•์ •/์ทจ์†Œ ๋ชจ๋‘)\n const cleanupActions: any[] = [{ action: 'highlightComponents', refids: [] }]\n if (!commit) {\n // ์ทจ์†Œ โ€” ์›๋ž˜ selection ์œผ๋กœ ์›๋ณต\n cleanupActions.push({\n action: 'selectComponents',\n refids: this.originalSelectedRefids\n })\n }\n this.dispatchActions(cleanupActions)\n }\n }\n\n /** ํ›„๋ณด 1๊ฐœ๋ฅผ textarea ์— ์ ์šฉ + popup ๋‹ซ๊ณ  cursor ์žฌ๋ฐฐ์น˜. */\n private applyMention(candidate: MentionCandidate) {\n const ta = this.renderRoot.querySelector('textarea') as HTMLTextAreaElement | null\n if (!ta || this.mentionHashPos < 0) {\n this.closeMentionPopup()\n return\n }\n const cursor = ta.selectionStart ?? ta.value.length\n const r = applyMentionSelection(\n ta.value,\n cursor,\n this.mentionHashPos,\n candidate,\n this.mentionTrigger\n )\n this.input = r.text\n // # trigger + refid ๋ณด์œ  ํ›„๋ณด โ€” commit ์‹œ์ ์—๋งŒ select + centerTo (์‚ฌ์šฉ์ž ์˜๋„ ํ™•์ • ์ˆœ๊ฐ„).\n // ๋™์‹œ์— picks ๋กœ ๊ธฐ๋ก: textarea ์—๋Š” ๊นจ๋—ํ•œ #label, server ์—๋Š” ์ •ํ™•ํ•œ refid ์ „๋‹ฌ.\n if (\n this.mentionTrigger === '#' &&\n typeof candidate.refid === 'number'\n ) {\n this.pickedMentions.set(candidate.label, candidate.refid)\n this.dispatchActions([\n { action: 'selectComponents', refids: [candidate.refid] },\n { action: 'centerToComponent', refid: candidate.refid, animated: true }\n ])\n } else if (\n this.mentionTrigger === '@' &&\n typeof candidate.userId === 'string' &&\n candidate.userId.length > 0\n ) {\n // @user ๋ฉ˜์…˜ โ€” userId ๋ฐ•์ œ. ๋ณด๋“œ ์•ก์…˜์€ ๋ฐœ์‚ฌ ์•ˆ ํ•จ (์‚ฌ์šฉ์ž๋Š” ์ปดํฌ๋„ŒํŠธ ์•„๋‹˜).\n this.pickedUserMentions.set(candidate.label, candidate.userId)\n }\n this.closeMentionPopup(true) // commit โ€” preview selection ์œ ์ง€, highlight ๋งŒ ์ •๋ฆฌ\n requestAnimationFrame(() => {\n const ta2 = this.renderRoot.querySelector('textarea') as HTMLTextAreaElement | null\n ta2?.focus()\n ta2?.setSelectionRange(r.cursorPos, r.cursorPos)\n })\n }\n\n // โ”€โ”€ Empty state with onboarding guide โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\n /** ์˜ˆ์‹œ ๊ทธ๋ฃน โ€” i18n ํ‚ค. localize mixin ์ด ์–ธ์–ด ๋ณ€๊ฒฝ ์‹œ ์ž๋™ ์žฌ๋ Œ๋”. */\n /**\n * ํ™”๋ฉด์— ๊ทธ๋ฆด ์˜ˆ์‹œ โ€” ํ˜ธ์ŠคํŠธ๊ฐ€ ์ค€ ๊ฒƒ์ด ์žˆ์œผ๋ฉด ๊ทธ๊ฒƒ, ์—†์œผ๋ฉด ๋ณด๋“œ ๊ธฐ๋ณธ๊ฐ’(i18n ํ‚ค๋ฅผ ์—ฌ๊ธฐ์„œ ํ‘ผ๋‹ค).\n *\n * ๋‘ ์ž๋ฆฌ(๋นˆ ํ™”๋ฉด ยท ์ ‘ํžŒ ์ค„)๊ฐ€ ๊ฐ™์€ ๊ฐ’์„ ์จ์•ผ ํ•œ๋‹ค. ์ „์—๋Š” ๋‘˜์ด ๊ฐ๊ฐ `EXAMPLE_GROUPS` ๋ฅผ ์ง์ ‘\n * ์ฝ์—ˆ๊ณ , ๊ทธ๋Ÿฌ๋ฉด ํ˜ธ์ŠคํŠธ ๊ฐ’์„ ํ•œ์ชฝ๋งŒ ๋ฐ˜์˜ํ•˜๋Š” ์ƒํƒœ๊ฐ€ ๋งŒ๋“ค์–ด์งˆ ์ˆ˜ ์žˆ์—ˆ๋‹ค.\n */\n private get exampleGroups(): Array<{ label: string; items: string[] }> {\n /*\n * ๋Œ€ํ™”๊ฐ€ ์ž๊ธฐ ์˜ˆ์‹œ๋ฅผ ๊ฐ€์ง€๋ฉด ๊ทธ๊ฒƒ์ด ๋จผ์ €๋‹ค โ€” ์ž๋ฆฌํ‘œยท`/` ์™€ ๊ฐ™์€ ์ฐจ๋ก€(ADR-0061 ๊ฒฐ์ • 7). host ์†์„ฑ์€\n * ๋Œ€ํ™”๋ฅผ ๋ชจ๋ฅด๋ฏ€๋กœ, ํ•œ ํ™”๋ฉด์— ๋Œ€ํ™”๊ฐ€ ๋‘˜ ์„œ๋ฉด ํ•œ์ชฝ์— ๋งž๋Š” ๊ธ€์ด ๋‹ค๋ฅธ ์ชฝ์—๋„ ๋œฌ๋‹ค.\n */\n if (this.modeView?.examples?.length) return this.modeView.examples\n if (this.examples?.length) return this.examples\n return OxAssistantChat.EXAMPLE_GROUPS.map(group => ({\n label: i18next.t(group.labelKey),\n items: group.itemKeys.map(key => i18next.t(key))\n }))\n }\n\n /** ์ด ํ‘œ๋ฉด์ด ์‹ค์ œ๋กœ ์“ธ ์ˆ˜ ์žˆ๋Š” ํŠธ๋ฆฌ๊ฑฐ โ€” ํŒ์ •์€ `chat-triggers.ts` ๊ฐ€ ํ•˜๊ณ  ์—ฌ๊ธฐ์„œ๋Š” ์‚ฌ์‹ค๋งŒ ์ฝ๋Š”๋‹ค. */\n private get triggerChips(): TriggerChip[] {\n return availableTriggers({\n hasMentionableThings: !!(this.boardProvider || this.currentBoard || this.knownTypes?.length),\n hasSession: !!this.sessionId,\n slashTemplateCount: this.conversation.slashTemplates.length\n })\n }\n\n private static readonly EXAMPLE_GROUPS: Array<{\n labelKey: string\n itemKeys: string[]\n }> = [\n {\n labelKey: 'ai-assistant.label.create',\n itemKeys: [\n 'ai-assistant.example.create-monitoring-dashboard',\n 'ai-assistant.example.create-welcome-screen'\n ]\n },\n {\n labelKey: 'ai-assistant.label.edit',\n itemKeys: [\n 'ai-assistant.example.edit-align-distribute',\n 'ai-assistant.example.edit-resize-board'\n ]\n },\n {\n labelKey: 'ai-assistant.label.style',\n itemKeys: [\n 'ai-assistant.example.style-dark-mode',\n 'ai-assistant.example.style-rounded-shadow'\n ]\n }\n ]\n\n /** ๋ณด๋“œ์˜ ์„ธ์…˜ ํƒญ โ€” ๋‹ค์ค‘ ์„ธ์…˜ ํ™œ์„ฑํ™” ์‹œ ํŒจ๋„ ์ƒ๋‹จ. host ๊ฐ€ sessions ๋น„์›Œ๋‘๋ฉด ํ‘œ์‹œ X.\n * ๋ ˆ์ด๋ธ”์€ session.name ์šฐ์„ , ์—†์œผ๋ฉด fallback \"์„ธ์…˜ N\". */\n /**\n * ์ด ๋Œ€ํ™”์˜ **์ฃผ์–ด** โ€” ๊ฐ™์€ ํ™”๋ฉด ์œ„์— ๋‘ ๋Œ€ํ™”๊ฐ€ ์„ค ๋•Œ๋งŒ ๋‚˜์˜จ๋‹ค(ADR-0072 A17 โ‘ ).\n *\n * ํ•˜๋‚˜๋ฟ์ด๋ฉด ์•„๋ฌด๊ฒƒ๋„ ๊ทธ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค. ๊ณ ๋ฅผ ๊ฒƒ์ด ์—†๋Š” ๊ณ ๋ฅด๊ฐœ๋Š” ์ž๋ฆฌ๋งŒ ์ฐจ์ง€ํ•˜๊ณ , ์‚ฌ๋žŒ์—๊ฒŒ ใ€Œ๋ฌด์–ธ๊ฐ€\n * ๊ณ ๋ฅผ ๊ฒƒ์ด ์žˆ๋‹คใ€๋Š” ์ž˜๋ชป๋œ ์‹ ํ˜ธ๋ฅผ ์ค€๋‹ค.\n *\n * โ”€โ”€ ์™œ ํƒญ ์ค„์ด ์•„๋‹Œ๊ฐ€ (UX ๋ ˆ์ธ, 2026-09-18) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ์ฒ˜์Œ์—๋Š” ์นฉ ์ค„์— `role=\"tablist\"` ๋ฅผ ๋‹ฌ์•˜๋‹ค. ๋ฐ”๋กœ ์•„๋ž˜๊ฐ€ ์„ธ์…˜ ํƒญ์ด๊ณ  ๊ทธ์ชฝ๋„ tablist ๋ผ์„œ, ํ™”๋ฉด\n * ๋‚ญ๋…๊ธฐ๋กœ ๋“ค์œผ๋ฉด ใ€Œํƒญ ๋ชฉ๋ก, ๋Œ€ํ™”ใ€ ๋‹ค์Œ์— ใ€Œํƒญ ๋ชฉ๋ก, Conversation historyใ€ ๊ฐ€ ์ด์–ด์กŒ๋‹ค โ€” ๊ณ ๋ฅด๋Š”\n * ์ถ•์ด ๋‘˜์ธ๋ฐ ๋‘˜ ๋‹ค ใ€Œํƒญใ€์ด๋ผ๊ณ  ๋งํ•œ๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ ARIA ํƒญ์€ ์ขŒ์šฐ ํ™”์‚ดํ‘œ ์ด๋™๊ณผ `tabpanel` ์ด ํ•จ๊ป˜\n * ์žˆ์–ด์•ผ ์„ฑ๋ฆฝํ•˜๊ณ , ๋‘˜ ๋‹ค ์—†์œผ๋ฉด ๋‚ญ๋…๊ธฐ๋Š” ใ€Œ2 ์ค‘ 1๋ฒˆ์งธ ํƒญใ€์ด๋ผ ๋งํ•˜๊ณ  ํ™”์‚ดํ‘œ๋Š” ์•„๋ฌด ์ผ๋„ ์•ˆ ํ•œ๋‹ค.\n *\n * ๋ฌด๊ฒŒ๋„ ๋‹ค๋ฅด๋‹ค. ์„ธ์…˜์€ ใ€Œ์–ด๋А ์ง€๋‚œ ๋Œ€ํ™”๋ƒใ€์ด๊ณ  ๋ชจ๋“œ๋Š” ใ€Œ์ด ๋Œ€ํ™”๊ฐ€ ๋ฌด์—‡์— ๋Œ€ํ•œ ๊ฒƒ์ด๋ƒใ€์ด๋‹ค. ๊ฐ™์€\n * ๋ฌด๊ฒŒ๋กœ ๊ทธ๋ฆฌ๋ฉด ์–ด๋А ์ชฝ์ด ํ™”์ œ๋ฅผ ๋ฐ”๊พธ๊ณ  ์–ด๋А ์ชฝ์ด ์‹คํƒ€๋ž˜๋ฅผ ๋ฐ”๊พธ๋Š”์ง€ ๊ตฌ๋ณ„๋˜์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ž˜์„œ ์ง€๊ธˆ\n * ๋Œ€ํ™”๊ฐ€ ์ œ๋ชฉ ๊ตต๊ธฐ๋กœ ์„œ๊ณ , ๋ฐ”๊ฟ€ ์ž๋ฆฌ๋Š” ๊ทธ ์˜†์— ๋ถ™๋Š”๋‹ค.\n *\n * โ”€โ”€ ์™œ ๋„ํฌ ์ œ๋ชฉ ์ค„๋กœ ์•ˆ ์˜ฌ๋ฆฌ๋‚˜ (UX ๋ ˆ์ธ ํŒ์ •, 2026-09-18) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ๋„ํฌ ์ œ๋ชฉ์€ ใ€Œ์ง€๊ธˆ ์–ด๋””์— ์žˆ๋‚˜ใ€(์ด ๋„ํ˜• ยท ์ด ํ˜„์žฅ ยท ์ด ์Šคํ…Œ์ด์…˜ ํ™”๋ฉด)์ด๊ณ  ์ด ์ค„์€ ใ€Œ์ด ๋Œ€ํ™”๊ฐ€\n * ๋ฌด์—‡์— ๋Œ€ํ•œ ๊ฒƒ์ด๋ƒใ€์ด๋‹ค. ๋Œ€ํ™”์˜ ์ฃผ์–ด๋Š” ๋Œ€ํ™” ์•ˆ์— ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์„ธ ๋„ํฌ๊ฐ€ ๊ฐ์ž ๊ทธ๋ฆฌ๋ฉด ์„ธ ๋ฒŒ์ด ๋˜๊ณ \n * ๊ทธ ์„ธ ๋ฒŒ์€ ๊ฐˆ๋ฆฐ๋‹ค โ€” `modeChoices` ๋ฅผ ์•„๋Š” ๊ฒƒ๋„ ์—ฌ๊ธฐ๋‹ค. ์˜ฌ๋ฆฌ๋ฉด ๋ชฉ๋ก๊ณผ ๊ณ ๋ฅธ ๊ฒƒ์ด ์„ธ ์ž๋ฆฌ๋กœ ๋‚˜๊ฐ”๋‹ค\n * ๋Œ์•„์˜จ๋‹ค.\n */\n private renderModeSubject() {\n if (this.modeChoices.length < 2) return nothing\n\n const current = this.modeChoices.find(choice => choice.kind === this.mode?.kind)\n const others = this.modeChoices.filter(choice => choice.kind !== this.mode?.kind)\n\n return html`\n <div class=\"mode-subject\">\n <span class=\"mode-now\">${current?.label ?? this.mode?.kind ?? ''}</span>\n ${others.length === 1\n ? html`\n <button\n class=\"mode-switch\"\n title=${i18next.t('ai-assistant.text.switch-conversation', { name: others[0].label })}\n aria-label=${i18next.t('ai-assistant.text.switch-conversation', { name: others[0].label })}\n ?disabled=${this.busy}\n @click=${() => this.onModePick(others[0].kind)}>\n ${others[0].label}\n </button>\n `\n : html`\n <select\n class=\"mode-select\"\n aria-label=${i18next.t('ai-assistant.label.conversation')}\n ?disabled=${this.busy}\n @change=${(event: Event) => this.onModePick((event.target as HTMLSelectElement).value)}>\n ${this.modeChoices.map(\n choice => html`<option value=${choice.kind} ?selected=${choice.kind === this.mode?.kind}>${choice.label}</option>`\n )}\n </select>\n `}\n </div>\n `\n }\n\n private renderSessionTabs() {\n if (!this.sessions || this.sessions.length === 0) return nothing\n return html`\n <ox-assistant-session-toolbar style=\"padding:8px 12px\" .sessions=${this.sessions}\n .sessionId=${this.sessionId || ''} .disabled=${this.busy}\n @assistant-session-select=${(event: CustomEvent) => { event.stopPropagation(); this._onSessionTabClick(event.detail.sessionId) }}\n @assistant-session-reset=${(event: Event) => { event.stopPropagation(); this._onSessionCreateClick() }}\n ></ox-assistant-session-toolbar>\n `\n }\n\n /** C4 roster โ€” ์„ธ์…˜ ์ฐธ์—ฌ์ž + online ํ‘œ์‹œ. ์ฐธ์—ฌ์ž 2๋ช… ๋ฏธ๋งŒ์ด๋ฉด ์ˆจ๊น€(ํ˜ผ์ž๋ฉด ์˜๋ฏธ ์—†์Œ). */\n private renderRoster() {\n if (!this.sessionId || this.participants.length < 2) return nothing\n const online = this.participants.filter(p => this._isOnline(p.lastSeenAt)).length\n return html`\n <div class=\"roster\" role=\"group\" aria-label=\"participants\">\n <span class=\"roster-count\" title=${`${online} online / ${this.participants.length} total`}>\n <md-icon>group</md-icon>${online}/${this.participants.length}\n </span>\n ${this.participants.map(p => {\n const name = p.user?.name || p.user?.id || '?'\n const on = this._isOnline(p.lastSeenAt)\n return html`<span\n class=\"roster-chip ${on ? 'online' : 'offline'}\"\n title=${`${name} ยท ${p.role}${on ? ' ยท online' : ''}`}>\n <span class=\"roster-dot\"></span>${initials(name)}\n </span>`\n })}\n </div>\n `\n }\n\n private _onSessionTabClick(sessionId: string) {\n if (sessionId === this.sessionId) return\n this.dispatchEvent(\n new CustomEvent('session-switch', {\n detail: { sessionId },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private _onSessionCreateClick = () => {\n if (this.busy || this.lines.length === 0) return\n this.dispatchEvent(\n new CustomEvent('session-create', {\n bubbles: true,\n composed: true\n })\n )\n }\n\n private renderEmpty() {\n return html`\n <div class=\"empty\">\n <div class=\"header\">\n <md-icon class=\"icon\">auto_awesome</md-icon>\n <!-- ๋Œ€ํ™”๊ฐ€ ์ž๊ธฐ ๊ธ€์„ ๊ฐ€์ง€๋ฉด ๊ทธ๊ฒƒ์ด ๋จผ์ €๋‹ค โ€” host ์†์„ฑ์€ ๋Œ€ํ™”๋ฅผ ๋ชจ๋ฅธ๋‹ค. -->\n <div class=\"title\">\n ${this.modeView?.intro?.title ?? this.intro?.title ?? i18next.t('ai-assistant.text.empty-title')}\n </div>\n <div class=\"subtitle\">\n ${this.modeView?.intro?.subtitle ?? this.intro?.subtitle ?? i18next.t('ai-assistant.text.empty-subtitle')}\n </div>\n </div>\n\n ${this.triggerChips.length > 0\n ? html`\n <div class=\"trigger-row\">\n <div class=\"trigger-row-label\">${i18next.t('ai-assistant.text.triggers-heading')}</div>\n <div class=\"trigger-chips\">\n ${this.triggerChips.map(\n trigger => html`\n <button\n class=\"trigger-chip\"\n title=${i18next.t(trigger.tooltipKey)}\n @click=${() => this.insertTrigger(trigger.char)}>\n <span class=\"trigger-char\">${trigger.char}</span>\n <span class=\"trigger-desc\">${i18next.t(trigger.labelKey)}</span>\n </button>\n `\n )}\n </div>\n </div>\n `\n : ''}\n\n ${this.exampleGroups.map(\n group => html`\n <div class=\"group\">\n <div class=\"group-label\">${group.label}</div>\n ${group.items.map(\n text => html`\n <button class=\"example\" @click=${() => this.useExample(text)}>\n ${text}<span class=\"arrow\">โ†’</span>\n </button>\n `\n )}\n </div>\n `\n )}\n\n <div class=\"footer\">\n <span class=\"badge\">${i18next.t('ai-assistant.label.korean-supported')}</span>\n <span class=\"badge\">${i18next.t('ai-assistant.label.multi-command')}</span>\n <span class=\"badge\">${i18next.t('ai-assistant.label.review-able')}</span>\n ${this.conversation.footerNotice\n ? html`<br />${this.conversation.footerNotice}`\n : ''}\n </div>\n </div>\n `\n }\n\n /** trigger chip ํด๋ฆญ โ€” textarea ์— trigger ๋ฌธ์ž ์‚ฝ์ž… + focus + popup ์ž๋™ ํ™œ์„ฑ. */\n private insertTrigger(trigger: '#' | '@' | '/') {\n // ์ž…๋ ฅ ๋์— ๊ณต๋ฐฑ์ด ์—†์œผ๋ฉด ๊ณต๋ฐฑ ์ถ”๊ฐ€ ํ›„ trigger โ€” ์ž์—ฐ์Šค๋Ÿฌ์šด ์œ„์น˜\n const needsSpace = this.input.length > 0 && !/\\s$/.test(this.input)\n this.input = this.input + (needsSpace ? ' ' : '') + trigger\n requestAnimationFrame(() => {\n const ta = this.renderRoot.querySelector('textarea') as HTMLTextAreaElement | null\n if (!ta) return\n ta.focus()\n ta.setSelectionRange(ta.value.length, ta.value.length)\n // popup refresh โ€” onTextareaInput ์ด ๋””๋ฐ”์šด์Šค ํ›„ ํ˜ธ์ถœ๋˜์ง€๋งŒ ์ง์ ‘ ํ˜ธ์ถœ๋กœ ์ฆ‰๊ฐ ๋ฐ˜์˜\n this.refreshMentionPopup(ta)\n })\n }\n\n /** ์˜ˆ์‹œ ํด๋ฆญ โ€” ์ž…๋ ฅ์ฐฝ์— ์ฑ„์šฐ๊ณ  ํฌ์ปค์Šค (์‚ฌ์šฉ์ž๊ฐ€ ์ˆ˜์ • ํ›„ ์ „์†ก ๊ฐ€๋Šฅ) */\n private useExample(text: string) {\n this.input = text\n this.examplesOpen = false\n requestAnimationFrame(() => {\n const ta = this.renderRoot.querySelector('textarea') as HTMLTextAreaElement | null\n ta?.focus()\n ta?.setSelectionRange(text.length, text.length)\n })\n }\n\n // โ”€โ”€ Mini actions โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\n private renderInlineExamples() {\n return html`\n <div class=\"inline-examples\">\n ${this.exampleGroups.map(\n group => html`\n <div class=\"ex-row\">\n <span class=\"ex-label\">${group.label}</span>\n ${group.items.map(t => html`<button class=\"ex\" @click=${() => this.useExample(t)}>${t}</button>`)}\n </div>\n `\n )}\n </div>\n `\n }\n\n // โ”€โ”€ Retry (์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\n private async retryLastSend() {\n if (!this.lastFailedInput) return\n this.input = this.lastFailedInput\n this.errorMessage = undefined\n this.lastFailedInput = undefined\n await this.send()\n }\n\n // โ”€โ”€ Per-message hover action row โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\n /**\n * ๋ฉ”์‹œ์ง€๋ณ„ hover ์•ก์…˜ โ€” ํ…์ŠคํŠธ chip ์œผ๋กœ ๋ช…ํ™•.\n * user : ์•ก์…˜ row ์ž์ฒด X (์ž๊ธฐ ๋ฉ”์‹œ์ง€์— ์‹œ๊ฐ ๋…ธ์ด์ฆˆ X โ€” ํŽธ์ง‘์€ input ์œ„ \"์ƒˆ ๋Œ€ํ™”\" ํ๋ฆ„ ๋˜๋Š” ๋งˆ์šฐ์Šค ๋”๋ธ”ํด๋ฆญ)\n * assistant : ๋ณต์‚ฌ + ์žฌ์ƒ์„ฑ + (patch ์ ์šฉ๋œ ๊ฒฝ์šฐ๋งŒ) ๋˜๋Œ๋ฆฌ๊ธฐ\n * system : ์—†์Œ\n */\n private renderMessageActions(idx: number, line: ChatLine, content: string) {\n if (line.role !== 'assistant') return nothing\n\n const isCopied = this.copiedIdx === idx\n // revert ๋Š” ์ธ๋ผ์ธ patch chip (๋ฉ”์‹œ์ง€ ์•ˆ) ํ•œ ๊ณณ์—๋งŒ โ€” hover ์•ก์…˜์—์„œ ์ œ์™ธ (์ค‘๋ณต ๋ฐฉ์ง€).\n return html`\n <div class=\"msg-actions\">\n <button\n class=\"msg-action ${isCopied ? 'confirmed' : ''}\"\n title=${isCopied\n ? i18next.t('ai-assistant.text.copied')\n : i18next.t('ai-assistant.button.copy')}\n @click=${() => this.copyMessage(idx, content)}>\n <md-icon>${isCopied ? 'check' : 'content_copy'}</md-icon>\n </button>\n <button\n class=\"msg-action\"\n ?disabled=${this.busy}\n title=${i18next.t('ai-assistant.button.regenerate')}\n @click=${() => this.regenerateAssistant(idx)}>\n <md-icon>refresh</md-icon>\n </button>\n </div>\n `\n }\n\n /**\n * \"๋Œ€ํ™”๊ฐ€ ๊ธธ์–ด์กŒ์Šต๋‹ˆ๋‹ค\" ์•ˆ๋‚ด โ€” **์‚ฌ์‹ค๋งŒ** ์•Œ๋ฆฌ๊ณ  ๊ฒฐ์ •์€ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋งก๊ธด๋‹ค.\n *\n * ์ฃผ์ œ๊ฐ€ ๋ฐ”๋€Œ์—ˆ๋Š”์ง€ ํŒ์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค: ํŒ์ •ํ•˜๋ฉด ์˜คํƒ์ด ์ƒ๊ธฐ๊ณ , ์˜คํƒ์ด ์ƒ๊ธฐ๋ฉด ์‚ฌ์šฉ์ž๋Š” ์•ˆ๋‚ด ์ž์ฒด๋ฅผ\n * ๋ฌด์‹œํ•œ๋‹ค(์ ‘์ง€ ๊ฒฝ๊ณ ์—์„œ ๋ฐฐ์šด ๊ฒƒ๊ณผ ๊ฐ™๋‹ค). ๊ทผ๊ฑฐ๋Š” \"์•ž๋ถ€๋ถ„์ด ํ”„๋กฌํ”„ํŠธ์—์„œ ์ ‘ํ˜”๋‹ค\" ๋Š” ๊ฐ๊ด€์  ์‚ฌ์‹ค๋ฟ์ด๋‹ค.\n *\n * ์™œ ์•Œ๋ ค์•ผ ํ•˜๋Š”๊ฐ€: ํ•œ ๋Œ€ํ™”์— ์ฃผ์ œ๊ฐ€ ์—ฌ๋Ÿฟ ์„ž์ด๋ฉด (1) ์˜› ๋งฅ๋ฝ์ด ์ƒˆ ๋‹ต์„ ์˜ค์—ผ์‹œํ‚ค๊ณ  (2) ์š”์•ฝ์ด\n * ๋ญ‰๊ฐœ์ง€๊ณ  (3) ๋ชฉ๋ก์˜ ๋Œ€ํ™” ์ด๋ฆ„์ด ๊ฑฐ์ง“๋ง์ด ๋œ๋‹ค. ๊ทธ๊ฑธ ์•„๋Š” ์‚ฌ๋žŒ์€ ์‚ฌ์šฉ์ž๋ฟ์ด๋‹ค.\n */\n private renderFoldNotice() {\n const folded = this.historyFolded\n if (!folded || this.foldNoticeDismissed) return nothing\n return html`\n <div class=\"fold-notice\">\n <md-icon>unfold_less</md-icon>\n <span class=\"fn-text\">\n ${folded.summarized\n ? i18next.t('ai-assistant.text.history-folded-summarized', {\n count: folded.omitted,\n defaultValue: 'this conversation grew long โ€” the earlier {count} messages were folded into a summary. a new conversation is better for a different topic.'\n })\n : i18next.t('ai-assistant.text.history-folded', {\n count: folded.omitted,\n defaultValue: 'this conversation grew long โ€” the earlier {count} messages were left out. a new conversation is better for a different topic.'\n })}\n </span>\n <button class=\"fn-new\" @click=${this.startNewFromNotice}>\n ${i18next.t('ai-assistant.button.new-chat')}\n </button>\n <button class=\"fn-close\" title=${i18next.t('ai-assistant.button.close')} @click=${() => (this.foldNoticeDismissed = true)}>\n <md-icon>close</md-icon>\n </button>\n </div>\n `\n }\n\n /**\n * ์ƒˆ ๋Œ€ํ™”๋กœ โ€” **๋งฅ๋ฝ์„ ์˜ฎ๊ธฐ์ง€ ์•Š๋Š”๋‹ค.** ์ฃผ์ œ๋ฅผ ๋ฐ”๊พธ๋ ค๊ณ  ์ƒˆ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ, ์˜ฎ๊ธฐ๋ฉด ๊ทธ ์ด์œ ๊ฐ€\n * ์‚ฌ๋ผ์ง„๋‹ค(์Šน๊ฒฉ์€ ์ด์–ด๊ฐ€๋ ค๋Š” ๊ฒƒ์ด๊ณ  ์ด๊ฑด ๋Š์œผ๋ ค๋Š” ๊ฒƒ์ด๋‹ค). ์„ธ์…˜ ์ƒ์„ฑ์€ ํ˜ธ์ŠคํŠธ์˜ ๋ชซ์ด๋‹ค.\n */\n private startNewFromNotice = () => {\n this.foldNoticeDismissed = true\n this.dispatchEvent(new CustomEvent('assistant-start-new-session', { bubbles: true, composed: true }))\n }\n\n /**\n * ์กฐ์น˜ ์ œ์•ˆ ์นด๋“œ โ€” AI ๋Š” ์ œ์•ˆ๊นŒ์ง€, **์‹คํ–‰์€ ์‚ฌ์šฉ์ž**.\n *\n * ์™œ ์นด๋“œ์ธ๊ฐ€: ๋˜๋Œ๋ฆด ์ˆ˜ ์—†๋Š” ํ˜„์žฅ ๋ช…๋ น์„ ๋ฌธ์žฅ ์† ๋งํฌ๋กœ ํ˜๋ฆฌ๋ฉด ์‹ค์ˆ˜๋กœ ๋ˆŒ๋ฆฐ๋‹ค. ๋ฌด์—‡์„ยท์™œ ํ•˜๋Š”์ง€\n * ํ•œ ์ค„๋กœ ๋ณด์ด๊ณ  ์‹คํ–‰์ด **๋ถ„๋ช…ํ•œ ํ•œ ๋ฒˆ์˜ ํ–‰๋™**์ด์–ด์•ผ ํ•œ๋‹ค.\n * ์‹คํ–‰ ๊ฒฐ๊ณผ๋Š” ํ˜ธ์ŠคํŠธ๊ฐ€ **๋Œ€ํ™”์— ๊ธฐ๋ก**ํ•œ๋‹ค โ€” ๋ˆ„๊ฐ€ ๋ฌด์—‡์„ ์‹คํ–‰ํ–ˆ๋Š”์ง€๊ฐ€ ํ˜‘์˜ ์ด๋ ฅ์— ๋‚จ์•„์•ผ ํ•œ๋‹ค.\n */\n private renderProposals(line: ChatLine) {\n const items = line.proposals ?? []\n if (items.length === 0) return nothing\n /* The card's state is the conversation's rows - read once for every card of this line. */\n const outcomes = this.proposalOutcomes\n const requested = this.proposalRequests\n /* A data entry card replaced by a newer one for the same record cannot be entered (design/ai/data-entry.md ยง5). */\n const latestEntry = items.some(isEntryProposal) ? latestEntryKeys(this.lines.map(one => one.proposals ?? [])) : undefined\n return html`\n <div class=\"proposals\">\n ${items.map(p => {\n const key = this.proposalKey(p)\n /* A workspace card opens the page; it runs nothing (design/ai/workspace.md ยง4). */\n if (isWorkspaceProposal(p)) return this.renderWorkspaceCard(p, key)\n /* A screen card opens the application's list with the question's conditions; it runs nothing (design/ai/read-targets.md ยง5). */\n if (isOpenPageProposal(p)) return this.renderOpenPageCard(p)\n const card = proposalCardState(key, { outcomes, requested, sentHere: this.sentProposals.has(key) })\n const entry = isEntryProposal(p)\n const replaced = entry && latestEntry?.get(entryGroupOf(p)) !== key && card.state === 'ready'\n const ready = entry ? entryReadyCount(p) : 0\n const sent = card.state !== 'ready' || replaced || (entry && ready === 0)\n /*\n Follow-up chips are the host's words, never this component's. The fallback that used\n to live here named a 3D modeller's operations in hardcoded Korean, and it reached the\n plant and twin chats too.\n */\n const rawChoices: any[] = Array.isArray(p.choices) ? p.choices : this.conversation.proposalChoices\n\n return html`\n <div class=\"proposal ${sent ? 'sent' : ''}\">\n <md-icon>${p.icon || (p.source ? 'view_in_ar' : 'bolt')}</md-icon>\n <span class=\"pbody\">\n <span class=\"plabel\">${entry ? entryTitle(p, (key, options) => i18next.t(key, options) as string) : p.label || p.command}</span>\n ${p.reason ? html`<span class=\"preason\">${p.reason}</span>` : nothing}\n </span>\n ${/*\n The run button and the follow-up chips answer different questions โ€” \"is there\n something to apply\" and \"what else could I ask for\" โ€” and they used to share one\n ternary on `rawChoices.length`. A proposal that carried chips lost its button, so\n the one action the card exists for became unreachable while the model kept\n telling people to press it.\n */ ''}\n ${card.state === 'unconfirmed'\n ? html`\n <span class=\"preason\">${i18next.t('ai-assistant.text.proposal-unconfirmed', { defaultValue: 'sent earlier - no answer received' })}</span>\n <button class=\"run\" @click=${() => this.checkProposal(p, key)}>\n ${i18next.t('ai-assistant.button.check-proposal', { defaultValue: 'check result' })}\n </button>\n `\n : html`\n <button\n class=\"run\"\n ?disabled=${sent}\n @click=${() => this.executeProposal(p, key)}>\n ${replaced\n ? i18next.t('ai-assistant.entry.replaced', { defaultValue: 'replaced by a newer card' })\n : card.state !== 'ready'\n ? this.proposalStateText(key)\n : entry\n ? ready\n ? isChangeProposal(p)\n ? i18next.t('ai-assistant.entry.change', { defaultValue: 'change {count} records', count: ready })\n : i18next.t('ai-assistant.entry.enter', { defaultValue: 'enter {count} rows', count: ready })\n : i18next.t('ai-assistant.entry.nothing-to-enter', { defaultValue: 'nothing to enter' })\n : i18next.t('ai-assistant.button.run-proposal', { defaultValue: 'run' })}\n </button>\n `}\n ${/*\n Drawn only where the host has said it staged this candidate, in the host's own\n words. Not knowing is not a claim: with no word from the host, nothing is drawn.\n This badge used to read \"there are chips\" as \"the model is in the 3D viewer\" and\n say so, in a component that plant and twin also use.\n */ ''}\n ${this.stagedProposals.has(key) && this.conversation.stagedNotice ? html`\n <span class=\"staged-badge\">\n <md-icon>check_circle</md-icon>\n <span>${this.conversation.stagedNotice}</span>\n </span>\n ` : nothing}\n </div>\n ${entry ? html`<ox-assistant-entry-review .proposal=${p}></ox-assistant-entry-review>` : nothing}\n ${entry && this.sessionId && offersWorkspaceReview(p)\n ? html`<button\n class=\"workspace-review\"\n @click=${() =>\n this.dispatchEvent(new CustomEvent('assistant-open-page', { detail: { href: entryReviewAddress(this.sessionId!, key) }, bubbles: true, composed: true }))}\n >\n <md-icon>open_in_full</md-icon>\n <span>${i18next.t('ai-assistant.entry.review-in-workspace', { defaultValue: 'review in the workspace' })}</span>\n </button>`\n : nothing}\n ${rawChoices.length ? html`\n <div class=\"proposal-choices\" role=\"group\" aria-label=${i18next.t('ai-assistant.text.proposal-choices', { defaultValue: 'follow-up choices' })}>\n ${rawChoices.map((c: any) => html`\n <button\n class=\"choice-chip ${c.primary ? 'primary' : ''}\"\n title=${c.prompt || c.label}\n @click=${() => this.onChoiceClick(c, p, key)}>\n ${c.icon ? html`<md-icon>${c.icon}</md-icon>` : nothing}\n <span>${c.label}</span>\n </button>\n `)}\n </div>\n ` : nothing}\n `\n })}\n </div>\n `\n }\n\n /** The screen card - which list, the conditions the screen does not take, and the way to open it. */\n private renderOpenPageCard(p: any) {\n const note = openPageNote(p, (key, options) => String(i18next.t(key, options)))\n const open = () => this.dispatchEvent(new CustomEvent('assistant-open-page', { detail: { href: p.href }, bubbles: true, composed: true }))\n return html`\n <div class=\"proposal workspace\">\n <md-icon>${p.icon || 'open_in_new'}</md-icon>\n <span class=\"pbody\">\n <span class=\"plabel\">${p.label}</span>\n ${note ? html`<span class=\"preason\">${note}</span>` : nothing}\n </span>\n <button class=\"run\" @click=${open}>${i18next.t('ai-assistant.screen.open', { defaultValue: 'open the screen' })}</button>\n </div>\n `\n }\n\n /** The AI ์ž‘์—…ํŒ card - what it holds, which version, and the way to open it. The person opens it; the model does not. */\n private renderWorkspaceCard(p: any, key: string) {\n const { version, of } = versionOfCard(this.lines.map(one => one.proposals ?? []), p.workspace.name, key)\n const contents = Object.entries(p.contents ?? {})\n .map(([kind, count]) => String(i18next.t(`ai-assistant.workspace.contains-${kind}`, { defaultValue: `${kind} {count}`, count: Number(count) } as any)))\n .join(' ยท ')\n const open = () => {\n if (!this.sessionId) return\n /* The page is the application's; navigate is the shell's, reached by an event so this component stays standalone. */\n this.dispatchEvent(new CustomEvent('assistant-open-page', { detail: { href: workspaceAddress(this.sessionId, p.workspace.name, version) }, bubbles: true, composed: true }))\n }\n return html`\n <div class=\"proposal workspace\">\n <md-icon>${p.icon || 'dashboard'}</md-icon>\n <span class=\"pbody\">\n <span class=\"plabel\">${p.workspace.title}</span>\n <span class=\"preason\">${[contents, of > 1 ? i18next.t('ai-assistant.workspace.version', { defaultValue: 'version {version} of {of}', version, of }) : ''].filter(Boolean).join(' ยท ')}</span>\n </span>\n <button class=\"run\" ?disabled=${!this.sessionId} @click=${open}>${i18next.t('ai-assistant.workspace.open', { defaultValue: 'open in workspace' })}</button>\n </div>\n `\n }\n\n /**\n * ๋ˆŒ๋ฆฐ ์นด๋“œ๊ฐ€ ๋งํ•˜๋Š” ๊ฒƒ โ€” **ํ˜ธ์ŠคํŠธ๊ฐ€ ํ•œ ์ผ**์ด๊ณ , ์•„์ง ๋ชจ๋ฅด๋ฉด ๋ชจ๋ฅธ๋‹ค๊ณ  ๋งํ•œ๋‹ค.\n *\n * ์˜ˆ์ „์—๋Š” ๋ˆ„๋ฅธ ์ˆœ๊ฐ„ ใ€Œ์‹คํ–‰๋จใ€์ด์—ˆ๋‹ค. 09-18 ํŠธ์œˆ์—์„œ ์•„๋ฌด ์ผ๋„ ์ผ์–ด๋‚˜์ง€ ์•Š์€ ์ฑ„ ใ€Œโœ“ ๋ฐ˜์˜ํ–ˆ์Šต๋‹ˆ๋‹คใ€๊ฐ€\n * ๋–ด๋‹ค(ADR-0070 A12-a).\n */\n private proposalStateText(key: string): string {\n const outcome = this.proposalOutcomes.get(key)\n\n if (!outcome) {\n /* ๋‹ต์ด ์˜ค๊ธฐ ์ „ โ€” ์•„๋Š” ์‚ฌ์‹ค์€ ใ€Œ๋ณด๋ƒˆ๊ณ  ์•„์ง ๋‹ต์ด ์—†๋‹คใ€๋ฟ์ด๋‹ค. ๊ฒฝ๊ณผ ์‹œ๊ฐ„์„ ํ•จ๊ป˜ ๋ณด์ธ๋‹ค. */\n const since = this.proposalSentAt.get(key)\n const seconds = since ? Math.max(0, Math.round((Date.now() - since) / 1000)) : 0\n return i18next.t('ai-assistant.text.proposal-waiting', {\n seconds,\n defaultValue: 'sending โ€” {seconds}s, no answer yet'\n })\n }\n\n const counted =\n typeof outcome.applied === 'number' && typeof outcome.total === 'number' && outcome.total > 0\n ? i18next.t('ai-assistant.text.proposal-applied-count', {\n applied: outcome.applied,\n total: outcome.total,\n defaultValue: ' {applied} of {total}'\n })\n : ''\n\n /* ์‚ฌ์œ ๋Š” ํ˜ธ์ŠคํŠธ๊ฐ€ ์ค€ ์ฝ”๋“œ ๊ทธ๋Œ€๋กœ๋‹ค โ€” ๋ฌธ์žฅ์œผ๋กœ ๋ฐ”๊พธ์ง€ ์•Š๋Š”๋‹ค(ADR-0042). */\n const reason = outcome.errorCode ? ` (${outcome.errorCode})` : ''\n\n const verdict = i18next.t(`ai-assistant.verdict.${outcome.verdict}`, {\n defaultValue:\n outcome.verdict === 'accepted'\n ? 'done'\n : outcome.verdict === 'refused'\n ? 'refused'\n : outcome.verdict === 'declined'\n ? 'cancelled'\n : 'could not run'\n })\n\n return `${verdict}${counted}${reason}`\n }\n\n private onChoiceClick(choice: any, proposal: any, key: string) {\n if (choice.action === 'save') {\n this.dispatchEvent(\n new CustomEvent('assistant-choice', {\n detail: { action: 'save', choice, proposal, sessionId: this.sessionId },\n bubbles: true,\n composed: true\n })\n )\n this.executeProposal(proposal, key)\n return\n }\n\n if (choice.action === 'prompt' && choice.prompt) {\n this.input = choice.prompt\n this.dispatchEvent(\n new CustomEvent('assistant-choice', {\n detail: { action: 'prompt', choice, proposal, sessionId: this.sessionId },\n bubbles: true,\n composed: true\n })\n )\n void this.send()\n return\n }\n\n this.dispatchEvent(\n new CustomEvent('assistant-choice', {\n detail: { action: choice.action || 'custom', choice, proposal, sessionId: this.sessionId },\n bubbles: true,\n composed: true\n })\n )\n }\n\n /**\n * ์ œ์•ˆ ์‹๋ณ„ ํ‚ค โ€” ๊ฐ™์€ ์กฐ์น˜๋ฅผ ๋‘ ๋ฒˆ ์‹คํ–‰ํ•˜์ง€ ์•Š๋„๋ก **ํšจ๊ณผ**(๋ช…๋ นยท๋Œ€์ƒยท์ธ์ž)๋กœ๋งŒ ๋งŒ๋“ ๋‹ค.\n *\n * ์ธ์ž๋Š” **ํ‚ค ์ˆœ์„œ๋ฅผ ์ •๋ ฌ**ํ•ด ์ง๋ ฌํ™”ํ•œ๋‹ค: ๊ฐ™์€ ์ธ์ž๋ฅผ ๋‹ค๋ฅธ ์ˆœ์„œ๋กœ ๋ฐ›์•˜์„ ๋ฟ์ธ๋ฐ ํ‚ค๊ฐ€ ๋‹ฌ๋ผ์ง€๋ฉด\n * ํ•œ ์นด๋“œ๋ฅผ ์‹คํ–‰ํ•œ ๋’ค์—๋„ ๋‹ค๋ฅธ ์นด๋“œ๊ฐ€ ์‚ด์•„ ์žˆ์–ด **๊ฐ™์€ ๋ช…๋ น์ด ๋‘ ๋ฒˆ ๋‚˜๊ฐ„๋‹ค**(์‹ค์ œ๋กœ ๊ทธ๋žฌ๋‹ค).\n * ์„ค๋ช… ๋ฌธ๊ตฌ(labelยทreason)๋Š” ํ‚ค์— ๋„ฃ์ง€ ์•Š๋Š”๋‹ค โ€” ๋ฌธ๊ตฌ๊ฐ€ ๋‹ฌ๋ผ๋„ ๊ฐ™์€ ์กฐ์น˜๋‹ค.\n */\n private proposalKey(p: any): string {\n const stable = (v: any): string => {\n if (v === null || typeof v !== 'object') return JSON.stringify(v ?? null)\n if (Array.isArray(v)) return `[${v.map(stable).join(',')}]`\n return `{${Object.keys(v)\n .sort()\n .map(k => `${JSON.stringify(k)}:${stable(v[k])}`)\n .join(',')}}`\n }\n /*\n * ์„œ๋ฒ„๊ฐ€ ์‹ค์–ด ๋ณด๋‚ธ ํ‚ค๊ฐ€ ์ •๋ณธ์ด๋‹ค โ€” ๋ฌด์—‡์ด ๊ฐ™์€ ์กฐ์น˜์ธ๊ฐ€๋Š” ์ œ์•ˆ์„ ๋งŒ๋“  ์ชฝ์ด ์•ˆ๋‹ค(ADR-0061 ๊ฒฐ์ •\n * 7 ๋’ค ์ •๋ฆฌ). ์˜ˆ์ „์—๋Š” ์—ฌ๊ธฐ์„œ `command|instanceId|args` ๋กœ ๋‹ค์‹œ ์…Œ๋Š”๋ฐ, ๋ช…๋ น์ด ์—†๋Š” ์ œ์•ˆ(์„ ์–ธ ยท\n * ์ƒˆ ํŠธ์œˆ ์ดˆ์•ˆ)์€ ๊ทธ ์…‹์ด ๋ชจ๋‘ ๋น„์–ด **์„œ๋กœ ๋‹ค๋ฅธ ์ œ์•ˆ์ด ํ•œ ์นด๋“œ๋กœ ์ ‘ํ˜”๊ณ **, ํ•˜๋‚˜๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋‚˜๋จธ์ง€๊ฐ€\n * ํ•จ๊ป˜ ใ€Œ์š”์ฒญ๋จใ€์ด ๋๋‹ค.\n */\n if (typeof p?.key === 'string' && p.key) return p.key\n try {\n return `${p?.tool ?? ''}|${p?.command ?? ''}|${p?.instanceId ?? ''}|${stable(p?.args)}|${stable(p?.ops)}`\n } catch {\n return `${p?.tool ?? ''}|${p?.command ?? ''}|${p?.instanceId ?? ''}`\n }\n }\n\n /**\n * ์‹คํ–‰์€ ํ˜ธ์ŠคํŠธ๊ฐ€ ํ•œ๋‹ค โ€” ์ด ์ปดํฌ๋„ŒํŠธ๋Š” ๋„๋ฉ”์ธ(ํŠธ์œˆ ๋ช…๋ น ์ฑ„๋„)์„ ๋ชจ๋ฅธ๋‹ค.\n * ํ™•์ธ ๋Œ€ํ™”ยท๋ช…๋ น ์ „์†กยท๊ฒฐ๊ณผ ๊ธฐ๋ก์€ ํ˜ธ์ŠคํŠธ์˜ ๋ชซ์ด๊ณ , ์—ฌ๊ธฐ์„œ๋Š” ์ค‘๋ณต ํด๋ฆญ๋งŒ ๋ง‰๋Š”๋‹ค.\n */\n /**\n * ๋ˆ„๋ฅธ ์‹œ๊ฐ โ€” ใ€Œ๋ณด๋‚ด๋Š” ์ค‘ใ€ ์˜†์˜ ๊ฒฝ๊ณผ ์‹œ๊ฐ„์šฉ.\n *\n * ์‹œ๊ฐ„์œผ๋กœ ์‹คํŒจ๋ฅผ ํŒ์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค(ADR-0070 A12-a ๊ฒฐ์ • โ‘ก). ์•„๋Š” ์‚ฌ์‹ค์€ ใ€Œ์•„์ง ๋‹ต์„ ๋ฐ›์ง€ ๋ชปํ–ˆ๋‹คใ€\n * ํ•˜๋‚˜์ด๊ณ , ์‹œ๊ฐ„์ด ์ง€๋‚ฌ๋‹ค๊ณ  ์‹คํŒจ๋กœ ๋ฐ”๊พธ๋ฉด ๊ทธ๊ฒƒ์ด ์ง€์–ด๋‚ธ ์›์ธ์ด๋‹ค.\n */\n private proposalSentAt = new Map<string, number>()\n\n private elapsedTimer?: ReturnType<typeof setInterval>\n\n private async executeProposal(p: any, key: string) {\n if (this.sentProposals.has(key)) return\n this.sentProposals = new Set(this.sentProposals).add(key)\n this.proposalSentAt.set(key, Date.now())\n this._startElapsedTicker()\n\n /*\n * The server records the request first and answers whether this conversation has taken the proposal\n * already (ADR-0097 Q-D4 โ‘ฃ). Only a granted request reaches the host. A refused one - taken in another\n * window, or before a refresh - leaves the card to the rows; a failed one leaves it as it was, and the\n * error is said by the client's own error line. Either way the host is not asked.\n */\n if (this.sessionId) {\n let granted = false\n try {\n granted = await this.requestProposal(key)\n } catch {\n granted = false\n }\n if (!granted) {\n const left = new Set(this.sentProposals)\n left.delete(key)\n this.sentProposals = left\n this.proposalSentAt.delete(key)\n return\n }\n }\n\n this.dispatchEvent(\n new CustomEvent('assistant-proposal-execute', {\n /*\n * `proposalKey` ๋ฅผ ํ•จ๊ป˜ ์ค€๋‹ค โ€” ํ˜ธ์ŠคํŠธ๊ฐ€ `reportProposalOutcome` ์œผ๋กœ ๋‹ตํ•  ๋•Œ ์“ฐ๋Š” ์ด๋ฆ„์ด๋‹ค.\n * ํ˜ธ์ŠคํŠธ๊ฐ€ ์ž๊ธฐ ๊ทœ์น™์œผ๋กœ ํ‚ค๋ฅผ ๋‹ค์‹œ ๋งŒ๋“ค๋ฉด ์นด๋“œ๊ฐ€ ๋ชป ์ฐพ๋Š” ๋‹ต์ด ์ƒ๊ธด๋‹ค(์›๋ณธ์€ ํ•˜๋‚˜).\n */\n detail: { proposal: p, sessionId: this.sessionId, proposalKey: key },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private async requestProposal(key: string): Promise<boolean> {\n const result = await client.mutate({\n mutation: gql`\n mutation ($id: String!, $key: String!) {\n requestProposal(sessionId: $id, proposalKey: $key)\n }\n `,\n variables: { id: this.sessionId, key }\n })\n if (result.errors?.length) throw new Error(result.errors[0].message)\n return result.data?.requestProposal === true\n }\n\n /**\n * \"Check result\" on a card that was requested and never answered: the host is asked what happened\n * (`AssistantSurface.proposalOutcome`), never to run it again. The dock reports what it learns.\n */\n private checkProposal(p: any, key: string) {\n this.dispatchEvent(\n new CustomEvent('assistant-proposal-check', {\n detail: { proposal: p, sessionId: this.sessionId, proposalKey: key },\n bubbles: true,\n composed: true\n })\n )\n }\n\n /** Keys whose run was requested - from the conversation's rows, like the outcomes. */\n private get proposalRequests(): Set<string> {\n const requested = new Set<string>()\n for (const line of this.lines) {\n if (line.role !== 'system') continue\n const key = parseProposalRequestLine(line.content ?? '')\n if (key) requested.add(key)\n }\n return requested\n }\n\n /**\n * ํ˜ธ์ŠคํŠธ๊ฐ€ ๋ฌด์—‡์„ ํ–ˆ๋Š”์ง€ โ€” ๋Œ€ํ™”์— ๋‚จ์€ `system` ํ–‰์—์„œ ์ฝ๋Š”๋‹ค(ADR-0070 A12-a ๊ฒฐ์ • โ‘ ).\n *\n * ์นด๋“œ๊ฐ€ ์ž๊ธฐ ๊ธฐ์–ต์œผ๋กœ ์ƒํƒœ๋ฅผ ๋“ค๊ณ  ์žˆ์œผ๋ฉด ์ƒˆ๋กœ ๊ณ ์น˜๋Š” ์ˆœ๊ฐ„ ์‚ฌ๋ผ์ง€๊ณ , ๋‹ค๋ฅธ ์ฐฝ์—์„œ ์‹คํ–‰ํ•œ ๊ฒƒ์€\n * ์• ์ดˆ์— ๋ณด์ด์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ž˜์„œ ์ƒํƒœ์˜ ์ž๋ฆฌ๋Š” ์ด๋ ฅ์ด๋‹ค.\n */\n private get proposalOutcomes(): Map<string, ParsedProposalOutcome> {\n const outcomes = new Map<string, ParsedProposalOutcome>()\n for (const line of this.lines) {\n if (line.role !== 'system') continue\n const parsed = parseProposalOutcomeLine(line.content ?? '')\n if (parsed) outcomes.set(parsed.key, parsed)\n }\n return outcomes\n }\n\n /** ๊ฒฝ๊ณผ ์‹œ๊ฐ„์„ ๋ณด์ด๋Š” ๋™์•ˆ์—๋งŒ ๋ˆ๋‹ค โ€” ๋‹ต์ด ์˜ค๋ฉด ๋ฉˆ์ถ˜๋‹ค. */\n private _startElapsedTicker() {\n if (this.elapsedTimer) return\n this.elapsedTimer = setInterval(() => {\n const outcomes = this.proposalOutcomes\n const waiting = [...this.proposalSentAt.keys()].some(key => !outcomes.has(key))\n if (!waiting) {\n clearInterval(this.elapsedTimer)\n this.elapsedTimer = undefined\n return\n }\n this.requestUpdate()\n }, 1000)\n }\n\n /**\n * ์ ‘์ง€ ๊ฒฝ๊ณ  โ€” ๋‹ต์ด ์–ธ๊ธ‰ํ–ˆ์ง€๋งŒ **๊ทผ๊ฑฐ์— ์—†๋˜** ๋Œ€์ƒ์„ ์•Œ๋ฆฐ๋‹ค.\n *\n * ์™œ ๋‹ต์„ ์ง€์šฐ์ง€ ์•Š๋Š”๊ฐ€: ํŒ์ •์€ ์‹๋ณ„์ž ๋Œ€์กฐ๋ผ ํ™•์ •์ด ์•„๋‹ˆ๋‹ค(์˜ˆ: ์‚ฌ์šฉ์ž๊ฐ€ ํ™”๋ฉด์—์„œ ๋ณธ ์ด๋ฆ„์„\n * ๋Œ€ํ™” ๋ฐ–์—์„œ ์•Œ๊ณ  ๋งํ•œ ๊ฒฝ์šฐ). ๊ทธ๋ž˜์„œ ๋‹ต์€ ๊ทธ๋Œ€๋กœ ๋ณด์—ฌ์ฃผ๊ณ , ๊ฒ€์ฆ๋˜์ง€ ์•Š์•˜๋‹ค๋Š” ์‚ฌ์‹ค๋งŒ ๋ถ™์ธ๋‹ค โ€”\n * ์‚ฌ์šฉ์ž๊ฐ€ ๊ทธ ๋Œ€์ƒ์„ ์‹ค์ œ ์ž‘์—…์˜ ๊ทผ๊ฑฐ๋กœ ์‚ผ๊ธฐ ์ „์— ์•Œ์•„์•ผ ํ•˜๋Š” ์ •๋ณด๋‹ค.\n */\n private renderGroundingWarning(line: ChatLine) {\n const ids = line.groundingWarnings ?? []\n if (ids.length === 0) return nothing\n return html`\n <div class=\"grounding-warning\" role=\"note\">\n <md-icon>report</md-icon>\n <span>\n ${i18next.t('ai-assistant.text.ungrounded-mention', {\n defaultValue: 'Mentions an unverified target โ€” not present in the actual data:'\n })}\n <span class=\"ids\">${ids.join(', ')}</span>\n </span>\n </div>\n `\n }\n\n /**\n * \"AI ๊ฐ€ ์ด๋Ÿฐ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค\" fold-able ๋ฐ•์Šค.\n *\n * - ๊ธฐ๋ณธ ๋‹ซํž˜ (toolUsagesOpen=false). ํ—ค๋” ํด๋ฆญ ์‹œ toggle.\n * - ํŽผ์ณค์„ ๋•Œ ๋„๊ตฌ ๋ณ„๋กœ name + arguments + result + read/write ์ƒ‰์ƒ ๋ฐฐ์ง€.\n * - ๋””๋ฒ„๊ทธ / ์‹ ๋ขฐ๋„ ํ–ฅ์ƒ์šฉ โ€” ์‚ฌ์šฉ์ž๊ฐ€ \"์™œ ์ด๋ ‡๊ฒŒ ๋‹ตํ–ˆ์ง€\" ์˜๋ฌธ ๊ฐ€์งˆ ๋•Œ ์ฆ‰์‹œ ๊ฒ€์ฆ.\n */\n private renderToolUsages(idx: number, line: ChatLine) {\n const usages = line.toolUsages\n if (!usages || usages.length === 0) return nothing\n const open = !!line.toolUsagesOpen\n const readCount = usages.filter(u => u.kind === 'read').length\n const writeCount = usages.filter(u => u.kind === 'write').length\n const toolsLabel = i18next.t('ai-assistant.text.tools-used', { defaultValue: 'Tools used' })\n /* ๋ˆˆ์— ๊ฑธ๋ ค์•ผ ํ•˜๋Š” ๊ฒƒ์„ ๋จธ๋ฆฌ์ค„์— ์˜ฌ๋ฆฐ๋‹ค โ€” ๊ฑฐ์ ˆยท์ ‘ํž˜์ด ์žˆ์œผ๋ฉด ํŽผ์น˜๊ธฐ ์ „์— ๋ณด์ธ๋‹ค.\n * (์ด๋ฒˆ ์‚ฌ๊ณ ๋“ค์ด ์ „๋ถ€ ๊ทธ๊ฒƒ์ด์—ˆ๋‹ค: ์ธ์ž ๋น ์ง„ ํ˜ธ์ถœ์ด ๊ฑฐ์ ˆ๋๊ณ , ์ค‘๋ณต ์ œ์•ˆ์ด ์ ‘ํ˜”๋‹ค.) */\n const problems = usages.filter(u => u.outcome === 'rejected' || u.outcome === 'error').length\n const folded = usages.filter(u => u.outcome === 'folded').length\n return html`\n <div class=\"tool-usages ${open ? 'open' : ''} ${problems ? 'has-problem' : ''}\">\n <button\n class=\"tool-usages-header\"\n aria-expanded=${open}\n @click=${() => this.toggleToolUsages(idx)}>\n <md-icon class=\"tool-usages-icon\">${open ? 'expand_less' : 'account_tree'}</md-icon>\n <span class=\"tool-usages-summary\">\n <strong>${usages.length}</strong> ${toolsLabel}\n <span class=\"tool-usages-counts\">\n ยท read ${readCount} ยท write ${writeCount}${problems\n ? html` ยท <span class=\"tu-flag bad\">${i18next.t('ai-assistant.text.tool-rejected-count', {\n count: problems,\n defaultValue: 'rejected {count}'\n })}</span>`\n : nothing}${folded\n ? html` ยท <span class=\"tu-flag\">${i18next.t('ai-assistant.text.tool-folded-count', {\n count: folded,\n defaultValue: 'folded {count}'\n })}</span>`\n : nothing}\n </span>\n </span>\n <md-icon class=\"tool-usages-chevron\">${open ? 'expand_less' : 'expand_more'}</md-icon>\n </button>\n ${open\n ? html`\n <ol class=\"tool-usages-list\">\n ${usages.map((u, i) => this.renderToolStep(idx, u, i, usages[i - 1]))}\n </ol>\n `\n : nothing}\n </div>\n `\n }\n\n /** ์‹œ์Šคํ…œ ๊ธฐ๋ก ํŽผ์น˜๊ธฐ/์ ‘๊ธฐ โ€” ๊ณ์ค„์ด ๊ธธ์–ด๋„ ๋Œ€ํ™”๊ฐ€ ๊ฐ€๋ ค์ง€์ง€ ์•Š๊ฒŒ. */\n private toggleSystemNote(idx: number) {\n const next = [...this.lines]\n const line = next[idx]\n if (!line) return\n next[idx] = { ...line, systemOpen: !line.systemOpen }\n this.lines = next\n }\n\n /**\n * ํŒ๋‹จ ๊ณผ์ •์˜ ํ•œ ๋‹จ๊ณ„ โ€” ํ„ด ๊ตฌ๋ถ„ ยท ๋„๊ตฌ ยท ๋ฐฐ์ง€ ยท **ํ•œ ์ค„ ์š”์•ฝ**.\n *\n * ์›๋ณธ JSON ์„ ์ฒ˜์Œ๋ถ€ํ„ฐ ํŽผ์ณ ๋‘๋ฉด ๋ˆˆ์ด ํ๋ ค์ ธ ์ •์ž‘ ์ค‘์š”ํ•œ ๊ฒƒ(๋ฌด์—‡์ด ๊ฑฐ์ ˆ๋๋Š”์ง€, ๋ฌด์—‡์ด ์ ‘ํ˜”๋Š”์ง€)์ด\n * ์•ˆ ๋ณด์ธ๋‹ค. ํ•œ ์ค„๋กœ ์ค„์ด๊ณ  ์›๋ณธ์€ ํ•ญ๋ชฉ๋ณ„๋กœ ๋ˆŒ๋Ÿฌ์„œ ๋ณธ๋‹ค.\n */\n private renderToolStep(lineIdx: number, u: any, i: number, prev: any) {\n const outcome = u.outcome ?? 'ok'\n const openKey = `${lineIdx}:${i}`\n const open = this.openToolSteps.has(openKey)\n /* ํ„ด์ด ๋ฐ”๋€Œ๋ฉด ๊ตฌ๋ถ„์„  โ€” \"ํ•œ ํ„ด ์•ˆ์—์„œ ์ •์ •ํ–ˆ๋Š”์ง€, ๋‹ค์Œ ํ„ด์—์„œ ํ–ˆ๋Š”์ง€\" ๊ฐ€ ์ง„๋‹จ์˜ ์ ˆ๋ฐ˜์ด๋‹ค. */\n const newTurn = typeof u.iter === 'number' && (!prev || prev.iter !== u.iter)\n return html`\n ${newTurn\n ? html`<li class=\"tu-turn\">\n ${i18next.t('ai-assistant.text.tool-turn', { n: (u.iter ?? 0) + 1, defaultValue: 'decision {n}' })}\n </li>`\n : nothing}\n <li class=\"tool-usage-item kind-${u.kind} outcome-${outcome}\">\n <div class=\"tool-usage-head\" @click=${() => this.toggleToolStep(openKey)}>\n <span class=\"tool-usage-step\">${i + 1}.</span>\n <span class=\"tool-usage-name\">${u.name}</span>\n <span class=\"tu-badge ${outcome}\">${this.outcomeLabel(outcome, u.kind)}</span>\n <span class=\"tu-line\" title=${this.stepSummary(u)}>${this.stepSummary(u)}</span>\n <md-icon class=\"tu-more\">${open ? 'expand_less' : 'expand_more'}</md-icon>\n </div>\n ${open\n ? html`\n ${u.arguments && Object.keys(u.arguments).length > 0\n ? html`<pre class=\"tool-usage-args\">${this.formatJson(u.arguments)}</pre>`\n : nothing}\n <pre class=\"tool-usage-result\">${this.formatJson(u.result)}</pre>\n `\n : nothing}\n </li>\n `\n }\n\n /**\n * ๋ฐฐ์ง€ ๋ฌธ๊ตฌ โ€” ์ฝ”๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ ์‚ฌ๋žŒ ๋ง๋กœ.\n *\n * ๋๊นŒ์ง€ ๊ฐ„ ํ˜ธ์ถœ(ok)์€ ๋ฌด์—‡์„ ํ–ˆ๋Š”์ง€๋กœ ๋ถ€๋ฅธ๋‹ค โ€” ์ฝ๊ธฐ๋Š” ใ€Œ์กฐํšŒใ€, ์“ฐ๊ธฐ๋Š” ใ€Œ์ ์šฉใ€. ์ „์—๋Š” ok ๊ฐ€\n * ์–ธ์ œ๋‚˜ ใ€Œ์กฐํšŒใ€์˜€์–ด์„œ, ๋ณด๋“œ๋ฅผ ๋ฐ”๊พผ addComponent ๋„ ใ€Œreadใ€ ๋ฐฐ์ง€๋ฅผ ๋‹ฌ์•˜๋‹ค(๋จธ๋ฆฌ์ค„์€ write 2 ๋ผ๊ณ \n * ์„ธ๋Š”๋ฐ).\n */\n private outcomeLabel(outcome: string, kind?: string): string {\n if (outcome === 'ok' && kind === 'write') {\n return i18next.t('ai-assistant.text.outcome-applied', { defaultValue: 'applied' })\n }\n const map: Record<string, [string, string]> = {\n ok: ['ai-assistant.text.outcome-ok', 'read'],\n rejected: ['ai-assistant.text.outcome-rejected', 'rejected'],\n queued: ['ai-assistant.text.outcome-queued', 'to apply'],\n proposed: ['ai-assistant.text.outcome-proposed', 'proposed'],\n folded: ['ai-assistant.text.outcome-folded', 'duplicate'],\n error: ['ai-assistant.text.outcome-error', 'error']\n }\n const [key, fallback] = map[outcome] ?? map.ok\n return i18next.t(key, { defaultValue: fallback })\n }\n\n /**\n * ๊ฒฐ๊ณผ ํ•œ ์ค„ โ€” ๋ฌด์—‡์„ ์–ป์—ˆ๋Š”์ง€/์™œ ๋ง‰ํ˜”๋Š”์ง€๋งŒ. ๋ชฉ๋ก์—์„œ ํ›‘์–ด ์ฝ์„ ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.\n * ๊ฑฐ์ ˆ์ด๋ฉด ์‚ฌ์œ ๋ฅผ, ์กฐํšŒ๋ฉด ๋Œ€ํ‘œ์ ์ธ ๊ฐœ์ˆ˜๋ฅผ, ์ œ์•ˆ์ด๋ฉด ๋ฌด์—‡์„ ์ œ์•ˆํ–ˆ๋Š”์ง€.\n */\n private stepSummary(u: any): string {\n const r = u?.result\n if (!r || typeof r !== 'object') return typeof r === 'string' ? r.slice(0, 80) : ''\n if (u.outcome === 'rejected' || u.outcome === 'error') {\n return String(r.errorCode || r.error || r.issues?.[0]?.message || '').slice(0, 80)\n }\n if (u.outcome === 'proposed' || u.outcome === 'folded') {\n return [r.command, r.args && Object.keys(r.args).length ? this.formatJson(r.args) : '']\n .filter(Boolean)\n .join(' ')\n .slice(0, 80)\n }\n /* ์กฐํšŒ ๊ฒฐ๊ณผ โ€” ๋ฐฐ์—ด ๊ธธ์ด๊ฐ€ ์žˆ๋Š” ํ•„๋“œ๋ฅผ ๊ณจ๋ผ \"๋ฌด์—‡์ด ๋ช‡ ๊ฐœ\" ๋กœ ์š”์•ฝํ•œ๋‹ค(์ „์ฒด ๋คํ”„ ๊ธˆ์ง€). */\n const counts = Object.keys(r)\n .filter(k => Array.isArray(r[k]) && r[k].length > 0)\n .slice(0, 2)\n .map(k => `${k} ${r[k].length}`)\n if (counts.length) return counts.join(' ยท ')\n const keys = Object.keys(r).slice(0, 4)\n return keys.map(k => (typeof r[k] === 'object' ? k : `${k} ${r[k]}`)).join(' ยท ').slice(0, 80)\n }\n\n private toggleToolStep(key: string) {\n const next = new Set(this.openToolSteps)\n next.has(key) ? next.delete(key) : next.add(key)\n this.openToolSteps = next\n }\n\n private toggleToolUsages(idx: number) {\n const next = [...this.lines]\n const line = next[idx]\n if (!line) return\n next[idx] = { ...line, toolUsagesOpen: !line.toolUsagesOpen }\n this.lines = next\n }\n\n private formatJson(value: any): string {\n try {\n return JSON.stringify(value, null, 2)\n } catch {\n return String(value)\n }\n }\n\n // โ”€โ”€ Per-message actions โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\n private async copyMessage(idx: number, content: string) {\n try {\n // ํด๋ฆฝ๋ณด๋“œ์—๋Š” marker ์ œ๊ฑฐ๋œ ๊นจ๋—ํ•œ ํ…์ŠคํŠธ\n await navigator.clipboard.writeText(stripMentionRefids(content))\n this.copiedIdx = idx\n this.showToast(i18next.t('ai-assistant.text.copied'))\n setTimeout(() => {\n if (this.copiedIdx === idx) this.copiedIdx = undefined\n }, 1500)\n } catch {\n // clipboard ๊ถŒํ•œ ์—†๊ฑฐ๋‚˜ ๋น„-secure context โ€” ์กฐ์šฉํžˆ ๋ฌด์‹œ\n }\n }\n\n private showToast(message: string) {\n this.toastMessage = message\n setTimeout(() => {\n if (this.toastMessage === message) this.toastMessage = undefined\n }, 1500)\n }\n\n /**\n * ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€ ํŽธ์ง‘ โ€” ํ•ด๋‹น ๋ฉ”์‹œ์ง€ + ์ดํ›„ ๋ชจ๋‘ UI ์—์„œ ์ œ๊ฑฐํ•˜๊ณ  ์ž…๋ ฅ์ฐฝ์— ์ฑ„์›€.\n * ์„œ๋ฒ„ ์˜์† history ๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€ (๋‹ค์Œ send ์‹œ ์ƒˆ ๋ฉ”์‹œ์ง€๋กœ ์ถ”๊ฐ€).\n */\n /** ํŽธ์ง‘์œผ๋กœ ์ ‘์€ ์ง€์  โ€” ๋งˆ์ง€๋ง‰์œผ๋กœ ๋‚จ๊ธด **์„œ๋ฒ„ ๋ฉ”์‹œ์ง€ id**. ์„œ๋ฒ„ ์ด๋ ฅ์€ ์œ ์ง€๋˜๋ฏ€๋กœ ์ด๊ฑธ ํ•จ๊ป˜\n * ๋ณด๋‚ด์•ผ ์ ‘์€ ๋ง์ด ์—์ด์ „ํŠธ ๋ฌธ๋งฅ์— ๋˜์‚ด์•„๋‚˜์ง€ ์•Š๋Š”๋‹ค(์„œ๋ฒ„ buildLlmHistory ๊ฐ€ ๊ทธ ๋’ค๋ฅผ ๋ฒ„๋ฆฐ๋‹ค). */\n private _truncateAfterId?: string\n\n private editUserMessage(idx: number, content: string) {\n // textarea ์—๋Š” marker ์ œ๊ฑฐ๋œ ๊นจ๋—ํ•œ ํ…์ŠคํŠธ โ€” ์‚ฌ์šฉ์ž๊ฐ€ raw `{refid:N}` ๋ณด์ง€ ์•Š๊ฒŒ.\n // ๋‹ค์‹œ send ์‹œ popup pickedMentions ๊ธฐ๋ฐ˜์œผ๋กœ marker ์žฌ์ฃผ์ž….\n const cleaned = stripMentionRefids(content)\n /* ๋‚จ๊ธธ ๋งˆ์ง€๋ง‰ ์ค„์˜ ์„œ๋ฒ„ id โ€” ์—†์œผ๋ฉด(์•„์ง ์˜์† ์•ˆ ๋œ ์ค„๋ฟ) ์ง€์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค(์„œ๋ฒ„๊ฐ€ ์ „๋ถ€ ์œ ์ง€). */\n this._truncateAfterId = this.lines\n .slice(0, idx)\n .reverse()\n .find(l => !!l.id)?.id\n this.lines = this.lines.slice(0, idx)\n this.input = cleaned\n requestAnimationFrame(() => {\n const ta = this.renderRoot.querySelector('textarea') as HTMLTextAreaElement | null\n ta?.focus()\n ta?.setSelectionRange(cleaned.length, cleaned.length)\n })\n }\n\n /**\n * AI ์‘๋‹ต ์žฌ์ƒ์„ฑ โ€” ํ•ด๋‹น assistant ๋ฉ”์‹œ์ง€ + ์ดํ›„ ์ œ๊ฑฐํ•˜๊ณ , ์ง์ „ user ๋ฉ”์‹œ์ง€๋ฅผ ๋‹ค์‹œ send.\n */\n private async regenerateAssistant(idx: number) {\n if (this.busy) return\n // ์ง์ „ user ๋ฉ”์‹œ์ง€ ์ฐพ๊ธฐ\n let userIdx = idx - 1\n while (userIdx >= 0 && this.lines[userIdx].role !== 'user') userIdx--\n if (userIdx < 0) return\n // textarea ์—๋Š” marker ์ œ๊ฑฐ๋œ ๊นจ๋—ํ•œ ๋ณธ๋ฌธ. send() ๊ฐ€ ๋ณธ๋ฌธ์„ ๋‹ค์‹œ line ์œผ๋กœ push ํ•˜๋Š”๋ฐ,\n // pickedMentions ๋Š” ์ง์ „ send ์—์„œ ๋น„์›Œ์กŒ์œผ๋ฏ€๋กœ ์ƒˆ line ์—๋Š” marker ์—†์Œ โ€” ํด๋ฆญ ์‹œ\n // runtime fallback resolver ๊ฐ€ ์ฒ˜๋ฆฌ. (์˜์†๋œ ์›๋ณธ user ๋ฉ”์‹œ์ง€์˜ marker ๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€)\n const userContent = stripMentionRefids(this.lines[userIdx].content)\n // assistant ๋ฉ”์‹œ์ง€ + ์ดํ›„ ์ œ๊ฑฐ\n this.lines = this.lines.slice(0, idx)\n this.input = userContent\n await this.send()\n }\n\n // โ”€โ”€ Patch revert โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\n private onRevertClick(patchId: string) {\n if (this.revertedPatchIds.has(patchId)) return\n this.revertedPatchIds = new Set([...this.revertedPatchIds, patchId])\n // ํ˜ธ์ŠคํŠธ (board-modeller-page) ์—๊ฒŒ revert ์š”์ฒญ โ€” ํ˜ธ์ŠคํŠธ๊ฐ€ snapshot ๋ณต์› + ์„œ๋ฒ„ mutation ํ˜ธ์ถœ\n this.dispatchEvent(\n new CustomEvent('board-edit-revert', {\n detail: { patchId },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private async send() {\n if (this.sendBlocked) { this.errorMessage = this.sendBlocked; return }\n const text = this.input.trim()\n const attachmentsToSend = [...this.attachments]\n if ((!text && attachmentsToSend.length === 0) || this.busy) return\n this.attachments = []\n /* What was written wide is sent to be answered - the conversation comes back to show it. */\n this.composerWide = false\n this.previewAttachmentId = null\n\n const promptText = text || (attachmentsToSend.length > 0\n ? (attachmentsToSend[0].type.startsWith('image/')\n ? i18next.t('ai-assistant.text.attached-image-ask', { defaultValue: 'here is an image โ€” go by it.' })\n : i18next.t('ai-assistant.text.attached-file-ask', { defaultValue: 'here is a file โ€” take a look.' }))\n : '')\n if (!this.sessionId && this.prepareSession) {\n this.busy = true\n try {\n await this.prepareSession(id => { this.adoptingSession = true; this.sessionId = id })\n await this.updateComplete\n } catch (error) {\n this.errorMessage = error instanceof Error ? error.message : String(error)\n this.busy = false\n return\n }\n this.busy = false\n }\n\n /* The neutral door takes stored files by id: upload them to the conversation first (ยง9-2). */\n let attachmentIds: string[] | undefined\n if (attachmentsToSend.length > 0 && this.usesAttachmentPolicy) {\n if (!this.sessionId) {\n this.errorMessage = i18next.t('ai-assistant.text.attachments-need-session', { defaultValue: 'attachments need a saved conversation.' })\n this.attachments = attachmentsToSend\n return\n }\n this.busy = true\n try {\n const uploaded = await client.mutate({\n mutation: ATTACH_TO_CONVERSATION_MUTATION,\n variables: { sessionId: this.sessionId, files: attachmentsToSend.map(a => a.file), kind: this.conversation.kind },\n /* The shell's client sends multipart only when asked - without it a File travels as {} and is refused. */\n context: { hasUpload: true }\n })\n if (uploaded.errors?.length) throw new Error(uploaded.errors.map(error => error.message).join('\\n'))\n attachmentIds = (uploaded.data?.attachToConversation ?? []).map((file: any) => file.id)\n } catch (error) {\n this.errorMessage = error instanceof Error ? error.message : String(error)\n this.attachments = attachmentsToSend\n this.busy = false\n return\n }\n this.busy = false\n }\n\n let requestContext: AssistantRequestContext\n let liveBoard: any\n let requestBase: any\n try {\n const provided = this.contextProvider?.() || {}\n requestContext = structuredClone({ hostContext: this.conversation.hostContext, ...provided })\n liveBoard = structuredClone(this.boardProvider ? this.boardProvider() : this.currentBoard)\n requestBase = { version: 1, sessionId: this.sessionId, hostContext: requestContext.hostContext,\n modelFingerprint: assistantModelFingerprint(liveBoard) }\n } catch (error) {\n this.errorMessage = error instanceof Error ? error.message : String(error)\n this.attachments = attachmentsToSend\n return\n }\n\n // pickedMentions / pickedUserMentions ์—์„œ ํ˜„์žฌ ํ…์ŠคํŠธ์— ์‹ค์ œ #/@ token ์œผ๋กœ\n // ๋“ฑ์žฅํ•˜๋Š” ๊ฒƒ๋งŒ ์ถ”์ถœ โ€” ์ง€์šด ํ† ํฐ ์ œ์™ธ. inline ๋งˆ์ปค๋กœ content ์— ์ฃผ์ž….\n const mentions: Array<{ token: string; refid: number }> = []\n for (const [token, refid] of this.pickedMentions.entries()) {\n if (promptText.includes(`#${token}`)) mentions.push({ token, refid })\n }\n const userMentions: Array<{ token: string; userId: string }> = []\n for (const [token, userId] of this.pickedUserMentions.entries()) {\n if (promptText.includes(`@${token}`)) userMentions.push({ token, userId })\n }\n let enrichedContent = injectMentionRefids(promptText, mentions)\n enrichedContent = injectMentionUserIds(enrichedContent, userMentions)\n\n // optimistic ๋ผ์ธ์— ์ž„์‹œ ํ•ธ๋“ค โ€” ๋ฐฉ์†ก ์—์ฝ”์™€์˜ reconcile ์„ index ๋น„์˜์กด์œผ๋กœ.\n const userLocalId = `local-${++this._localSeq}-u`\n const asstLocalId = `local-${++this._localSeq}-a`\n\n this.lines = [\n ...this.lines,\n {\n role: 'user',\n content: enrichedContent,\n attachments: attachmentsToSend.map(a => ({\n name: a.name,\n size: a.size,\n type: a.type,\n url: a.url,\n base64: a.base64\n })),\n _localId: userLocalId,\n senderEmail: this._myEmail\n }\n ]\n this.input = ''\n this.busy = true\n this.errorMessage = undefined\n\n // ๊ฐ€์งœ pending ์‘๋‹ต ํ‘œ์‹œ (UX ๋ถ€๋“œ๋Ÿฝ๊ฒŒ)\n this.lines = [...this.lines, { role: 'assistant', content: '', pending: true, _localId: asstLocalId }]\n\n try {\n if (attachmentsToSend.length > 0 && !attachmentIds) {\n requestContext.hostContext = {\n ...requestContext.hostContext,\n attachments: attachmentsToSend.map(a => ({\n name: a.name,\n size: a.size,\n mediaType: a.type,\n data: a.base64\n })),\n image: attachmentsToSend.find(a => a.type.startsWith('image/'))\n ? {\n name: attachmentsToSend.find(a => a.type.startsWith('image/'))!.name,\n mediaType: attachmentsToSend.find(a => a.type.startsWith('image/'))!.type,\n data: attachmentsToSend.find(a => a.type.startsWith('image/'))!.base64\n }\n : undefined\n }\n }\n // LLM ์œผ๋กœ ๋ณด๋‚ผ history โ€” user/assistant ๋งŒ (system ์€ ๋ฐฑ์—”๋“œ๊ฐ€ ์ž๋™ ํ•ฉ๋ฅ˜).\n // pending placeholder ์™€ system ์€ ์ œ์™ธ (index ๋น„์˜์กด โ€” ๋ฐฉ์†ก append ์™€ ๋ฌด๊ด€).\n const history = this.lines\n .filter(l => !l.pending && l._localId !== asstLocalId && l.role !== 'system')\n .map(l => ({ role: l.role, content: l.content }))\n\n // ๋ผ์ด๋ธŒ ๋ณด๋“œ ์šฐ์„  โ€” ํ˜ธ์ŠคํŠธ์˜ ์บ”๋ฒ„์Šค๊ฐ€ ์‚ฌ์šฉ์ž ์ˆ˜์ž‘์—… ํŽธ์ง‘์„ ๋“ค๊ณ  ์žˆ์„ ์ˆ˜ ์žˆ์Œ.\n // boardProvider ๊ฐ€ ์žˆ์œผ๋ฉด send ์‹œ์ ์— ๊ทธ๊ฒƒ์„ pull, ์—†์œผ๋ฉด ์ •์  currentBoard.\n // mentions ๋Š” ์œ„์—์„œ ์ด๋ฏธ ๊ณ„์‚ฐํ•ด user line ์— thread โ€” ๊ทธ๋Œ€๋กœ mutation ์ž…๋ ฅ์œผ๋กœ ์žฌ์‚ฌ์šฉ.\n const neutral = this.conversation.chatEndpoint === 'assistantChat'\n const result = await client.mutate({\n mutation: neutral ? ASSISTANT_CHAT_MUTATION : BOARD_AI_CHAT_MUTATION,\n variables: {\n input: neutral\n ? buildAssistantChatInput({\n sessionId: this.sessionId,\n history,\n mode: { kind: this.conversation.kind!, target: this.conversation.target },\n truncateAfterMessageId: this._truncateAfterId,\n hostContext: requestContext.hostContext,\n attachmentIds\n })\n : buildChatMutationInput({\n sessionId: this.sessionId,\n history,\n liveBoard,\n scopes: this.scopes,\n truncateAfterMessageId: this._truncateAfterId,\n hostContext: requestContext.hostContext,\n /* The board door still takes its categories from the element โ€” it declares no mode. */\n toolCategories: this.toolCategories,\n boardTools: this.boardTools,\n requireGroundingTools: this.requireGroundingTools,\n knownTypes: this.knownTypes,\n categories: this.categories,\n componentSchemas: this.componentSchemas,\n selectedRefids: this.selectedRefids ?? [],\n mentions,\n /* With a declared mode the server owns persona and tools; the board door still carries the board. */\n mode: this.conversation.kind ? { kind: this.conversation.kind, target: this.conversation.target } : undefined\n })\n }\n })\n\n /*\n * Apollo๊ฐ€ errorPolicy: all ๋กœ ์‘๋‹ตํ•˜๋ฉด data๋Š” ๋น„๊ณ  GraphQL ์˜ค๋ฅ˜๋Š” result.errors ์— ๋‚จ๋Š”๋‹ค.\n * ์ด๋ฅผ ํ™•์ธํ•˜์ง€ ์•Š์œผ๋ฉด ์‹ค์ œ ์„œ๋ฒ„ ์‚ฌ์œ (์˜ˆ: Figure ํ›„๋ณด์˜ ๋งˆ์ง€๋ง‰ ๊ฒ€์ฆ ์‚ฌ์œ )๋ฅผ ๋ฒ„๋ฆฌ๊ณ \n * \"์‘๋‹ต์ด ๋น„์–ด์žˆ์Šต๋‹ˆ๋‹ค\"๋ผ๋Š” ๊ฑฐ์ง“ ์˜ค๋ฅ˜๋ฅผ ๋ณด์—ฌ ์ค€๋‹ค.\n */\n if (result.errors?.length) {\n throw new Error(result.errors.map(error => error.message).join('\\n'))\n }\n\n const out = neutral ? result.data?.assistantChat : result.data?.boardAIChat\n if (!out) throw new Error(i18next.t('ai-assistant.text.empty-response'))\n\n /* ๋Œ€ํ™”๊ฐ€ ๊ธธ์–ด์กŒ๋‹ค๋Š” ์„œ๋ฒ„ ๋ณด๊ณ  โ€” ๋‹ซ์ง€ ์•Š์•˜๋‹ค๋ฉด ์•ˆ๋‚ด๋ฅผ ๋„์šด๋‹ค. */\n this.historyFolded = out.historyFolded ?? undefined\n\n // ์ „์†ก ์„ฑ๊ณต โ€” picks ์ •๋ฆฌ (๋‹ค์Œ ๋ฉ”์‹œ์ง€๋ถ€ํ„ฐ๋Š” ์ƒˆ picks ๋งŒ)\n this.pickedMentions.clear()\n this.pickedUserMentions.clear()\n\n // optimistic ๋ผ์ธ์„ ์„œ๋ฒ„ id ๋กœ reconcile (๋ฐฉ์†ก ์—์ฝ”์™€ ์ค‘๋ณต ๋ฐฉ์ง€, index ๋น„์˜์กด).\n // ์‚ฌ์šฉ์ž ๋ผ์ธ: enrich ๋œ ๋ณธ๋ฌธ ์œ ์ง€, id ๋งŒ ๋ถ€์—ฌ. AI ๋ผ์ธ: pending โ†’ ์‹ค์ œ ์‘๋‹ต.\n this._reconcileSentLine(userLocalId, out.userMessageId, {})\n this._reconcileSentLine(asstLocalId, out.assistantMessageId, {\n role: 'assistant',\n content: out.reply,\n patchSummary: out.patch?.summary,\n followUp: out.followUp || undefined,\n patchId: out.patchId || undefined,\n toolUsages: Array.isArray(out.toolUsages) ? out.toolUsages : undefined,\n groundingWarnings: Array.isArray(out.groundingWarnings) ? out.groundingWarnings : undefined,\n proposals: Array.isArray(out.proposals) ? out.proposals : undefined,\n pending: false\n })\n\n // ์ œ์•ˆ ์ž๋™ ํ”„๋ฆฌ๋ทฐ ์ „ํŒŒ (3D ๋ทฐ์–ด ์ž๋™ ๋ฐ˜์˜)\n if (Array.isArray(out.proposals) && out.proposals.length > 0) {\n for (const p of out.proposals) {\n if (p?.source || p?.autoStage) {\n this.dispatchEvent(\n new CustomEvent('assistant-proposal-preview', {\n detail: { proposal: p, sessionId: out.sessionId },\n bubbles: true,\n composed: true\n })\n )\n }\n }\n }\n\n // ํ˜ธ์ŠคํŠธ๋กœ patch ์ด๋ฒคํŠธ ์ „ํŒŒ\n if (out.patch) {\n this.dispatchEvent(\n new CustomEvent('scene-edit-patch', {\n detail: {\n patch: out.patch,\n requestBase,\n summary: out.patch.summary,\n confidence: out.patch.confidence,\n patchId: out.patchId,\n sessionId: out.sessionId\n },\n bubbles: true,\n composed: true\n })\n )\n }\n // ํ˜ธ์ŠคํŠธ๋กœ ephemeral scene ์กฐ์ž‘ actions ์ „ํŒŒ (selection / view / mode)\n if (Array.isArray(out.actions) && out.actions.length > 0) {\n this.dispatchEvent(\n new CustomEvent('scene-action-execute', {\n detail: { actions: out.actions, sessionId: out.sessionId, requestBase },\n bubbles: true,\n composed: true\n })\n )\n }\n if (out.followUp) {\n this.dispatchEvent(\n new CustomEvent('chat-followup', {\n detail: { question: out.followUp },\n bubbles: true,\n composed: true\n })\n )\n }\n } catch (e: any) {\n // pending(AI) placeholder ๋งŒ ์ œ๊ฑฐ โ€” ์‚ฌ์šฉ์ž ๋ผ์ธ์€ ๋ณด์กด(์žฌ์‹œ๋„). index ๋น„์˜์กด.\n this.lines = this.lines.filter(l => l._localId !== asstLocalId)\n this.errorMessage = e?.message ?? String(e)\n this.lastFailedInput = text\n } finally {\n this.busy = false\n }\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ox-assistant-chat': OxAssistantChat\n }\n}\n"]}
1
+ {"version":3,"file":"assistant-chat.js","sourceRoot":"","sources":["../../client/components/assistant-chat.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * <ox-assistant-chat> โ€” AI ๋„์šฐ๋ฏธ ์ฑ„ํŒ… ์ปดํฌ๋„ŒํŠธ (Lit).\n *\n * ์ž…๋ ฅ:\n * - sessionId: ์˜์† ChatSession ์‹๋ณ„์ž (์—†์œผ๋ฉด ad-hoc ๋ชจ๋“œ, ๋ฉ”์‹œ์ง€ ์˜์† ์•ˆ ๋จ)\n * - currentBoard: ํ˜„์žฌ BoardModel JSON (ํ˜ธ์ŠคํŠธ๊ฐ€ ๋™๊ธฐํ™”)\n * - scopes / knownTypes / categories: ๋„๋ฉ”์ธ ์ปจํ…์ŠคํŠธ\n *\n * ์ถœ๋ ฅ (์ด๋ฒคํŠธ):\n * - `scene-edit-patch` { detail: { patch, summary, confidence, patchId } }\n * ํ˜ธ์ŠคํŠธ๊ฐ€ ๋ฐ›์•„์„œ ๋ณด๋“œ ๋ชจ๋ธ์— ์ ์šฉ (applyScenePatch from @operato/scene-ops).\n * - `chat-followup` { detail: { question } }\n *\n * ๋ชจ๋“œ ์ „ํ™˜์€ ์ปจํ…Œ์ด๋„ˆ (์›Œํฌ์ŠคํŽ˜์ด์Šค) ์˜ ์ฑ…์ž„. ์ด ์ปดํฌ๋„ŒํŠธ๋Š” ์ž์ฒด๋กœ ํ’€ ์ฑ„ํŒ… UX.\n */\nimport '@material/web/icon/icon.js'\nimport './assistant-session-toolbar.js'\nimport { assistantAutoAskKey, assistantDraftDecision, assistantModelFingerprint, type AssistantRequestContext } from '../utils/assistant-request-context.js'\n\nimport { LitElement, css, html, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js'\nimport { client } from '@operato/graphql'\nimport { auth } from '@things-factory/auth-base/dist-client/index.js'\nimport { i18next, localize } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\nimport gql from 'graphql-tag'\n\nimport {\n renderMarkdown,\n injectMentionRefids,\n injectMentionUserIds,\n stripMentionRefids\n} from './markdown.js'\nimport { acceptOf, chatAttachmentUrl, refuseAttachments, textCharsOf } from '../utils/attachment-policy.js'\nimport { pastedTableFile } from '../utils/pasted-table.js'\nimport { appendWords, composerHeight, composerKeyAction, sendShortcut, tableAsWords } from '../utils/composer-frame.js'\nimport { readSpreadsheet, spreadsheetKindOf, type SpreadsheetRefusal } from '../utils/spreadsheet-text.js'\nimport { entryReviewAddress, offersWorkspaceReview } from '../utils/entry-workspace.js'\nimport { buildAssistantChatInput, buildChatMutationInput } from './chat-input-builder.js'\nimport { receiveRemoteMessage, reconcileSentLine, remoteMessageToLine } from './chat-echo-dedup.js'\nimport './mention-popup.js'\nimport {\n buildMentionCandidates,\n buildCatalogCandidates,\n buildSlashCandidates,\n buildUserCandidates,\n extractMentionContext,\n filterMentionCandidates,\n applyMentionSelection,\n resolveMentionToken,\n type MentionCandidate,\n type FilterResult\n} from './mention-popup.js'\n/*\n * ๊ธฐ๋ณธ ์นดํƒˆ๋กœ๊ทธยท์Šฌ๋ž˜์‹œ ๋ชฉ๋ก์€ **ํ˜ธ์ŠคํŠธ๊ฐ€ ๋„ฃ๋Š”๋‹ค** (2026-09-10).\n *\n * ์—ฌ๊ธฐ์„œ `./default-catalog-entries.js` ๋ฅผ ์ง์ ‘ import ํ•˜๊ณ  ์žˆ์—ˆ๋‹ค. ๊ทธ ๋‘ ํŒŒ์ผ์€ ๋ณด๋“œ ์ €์ž‘์˜\n * ๋ชฉ๋ก์ด๊ณ , ๊ทธ๋ž˜์„œ ์ด ๋Œ€ํ™”๋ฉด์ด ๋ณด๋“œ ํŽธ์ง‘๊ธฐ ์—†์ด๋Š” ์„ค ์ˆ˜ ์—†์—ˆ๋‹ค โ€” ์ด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ค‘๋ฆฝ ํŒจํ‚ค์ง€๋กœ\n * ์˜ค์ง€ ๋ชปํ•œ ์œ ์ผํ•œ ์ด์œ ๊ฐ€ ๊ทธ ๋‘ ์ค„์ด์—ˆ๋‹ค.\n *\n * ๋“ฑ๋กํ•˜๋Š” ์ชฝ์ด ์ฃผ์ธ์ด๋ผ๋Š” ๊ทœ์•ฝ์„ ๋”ฐ๋ฅธ๋‹ค(`registerToolCategory` ์™€ ๊ฐ™์€ ๋ชจ์–‘): `board-ai` ๋ฅผ\n * import ํ•˜๋ฉด ๊ทธ ํŒจํ‚ค์ง€๊ฐ€ ์ž๊ธฐ ๊ธฐ๋ณธ๊ฐ’์„ ๋„ฃ๊ณ , ์•ˆ ํ•˜๋ฉด ๋น„์–ด ์žˆ๋‹ค. ๋ณด๋“œ๊ฐ€ ์—†๋Š” ์ œํ’ˆ์— ๋ณด๋“œ ๋ชฉ๋ก์ด\n * ๋œจ์ง€ ์•Š๋Š” ๊ฒƒ์ด ๋งž๋‹ค.\n */\nimport { chatDefaults } from './chat-defaults.js'\nimport { isDifferentConversation, resolveConversation, type AssistantMode, type AssistantModeView, pickInitialMode } from './assistant-mode.js'\nimport { parseProposalOutcomeLine, parseProposalRequestLine, proposalCardState, type ParsedProposalOutcome } from './proposal-outcome-line.js'\nimport { availableTriggers, type TriggerChip } from './chat-triggers.js'\nimport './entry-review.js'\nimport { entryGroupOf, entryReadyCount, entryTitle, isChangeProposal, isEntryProposal, latestEntryKeys } from '../utils/entry-proposal.js'\nimport { isWorkspaceProposal, versionOfCard, workspaceAddress } from '../utils/workspace.js'\nimport { isOpenPageProposal, openPageNote } from '../utils/open-page.js'\n\ninterface ChatLine {\n role: 'user' | 'assistant' | 'system'\n /** ์„œ๋ฒ„ ChatMessage.id โ€” ์‹ค์‹œ๊ฐ„ ๋ฐฉ์†ก ์—์ฝ” dedup ์˜ ํ‚ค (์žˆ์„ ๋•Œ๋งŒ). */\n id?: string\n /** ํด๋ผ ์ž„์‹œ ํ•ธ๋“ค โ€” ์˜์† id ๋ถ€์—ฌ ์ „ optimistic ๋ผ์ธ์„ index ๋น„์˜์กด์œผ๋กœ ์‹๋ณ„/reconcile. */\n _localId?: string\n /** ๋ณด๋‚ธ ์‚ฌ์šฉ์ž email/name โ€” ๊ทธ๋ฃน์ฑ— ๋ฐœ์‹ ์ž ํ‘œ์‹œ + ์ž๊ธฐ ์—ฌ๋ถ€ ํŒ์ •.\n * **email ๋กœ ํŒ์ •ํ•œ๋‹ค**: ๋กœ๊ทธ์ธ ์‹๋ณ„์ž๋ผ ๋น„์–ด ์žˆ์ง€ ์•Š๊ณ , ์‹œ์Šคํ…œ ๋‚ด๋ถ€ ๊ด€๋ฆฌํ‚ค(User.id)๋ฅผ\n * ํด๋ผ์ด์–ธํŠธ ํŒ์ •์— ๋Œ์–ด๋“ค์ด์ง€ ์•Š๋Š”๋‹ค(๊ด€๋ฆฌํ‚ค ๋…ธ์ถœ์ด ๊ณ„์•ฝ์ฒ˜๋Ÿผ ๊ตณ๋Š” ๊ฒƒ์„ ํ”ผํ•œ๋‹ค). */\n senderEmail?: string\n senderName?: string\n /** ๋ฉ”์‹œ์ง€ ๋ณธ๋ฌธ. `#token{refid:N}` inline marker ๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ์Œ (์˜์†๋œ ๋ฉ”์‹œ์ง€ / ์‚ฌ์šฉ์ž\n * popup pick / AI resolved mention). ๋ Œ๋”๋ง ์‹œ ์ถ”์ถœํ•ด์„œ `<span data-refid=\"N\">` ์œผ๋กœ ๋ณ€ํ™˜. */\n content: string\n patchSummary?: string\n followUp?: string\n patchId?: string\n pending?: boolean\n /**\n * ์„œ๋ฒ„๊ฐ€ ์ด ์‚ฌ๋žŒ์—๊ฒŒ ๊ฐ’์„ ์•ˆ ๋‚ด์ค€ ์ค„ โ€” ADR-0073 ํŒ์ • 1.\n *\n * `content` ์— ์˜จ ๊ฒƒ์€ ใ€Œ์ด ๋‹ต์€ <๋ฌธ> ๊ถŒํ•œ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹คใ€ ํ•œ ์ค„์ด๋‹ค. ์ค„์„ ์ง€์šฐ์ง€ ์•Š๋Š” ์ด์œ ๋Š”, ๋ฐฉ์—\n * ๋ฌด์Šจ ์ผ์ด ์žˆ์—ˆ๋Š”์ง€๋Š” ์•Œ ์ˆ˜ ์žˆ์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ฐ’๋งŒ ์•ˆ ๋ณด์ธ๋‹ค.\n */\n redacted?: boolean\n /** AI ๊ฐ€ ์‘๋‹ต์„ ๋งŒ๋“œ๋Š” ๋™์•ˆ ํ˜ธ์ถœํ•œ ๋„๊ตฌ trace โ€” fold-able ๋ฐ•์Šค์—์„œ ๋…ธ์ถœ. */\n toolUsages?: Array<{\n name: string\n arguments: any\n result: any\n kind: 'read' | 'write' | 'unknown'\n /** ๋ช‡ ๋ฒˆ์งธ LLM ํ„ด โ€” ๋‹จ๊ณ„๋กœ ์ฝ๊ธฐ ์œ„ํ•œ ๊ฐ’. */\n iter?: number\n /** ์ด ํ˜ธ์ถœ์ด ์–ด๋–ป๊ฒŒ ๋๋‚ฌ๋Š”๊ฐ€ โ€” ๋ฐฐ์ง€. */\n outcome?: 'ok' | 'rejected' | 'queued' | 'proposed' | 'folded' | 'error'\n }>\n /** UI ์ƒํƒœ: tool usage ๋ฐ•์Šค ํŽผ์นจ ์—ฌ๋ถ€ (assistant ๋ฉ”์‹œ์ง€๋งˆ๋‹ค ๋…๋ฆฝ). */\n toolUsagesOpen?: boolean\n /** UI ์ƒํƒœ: ์ ‘ํžŒ ์‹œ์Šคํ…œ ๊ธฐ๋ก์„ ํŽผ์ณค๋Š”๊ฐ€(๊ณ์ค„์ด ๋Œ€ํ™”๋ฅผ ๊ฐ€๋ฆฌ์ง€ ์•Š๊ฒŒ ๊ธฐ๋ณธ์€ 3์ค„ ์ ‘๊ธฐ). */\n systemOpen?: boolean\n /**\n * ์กฐ์น˜ ์ œ์•ˆ โ€” AI ๊ฐ€ **์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ ** ์ œ์•ˆํ•œ ๊ฒƒ๋“ค. ์‚ฌ์šฉ์ž๊ฐ€ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ์•ผ ์‹คํ–‰๋œ๋‹ค.\n *\n * ์˜์†ํ•˜์ง€ ์•Š๋Š”๋‹ค(์ด๋ฒˆ ์‘๋‹ต์—๋งŒ ๋ถ™๋Š”๋‹ค): ์Šน์ธ์€ **์ง€๊ธˆ** ํ•˜๋Š” ํŒ๋‹จ์ด๊ณ , ๋˜๋Œ๋ฆด ์ˆ˜ ์—†๋Š” ์กฐ์น˜๋ฅผ\n * ์ง€๋‚œ ๋งฅ๋ฝ์œผ๋กœ ๋‹ค์‹œ ๊ถŒํ•˜๋Š” ๊ฒƒ์€ ์œ„ํ—˜ํ•˜๋‹ค. ๋‹ค์‹œ ํ•„์š”ํ•˜๋ฉด ๋‹ค์‹œ ๋ฌผ์–ด๋ณด๋ฉด ๋œ๋‹ค.\n */\n proposals?: any[]\n /**\n * ์ ‘์ง€ ๊ฒฝ๊ณ  โ€” ์ด ๋‹ต์ด ์–ธ๊ธ‰ํ–ˆ์œผ๋‚˜ ๋ชจ๋ธ์ด ๋ฐ›์€ ๊ทผ๊ฑฐ(ํ”„๋กฌํ”„ํŠธยท๋ณด๋“œ ๋ฌธ๋งฅยท์ด๋ ฅยท๋„๊ตฌ ๊ฒฐ๊ณผ)์— ์—†๋˜ ์‹๋ณ„์ž.\n * ์žˆ์œผ๋ฉด ๊ทธ ๋Œ€์ƒ์€ ๋งŒ๋“ค์–ด ๋‚ธ ๊ฒƒ์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ฃผ์˜๋ฅผ ๋‹ต ์•„๋ž˜์— ํ‘œ์‹œํ•œ๋‹ค(๋‹ต ์ž์ฒด๋Š” ๊ทธ๋Œ€๋กœ ๋ณด์—ฌ์ค€๋‹ค).\n */\n groundingWarnings?: string[]\n attachments?: Array<{\n /** A stored file of the conversation (shared dock ยง9) - opened by its route, not carried inline. */\n id?: string\n name: string\n size: number\n type: string\n url?: string\n base64?: string\n }>\n}\n\nexport interface ChatAttachment {\n id: string\n file: File\n name: string\n size: number\n type: string\n url: string\n base64?: string\n /** A table pasted into the composer - its shape for the chip, its rows for the preview, its words to give back. */\n table?: { rows: string[][]; columns: number; text?: string }\n}\n\nfunction formatFileSize(bytes: number): string {\n if (!bytes || bytes < 1024) return `${bytes || 0} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nconst BOARD_AI_CHAT_MUTATION = gql`\n mutation BoardAIChat($input: BoardAIChatInput!) {\n boardAIChat(input: $input) {\n reply\n patch\n followUp\n clientId\n sessionId\n userMessageId\n assistantMessageId\n patchId\n toolUsages\n actions\n proposals\n groundingWarnings\n historyFolded\n }\n }\n`\n\n/*\n * The neutral door. Selected by `chatEndpoint`, and it asks for fewer fields because there is\n * less to ask for: no patch, no scene actions, no patch id โ€” this surface has no document.\n *\n * `offeredTools` has no counterpart on the board side. It is what the server actually put in\n * front of the model this turn, so a surface that granted a category and sees it missing knows\n * the registration never happened, instead of reading a vague answer as a refusal.\n */\n/* Files go to the conversation first; the turn then names them (design/ai/shared-dock.md ยง9). */\nconst ATTACH_TO_CONVERSATION_MUTATION = gql`\n mutation AttachToConversation($sessionId: String!, $files: [Upload!]!, $kind: String) {\n attachToConversation(sessionId: $sessionId, files: $files, kind: $kind) {\n id\n name\n mimetype\n size\n }\n }\n`\n\nconst ASSISTANT_CHAT_MUTATION = gql`\n mutation AssistantChat($input: AssistantChatInput!) {\n assistantChat(input: $input) {\n reply\n clientId\n sessionId\n userMessageId\n assistantMessageId\n toolUsages\n offeredTools\n proposals\n groundingWarnings\n historyFolded\n }\n }\n`\n\n/*\n * What this conversation offers on screen, in this person's language.\n *\n * The `/` sentences, the `@` catalog and the two notices are declared with the mode on the server\n * (ADR-0061 decision 7) and translated there, so the panel and the door cannot describe different\n * conversations, and a host does not carry a second copy of the words.\n */\n/*\n * ์ด ํ™”๋ฉด์— ์„ค ์ˆ˜ ์žˆ๋Š” ๋Œ€ํ™”๋“ค โ€” ADR-0072 A17 โ‘ .\n *\n * ํ™”๋ฉด์€ ์ž๊ธฐ๊ฐ€ ๋ฌด์—‡์„ ๋ณด์—ฌ ์ฃผ๋Š”์ง€๋งŒ ๋งํ•˜๊ณ , ๊ทธ ์œ„์— ์–ด๋А ๋Œ€ํ™”๊ฐ€ ์„œ๋Š”์ง€๋Š” ์•ฑ ์„œ๋ฒ„๊ฐ€ ๋‹ตํ•œ๋‹ค.\n */\nconst ASSISTANT_MODES_QUERY = gql`\n query AssistantModes($subject: String!) {\n assistantModes(subject: $subject) {\n kind\n label\n isDefault\n }\n }\n`\n\nconst ASSISTANT_MODE_QUERY = gql`\n query AssistantMode($kind: String!) {\n assistantMode(kind: $kind) {\n kind\n slashTemplates {\n name\n description\n template\n }\n catalogEntries\n proposalChoices\n placeholder\n intro\n examples\n footerNotice\n stagedNotice\n attachments\n }\n }\n`\n\n/*\n * ๋ฐฉ์— ๋งํ•˜๋Š” ๋ฌธ โ€” ์‚ฌ๋žŒ์—๊ฒŒ ํ•˜๋Š” ๋ง์ด๊ณ  ๋ชจ๋ธ์„ ๋ถ€๋ฅด์ง€ ์•Š๋Š”๋‹ค(ADR-0070 A15).\n *\n * ์ด ๋ฌธ์ด ์„œ๊ธฐ ์ „์—๋Š” ํ™”๋ฉด์—์„œ ๋‚˜๊ฐ€๋Š” ๋ชจ๋“  ๋ง์ด ์–ด์‹œ์Šคํ„ดํŠธ๋ฅผ ํ–ฅํ–ˆ๋‹ค. ์˜† ์‚ฌ๋žŒ์—๊ฒŒ ํ•œ๋งˆ๋”” ํ•˜๋ ค๋ฉด\n * ์–ด์‹œ์Šคํ„ดํŠธ๊ฐ€ ๋ฐ˜๋“œ์‹œ ๋Œ€๋‹ตํ–ˆ๊ณ , ๊ทธ ๋Œ€๋‹ต์ด ๋‹ค์‹œ ๋Œ€ํ™”์— ๋‚จ์•˜๋‹ค.\n */\n/*\n * `@` ๊ฐ€ ๊ณ ๋ฅผ ์ˆ˜ ์žˆ๋Š” ์‚ฌ๋žŒ๋“ค โ€” ์ด ๋„๋ฉ”์ธ์˜ ์‚ฌ์šฉ์ž.\n *\n * ํ˜ธ์ŠคํŠธ๊ฐ€ `userProvider` ๋ฅผ ์ฃผ์ง€ ์•Š์œผ๋ฉด ์—ฌ๊ธฐ์„œ ์ง์ ‘ ๋ฌป๋Š”๋‹ค. ์ฃผ์ง€ ์•Š๋Š” ๊ฒƒ์ด ๊ธฐ๋ณธ์ด์—ˆ๊ณ , ๊ทธ๋ž˜์„œ ์•ฑ ์…‹\n * ์–ด๋””์—์„œ๋„ `@์ด๋ฆ„` ์„ **๊ณ ๋ฅผ ์ˆ˜๊ฐ€ ์—†์—ˆ๋‹ค** โ€” ๋ฉ˜์…˜์ด ์‚ฌ๋žŒ์„ ๋ถˆ๋Ÿฌ๋“ค์ด๋Š” ๊ธฐ์ „(ADR-0071 ๊ฒฐ์ • 1)์„ ์„ธ์›Œ\n * ๋†“๊ณ  ๋ถ€๋ฅด๋Š” ์ž๋ฆฌ๊ฐ€ ์—†๋Š” ์ƒํƒœ์˜€๋‹ค. ์ด ๋ฌธ์€ `ai-assistant` ์˜ ๊ฒƒ์ด๊ณ  ๋Œ€ํ™”์ฐฝ์ด ๊ทธ ๋ฌธ์˜ ํ™”๋ฉด์ด๋‹ค.\n */\nconst DOMAIN_USERS_FOR_MENTION_QUERY = gql`\n query DomainUsersForMention($query: String) {\n domainUsersForMention(query: $query) {\n id\n name\n email\n }\n }\n`\n\nconst SAY_TO_ROOM_MUTATION = gql`\n mutation SayToRoom($sessionId: String!, $content: String!) {\n sayToRoom(sessionId: $sessionId, content: $content)\n }\n`\n\nconst CHAT_MESSAGES_QUERY = gql`\n query ChatMessages($sessionId: String!, $limit: Int, $offset: Int) {\n chatMessages(sessionId: $sessionId, limit: $limit, offset: $offset) {\n id\n role\n content\n relatedPatchId\n toolUsagesJson\n proposalsJson\n groundingWarningsJson\n attachmentsJson\n createdAt\n redacted\n creator {\n name\n email\n }\n }\n }\n`\n\n// C4 ๊ทธ๋ฃน์ฑ— โ€” ๊ฐ™์€ ์„ธ์…˜์˜ ๋ฉ”์‹œ์ง€(์‚ฌ์šฉ์ž/AI/system) ์‹ค์‹œ๊ฐ„ ๋ฐฉ์†ก ๊ตฌ๋….\n// ์ž๊ธฐ ๋ฐœ์‹  ์—์ฝ”๋Š” message.id ๋กœ dedup (mutation ์‘๋‹ต์œผ๋กœ ์ด๋ฏธ ๋ Œ๋”).\nconst CHAT_MESSAGE_SUBSCRIPTION = gql`\n subscription ChatMessageActivity($sessionId: String!) {\n chatMessageActivity(sessionId: $sessionId) {\n id\n role\n content\n relatedPatchId\n toolUsagesJson\n proposalsJson\n groundingWarningsJson\n attachmentsJson\n createdAt\n redacted\n creator {\n name\n email\n }\n }\n }\n`\n\n// C4 presence/roster โ€” ์„ธ์…˜ ์ฐธ์—ฌ์ž ๋ชฉ๋ก + ๋งˆ์ง€๋ง‰ ์ ‘์†(online ํŒ์ •์šฉ).\nconst CHAT_PARTICIPANTS_QUERY = gql`\n query ChatSessionParticipants($sessionId: String!) {\n chatSessionParticipants(sessionId: $sessionId) {\n id\n role\n lastSeenAt\n user {\n id\n name\n }\n }\n }\n`\nconst TOUCH_PRESENCE_MUTATION = gql`\n mutation TouchPresence($sessionId: String!) {\n touchPresence(sessionId: $sessionId)\n }\n`\n// heartbeat ์ฃผ๊ธฐ(ms) โ€” ์„œ๋ฒ„ PRESENCE_TTL_MS(75s)์˜ ~1/2.5. ๋กœ์ปฌ online ํŒ์ •๋„ ๋™์ผ TTL.\nconst PRESENCE_HEARTBEAT_MS = 30_000\nconst PRESENCE_TTL_MS = 75_000\n\n/** ์ด๋ฆ„ โ†’ roster chip ์ด๋‹ˆ์…œ (ํ•œ๊ธ€ 1์ž / ์˜๋ฌธ ์ตœ๋Œ€ 2์ž). */\nfunction initials(name: string): string {\n const n = (name || '?').trim()\n if (!n) return '?'\n const parts = n.split(/\\s+/)\n if (parts.length >= 2) return (parts[0][0] + parts[1][0]).toUpperCase()\n return /[a-zA-Z]/.test(n) ? n.slice(0, 2).toUpperCase() : n.slice(0, 1)\n}\n\n@customElement('ox-assistant-chat')\nexport class OxAssistantChat extends LitElement {\n /** ์˜์† ์„ธ์…˜ id. ์—†์œผ๋ฉด ad-hoc (๋ฉ”์‹œ์ง€ ์˜์† ์•ˆ ๋จ). */\n @property({ type: String, attribute: 'session-id' })\n sessionId?: string\n @property({ attribute: false }) prepareSession?: (adopt: (id: string) => void) => Promise<string | undefined>\n private adoptingSession = false\n\n /**\n * ๋ณด๋“œ์˜ ๋ชจ๋“  ChatSession ๋ฆฌ์ŠคํŠธ โ€” ๋‹ค์ค‘ ์„ธ์…˜ ํ™œ์„ฑํ™” ์‹œ ํƒญ UI ๋กœ ํ‘œ์‹œ.\n *\n * ๋นˆ ๋ฐฐ์—ด / ๋ฏธ์ง€์ • โ†’ ๋‹จ์ผ ์„ธ์…˜ UX (ํƒญ ์•ˆ ๋ณด์ž„). ํ•œ ๋ณด๋“œ = ํ•œ ์„ธ์…˜ ๊ฐ€์ •์˜ ๊ธฐ์กด ํ˜ธ์ถœ์ž\n * ํ˜ธํ™˜. host (board-modeller-page) ๊ฐ€ chatSessionsByBoard query ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌ.\n *\n * ์ด ์ปดํฌ๋„ŒํŠธ๋Š” list ์ž์ฒด๋ฅผ fetch ํ•˜์ง€ ์•Š์Œ โ€” ์˜์† ๋ชจ๋ธ / ๊ถŒํ•œ / ํŽ˜์ด์ง€๋„ค์ด์…˜ ์ •์ฑ…์€\n * host ์ฑ…์ž„. ๋ณธ ์ปดํฌ๋„ŒํŠธ๋Š” ํ‘œ์‹œ + ์ด๋ฒคํŠธ emission ๋งŒ.\n */\n @property({ type: Array, attribute: false })\n sessions: Array<{ id: string; name?: string; createdAt?: string }> = []\n\n /**\n * ํ˜„์žฌ BoardModel โ€” chat() ์ž…๋ ฅ์œผ๋กœ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌ.\n *\n * ์ฃผ์˜: ํ˜ธ์ŠคํŠธ๊ฐ€ ๋ผ์ด๋ธŒ ํŽธ์ง‘ ๊ฐ€๋Šฅํ•œ ์บ”๋ฒ„์Šค(things-scene)๋ฅผ ๊ฐ–๊ณ  ์žˆ๋‹ค๋ฉด, ์บ”๋ฒ„์Šค ์•ˆ์—์„œ\n * ์ผ์–ด๋‚˜๋Š” ์ˆ˜์ž‘์—… ํŽธ์ง‘์ด ์ด property ์—๋Š” ์ž๋™ ๋ฐ˜์˜๋˜์ง€ ์•Š๋Š”๋‹ค. ์ด ๊ฒฝ์šฐ `boardProvider`\n * ์ฝœ๋ฐฑ์„ ๊ฐ™์ด ๋„˜๊ธฐ๋ฉด send() ์‹œ์ ์— ๋ผ์ด๋ธŒ ๋ณด๋“œ๋ฅผ pull ํ•œ๋‹ค.\n */\n @property({ type: Object })\n currentBoard?: any\n\n /**\n * ๋ผ์ด๋ธŒ ๋ณด๋“œ ๋ชจ๋ธ ๊ณต๊ธ‰์ž (์„ ํƒ).\n *\n * ํ˜ธ์ŠคํŠธ๊ฐ€ things-scene ๊ฐ™์€ ์บ”๋ฒ„์Šค๋ฅผ ์‚ฌ์šฉ ์ค‘์ด๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ์บ”๋ฒ„์Šค์—์„œ ์ˆ˜์ž‘์—… ํŽธ์ง‘ํ•œ\n * ๋‚ด์šฉ์€ `currentBoard` property ์— ์ž๋™ ๋ฐ˜์˜๋˜์ง€ ์•Š๋Š”๋‹ค. ์ด ์ฝœ๋ฐฑ์„ ๋“ฑ๋กํ•˜๋ฉด `send()`\n * ์ง์ „์— ํ˜ธ์ถœํ•ด ๊ฐ€์žฅ ์ตœ์‹  ๋ณด๋“œ๋ฅผ pull โ†’ AI ๊ฐ€ ํ•ญ์ƒ ๋ผ์ด๋ธŒ ์ƒํƒœ๋ฅผ ๋ณธ๋‹ค.\n *\n * ์šฐ์„ ์ˆœ์œ„: boardProvider() ?? currentBoard.\n */\n @property({ attribute: false })\n boardProvider?: () => any\n\n /**\n * `#` mention ๊ฒ€์ƒ‰ ๊ณต๊ธ‰์ž (์„ ํƒ). ํ˜ธ์ŠคํŠธ๊ฐ€ things-scene ์˜ SceneSearchEngine ์œผ๋กœ wrap.\n *\n * ํ˜ธ์ŠคํŠธ๋Š” query ๋ฅผ ๋ฐ›์•„ popup ์— ํ‘œ์‹œํ•  FilterResult[] ๋ฅผ ๋Œ๋ ค์ค€๋‹ค โ€” chat ์ž์ฒด๋Š”\n * things-scene ์˜์กด์„ฑ์„ ๊ฐ–์ง€ ์•Š๊ณ  popup ํ‘œ์‹œ ๋กœ์ง๋งŒ ๋‹ด๋‹น. ๊ฒ€์ƒ‰ ์šฐ์„ ์ˆœ์œ„ / ๋งค์นญ ๋ฃฐ์€\n * SceneSearchEngine (F-Finder ์™€ ๊ณต์œ ) ์— ์œ„์ž„ โ†’ ์ผ๊ด€์„ฑ ๋ณด์žฅ.\n *\n * ๋ฏธ์„ค์ • ์‹œ `currentBoard.components` ์—์„œ ๋‹จ์ˆœ substring ๋งค์นญ (legacy fallback).\n * ๋นˆ query ์—์„œ๋Š” ํ˜ธ์ถœ๋˜์ง€ ์•Š์Œ โ€” ๋นˆ query ๋Š” ์ „์ฒด ํ›„๋ณด enumeration ์ด์ง€ ๊ฒ€์ƒ‰์ด ์•„๋‹˜.\n */\n @property({ attribute: false })\n searchProvider?: (query: string) => FilterResult[]\n\n /**\n * `@` mention ๋„๋ฉ”์ธ ์‚ฌ์šฉ์ž ๊ณต๊ธ‰์ž (์„ ํƒ). ํ˜ธ์ŠคํŠธ๊ฐ€ `domainUsersForMention` query ๋กœ wrap.\n *\n * ํ˜ธ์ŠคํŠธ๋Š” query ๋ฌธ์ž์—ด์„ ๋ฐ›์•„ ๋„๋ฉ”์ธ ์‚ฌ์šฉ์ž ํ›„๋ณด (id/name/email) ๋ฐฐ์—ด์„ ๋Œ๋ ค์ค€๋‹ค.\n *\n * **๋ฏธ์„ค์ •์ด๋ฉด ๋Œ€ํ™”์ฐฝ์ด ์ด ํŒจํ‚ค์ง€์˜ ๋ฌธ(`domainUsersForMention`)์— ์ง์ ‘ ๋ฌป๋Š”๋‹ค.** ์˜ˆ์ „์—๋Š” ๋นˆ\n * ๊ฒฐ๊ณผ์˜€๊ณ , ๊ทธ๋ž˜์„œ ์•ฑ ์…‹์—์„œ๋Š” `@์ด๋ฆ„` ์„ ๊ณ ๋ฅผ ์ˆ˜ ์—†์—ˆ๋‹ค โ€” ๋ฉ˜์…˜์ด ์‚ฌ๋žŒ์„ ๋ถˆ๋Ÿฌ๋“ค์ด๋Š” ๊ธธ์„ ์„ธ์›Œ๋„\n * ๋ถ€๋ฅด๋Š” ์ž๋ฆฌ๊ฐ€ ์—†์—ˆ๋‹ค. ์ž๊ธฐ ๋ชฉ๋ก์„ ๋”ฐ๋กœ ์“ฐ๋Š” ํ˜ธ์ŠคํŠธ๋งŒ ์ด๊ฒƒ์„ ์ค€๋‹ค.\n */\n @property({ attribute: false })\n userProvider?: (\n query: string\n ) =>\n | Promise<Array<{ id: string; name?: string | null; email?: string | null }>>\n | Array<{ id: string; name?: string | null; email?: string | null }>\n\n /**\n * ๋ชจ๋ธ๋Ÿฌ์—์„œ ํ˜„์žฌ ์„ ํƒ๋œ ์ปดํฌ๋„ŒํŠธ์˜ `refid` ๋ชฉ๋ก.\n *\n * refid ๋Š” things-scene ์ด ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ์— ์ž๋™ ๋ฐœ๊ธ‰ํ•˜๋Š” universal numeric handle.\n * ํ˜ธ์ŠคํŠธ๊ฐ€ ๋งค render ๋งˆ๋‹ค `.selectedRefids=${...}` ๋กœ ๊ฐฑ์‹ . AI ํ•œํ…Œ selection ์ •๋ณด๋กœ\n * ๊ทธ๋Œ€๋กœ ์ „๋‹ฌ๋˜์–ด \"์„ ํƒํ•œ\" / \"selected\" / \"this\" ๋ฅ˜ ์ง€์‹œ์–ด ํ•ด์„์— ์‚ฌ์šฉ.\n */\n @property({ type: Array, attribute: false })\n selectedRefids: number[] = []\n\n /**\n * ์ด ๋Œ€ํ™”๋ฉด์ด ์“ธ ์ˆ˜ ์žˆ๋Š” **์™ธ๋ถ€ ๋„๊ตฌ ์นดํ…Œ๊ณ ๋ฆฌ** ํ™”์ดํŠธ๋ฆฌ์ŠคํŠธ(registerToolCategory ์ด๋ฆ„).\n * ๋ฏธ์ง€์ •์ด๋ฉด ๋“ฑ๋ก๋œ ์ „๋ถ€(ํ˜„ํ–‰ ๋™์ž‘) โ€” ๋ณด๋“œ ๋ชจ๋ธ๋Ÿฌ๋Š” ์ง€์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค.\n * ์„ฑ๊ฒฉ์ด ๋‹ค๋ฅธ ๋Œ€ํ™”๋ฉด(์˜ˆ: ํŠธ์œˆ ์šด์˜ ๋„ํฌ)์ด ์„œ๋กœ์˜ ๋Šฅ๋ ฅ์„ ๊ฐ–์ง€ ์•Š๊ฒŒ ํ•˜๋Š” ๊ฒฝ๊ณ„.\n */\n @property({ type: Array, attribute: false })\n toolCategories?: string[]\n\n /**\n * ์ด ๋Œ€ํ™”๋ฉด์ด ๋ฌด์—‡์„ ๋ณด๊ณ  ์žˆ๋Š”์ง€ โ€” ์„œ๋ฒ„ ๋„๊ตฌ๊ฐ€ `ctx.state.host` ๋กœ ์ฝ๋Š”๋‹ค(์˜ˆ: `{ spaceId }`).\n * ์—†์œผ๋ฉด ๋„๊ตฌ๊ฐ€ ๋Œ€์ƒ์„ ๋ชฐ๋ผ ๋ชจ๋ธ์ด ์‚ฌ์šฉ์ž์—๊ฒŒ ์‹๋ณ„์ž๋ฅผ ๋˜๋ฌป๋Š”๋‹ค.\n */\n @property({ type: Object, attribute: false })\n hostContext?: any\n\n /** ์ฝ”์–ด ๋ณด๋“œ ํŽธ์ง‘ ๋„๊ตฌ ์‚ฌ์šฉ ์—ฌ๋ถ€. ๊ธฐ๋ณธ true. ๋ณด๋“œ๋ฅผ ๊ณ ์น  ์ด์œ ๊ฐ€ ์—†๋Š” ๋ฉด์—์„œ false. */\n @property({ type: Boolean, attribute: 'board-tools' })\n boardTools = true\n\n /*\n * Which server operation this surface talks to. A closed set of two, named after the operations\n * themselves so a reader can grep either way.\n *\n * boardAIChat board authoring โ€” lives in @things-factory/board-ai, carries the board model,\n * returns patches and scene actions\n * assistantChat a surface with no document of its own โ€” lives here, runs registered tools only\n *\n * **There is no default** (ADR-0061 decision 7). It was `boardAIChat`, which meant a surface that\n * said nothing talked to a package it may not even load โ€” operato-figure got\n * `Cannot query field \"boardAIChat\" on type \"Mutation\"` that way (2026-09-11). A surface that\n * declares a mode talks to `assistantChat`; one that declares no mode names this itself.\n */\n @property({ type: String, attribute: 'chat-endpoint' })\n chatEndpoint?: 'boardAIChat' | 'assistantChat'\n\n /**\n * What this conversation is โ€” see `AssistantMode`.\n *\n * A host that sets this sets nothing else about the conversation: the persona, the tool\n * categories, the model and the limits belong to the mode its app server registered, and what\n * `@` and `/` offer comes from that same declaration, translated. They cannot disagree because\n * there is one of them.\n *\n * When `kind` or `target` changes the conversation on screen is closed and a new one begins.\n */\n @property({ attribute: false })\n mode?: AssistantMode\n\n /**\n * ์ด ํ™”๋ฉด์ด ๋ณด์—ฌ ์ฃผ๋Š” ๊ฒƒ์˜ **์ข…๋ฅ˜** โ€” `'board'`, `'space'`, `'station'`, `'figure'` (ADR-0072 A17 โ‘ ).\n *\n * `mode` ๊ฐ€ ใ€Œ์ง€๊ธˆ ์–ด๋А ๋Œ€ํ™”์ธ๊ฐ€ใ€๋ผ๋ฉด ์ด๊ฒƒ์€ ใ€Œ๊ทธ ์ž๋ฆฌ์— ์–ด๋–ค ๋Œ€ํ™”๋“ค์ด ์„ค ์ˆ˜ ์žˆ๋‚˜ใ€์ด๋‹ค. ์„œ๋ฒ„๊ฐ€\n * `assistantModes(subject)` ๋กœ ๋‹ตํ•˜๊ณ , ๋‘˜ ์ด์ƒ์ด๋ฉด ๊ณ ๋ฅด๊ฐœ๊ฐ€ ๋œฌ๋‹ค. ํ•˜๋‚˜๋ฉด ๊ณ ๋ฅด๊ฐœ๋ฅผ ๋‚ด์ง€ ์•Š๋Š”๋‹ค โ€”\n * ๊ณ ๋ฅผ ๊ฒƒ์ด ์—†๋Š” ๊ณ ๋ฅด๊ฐœ๋Š” ์ž๋ฆฌ๋งŒ ์ฐจ์ง€ํ•œ๋‹ค.\n *\n * ํ™”๋ฉด์ด ์ด๊ฒƒ์„ ์•ˆ ์ฃผ๋ฉด ๊ณ ๋ฅด๊ฐœ๋Š” ์—†๊ณ  host ๊ฐ€ ์ •ํ•œ ๋Œ€ํ™” ํ•˜๋‚˜๋งŒ ์‚ฐ๋‹ค. ๊ทธ๊ฒƒ์ด ์˜ค๋Š˜๊นŒ์ง€์˜ ๋ชจ์–‘์ด๋‹ค.\n */\n @property({ type: String })\n subject?: string\n\n /**\n * ๋ผ์ด๋ธŒ ์ƒํƒœ๋ฅผ ๋‹ค๋ฃจ๋Š” ๋Œ€ํ™”๋ฉด์ธ๊ฐ€ โ€” true ๋ฉด **์ฒซ ํ„ด์— ๋„๊ตฌ ํ˜ธ์ถœ์„ ๊ฐ•์ œ**ํ•œ๋‹ค.\n *\n * ์ ‘์ง€ ๊ฐ€๋“œ๋Š” ์ง€์–ด๋‚ธ ์‹๋ณ„์ž๋ฅผ ์žก์ง€๋งŒ ์‹๋ณ„์ž ์—†๋Š” ์ƒํ™ฉ ์„œ์ˆ (\"๋ฐ”์˜๊ฒŒ ์›€์ง์ด๊ณ  ์žˆ๋‹ค\")์€ ์žก์ง€ ๋ชปํ•œ๋‹ค.\n * ๊ทธ๊ฑด ๋„๊ตฌ๋ฅผ ๋ถ€๋ฅด์ง€ ์•Š๊ณ  ๋‹ตํ•œ ๊ฒฝ์šฐ์ด๋ฏ€๋กœ, ์กฐํšŒ๋ฅผ ๋จผ์ € ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด ์›์ฒœ์„ ๋ง‰๋Š”๋‹ค.\n */\n @property({ type: Boolean, attribute: 'require-grounding-tools' })\n requireGroundingTools = false\n\n /** board-import registry scopes. */\n @property({ type: Array })\n scopes?: string[]\n\n @property({ type: Array, attribute: 'known-types' })\n knownTypes?: string[]\n\n @property({ type: Array })\n categories?: string[]\n\n /**\n * ์ปดํฌ๋„ŒํŠธ type ๋ณ„ ์œ ํšจ ์†์„ฑ ์Šคํ‚ด.\n * ํ˜•ํƒœ: [{ type, description?, group?, properties? }]\n * LLM ์ด ์ •ํ™•ํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค๋„๋ก mutation input ์œผ๋กœ forwarding.\n */\n @property({ type: Array, attribute: false })\n componentSchemas?: Array<{ type: string; description?: string; group?: string; properties?: Record<string, any> }>\n\n /* No default here โ€” the render falls back to `ai-assistant.text.input-placeholder`, which every locale has.\n * A literal default is one language for every reader, and it hid the key that already existed. */\n @property({ type: String })\n placeholder?: string\n\n @state()\n private lines: ChatLine[] = []\n\n @state()\n private input = ''\n\n /**\n * ๋ฐ–์—์„œ ์งˆ๋ฌธ์„ ๋„ฃ์–ด **์ž๋™์œผ๋กœ ๋ณด๋‚ด๊ฒŒ** ํ•˜๋Š” ์ง„์ž…์ .\n *\n * ์˜ค๋ฅ˜ ํ† ์ŠคํŠธ์˜ \"AI์—๊ฒŒ ๋ฌป๊ธฐ\" ์ฒ˜๋Ÿผ, ์‚ฌ์šฉ์ž๊ฐ€ ํƒ€์ดํ•‘ํ•˜์ง€ ์•Š๊ณ  ๊ณง๋ฐ”๋กœ ๋‹ต์„ ๋ฐ›์•„์•ผ ํ•˜๋Š” ๊ฒฝ๋กœ๊ฐ€ ์žˆ๋‹ค.\n * ๊ฐ’์ด ๋“ค์–ด์˜ค๋ฉด ๊ทธ ๋ฌธ์žฅ์„ ์ž…๋ ฅ์œผ๋กœ ์‚ผ์•„ ํ•œ ๋ฒˆ ์ „์†กํ•˜๊ณ  ๋น„์šด๋‹ค(๊ฐ™์€ ์งˆ๋ฌธ์ด ๋ฐ˜๋ณต ์ „์†ก๋˜์ง€ ์•Š๊ฒŒ).\n */\n @property({ attribute: false })\n autoAsk?: string\n @property() autoAskRequestId?: string\n\n /**\n * A sentence to place in the input **without sending it** โ€” the pair of `autoAsk`.\n *\n * Some paths hand the person a starting sentence to edit and send themselves (twin's \"new twin โ†’\n * AI\"). Filled once per `draftRequestId`, with focus on the input; never over text the person is\n * typing; and when `autoAsk` arrives for the same request, `autoAsk` wins\n * (`assistantDraftDecision`).\n */\n @property({ attribute: false })\n draft?: string\n @property() draftRequestId?: string\n @property({ attribute: false }) contextProvider?: () => AssistantRequestContext\n\n /**\n * ๋นˆ ํ™”๋ฉด์˜ ์ œ๋ชฉยท๋ถ€์ œ โ€” **ํ˜ธ์ŠคํŠธ๊ฐ€ ์ž๊ธฐ ๋ง๋กœ ์ค€๋‹ค.**\n *\n * โ”€โ”€ ์™œ ์—ด์—ˆ๋‚˜ (2026-09-11) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ์ด ๊ฐ’์ด `board-ai.text.empty-title` ๋กœ ๊ณ ์ •๋ผ ์žˆ์—ˆ๋‹ค. ๊ทธ๋ž˜์„œ figure ์ €์ž‘๋ฉด์—์„œ ๋„ํฌ๋ฅผ ์—ด๋ฉด\n * ๋„ํ˜•์„ ํŽธ์ง‘ํ•˜๋Š” ์‚ฌ๋žŒ์—๊ฒŒ **ใ€Œ๋ณด๋“œ๋ฅผ ๋งŒ๋“ค๋ผใ€๊ณ  ๊ฐ€๋ฅด์ณค๋‹ค** โ€” ใ€ŒMonitoring dashboard with 3\n * gaugesใ€ ๊ฐ™์€ ์˜ˆ์‹œ๊นŒ์ง€ ํ•จ๊ป˜.\n *\n * ๋นˆ ํ™”๋ฉด์€ ๊ทธ ํ™”๋ฉด์ด ๋ฌด์—‡์ธ์ง€ ๊ฐ€๋ฅด์น˜๋Š” ์ž๋ฆฌ๋‹ค. ๊ฑฐ๊ธฐ์„œ ํ‹€๋ฆฌ๋ฉด ์ฒ˜์Œ ์—ฌ๋Š” ์‚ฌ๋žŒ์ด ์ด ๋„๊ตฌ๋ฅผ\n * ์˜คํ•ดํ•œ๋‹ค. ๋„๊ตฌ ์ชฝ(`toolCategories`ยท`boardTools`)์€ ์ด๋ฏธ ์ค‘๋ฆฝ์ด์—ˆ๊ณ  **๊ธ€๋งŒ ์•ˆ ์—ด๋ ค ์žˆ์—ˆ๋‹ค.**\n *\n * โš  **ํ‚ค๊ฐ€ ์•„๋‹ˆ๋ผ ๋ฒˆ์—ญ๋œ ๊ธ€์„ ๋ฐ›๋Š”๋‹ค.** ํ˜ธ์ŠคํŠธ๋งˆ๋‹ค ์ž๊ธฐ ์ ‘๋‘ ์•„๋ž˜ ํ‚ค๋ฅผ ๋‘๋ฏ€๋กœ(figure ๋Š”\n * `figure.text.โ€ฆ`), ํ‚ค๋ฅผ ๋ฐ›์œผ๋ฉด ์ด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋‚จ์˜ ์ ‘๋‘๋ฅผ ์•Œ์•„์•ผ ํ•œ๋‹ค.\n *\n * โš  ์•ˆ ์ฃผ๋ฉด **์ง€๊ธˆ๊นŒ์ง€์˜ ๋ณด๋“œ ๋ฌธ๊ตฌ**๊ฐ€ ๋‚˜์˜จ๋‹ค โ€” ๊ฑฐ๋™์„ ๋ฐ”๊พธ์ง€ ์•Š์œผ๋ ค๊ณ  ๊ทธ๋ ‡๊ฒŒ ๋’€๋‹ค. ์ฆ‰ ๋ณด๋“œ๊ฐ€\n * ์•„๋‹Œ ํ˜ธ์ŠคํŠธ๊ฐ€ ์ด ๊ฐ’์„ ์žŠ์œผ๋ฉด ํ‹€๋ฆฐ ๊ธ€์ด ์กฐ์šฉํžˆ ๋œฌ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์„ ์ค‘๋ฆฝ์œผ๋กœ ๋ฐ”๊พธ๋Š” ๊ฒƒ์€\n * board-uiยทtwin ์ด ์ž๊ธฐ ๊ธ€์„ ๋„˜๊ธฐ๊ฒŒ ํ•˜๋Š” ๋ณ„ ๊ฑด์ด๋‹ค(๊ทธ๋•Œ ์ด ์ฃผ์„์„ ์ง€์šด๋‹ค).\n */\n @property({ type: Object, attribute: false }) intro?: { title: string; subtitle: string }\n\n /**\n * ๋นˆ ํ™”๋ฉด์˜ ์˜ˆ์‹œ โ€” ํ˜ธ์ŠคํŠธ๊ฐ€ ์ž๊ธฐ ๊ฒƒ์„ ์ค€๋‹ค. ์•ˆ ์ฃผ๋ฉด ๋ณด๋“œ ์˜ˆ์‹œ๊ฐ€ ๋‚˜์˜จ๋‹ค(์œ„ โš  ์™€ ๊ฐ™์€ ์ด์œ ).\n *\n * ์˜ˆ์‹œ๋Š” **๊ทธ ๋„๊ตฌ๋กœ ์‹ค์ œ๋กœ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ง**์ด์–ด์•ผ ํ•œ๋‹ค. ํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ์„ ์˜ˆ์‹œ๋กœ ๋‘๋ฉด ๋นˆ ํ™”๋ฉด์ด\n * ๊ฑฐ์ง“์„ ๊ฐ€๋ฅด์นœ๋‹ค.\n */\n @property({ type: Array, attribute: false }) examples?: Array<{ label: string; items: string[] }>\n\n /** autoAsk ๋ฅผ ์ด๋ฏธ ๋ณด๋ƒˆ๋Š”์ง€ โ€” ์žฌ๋ Œ๋”๋งˆ๋‹ค ๋‹ค์‹œ ๋ณด๋‚ด์ง€ ์•Š๊ธฐ ์œ„ํ•œ ํ‘œ์‹. */\n private _autoAsked?: string\n /** The draft already placed (or deliberately skipped) โ€” so a re-render does not place it again. */\n private _drafted?: string\n\n /** ๋งˆ์ง€๋ง‰ send ์‹คํŒจ ์‹œ ๋ณด์กด โ€” ๋‹ค์‹œ ์‹œ๋„ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ์‚ฌ์šฉ */\n @state()\n private lastFailedInput?: string\n\n /** ๋˜๋Œ๋ ค์ง„ patch id ๋“ค โ€” ํ•œ ๋ฒˆ revert ํ•œ patch ๋Š” ๋ฒ„ํŠผ ๋น„ํ™œ์„ฑ */\n @state()\n private revertedPatchIds = new Set<string>()\n\n /** ์ฒจ๋ถ€๋œ ํŒŒ์ผ/์ด๋ฏธ์ง€ ๋ชฉ๋ก */\n @state()\n private attachments: ChatAttachment[] = []\n\n /** ๋“œ๋ž˜๊ทธ ์˜ค๋ฒ„ ์ƒํƒœ (์‹œ๊ฐ ํ”ผ๋“œ๋ฐฑ์šฉ) */\n @state()\n private dragOver = false\n\n /** The wide box (๋„“๊ฒŒ ์“ฐ๊ธฐ) covers the conversation inside the dock - shared-dock.md ยง10. */\n @state()\n private composerWide = false\n\n /** The pasted table whose rows cover the conversation, or null. */\n @state()\n private previewAttachmentId: string | null = null\n\n /*\n * โ”€โ”€ ์™œ ์ด๋ฏธ์ง€๋งŒ ๋ฐ›๋‚˜ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * `.json` ยท `.txt` ยท `.csv` ๋„ ๋ฐ›๊ณ  ์žˆ์—ˆ๋‹ค. ๊ทธ ํŒŒ์ผ๋“ค์€ `hostContext.attachments` ๋กœ ์‹ค๋ ค ๊ฐ”๊ณ \n * **๊ทธ๊ฒƒ์„ ์ฝ์–ด ๋ชจ๋ธ์— ๋ถ™์ด๋Š” ์ฝ”๋“œ๊ฐ€ ์—†์—ˆ๋‹ค.** ์‚ฌ๋žŒ์ด CSV ๋ฅผ ๋ถ™์ด๊ณ  ใ€Œ์ด ํ‘œ ์ข€ ๋ด์ค˜ใ€๋ผ๊ณ  ํ•˜๋ฉด ํ™”๋ฉด์—\n * ํŒŒ์ผ ์นฉ์ด ๋œจ๊ณ  ๋‹ต๋„ ์™”๋‹ค. ๊ทธ ๋‹ต์€ ํŒŒ์ผ์„ ๋ณธ ์ ์ด ์—†๊ณ , ์˜ค๋ฅ˜๋„ ์•ˆ ๋‚ฌ๋‹ค(2026-09-18 ํ‘œ๋ฉด ์กฐ์‚ฌ).\n *\n * ์ด๋ฏธ์ง€๋Š” ๊ธธ์ด ์žˆ๋‹ค โ€” `assistant-chat-resolver.ts` ๊ฐ€ `hostContext.image` ๋ฅผ ๋งˆ์ง€๋ง‰ ์‚ฌ๋žŒ ํ„ด์—\n * ๋ถ™์ธ๋‹ค. ๊ทธ๋ž˜์„œ ๋˜๋Š” ๊ฒƒ๋งŒ ๋‚จ๊ธฐ๊ณ  ์ขํ˜”๋‹ค. ๋ชป ํ•˜๋Š” ์ผ์„ ํ™”๋ฉด์ด ๊ถŒํ•˜์ง€ ์•Š๋Š”๋‹ค.\n *\n * โ”€โ”€ ๊ธ€ ํŒŒ์ผ์„ ์ฒญํ•˜๋Š” ์ œํ’ˆ์ด ์„ค ๋•Œ์˜ ๋ชจ์–‘ (์ˆ˜์„ ์•„ํ‚คํ…ํŠธ, ADR-0071 ๋ณดํƒฌ) โ”€โ”€โ”€\n * ์ด๋ฏธ์ง€์™€ **๊ฐ™์€ ์ž๋ฆฌ**(์‚ฌ๋žŒ ํ„ด)์— ๋ถ™์ธ๋‹ค. ํฌ๊ธฐ ์ƒํ•œ์€ ๋ชจ๋“œ๊ฐ€ ์„ ์–ธํ•˜๊ณ , ๋„˜์œผ๋ฉด ๋ณด๋‚ด๊ธฐ ์ „์— ์‚ฌ์‹ค ํ•œ\n * ์ค„๋กœ ๊ฑฐ์ ˆํ•œ๋‹ค โ€” ์กฐ์šฉํžˆ ์ž๋ฅด์ง€ ์•Š๋Š”๋‹ค. ๋น„์šฉ์€ ์‚ฌ์šฉ๋Ÿ‰์˜ ์ถ•์ด๋‹ค(ADR-0061 ๊ฒฐ์ • 6).\n *\n * `attachments` ์ง ์ž์ฒด๋Š” ๊ทธ๋Œ€๋กœ ๋‘”๋‹ค: figure ์˜ ๋„๊ตฌ๊ฐ€ ๊ฑฐ๊ธฐ์„œ ์ด๋ฏธ์ง€๋ฅผ ์ฐพ๋Š”๋‹ค\n * (`figure-tools.ts` โ€” `ctx.host.image` ๊ฐ€ ์—†์„ ๋•Œ์˜ ๊ฐˆ๋ž˜).\n */\n /** This conversation talks to the neutral door - its attachments follow the mode's policy (ยง9). */\n private get usesAttachmentPolicy(): boolean {\n return this.conversation.chatEndpoint === 'assistantChat'\n }\n\n /** Whether the attach button stands: a mode that declares nothing takes nothing (the board door keeps its images). */\n private get acceptsAttachments(): boolean {\n return !this.usesAttachmentPolicy || !!this.modeView?.attachments?.kinds?.length\n }\n\n /** A refusal in the reader's words - the same keys the door uses. */\n private attachmentRefusalText(refusal: NonNullable<ReturnType<typeof refuseAttachments>>): string {\n const params: any = { ...refusal }\n if (refusal.code === 'attachment-too-large') params.max = Math.round(refusal.maxBytes / 1024 / 1024)\n if (refusal.code === 'too-many-attachments') params.max = refusal.maxFiles\n if (refusal.code === 'attachment-kind-not-accepted') params.kinds = refusal.kinds.join(', ')\n return String(i18next.t(`ai-assistant.text.${refusal.code}`, { ...params, defaultValue: refusal.code }))\n }\n\n private async onAttachFiles(files: FileList | File[] | null | undefined, table?: ChatAttachment['table']) {\n if (!files || files.length === 0) return\n let list = Array.from(files)\n if (this.usesAttachmentPolicy && this.modeView?.attachments?.kinds?.includes('spreadsheet')) {\n /* A spreadsheet travels as the text of its sheets (ยง9-5) - read here, refused by name when it cannot be. */\n const read = await this.readSpreadsheets(list)\n if ('refusal' in read) {\n this.errorMessage = String(i18next.t(`ai-assistant.text.${read.refusal.code}`, { ...(read.refusal as any), defaultValue: read.refusal.code }))\n return\n }\n list = read.files\n }\n if (this.usesAttachmentPolicy) {\n /* Said before anything is sent - never cut silently (ยง9-1). */\n const refusal = refuseAttachments(this.modeView?.attachments, [...this.attachments, ...list].map(f => ({ name: f.name, type: f.type, size: f.size })))\n if (refusal) {\n this.errorMessage = this.attachmentRefusalText(refusal)\n return\n }\n }\n const newAttachments: ChatAttachment[] = []\n\n for (const file of list) {\n const id = 'att-' + Math.random().toString(36).substring(2, 9)\n const url = URL.createObjectURL(file)\n let base64: string | undefined\n try {\n base64 = await this.readFileAsBase64(file)\n } catch (err) {\n console.warn('Failed to read file as base64', err)\n }\n newAttachments.push({\n id,\n file,\n name: file.name,\n size: file.size,\n type: file.type || 'application/octet-stream',\n url,\n base64,\n table\n })\n }\n\n this.attachments = [...this.attachments, ...newAttachments]\n }\n\n /** Each .xlsx replaced by one CSV file per sheet; any other file passes as it is. */\n private async readSpreadsheets(list: File[]): Promise<{ files: File[] } | { refusal: SpreadsheetRefusal }> {\n const out: File[] = []\n let Workbook: any\n for (const file of list) {\n const kind = spreadsheetKindOf(file)\n if (!kind) {\n out.push(file)\n continue\n }\n if (kind === 'xls') return { refusal: { code: 'attachment-xls-not-read', name: file.name } }\n if (!Workbook) {\n const mod: any = await import('exceljs')\n Workbook = (mod.default ?? mod).Workbook\n }\n const read = await readSpreadsheet(await file.arrayBuffer(), file.name, textCharsOf(this.modeView?.attachments), Workbook)\n if ('refusal' in read) return read\n for (const sheet of read.files) out.push(new File([sheet.text], sheet.name, { type: 'text/csv' }))\n }\n return { files: out }\n }\n\n private readFileAsBase64(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => resolve(reader.result as string)\n reader.onerror = reject\n reader.readAsDataURL(file)\n })\n }\n\n private removeAttachment(id: string) {\n const target = this.attachments.find(a => a.id === id)\n if (target?.url) {\n URL.revokeObjectURL(target.url)\n }\n this.attachments = this.attachments.filter(a => a.id !== id)\n if (this.previewAttachmentId === id) this.previewAttachmentId = null\n }\n\n /** A pasted table goes back into the box as the words it was copied as - the conversion was not the person's choice. */\n private tableToWords(id: string) {\n const target = this.attachments.find(a => a.id === id)\n if (!target?.table) return\n this.input = appendWords(this.input, tableAsWords(target.table))\n this.removeAttachment(id)\n this.updateComplete.then(() => (this.renderRoot.querySelector('textarea') as HTMLTextAreaElement | null)?.focus())\n }\n\n /** The small box stands as tall as its text, up to 40% of the chat; the wide box fills what it covers. */\n private fitComposer() {\n const ta = this.renderRoot.querySelector('.input-row textarea') as HTMLTextAreaElement | null\n if (!ta) return\n if (this.composerWide) {\n ta.style.height = ''\n ta.style.overflowY = ''\n return\n }\n ta.style.height = '0px'\n const border = ta.offsetHeight - ta.clientHeight\n const resting = parseFloat(getComputedStyle(ta).minHeight) || 0\n const { height, scrolls } = composerHeight(ta.scrollHeight + border, this.clientHeight, resting)\n ta.style.height = `${height}px`\n ta.style.overflowY = scrolls ? 'auto' : 'hidden'\n }\n\n private setComposerWide(wide: boolean) {\n this.composerWide = wide\n if (wide) this.previewAttachmentId = null\n this.updateComplete.then(() => (this.renderRoot.querySelector('.input-row textarea') as HTMLTextAreaElement | null)?.focus())\n }\n\n private onComposerPaste(e: ClipboardEvent) {\n const items = e.clipboardData?.items\n if (!items || items.length === 0) return\n\n /*\n Rows copied from a spreadsheet or a web page travel as a file, so the entry card can check each row against\n its line. A spreadsheet also puts a picture of the cells on the clipboard - with the table taken, it is left.\n */\n if (this.usesAttachmentPolicy) {\n const pasted = pastedTableFile(\n { html: e.clipboardData?.getData('text/html'), text: e.clipboardData?.getData('text/plain') },\n this.modeView?.attachments,\n rows => String(i18next.t('ai-assistant.text.pasted-table-name', { rows, defaultValue: 'pasted table ({rows} rows)' }))\n )\n if (pasted) {\n e.preventDefault()\n if ('refusal' in pasted) {\n this.errorMessage = String(i18next.t(`ai-assistant.text.${pasted.refusal.code}`, { ...pasted.refusal, defaultValue: pasted.refusal.code }))\n return\n }\n const words = e.clipboardData?.getData('text/plain')\n this.onAttachFiles([new File([pasted.text], pasted.name, { type: 'text/csv' })], { ...pasted.table, text: words })\n return\n }\n }\n\n const files: File[] = []\n for (let i = 0; i < items.length; i++) {\n const item = items[i]\n if (item.kind === 'file') {\n const file = item.getAsFile()\n if (file) files.push(file)\n }\n }\n\n if (files.length > 0) {\n this.onAttachFiles(files)\n }\n }\n\n private onComposerDragOver(e: DragEvent) {\n e.preventDefault()\n e.stopPropagation()\n if (!this.dragOver) this.dragOver = true\n }\n\n private onComposerDragLeave(e: DragEvent) {\n e.preventDefault()\n e.stopPropagation()\n const currentTarget = e.currentTarget as HTMLElement\n const relatedTarget = e.relatedTarget as Node | null\n if (!currentTarget.contains(relatedTarget)) {\n this.dragOver = false\n }\n }\n\n private onComposerDrop(e: DragEvent) {\n e.preventDefault()\n e.stopPropagation()\n this.dragOver = false\n if (e.dataTransfer?.files?.length) {\n this.onAttachFiles(e.dataTransfer.files)\n }\n }\n\n /** mini action โ€” ์ธ๋ผ์ธ ์˜ˆ์‹œ ํ† ๊ธ€ */\n @state()\n private examplesOpen = false\n\n /** ๋ณต์‚ฌ toast ํ‘œ์‹œ ์ƒํƒœ */\n @state()\n private toastMessage?: string\n\n /** ๋ณต์‚ฌ confirmation feedback (๋ฉ”์‹œ์ง€ idx โ†’ ์งง์€ ์‹œ๊ฐ„ ๋™์•ˆ โœ“ ํ‘œ์‹œ) */\n @state()\n private copiedIdx?: number\n\n /** ์›๋ณธ JSON ์„ ํŽผ์นœ ๋‹จ๊ณ„(๋ผ์ธ:๋‹จ๊ณ„) โ€” ๋ชฉ๋ก์€ ํ•œ ์ค„ ์š”์•ฝ์œผ๋กœ ํ›‘๊ณ  ํ•„์š”ํ•œ ๊ฒƒ๋งŒ ํŽผ์นœ๋‹ค. */\n @state()\n private openToolSteps = new Set<string>()\n\n /** ์ด๋ฏธ ์‹คํ–‰์„ ์š”์ฒญํ•œ ์ œ์•ˆ ํ‚ค โ€” ๊ฐ™์€ ์นด๋“œ๋ฅผ ๋‘ ๋ฒˆ ๋ˆŒ๋Ÿฌ ๋˜๋Œ๋ฆด ์ˆ˜ ์—†๋Š” ๋ช…๋ น์ด ๋‘ ๋ฒˆ ๋‚˜๊ฐ€์ง€ ์•Š๊ฒŒ. */\n @state()\n private sentProposals = new Set<string>()\n\n /** Proposal keys the host has reported staged. Only the host knows; see `acknowledgeProposalStaged`. */\n @state()\n private stagedProposals = new Set<string>()\n\n /**\n * The host reports that it put this candidate somewhere the person can look at it.\n *\n * Staging happens outside this component โ€” a dock catches `assistant-proposal-preview`, hands\n * the candidate to a viewer, and only that host knows whether it worked, or whether it has a\n * viewer at all. So the card says nothing until the host calls this, and it then says it in the\n * words the host registered (`chatDefaults.stagedNoticeKey`).\n *\n * Safe to call for a candidate the card never showed; the key simply never matches.\n */\n acknowledgeProposalStaged(proposal: any): void {\n /*\n Silence has two meanings and they are not the same defect. A host that never calls this is\n telling us it does not know, and drawing nothing is right. A host that calls it without\n registering `stagedNoticeKey` meant to say something and left out the words -- staying quiet\n about that reads to whoever wired it as \"the badge just doesn't appear here\".\n\n The screen still shows nothing either way. There is no sentence to show, and inventing one is\n what this whole correction removed.\n */\n if (!this.conversation.stagedNotice && !OxAssistantChat.warnedMissingStagedNotice) {\n OxAssistantChat.warnedMissingStagedNotice = true\n console.warn(\n '[assistant-chat] a host reported a proposal staged but declared no staged notice, so the card can ' +\n 'say nothing. Declare `stagedNoticeKey` on the mode (the server translates it), or pass one to ' +\n '`registerChatDefaults` from a host with no mode.'\n )\n }\n\n this.stagedProposals = new Set(this.stagedProposals).add(this.proposalKey(proposal))\n }\n\n /** Once per page: the miss is a wiring mistake, and repeating it per candidate buries it. */\n private static warnedMissingStagedNotice = false\n\n /**\n * ์ด ๋Œ€ํ™”๊ฐ€ ๊ธธ์–ด์ ธ ์•ž๋ถ€๋ถ„์ด ํ”„๋กฌํ”„ํŠธ์—์„œ ์ ‘ํ˜”๋‹ค๋Š” **์‚ฌ์‹ค**(์„œ๋ฒ„ ๋ณด๊ณ ). ์ฃผ์ œ ์ดํƒˆ์„ ํŒ์ •ํ•œ ๊ฒƒ์ด\n * ์•„๋‹ˆ๋‹ค โ€” ํŒ์ •ํ•˜๋ฉด ์˜คํƒ์ด ์ƒ๊ธฐ๊ณ , ์˜คํƒ์ด ์ƒ๊ธฐ๋ฉด ์‚ฌ์šฉ์ž๋Š” ์•ˆ๋‚ด ์ž์ฒด๋ฅผ ๋ฌด์‹œํ•œ๋‹ค.\n * ์‚ฌ์‹ค๋งŒ ์•Œ๋ฆฌ๊ณ  \"์ƒˆ ๋Œ€ํ™”๋กœ ์‹œ์ž‘ํ• ์ง€\" ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ •ํ•œ๋‹ค.\n */\n @state()\n private historyFolded?: { omitted: number; summarized: boolean }\n\n /** ์•ˆ๋‚ด๋ฅผ ๋‹ซ์•˜๋Š”๊ฐ€ โ€” ํ•œ ๋ฒˆ ๋‹ซ์œผ๋ฉด ์ด ์„ธ์…˜์—์„œ๋Š” ๋‹ค์‹œ ๋„์šฐ์ง€ ์•Š๋Š”๋‹ค(์ž”์†Œ๋ฆฌ ๊ธˆ์ง€). */\n @state()\n private foldNoticeDismissed = false\n\n @state()\n private busy = false\n\n /** Host navigation may retain a conversation for reading while its subject is off screen. */\n @property() sendBlocked = ''\n\n /** The host may inspect navigation risk without reading or copying the person's input. */\n get navigationState(): { busy: boolean; draft: boolean } {\n return { busy: this.busy, draft: !!this.input.trim() || this.attachments.length > 0 }\n }\n\n @state()\n private errorMessage?: string\n\n /** C4 presence/roster โ€” ์„ธ์…˜ ์ฐธ์—ฌ์ž ๋ชฉ๋ก. lastSeenAt ์œผ๋กœ online ํŒ์ •. */\n @state()\n private participants: Array<{ id: string; role: string; lastSeenAt?: string; user?: { id: string; name?: string } }> = []\n\n /** roster online ์žฌํ‰๊ฐ€ ํŠธ๋ฆฌ๊ฑฐ โ€” heartbeat tick ๋งˆ๋‹ค ๊ฐฑ์‹ (์‹œ๊ฐ„ ๊ฒฝ๊ณผ ๋ฐ˜์˜). */\n @state()\n private _presenceTick = 0\n\n private _heartbeatTimer?: ReturnType<typeof setInterval>\n\n /** C4 ๊ทธ๋ฃน์ฑ— โ€” ๋ฉ”์‹œ์ง€ ์‹ค์‹œ๊ฐ„ ๋ฐฉ์†ก ๊ตฌ๋… ํ•ธ๋“ค + ์—์ฝ” dedup. */\n private _messageSub?: { unsubscribe: () => void }\n /** ์ด๋ฏธ transcript ์— ๋ฐ˜์˜๋œ ์„œ๋ฒ„ ๋ฉ”์‹œ์ง€ id ์ง‘ํ•ฉ โ€” ์ž๊ธฐ ์—์ฝ”ยท์ค‘๋ณต ๋ฐฉ์†ก ์ฐจ๋‹จ. */\n private _seenMessageIds = new Set<string>()\n /** optimistic ๋ผ์ธ ์ž„์‹œ ํ•ธ๋“ค ์‹œํ€€์Šค (index ๋น„์˜์กด reconcile ์šฉ). */\n private _localSeq = 0\n\n /** ํ˜„์žฌ ๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž email โ€” ๊ทธ๋ฃน์ฑ—์—์„œ ๋‚ด ๋ฉ”์‹œ์ง€ vs ํƒ€์ธ ๋ฉ”์‹œ์ง€ ๊ตฌ๋ถ„.\n * email ์„ ์“ฐ๋Š” ์ด์œ : /auth/profile ์ด ํ•ญ์ƒ ๋‚ด๋ ค์ฃผ๋Š” ๋กœ๊ทธ์ธ ์‹๋ณ„์ž์ด๊ณ (๋น„์–ด ์žˆ์ง€ ์•Š๋‹ค),\n * ๋‚ด๋ถ€ ๊ด€๋ฆฌํ‚ค(User.id)๋ฅผ ํด๋ผ์ด์–ธํŠธ ํŒ์ •์— ์˜์กดํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•จ. */\n private get _myEmail(): string | undefined {\n return (auth.credential as any)?.email\n }\n\n private get _myUserId(): string | undefined {\n return (auth.credential as any)?.id\n }\n\n /** Mention popup โ€” `#` (์ปดํฌ๋„ŒํŠธ) / `@` (์นดํƒˆ๋กœ๊ทธ) / `/` (slash) ํŠธ๋ฆฌ๊ฑฐ ์‹œ ํ™œ์„ฑ.\n * ๋‹จ์ผ popup ์žฌ์‚ฌ์šฉ โ€” mentionTrigger ๋กœ ํ™œ์„ฑ trigger ์ถ”์ . */\n @state()\n private mentionOpen = false\n\n /** popup ํ‘œ์‹œ์šฉ โ€” F-Finder ์ฒ˜๋Ÿผ matchType + matchValue ๋™๋ด‰๋œ ๊ฒฐ๊ณผ */\n @state()\n private mentionResults: FilterResult[] = []\n\n @state()\n private mentionActiveIndex = 0\n\n /** filter cap (50) ์œผ๋กœ ์ž˜๋ผ๋‚ธ ์ถ”๊ฐ€ ๋งค์นญ ์ˆ˜ โ€” popup ์˜ 'N more' ํ‘œ์‹œ์šฉ */\n @state()\n private mentionOverflow = 0\n\n /** ํ˜„์žฌ ํ™œ์„ฑ mention ์˜ textarea ๋‚ด trigger ์œ„์น˜ */\n private mentionHashPos = -1\n\n /** ํ˜„์žฌ ํ™œ์„ฑ trigger char โ€” '#' / '@' / '/'. popup ๋น„ํ™œ์„ฑ ์‹œ ์˜๋ฏธ ์—†์Œ. */\n private mentionTrigger: '#' | '@' | '/' = '#'\n\n /** popup ์—ด๊ธฐ ์ง์ „ ์‚ฌ์šฉ์ž selection ์Šค๋ƒ…์ƒท โ€” Esc/blur close ์‹œ ์›๋ณต์šฉ */\n private originalSelectedRefids: number[] = []\n\n /** popup ์—์„œ ๋ช…์‹œ ์„ ํƒ๋œ #mention ๋งคํ•‘ โ€” {token: refid}.\n * ์‚ฌ์šฉ์ž textarea ์—๋Š” #token ๋งŒ ๋ณด์ด์ง€๋งŒ server ํ•œํ…Œ๋Š” ์ •ํ™•ํ•œ refid ์ „๋‹ฌ.\n * send ์‹œ mutation input.mentions ๋กœ ํ•จ๊ป˜ ์ „์†ก. ์‚ฌ์šฉ์ž๊ฐ€ textarea ๋น„์šฐ๊ฑฐ๋‚˜\n * ์ƒˆ ์ฑ„ํŒ… ์‹œ์ž‘ํ•˜๋ฉด ์ •๋ฆฌ. */\n private pickedMentions: Map<string, number> = new Map()\n\n /** popup ์—์„œ ๋ช…์‹œ ์„ ํƒ๋œ @user ๋ฉ˜์…˜ ๋งคํ•‘ โ€” {token: userId}.\n * textarea ์—๋Š” @username ๋งŒ ๋ณด์ด์ง€๋งŒ server ํ•œํ…Œ๋Š” ์ •ํ™•ํ•œ userId ์ „๋‹ฌ.\n * send ์‹œ mutation input.userMentions ๋กœ ํ•จ๊ป˜ ์ „์†ก. */\n private pickedUserMentions: Map<string, string> = new Map()\n\n /** input ๋””๋ฐ”์šด์Šค timer โ€” 150ms ํ›„ refreshMentionPopup ์‹คํ–‰ (F-Finder ์™€ ๋™์ผ) */\n private inputDebounceTimer?: ReturnType<typeof setTimeout>\n\n /** centerTo ๋””๋ฐ”์šด์Šค timer โ€” arrow nav / hover ๋น ๋ฅผ ๋•Œ ์นด๋ฉ”๋ผ ์• ๋‹ˆ๋ฉ”์ด์…˜ race ๋ฐฉ์ง€ */\n private centerDebounceTimer?: ReturnType<typeof setTimeout>\n\n /*\n * โ”€โ”€ What this conversation is, resolved โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n *\n * A host that declares a mode gets the mode and nothing else โ€” a field it leaves out is empty,\n * never filled from these properties or the registered defaults. A host that has not declared\n * one keeps the separate properties and the global defaults it had before.\n */\n private get conversation() {\n return resolveConversation(\n this.mode,\n {\n hostContext: this.hostContext,\n chatEndpoint: this.chatEndpoint,\n /* A host with no mode still registers its wording as keys; it is translated here. */\n footerNotice: chatDefaults.footerNoticeKey ? i18next.t(chatDefaults.footerNoticeKey) : undefined,\n stagedNotice: chatDefaults.stagedNoticeKey ? i18next.t(chatDefaults.stagedNoticeKey) : undefined\n } as any,\n chatDefaults as any,\n this.modeView\n )\n }\n\n /**\n * What the server said this mode offers, in this person's language.\n *\n * Fetched when the mode changes and kept until the next one answers. Until it arrives the panel\n * offers nothing rather than the list some other package registered globally.\n */\n @state() private modeView?: AssistantModeView\n\n private modeViewToken = 0\n\n /** ์ด subject ์— ์„ค ์ˆ˜ ์žˆ๋Š” ๋Œ€ํ™”๋“ค โ€” ๊ธฐ๋ณธ์ด ๋จผ์ €. ํ•˜๋‚˜๋ฟ์ด๋ฉด ๊ณ ๋ฅด๊ฐœ๋ฅผ ๊ทธ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค. */\n @state() private modeChoices: { kind: string; label: string; isDefault: boolean }[] = []\n\n private modeChoicesToken = 0\n\n /**\n * ์ด ํ™”๋ฉด์— ์„ค ์ˆ˜ ์žˆ๋Š” ๋Œ€ํ™”๋ฅผ ์„œ๋ฒ„์— ๋ฌป๋Š”๋‹ค.\n *\n * ํ™”๋ฉด์ด ์ข…๋ฅ˜ ๋ชฉ๋ก์„ ์†์— ๋“ค๊ณ  ์žˆ์œผ๋ฉด, ๋Œ€ํ™”๋ฅผ ํ•˜๋‚˜ ๋” ์„ธ์šด ๋‚  ๊ทธ ํ™”๋ฉด๋งŒ ๋ชจ๋ฅธ ์ฑ„๋กœ ๋‚จ๋Š”๋‹ค. ๋ชฉ๋ก์€\n * ์•ฑ ์„œ๋ฒ„์˜ ์„ ์–ธ์—์„œ ๋‚˜์˜จ๋‹ค(ADR-0072 A17 โ‘ ).\n */\n private async loadModeChoices() {\n const subject = this.subject\n if (!subject) {\n this.modeChoices = []\n return\n }\n const token = ++this.modeChoicesToken\n try {\n const result = await client.query({\n query: ASSISTANT_MODES_QUERY,\n variables: { subject },\n fetchPolicy: 'cache-first'\n })\n if (token !== this.modeChoicesToken) return\n this.modeChoices = result.data?.assistantModes ?? []\n } catch {\n /*\n * ๋ชป ๋ฌผ์–ด๋ดค๋‹ค๊ณ  ํ™”๋ฉด์„ ๋ง‰์ง€ ์•Š๋Š”๋‹ค โ€” host ๊ฐ€ ์ค€ ๋Œ€ํ™”๋Š” ๊ทธ๋Œ€๋กœ ์‚ฐ๋‹ค. ๊ณ ๋ฅด๊ฐœ๋งŒ ์•ˆ ๋‚˜์˜จ๋‹ค.\n * ์—ฌ๊ธฐ์„œ ์˜ค๋ฅ˜ ๋ฌธ๊ตฌ๋ฅผ ๋„์šฐ๋ฉด ๊ณ ๋ฅผ ๊ฒƒ์ด ํ•˜๋‚˜๋ฟ์ธ ํ™”๋ฉด์—์„œ๋„ ๋นจ๊ฐ„ ์ค„์ด ๋œฌ๋‹ค.\n */\n if (token !== this.modeChoicesToken) return\n this.modeChoices = []\n }\n }\n\n /**\n * ์‚ฌ๋žŒ์ด ๋‹ค๋ฅธ ๋Œ€ํ™”๋ฅผ ๊ณจ๋ž๋‹ค.\n *\n * ๊ณ ๋ฅธ ๊ฒƒ์€ **์ด subject ์ข…๋ฅ˜์— ๋Œ€ํ•ด** ๊ธฐ์–ตํ•œ๋‹ค โ€” ๋ณด๋“œ๋ฅผ ์—ด ๋•Œ๋งˆ๋‹ค ์ €์ž‘ ๋Œ€ํ™”๋กœ ๋Œ์•„๊ฐ€๋ฉด, ํ˜„์žฅ์„\n * ๋ฌผ์œผ๋ ค๋˜ ์‚ฌ๋žŒ์€ ํ™”๋ฉด์„ ์—ด ๋•Œ๋งˆ๋‹ค ๊ฐ™์€ ์†์งˆ์„ ๋‹ค์‹œ ํ•ด์•ผ ํ•œ๋‹ค. ๊ธฐ์–ต์€ ์ด ๋ธŒ๋ผ์šฐ์ €์—๋งŒ ๋‚จ๋Š”๋‹ค\n * (์„œ๋ฒ„์— ์นธ์„ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค โ€” A17 โ‘ ). ์„ธ์…˜ ์ž์ฒด๋Š” ์ž๊ธฐ๊ฐ€ ์–ด๋А ๋Œ€ํ™”์˜€๋Š”์ง€ ์ด๋ฏธ ์•ˆ๋‹ค.\n */\n private onModePick(kind: string) {\n if (!this.mode || kind === this.mode.kind) return\n try {\n if (this.subject) localStorage.setItem(`assistant-mode:${this.subject}`, kind)\n } catch {\n /* ์ €์žฅ์ด ๋ง‰ํžŒ ๋ธŒ๋ผ์šฐ์ €์—์„œ๋„ ๊ณ ๋ฅด๊ธฐ ์ž์ฒด๋Š” ๋œ๋‹ค โ€” ๋‹ค์Œ์— ๋‹ค์‹œ ๊ณ ๋ฅด๋ฉด ๋  ๋ฟ์ด๋‹ค. */\n }\n this.askHostForMode(kind)\n }\n\n /**\n * **๊ณ ๋ฅด๋Š” ๊ฒƒ์€ ์ฒญํ•˜๋Š” ์ผ์ด๋‹ค** โ€” `mode` ๋ฅผ ์—ฌ๊ธฐ์„œ ๋ฐ”๊พธ์ง€ ์•Š๋Š”๋‹ค.\n *\n * host ๋Š” ๋ Œ๋”๋งˆ๋‹ค `mode` ๋ฅผ ๋‹ค์‹œ ๋‚ด๋ ค ์ค€๋‹ค. ํŒจ๋„์ด ์ž๊ธฐ ์†์œผ๋กœ ๊ณ ์ณ ๋‘๋ฉด ๋‹ค์Œ ๋ Œ๋”๊ฐ€ ๊ทธ๊ฒƒ์„ ๋ฎ๊ณ ,\n * ๋” ๋‚˜์œ ๊ฒƒ์€ host ๊ฐ€ **์ž๊ธฐ๊ฐ€ ๋ฌด์—‡์„ ์—ด์—ˆ๋Š”์ง€ ๋ชจ๋ฅด๋Š” ์ฑ„๋กœ ๋‚จ๋Š”๋‹ค**๋Š” ๊ฒƒ์ด๋‹ค. host ๋Š” ๋Œ€ํ™”์˜ ์„ธ์…˜์„\n * ๋Œ€์ƒ๋ณ„๋กœ ๋“ค๊ณ  ์žˆ์œผ๋ฏ€๋กœ, ๋Œ€ํ™”๊ฐ€ ๋ฐ”๋€ ๊ฒƒ์„ ๋ชจ๋ฅด๋ฉด ์•ž ๋Œ€ํ™”์˜ ์„ธ์…˜์„ ๊ทธ๋Œ€๋กœ ๋„˜๊ธด๋‹ค โ€” ๊ทธ๋Ÿฌ๋ฉด ์ƒˆ ๋ง์ด ์•ž\n * ๋Œ€ํ™”์— ๋ถ™๋Š”๋‹ค(2026-09-18 Figure ๋ ˆ์ธ์ด :3300 ์—์„œ ๋ณธ ๊ฒƒ์ด ์ด๊ฒƒ์ด๋‹ค).\n *\n * ๊ทธ๋ž˜์„œ ์ฃผ์ธ์€ ํ•˜๋‚˜๋‹ค: host ๊ฐ€ `mode` ๋ฅผ ๊ฐ–๊ณ , ํŒจ๋„์€ ใ€Œ์ด๊ฒƒ์œผ๋กœ ๋ฐ”๊ฟ” ๋‹ฌ๋ผใ€๊ณ  ๋งํ•œ๋‹ค. ๊ธฐ์–ต์€ ํŒจ๋„์ด\n * ์ง„๋‹ค(๋ธŒ๋ผ์šฐ์ €๋งˆ๋‹ค ๋‹ค๋ฅธ ๊ฐ’์ด๋ผ host ๊ฐ€ ์งˆ ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค) โ€” ๊ธฐ์–ตํ•œ ๊ฒƒ์„ ๋˜์‚ด๋ฆด ๋•Œ๋„ ๊ฐ™์€ ์ฒญ์œผ๋กœ ๋‚˜๊ฐ„๋‹ค.\n */\n private askHostForMode(kind: string) {\n this.dispatchEvent(\n new CustomEvent('assistant-mode-change', { detail: { kind, subject: this.subject }, bubbles: true, composed: true })\n )\n }\n\n /** ์ด subject ์—์„œ ์ง€๋‚œ๋ฒˆ์— ๊ณ ๋ฅธ ๋Œ€ํ™” โ€” ์—†์œผ๋ฉด undefined. */\n private rememberedMode(subject: string): string | undefined {\n try {\n return localStorage.getItem(`assistant-mode:${subject}`) ?? undefined\n } catch {\n return undefined\n }\n }\n\n private async loadModeView() {\n const mode = this.mode\n if (!mode?.kind) {\n this.modeView = undefined\n return\n }\n const token = ++this.modeViewToken\n try {\n const result = await client.query({ query: ASSISTANT_MODE_QUERY, variables: { kind: mode.kind }, fetchPolicy: 'cache-first' })\n /* A late answer for a conversation the person has already left is dropped. */\n if (token !== this.modeViewToken) return\n this.modeView = result.data?.assistantMode\n this.rebuildMentionCaches()\n } catch (error) {\n if (token !== this.modeViewToken) return\n this.modeView = undefined\n /*\n * A kind this server does not have is a mismatched deployment, and the person should read it\n * rather than watch an empty `/` list.\n */\n this.errorMessage = error instanceof Error ? error.message : String(error)\n }\n }\n\n /*\n * The `@` and `/` candidates, built once per mode.\n *\n * These were built at field initialisation, which meant a host could not change what the\n * panel offers without replacing the element. A mode change rebuilds them below.\n */\n private cachedCatalogCandidates: MentionCandidate[] = buildCatalogCandidates(chatDefaults.catalogEntries)\n\n private cachedSlashCandidates: MentionCandidate[] = buildSlashCandidates(chatDefaults.slashTemplates)\n\n private rebuildMentionCaches() {\n this.cachedCatalogCandidates = buildCatalogCandidates(this.conversation.catalogEntries)\n this.cachedSlashCandidates = buildSlashCandidates(this.conversation.slashTemplates)\n }\n\n /** `@` ๋งˆ์ง€๋ง‰ query ์˜ ๋„๋ฉ”์ธ ์‚ฌ์šฉ์ž ํ›„๋ณด ์บ์‹œ โ€” userProvider ์‘๋‹ต ๋„์ฐฉ ์‹œ ๊ฐฑ์‹ .\n * query ๋ณ„ ์บ์‹œ๊ฐ€ ์•„๋‹ˆ๋ผ ๋‹จ์ˆœ \"์ตœ๊ทผ ๊ฒฐ๊ณผ\" โ€” async race ํšŒํ”ผ. */\n private cachedUserCandidates: MentionCandidate[] = []\n\n /** ์ง„ํ–‰ ์ค‘์ธ userProvider fetch token โ€” ๋Šฆ๊ฒŒ ๋„์ฐฉํ•œ ์‘๋‹ต์ด ์ตœ์‹ ์„ ๋ฎ์–ด์“ฐ์ง€ ์•Š๋„๋ก ์‹๋ณ„. */\n private userFetchToken = 0\n\n static styles = [\n // ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ‘œ์ค€ ์Šคํฌ๋กค๋ฐ” (--scrollbar-width / --scrollbar-thumb-color ๋“ฑ ํ˜ธ์ŠคํŠธ ๋ณ€์ˆ˜ ๋”ฐ๋ฆ„)\n ScrollbarStyles,\n css`\n /*\n Material Design 3 ํ† ํฐ ์‚ฌ์šฉ โ€” ์‚ฌ์šฉ์ž ํ…Œ๋งˆ (๋ผ์ดํŠธ/๋‹คํฌ/๋ธŒ๋žœ๋“œ) ์ž๋™ ๋ฐ˜์˜.\n ๊ฐ var() ์˜ ๋‘ ๋ฒˆ์งธ ์ธ์ž๋Š” ํ† ํฐ ๋ฏธ์ •์˜ ์‹œ fallback (ํ˜„ ๋””์ž์ธ ํ†ค).\n */\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 240px;\n position: relative;\n font:\n 400 11px / 1.55 -apple-system,\n BlinkMacSystemFont,\n 'Inter',\n 'Pretendard',\n 'Segoe UI',\n Roboto,\n sans-serif;\n letter-spacing: -0.005em;\n color: var(--md-sys-color-on-surface, #0f172a);\n background: var(--md-sys-color-surface, #ffffff);\n }\n\n /* โ”€โ”€ C4 Roster (participants + presence) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n /* ์ด ๋Œ€ํ™”์˜ ์ฃผ์–ด โ€” ๊ฐ™์€ ํ™”๋ฉด ์œ„์— ๋‘ ๋Œ€ํ™”๊ฐ€ ์„ค ๋•Œ๋งŒ ๋‚˜์˜จ๋‹ค(ADR-0072 A17 โ‘ ).\n ์ง€๊ธˆ ๋Œ€ํ™”๊ฐ€ ์ œ๋ชฉ ๊ตต๊ธฐ๋กœ ์„œ๊ณ , ๋ฐ”๊ฟ€ ์ž๋ฆฌ๊ฐ€ ๊ทธ ์˜†์— ๋ถ™๋Š”๋‹ค. ์„ธ์…˜ ํƒญ๊ณผ ๊ฐ™์€ ๋ฌด๊ฒŒ๋กœ ๊ทธ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค\n (UX ๋ ˆ์ธ, 2026-09-18) โ€” ํ•œ์ชฝ์€ ํ™”์ œ๋ฅผ ๋ฐ”๊พธ๊ณ  ํ•œ์ชฝ์€ ์‹คํƒ€๋ž˜๋ฅผ ๋ฐ”๊พผ๋‹ค. */\n .mode-subject {\n display: flex;\n align-items: baseline;\n gap: 8px;\n padding: 6px 12px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n }\n .mode-now {\n /* ๊ณ ๋ฅธ ์ƒํƒœ์˜ ์ƒ‰์€ ์„ธ์…˜ ํƒญ๊ณผ ๊ฐ™์€ ๊ณ„์—ด์ด๋‹ค โ€” ํ•œ ํŒจ๋„ ์•ˆ์—์„œ ใ€Œ๊ณจ๋ž๋‹คใ€๊ฐ€ ๋‘ ์ƒ‰์œผ๋กœ ๋‚˜์˜ค๋ฉด ์ฝ๋Š”\n ์‚ฌ๋žŒ์€ ๋‘ ์ƒ‰์ด ์„œ๋กœ ๋‹ค๋ฅธ ๋œป์ธ ์ค„ ์•ˆ๋‹ค.\n\n 12px ์ด์—ˆ๋‹ค๊ฐ€ ํ•œ ๋‹จ ๋‚ด๋ ธ๋‹ค. ๋„ํฌ ์ œ๋ชฉ(figure ์˜ .scope-title ์ด 12.5px / 650)๊ณผ 0.5px ยท\n ๊ตต๊ธฐ 50 ์ฐจ์ด๋Š” ๋ˆˆ์— ๋‹ฟ์ง€ ์•Š์•„์„œ, ๊ฑฐ์˜ ๊ฐ™์€ ์ œ๋ชฉ ์ค„์ด ๋‘˜ ํฌ๊ฐœ์กŒ๋‹ค. ๋„ํฌ ์ œ๋ชฉ์€ ๊ทธ ๋„ํฌ ์ „์ฒด๋ฅผ\n ๊ฑฐ๋А๋ฆฌ๊ณ  ์ด ์ค„์€ ๊ทธ ์•ˆ ๋Œ€ํ™” ํ•˜๋‚˜์˜ ์„ฑ์งˆ์ด๋‹ค โ€” 11px ์ด๋ฉด ์ด ํŒจ๋„์˜ ๋‹ค๋ฅธ ์กฐ์ž‘๋ถ€์™€ ๊ฐ™์€ ๋‹จ์ด๊ณ ,\n ใ€Œ์ด๊ฒƒ์ด ์ฃผ์–ด๋‹คใ€๋Š” ์ƒ‰์ด ๊ณ„์† ์ง„๋‹ค(UX ๋ ˆ์ธ, 2026-09-18). */\n color: var(--primary-color, #007f87);\n font-size: 11px;\n font-weight: 600;\n }\n .mode-switch,\n .mode-select {\n appearance: none;\n background: transparent;\n border: 1px solid var(--md-sys-color-outline-variant, #cbd5e1);\n border-radius: 999px;\n color: var(--md-sys-color-on-surface-variant, #475569);\n cursor: pointer;\n font: inherit;\n font-size: 11px;\n padding: 2px 10px;\n white-space: nowrap;\n }\n .mode-switch:hover:not([disabled]) {\n background: color-mix(in srgb, var(--primary-color, #007f87) 7%, transparent);\n color: var(--primary-color, #007f87);\n }\n /* ๋‹ตํ•˜๋Š” ๋™์•ˆ์—๋„ ใ€Œ๋‚ด๊ฐ€ ์ง€๊ธˆ ๋ฌด์—‡์— ๋Œ€ํ•ด ๋งํ•˜๊ณ  ์žˆ๋‚˜ใ€๋Š” ๋˜๋ ทํ•ด์•ผ ํ•œ๋‹ค โ€” ํ๋ ค์ง€๋Š” ๊ฒƒ์€ ๋ฐ”๊ฟ€\n ์ž๋ฆฌ๋ฟ์ด๋‹ค. ์ง€๊ธˆ ๋Œ€ํ™”๊นŒ์ง€ ํ๋ฆฌ๋ฉด ๊ทธ ํ•œ ์ค„์ด ๊ฐ€์žฅ ์•ˆ ๋ณด์ธ๋‹ค. */\n .mode-subject [disabled] {\n cursor: default;\n opacity: 0.5;\n }\n\n .roster {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 4px;\n padding: 4px 8px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n }\n .roster-count {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n font-size: 10px;\n opacity: 0.7;\n margin-right: 2px;\n }\n .roster-count md-icon {\n font-size: 13px;\n width: 13px;\n height: 13px;\n }\n .roster-chip {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 1px 6px 1px 4px;\n border-radius: 9px;\n font-size: 10px;\n background: var(--md-sys-color-surface-variant, #f1f5f9);\n }\n .roster-chip.offline {\n opacity: 0.45;\n }\n .roster-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #cbd5e1;\n }\n .roster-chip.online .roster-dot {\n background: #22c55e;\n }\n\n /* โ”€โ”€ Session tabs โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .session-tabs {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 4px 6px 0 6px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n background: var(--md-sys-color-surface-container-low, #fafbfc);\n overflow-x: auto;\n scrollbar-width: thin;\n flex-shrink: 0;\n }\n .session-tab {\n flex-shrink: 0;\n padding: 4px 10px;\n font-size: 11px;\n line-height: 1.4;\n color: var(--md-sys-color-on-surface-variant, #64748b);\n background: transparent;\n border: 1px solid transparent;\n border-bottom: 0;\n border-top-left-radius: 5px;\n border-top-right-radius: 5px;\n cursor: pointer;\n max-width: 160px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n .session-tab:hover {\n background: var(--md-sys-color-surface-container, #f1f5f9);\n }\n .session-tab.active {\n background: var(--md-sys-color-surface, #ffffff);\n color: var(--md-sys-color-on-surface, #0f172a);\n border-color: var(--md-sys-color-outline-variant, #e2e8f0);\n font-weight: 500;\n position: relative;\n }\n .session-tab.active::after {\n content: '';\n position: absolute;\n left: 0;\n right: 0;\n bottom: -1px;\n height: 1px;\n background: var(--md-sys-color-surface, #ffffff);\n }\n .session-tab-new {\n flex-shrink: 0;\n padding: 4px 8px 4px 6px;\n background: transparent;\n border: 0;\n cursor: pointer;\n color: var(--md-sys-color-on-surface-variant, #64748b);\n display: inline-flex;\n align-items: center;\n gap: 2px;\n font-size: 11px;\n line-height: 1.4;\n border-radius: 5px;\n white-space: nowrap;\n }\n .session-tab-new:hover {\n color: var(--md-sys-color-primary, #2563eb);\n background: var(--md-sys-color-surface-container, #f1f5f9);\n }\n .session-tab-new md-icon {\n --md-icon-size: 14px;\n font-size: 14px;\n }\n\n /* โ”€โ”€ Messages โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n /* ์Šคํฌ๋กค๋ฐ”๋Š” ScrollbarStyles (์œ„์ชฝ styles ๋ฐฐ์—ด) ๊ฐ€ ์ฒ˜๋ฆฌ โ€” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ‘œ์ค€ ๋”ฐ๋ฆ„ */\n .messages {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden; /* ๊ฐ€๋กœ ์Šคํฌ๋กค ์ฐจ๋‹จ โ€” ์ž์‹ (empty / msg) ๋‚ด๋ถ€์—์„œ wrap ์ฒ˜๋ฆฌ */\n padding: 10px 16px 4px;\n display: flex;\n flex-direction: column;\n gap: 4px; /* ๋‹จ์ผ spacing source โ€” .msg-wrap ์˜ ์ž์ฒด margin ์€ 0 */\n scroll-behavior: smooth;\n min-width: 0; /* flex item ์˜ ๊ธฐ๋ณธ min-content ๋ฌด์‹œ โ€” ์ž์‹ ellipsis/wrap ๋™์ž‘ */\n }\n\n /* โ”€โ”€ Empty state โ€” onboarding ๊ฐ€์ด๋“œ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .empty {\n margin: auto;\n text-align: left;\n width: 100%;\n max-width: 360px;\n box-sizing: border-box;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 16px;\n word-break: break-word; /* ๊ธด ํ•œ๊ธ€ / URL ๋„ ์ค„๋ฐ”๊ฟˆํ•ด ๊ฐ€๋กœ overflow ๋ฐฉ์ง€ */\n overflow-wrap: anywhere;\n }\n .empty .header {\n text-align: center;\n padding: 8px 0 4px;\n }\n .empty .icon {\n font-size: 22px;\n opacity: 0.4;\n margin-bottom: 8px;\n color: var(--md-sys-color-primary, currentColor);\n display: block;\n }\n .empty .title {\n color: var(--md-sys-color-on-surface, #0f172a);\n font-size: 12.5px;\n font-weight: 600;\n margin-bottom: 4px;\n letter-spacing: -0.01em;\n }\n .empty .subtitle {\n color: var(--md-sys-color-on-surface-variant, #475569);\n font-size: 10.5px;\n line-height: 1.5;\n }\n\n .empty .group {\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n .empty .group-label {\n font-size: 9.5px;\n color: var(--md-sys-color-outline, #94a3b8);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n font-weight: 600;\n padding: 0 2px;\n }\n .empty .example {\n all: unset;\n display: block;\n cursor: pointer;\n padding: 7px 10px;\n font-size: 11px;\n color: var(--md-sys-color-on-surface, #0f172a);\n background: var(--md-sys-color-surface-container, #f8fafc);\n border: 1px solid var(--md-sys-color-outline-variant, #eef2f6);\n border-radius: 8px;\n line-height: 1.5;\n box-sizing: border-box;\n width: 100%;\n max-width: 100%;\n word-break: break-word;\n overflow-wrap: anywhere;\n transition:\n background 0.15s,\n border-color 0.15s,\n transform 0.1s;\n }\n .empty .example:hover {\n background: var(--md-sys-color-surface-container-high, #f1f5f9);\n border-color: var(--md-sys-color-outline, #cbd5e1);\n }\n .empty .example:active {\n transform: scale(0.99);\n }\n .empty .example .arrow {\n float: right;\n opacity: 0.4;\n margin-left: 8px;\n font-size: 11px;\n }\n\n .empty .footer {\n margin-top: 4px;\n padding: 8px 4px 0;\n border-top: 1px solid var(--md-sys-color-outline-variant, #eef2f6);\n color: var(--md-sys-color-outline, #94a3b8);\n font-size: 10px;\n line-height: 1.6;\n text-align: center;\n }\n .empty .footer .badge {\n display: inline-block;\n margin: 0 4px;\n padding: 1px 7px;\n background: var(--md-sys-color-surface-container, #f8fafc);\n border-radius: 8px;\n font-size: 9.5px;\n color: var(--md-sys-color-on-surface-variant, #64748b);\n }\n /* โ”€โ”€ Trigger chip row (empty state) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .empty .trigger-row {\n margin: 12px 0 4px;\n padding: 10px 12px;\n background: var(--md-sys-color-surface-container-low, #f8fafc);\n border: 1px solid var(--md-sys-color-outline-variant, #eef2f6);\n border-radius: 10px;\n }\n .empty .trigger-row-label {\n font-size: 10px;\n color: var(--md-sys-color-on-surface-variant, #64748b);\n margin-bottom: 6px;\n text-align: center;\n letter-spacing: 0.02em;\n }\n .empty .trigger-chips {\n display: flex;\n gap: 6px;\n justify-content: center;\n flex-wrap: wrap;\n }\n .empty .trigger-chip {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 10px;\n background: var(--md-sys-color-surface, #ffffff);\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n border-radius: 18px;\n cursor: pointer;\n font-size: 11.5px;\n color: var(--md-sys-color-on-surface, #0f172a);\n transition:\n border-color 0.15s,\n background 0.15s,\n color 0.15s;\n }\n .empty .trigger-chip:hover {\n border-color: var(--md-sys-color-primary, #2563eb);\n background: var(--md-sys-color-primary-container, #dbeafe);\n color: var(--md-sys-color-on-primary-container, #1e3a8a);\n }\n .empty .trigger-chip .trigger-char {\n font-family:\n 'SF Mono',\n Menlo,\n Monaco,\n Consolas,\n monospace;\n font-size: 13px;\n font-weight: 600;\n color: var(--md-sys-color-primary, #2563eb);\n min-width: 12px;\n text-align: center;\n }\n .empty .trigger-chip:hover .trigger-char {\n color: var(--md-sys-color-on-primary-container, #1e3a8a);\n }\n .empty .trigger-chip .trigger-desc {\n font-weight: 500;\n }\n\n /* โ”€โ”€ Message label (sender hint) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .msg-label {\n font-size: 9.5px;\n color: var(--md-sys-color-outline, #94a3b8);\n letter-spacing: 0.05em;\n font-weight: 500;\n text-transform: uppercase;\n margin: 4px 0 1px 4px;\n align-self: flex-start;\n }\n .msg-label:first-child {\n margin-top: 0;\n }\n\n /* โ”€โ”€ Message wrapper (๋ฉ”์‹œ์ง€ + hover ์•ก์…˜) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .msg-wrap {\n display: flex;\n flex-direction: column;\n width: fit-content;\n max-width: min(92%, 420px);\n /* margin 0 โ€” spacing ์€ .messages gap ๋‹จ์ผ source */\n }\n .msg-wrap.user {\n align-self: flex-end;\n align-items: flex-end;\n }\n .msg-wrap.assistant {\n align-self: flex-start;\n align-items: flex-start;\n }\n .msg-wrap.system {\n align-self: center;\n align-items: center;\n max-width: 100%;\n }\n\n /* โ”€โ”€ Message bubble โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .msg {\n display: inline-block;\n width: fit-content;\n max-width: 100%;\n padding: 5px 9px;\n border-radius: 10px;\n white-space: normal;\n overflow-wrap: anywhere;\n font-size: 11px;\n line-height: 1.45;\n }\n\n .msg.user {\n align-self: flex-end;\n background: var(--md-sys-color-primary, #1e293b);\n color: var(--md-sys-color-on-primary, #f8fafc);\n border-radius: 12px 12px 3px 12px;\n /* margin-top 0 โ€” .messages gap ์œผ๋กœ๋งŒ spacing */\n }\n\n /* ๊ทธ๋ฃน์ฑ— โ€” ๋‹ค๋ฅธ ์ฐธ์—ฌ์ž์˜ ๋ฉ”์‹œ์ง€. ๋‚ด ๋ฉ”์‹œ์ง€(์šฐ์ธก primary)์™€ ๊ตฌ๋ถ„: ์ขŒ์ธก ์ •๋ ฌ + ๋ณด์กฐ ์ƒ‰. */\n .msg-wrap.user.other {\n align-self: flex-start;\n align-items: flex-start;\n }\n .msg.user.other {\n align-self: flex-start;\n background: var(--md-sys-color-secondary-container, #e2e8f0);\n color: var(--md-sys-color-on-secondary-container, #0f172a);\n border-radius: 12px 12px 12px 3px;\n }\n /* ๋ฐœ์‹ ์ž ์ด๋ฆ„ ๋ผ๋ฒจ โ€” AI ๋ผ๋ฒจ(๋Œ€๋ฌธ์ž)๊ณผ ๋‹ฌ๋ฆฌ ์‚ฌ๋žŒ ์ด๋ฆ„์€ ๊ทธ๋Œ€๋กœ. */\n .msg-label.sender {\n text-transform: none;\n letter-spacing: 0;\n color: var(--md-sys-color-primary, #475569);\n }\n\n .msg.assistant {\n align-self: flex-start;\n background: var(--md-sys-color-surface-container, #f8fafc);\n color: var(--md-sys-color-on-surface, #0f172a);\n border: 1px solid var(--md-sys-color-outline-variant, #eef2f6);\n border-radius: 12px 12px 12px 3px;\n }\n\n /* โ”€โ”€ Markdown ๋ Œ๋” (AI ์‘๋‹ต) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .md-body {\n display: block;\n }\n .md-body > :first-child {\n margin-top: 0;\n }\n .md-body > :last-child {\n margin-bottom: 0;\n }\n .md-body p {\n margin: 0 0 4px;\n line-height: 1.45;\n }\n .md-body ul,\n .md-body ol {\n margin: 2px 0 4px;\n padding-left: 16px;\n }\n .md-body li {\n margin: 0;\n line-height: 1.45;\n }\n .md-body li > p {\n margin: 0;\n }\n .md-body strong {\n font-weight: 600;\n }\n .md-body em {\n font-style: italic;\n }\n /* '#token' mention โ€” popup ์˜ match-badge ํ†ค๊ณผ ๋งž์ถค. ์ฑ„ํŒ… ๋ฒ„๋ธ”์—์„œ ์ปดํฌ๋„ŒํŠธ\n ์ฐธ์กฐ์ž„์„ ์‹œ๊ฐ์ ์œผ๋กœ ๊ตฌ๋ถ„ (์‚ฌ์šฉ์ž/AI ๋ฉ”์‹œ์ง€ ์–‘์ชฝ). */\n .md-body .mention {\n display: inline-block;\n padding: 0 5px;\n border-radius: 4px;\n background: var(--md-sys-color-primary-container, rgba(37, 99, 235, 0.12));\n color: var(--md-sys-color-on-primary-container, #1e40af);\n font-weight: 500;\n white-space: nowrap;\n cursor: pointer;\n transition: background 0.12s;\n }\n .md-body .mention:hover {\n background: var(--md-sys-color-primary, rgba(37, 99, 235, 0.25));\n color: var(--md-sys-color-on-primary, #ffffff);\n }\n .msg.user .md-body .mention {\n background: rgba(255, 255, 255, 0.22);\n color: inherit;\n }\n .msg.user .md-body .mention:hover {\n background: rgba(255, 255, 255, 0.40);\n }\n .md-body code {\n font-family:\n 'SF Mono',\n Menlo,\n Monaco,\n Consolas,\n monospace;\n font-size: 10px;\n padding: 1px 4px;\n background: var(--md-sys-color-surface-container-high, rgba(15, 23, 42, 0.06));\n border-radius: 3px;\n }\n .md-body pre {\n margin: 5px 0;\n padding: 6px 8px;\n background: var(--md-sys-color-surface-container-high, rgba(15, 23, 42, 0.06));\n border-radius: 5px;\n overflow-x: auto;\n font-size: 10px;\n line-height: 1.5;\n }\n /* user ๋ฉ”์‹œ์ง€(์–ด๋‘์šด ๋ฐฐ๊ฒฝ) ์œ„์—์„œ๋Š” code/pre ์˜ contrast ๋ณด์ • */\n .msg.user .md-body code,\n .msg.user .md-body pre {\n background: rgba(255, 255, 255, 0.15);\n }\n .msg.user .md-body a {\n color: inherit;\n text-decoration: underline;\n text-underline-offset: 2px;\n }\n .msg.user .md-body blockquote {\n border-left-color: rgba(255, 255, 255, 0.3);\n color: rgba(255, 255, 255, 0.85);\n }\n .msg.user .md-body hr {\n border-top-color: rgba(255, 255, 255, 0.2);\n }\n .md-body pre code {\n padding: 0;\n background: transparent;\n font-size: inherit;\n }\n .md-body a {\n color: var(--md-sys-color-primary, #1e293b);\n text-decoration: underline;\n text-underline-offset: 2px;\n }\n .md-body a:hover {\n text-decoration: none;\n }\n .md-body h1,\n .md-body h2,\n .md-body h3,\n .md-body h4 {\n margin: 4px 0 2px;\n font-weight: 600;\n line-height: 1.35;\n }\n .md-body h1 { font-size: 13px; }\n .md-body h2 { font-size: 12px; }\n .md-body h3,\n .md-body h4 { font-size: 11.5px; }\n .md-body blockquote {\n margin: 4px 0;\n padding: 1px 8px;\n border-left: 2px solid var(--md-sys-color-outline-variant, #cbd5e1);\n color: var(--md-sys-color-on-surface-variant, #64748b);\n }\n .md-body hr {\n border: 0;\n border-top: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n margin: 6px 0;\n }\n .md-body table {\n border-collapse: collapse;\n margin: 4px 0;\n font-size: 10px;\n }\n .md-body th,\n .md-body td {\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n padding: 2px 6px;\n }\n .md-body th {\n background: var(--md-sys-color-surface-container, #f8fafc);\n font-weight: 600;\n }\n\n .msg.system {\n align-self: center;\n background: transparent;\n color: var(--md-sys-color-outline, #94a3b8);\n font-size: 10px;\n font-style: italic;\n max-width: 100%;\n padding: 2px 8px;\n margin: 0;\n border: 0;\n }\n /* ์‹œ์Šคํ…œ ๊ธฐ๋ก์€ **๊ณ์ค„**์ด๋‹ค โ€” ๊ธธ๋ฉด ํ™”๋ฉด์„ ์žก์•„๋จน์–ด ๋Œ€ํ™”๊ฐ€ ์•ˆ ๋ณด์ธ๋‹ค(์˜ฎ๊ฒจ์˜จ ๋Œ€ํ™”๋ฅผ ํ•œ ๋ฉ์–ด๋ฆฌ๋กœ\n ๋„ฃ์—ˆ์„ ๋•Œ ์‹ค์ œ๋กœ ๊ทธ๋žฌ๋‹ค). ์„ธ ์ค„๋กœ ์ ‘๊ณ  ๋ˆŒ๋Ÿฌ์„œ ํŽผ์นœ๋‹ค. */\n .msg.system .sys-text {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 3;\n overflow: hidden;\n white-space: pre-wrap;\n cursor: pointer;\n }\n .msg.system.open .sys-text {\n display: block;\n -webkit-line-clamp: unset;\n overflow: visible;\n }\n\n /* ๊ฐ’์ด ์•ˆ ์˜จ ์ค„ โ€” ADR-0073 ํŒ์ • 1.\n ๋งํ’์„ ์˜ ์ž๋ฆฌ์™€ ใ€ŒAIใ€ ๋”ฑ์ง€๋Š” ์ง€ํ‚จ๋‹ค โ€” ๊ทธ ์ค„์€ ์–ด์‹œ์Šคํ„ดํŠธ์˜ ๋‹ต์ด ๋งž๊ณ , ์ฝ๋Š” ์‚ฌ๋žŒ์ด ๋ชป ์ง€๋‚˜๊ฐ„\n ๊ฒƒ์ด๋‹ค. ์ ์„  ํ…Œ๋‘๋ฆฌ์™€ ํ๋ฆฐ ์ƒ‰์ด ใ€Œ์ด๊ฒƒ์€ ๊ทธ๊ฐ€ ์“ด ๋ฌธ์žฅ์ด ์•„๋‹ˆ๋‹คใ€๋ฅผ ๋งํ•œ๋‹ค.\n\n ๊ธฐ์šธ์ž„์€ ์“ฐ์ง€ ์•Š๋Š”๋‹ค. ์ด ์•ฑ์˜ ๊ธ€๊ผด ๋ฌถ์Œ์— ํ•œ๊ธ€ ์ดํƒค๋ฆญ ์ž์†Œ๊ฐ€ ์—†์–ด ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ•ฉ์„ฑ์œผ๋กœ ๊ธฐ์šธ์ด๊ณ ,\n ํš ๊ท ํ˜•์ด ๋ฌด๋„ˆ์ ธ ์ž‘์€ ๊ธ€์ž๊ฐ€ ๋จผ์ € ์•ˆ ์ฝํžŒ๋‹ค. UX ๋ ˆ์ธ์ด :4000 ์—์„œ ์žฌ ๋ณด์•˜๋‹ค โ€” ใ€Œ๊ถŒํ•œใ€์˜ ์ง„ํ–‰\n ํญ์ด normalยทitalic ๋‘˜ ๋‹ค 27.6875px ๋กœ ๊ฐ™๋‹ค(2026-09-18). */\n .msg.redacted {\n background: transparent;\n border: 1px dashed var(--md-sys-color-outline-variant, #cbd5e1);\n color: var(--md-sys-color-outline, #94a3b8);\n }\n .redacted-body {\n align-items: center;\n display: flex;\n gap: 6px;\n }\n .redacted-body md-icon {\n /* md-icon ์€ ์ž๊ธฐ ํฌ๊ธฐ๋ฅผ ์ด ๋ณ€์ˆ˜๋กœ ์žก๋Š”๋‹ค โ€” width/height ๋งŒ ์ฃผ๋ฉด ์•„๋ฌด ์ผ๋„ ์•ˆ ์ผ์–ด๋‚œ๋‹ค. */\n --md-icon-size: 14px;\n font-size: 14px;\n }\n\n .msg.pending {\n opacity: 0.5;\n }\n .typing-dots {\n display: inline-flex;\n gap: 4px;\n align-items: center;\n vertical-align: middle;\n }\n .typing-dots > span {\n display: inline-block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: currentColor;\n opacity: 0.4;\n animation: pulse 1.2s ease-in-out infinite;\n }\n .typing-dots > span:nth-child(2) { animation-delay: 0.2s; }\n .typing-dots > span:nth-child(3) { animation-delay: 0.4s; }\n @keyframes pulse {\n 0%, 100% { opacity: 0.2; transform: scale(0.85); }\n 50% { opacity: 0.7; transform: scale(1.1); }\n }\n\n /* โ”€โ”€ Patch indicator + ์ธ๋ผ์ธ ๋˜๋Œ๋ฆฌ๊ธฐ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .summary {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n margin-top: 4px;\n padding: 3px 4px 3px 8px;\n background: var(--md-sys-color-surface-container-high, #f1f5f9);\n border-radius: 6px;\n font-size: 10px;\n color: var(--md-sys-color-on-surface-variant, #475569);\n line-height: 1;\n }\n .summary md-icon {\n --md-icon-size: 13px;\n color: var(--md-sys-color-tertiary, #10b981);\n }\n .summary.reverted {\n opacity: 0.6;\n }\n .summary.reverted md-icon {\n color: var(--md-sys-color-outline, #94a3b8);\n }\n .summary .summary-text {\n letter-spacing: 0.01em;\n }\n .summary .revert-btn {\n height: 20px;\n padding: 0 8px;\n background: transparent;\n border: 0;\n border-radius: 4px;\n cursor: pointer;\n font-family: inherit;\n letter-spacing: inherit;\n font-size: 10px;\n color: var(--md-sys-color-on-surface-variant, #475569);\n line-height: 1;\n transition: background 0.12s, color 0.12s;\n width: auto;\n }\n .summary .revert-btn:hover:not(:disabled) {\n background: var(--md-sys-color-surface, #ffffff);\n color: var(--md-sys-color-on-surface, #0f172a);\n }\n .summary.reverted .revert-btn,\n .summary .revert-btn:disabled {\n display: none;\n }\n\n /* โ”€โ”€ Follow-up question โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .followup {\n font-size: 10.5px;\n color: var(--md-sys-color-on-secondary-container, #92400e);\n background: var(--md-sys-color-secondary-container, #fffbeb);\n border-left: 2px solid var(--md-sys-color-secondary, #f59e0b);\n padding: 5px 8px;\n border-radius: 0 5px 5px 0;\n margin-top: 4px;\n line-height: 1.45;\n }\n\n /* โ”€โ”€ \"๋Œ€ํ™”๊ฐ€ ๊ธธ์–ด์กŒ์Šต๋‹ˆ๋‹ค\" ์•ˆ๋‚ด โ€” ์กฐ์šฉํ•œ ํ•œ ์ค„, ๊ฐ•์กฐํ•˜์ง€ ์•Š๋Š”๋‹ค โ”€โ”€โ”€โ”€โ”€ */\n .fold-notice {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 0 0 4px;\n padding: 5px 8px;\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n border-radius: 8px;\n background: var(--md-sys-color-surface-container-low, #f8fafc);\n color: var(--md-sys-color-on-surface-variant, #475569);\n font-size: 10.5px;\n line-height: 1.45;\n }\n .fold-notice md-icon {\n --md-icon-size: 14px;\n flex-shrink: 0;\n }\n .fold-notice .fn-text {\n flex: 1;\n min-width: 0;\n }\n /* ์ƒˆ ๋Œ€ํ™” โ€” ๊ถŒ์œ ์ด๋ฏ€๋กœ ๊ฐ•์กฐ์ƒ‰ ๊ธ€์ž๋งŒ(์ฑ„์šด ๋ฒ„ํŠผ์€ ์ง€์‹œ์ฒ˜๋Ÿผ ์ฝํžŒ๋‹ค). */\n .fold-notice .fn-new {\n flex-shrink: 0;\n border: 0;\n background: none;\n color: var(--md-sys-color-primary, #0f766e);\n font-family: inherit;\n font-size: 10.5px;\n font-weight: 650;\n cursor: pointer;\n padding: 2px 4px;\n border-radius: 5px;\n white-space: nowrap;\n }\n .fold-notice .fn-new:hover {\n background: var(--md-sys-color-surface-container-high, #e2e8f0);\n }\n .fold-notice .fn-close {\n flex-shrink: 0;\n border: 0;\n background: none;\n color: var(--md-sys-color-outline, #94a3b8);\n cursor: pointer;\n padding: 0;\n display: inline-flex;\n }\n .fold-notice .fn-close md-icon {\n --md-icon-size: 13px;\n }\n\n /* โ”€โ”€ ์กฐ์น˜ ์ œ์•ˆ โ€” AI ๋Š” ์ œ์•ˆ๊นŒ์ง€, ์‹คํ–‰์€ ์‚ฌ์šฉ์ž โ”€โ”€โ”€โ”€โ”€ */\n .proposals {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin-top: 6px;\n }\n .proposal {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n padding: 6px 8px 6px 7px;\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n /* ์™ผ์ชฝ ๊ฐ•์กฐ์„  โ€” ๋˜๋Œ๋ฆด ์ˆ˜ ์—†๋Š” ํ–‰๋™์ž„์„ ์กฐ์šฉํžˆ ๊ตฌ๋ถ„ํ•œ๋‹ค(์ƒ‰๋งŒ์œผ๋กœ ์†Œ๋ฆฌ์น˜์ง€ ์•Š๋Š”๋‹ค). */\n border-left: 3px solid var(--md-sys-color-primary, #0f766e);\n border-radius: 8px;\n background: var(--md-sys-color-surface-container-low, #f8fafc);\n }\n .proposal md-icon {\n --md-icon-size: 16px;\n color: var(--md-sys-color-primary, #0f766e);\n flex-shrink: 0;\n }\n .proposal .pbody {\n display: flex;\n flex-direction: column;\n gap: 1px;\n min-width: 0;\n /* ์ƒํƒœ ๋ฌธ๊ตฌ๊ฐ€ ๊ธธ์–ด์ ธ๋„ ์ œ๋ชฉ ์˜์—ญ์„ 0px๊นŒ์ง€ ๋ฐ€์–ด ํ•œ ๊ธ€์ž์”ฉ ์„ธ๋กœ๋กœ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค. */\n flex: 1 1 132px;\n }\n .proposal .plabel {\n font-size: 11.5px;\n font-weight: 650;\n color: var(--md-sys-color-on-surface, #0f172a);\n overflow-wrap: anywhere;\n }\n .proposal .preason {\n font-size: 10.5px;\n color: var(--md-sys-color-on-surface-variant, #475569);\n overflow-wrap: anywhere;\n }\n /* ์‹คํ–‰ ๋ฒ„ํŠผ โ€” ์ด ๋Œ€ํ™”์˜ ์œ ์ผํ•œ \"๋˜๋Œ๋ฆด ์ˆ˜ ์—†๋Š”\" ํ–‰๋™์ด๋ฏ€๋กœ ์ฑ„์šด ๋ฒ„ํŠผ ํ•˜๋‚˜๋กœ ๋ถ„๋ช…ํ•˜๊ฒŒ. */\n .proposal .run {\n /* ๋ณด๋‚ด๋Š” ์ค‘ n์ดˆ์ฒ˜๋Ÿผ ๊ธด ์ƒํƒœ๋„ ์ข์€ ๋„ํฌ์—์„œ ์นด๋“œ ํญ์„ ๋…์ ํ•˜์ง€ ์•Š๋Š”๋‹ค. */\n min-width: 0;\n max-width: 100%;\n overflow-wrap: anywhere;\n white-space: normal;\n line-height: 1.3;\n flex-shrink: 0;\n padding: 4px 12px;\n border: 0;\n border-radius: 999px;\n background: var(--md-sys-color-primary, #0f766e);\n color: var(--md-sys-color-on-primary, #ffffff);\n font-family: inherit;\n font-size: 11px;\n font-weight: 650;\n letter-spacing: 0.01em;\n cursor: pointer;\n transition: filter 0.12s;\n }\n .proposal .run:hover:not(:disabled) {\n filter: brightness(1.08);\n }\n .proposal .run:disabled {\n background: var(--md-sys-color-surface-container-high, #e2e8f0);\n color: var(--md-sys-color-on-surface-variant, #475569);\n cursor: default;\n }\n .proposal.sent {\n border-left-color: var(--md-sys-color-outline, #94a3b8);\n }\n .proposal .staged-badge {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 3px 8px;\n border-radius: 999px;\n background: rgba(15, 118, 110, 0.1);\n color: var(--md-sys-color-primary, #0f766e);\n font-size: 11px;\n font-weight: 600;\n flex-shrink: 0;\n }\n .proposal .staged-badge md-icon {\n --md-icon-size: 13px;\n color: inherit;\n }\n\n .proposal-choices {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-top: 6px;\n padding: 6px 8px;\n background: var(--md-sys-color-surface-container-lowest, #ffffff);\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n border-radius: 8px;\n }\n .proposal-choices .choice-chip {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 9px;\n border-radius: 999px;\n border: 1px solid var(--md-sys-color-outline-variant, #cbd5e1);\n background: var(--md-sys-color-surface-container-low, #f8fafc);\n color: var(--md-sys-color-on-surface, #1e293b);\n font-family: inherit;\n font-size: 11px;\n font-weight: 550;\n cursor: pointer;\n transition: all 0.14s ease-in-out;\n }\n .proposal-choices .choice-chip:hover {\n background: var(--md-sys-color-surface-container-high, #e2e8f0);\n border-color: var(--md-sys-color-primary, #0f766e);\n color: var(--md-sys-color-primary, #0f766e);\n }\n .proposal-choices .choice-chip.primary {\n background: var(--md-sys-color-primary-container, #ccfbf1);\n color: var(--md-sys-color-on-primary-container, #0f766e);\n border-color: var(--md-sys-color-primary, #0f766e);\n font-weight: 650;\n }\n .proposal-choices .choice-chip md-icon {\n --md-icon-size: 13px;\n color: inherit;\n }\n\n /* The entry card's way to the large review - a quiet action under its table, never a second run button. */\n .workspace-review {\n display: flex;\n align-items: center;\n gap: 5px;\n margin: 6px 0 0 auto;\n padding: 5px 11px 5px 9px;\n border: 1px solid transparent;\n border-radius: 999px;\n background: transparent;\n color: var(--md-sys-color-primary, #0f766e);\n font-family: inherit;\n font-size: 12px;\n font-weight: 600;\n letter-spacing: 0.01em;\n cursor: pointer;\n transition:\n background-color 0.14s ease-in-out,\n border-color 0.14s ease-in-out;\n }\n .workspace-review md-icon {\n --md-icon-size: 15px;\n color: inherit;\n }\n .workspace-review:hover {\n background: color-mix(in srgb, var(--md-sys-color-primary, #0f766e) 8%, transparent);\n border-color: color-mix(in srgb, var(--md-sys-color-primary, #0f766e) 24%, transparent);\n }\n .workspace-review:active {\n background: color-mix(in srgb, var(--md-sys-color-primary, #0f766e) 14%, transparent);\n }\n .workspace-review:focus-visible {\n outline: 2px solid var(--md-sys-color-primary, #0f766e);\n outline-offset: 1px;\n }\n\n /* โ”€โ”€ ์ ‘์ง€ ๊ฒฝ๊ณ  โ€” ๊ทผ๊ฑฐ์— ์—†๋Š” ๋Œ€์ƒ์„ ์ง€๋ชฉํ•œ ๋‹ต โ”€โ”€โ”€โ”€โ”€ */\n .grounding-warning {\n display: flex;\n align-items: flex-start;\n gap: 6px;\n margin-top: 4px;\n padding: 5px 8px;\n border-radius: 6px;\n border: 1px solid var(--md-sys-color-error, #dc2626);\n background: var(--md-sys-color-error-container, #fef2f2);\n color: var(--md-sys-color-on-error-container, #7f1d1d);\n font-size: 10.5px;\n line-height: 1.45;\n }\n .grounding-warning md-icon {\n --md-icon-size: 14px;\n flex-shrink: 0;\n }\n .grounding-warning .ids {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-weight: 600;\n word-break: break-all;\n }\n\n /* โ”€โ”€ Tool usages fold-able ๋ฐ•์Šค โ€” AI ๋„๊ตฌ ํ˜ธ์ถœ trace โ”€โ”€โ”€โ”€โ”€ */\n .tool-usages {\n margin-top: 4px;\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n border-radius: 6px;\n background: var(--md-sys-color-surface-container-low, #f8fafc);\n overflow: hidden;\n font-size: 10.5px;\n }\n .tool-usages-header {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n padding: 5px 8px;\n background: transparent;\n border: 0;\n cursor: pointer;\n color: var(--md-sys-color-on-surface-variant, #475569);\n font-family: inherit;\n font-size: inherit;\n letter-spacing: inherit;\n text-align: left;\n }\n .tool-usages-header:hover {\n background: var(--md-sys-color-surface-container, #f1f5f9);\n }\n .tool-usages-icon,\n .tool-usages-chevron {\n --md-icon-size: 14px;\n flex-shrink: 0;\n }\n .tool-usages-summary {\n flex: 1;\n font-weight: 500;\n }\n .tool-usages-counts {\n color: var(--md-sys-color-outline, #94a3b8);\n font-weight: 400;\n font-size: 10px;\n }\n .tool-usages-list {\n list-style: none;\n margin: 0;\n padding: 0 8px 8px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n .tool-usage-item {\n border-left: 2px solid var(--md-sys-color-outline-variant, #cbd5e1);\n padding: 4px 8px 4px 8px;\n background: var(--md-sys-color-surface, #ffffff);\n border-radius: 0 4px 4px 0;\n }\n .tool-usage-item.kind-read {\n border-left-color: var(--md-sys-color-tertiary, #10b981);\n }\n .tool-usage-item.kind-write {\n border-left-color: var(--md-sys-color-primary, #1e293b);\n }\n .tool-usage-item.kind-unknown {\n border-left-color: var(--md-sys-color-error, #b91c1c);\n }\n .tool-usage-head {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 3px;\n }\n .tool-usage-step {\n color: var(--md-sys-color-outline, #94a3b8);\n font-size: 10px;\n }\n .tool-usage-name {\n font-weight: 600;\n color: var(--md-sys-color-on-surface, #0f172a);\n font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace;\n font-size: 10.5px;\n }\n .tool-usage-kind {\n font-size: 9.5px;\n padding: 1px 5px;\n border-radius: 3px;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-weight: 600;\n }\n .tool-usage-kind.kind-read {\n color: var(--md-sys-color-on-tertiary, #ffffff);\n background: var(--md-sys-color-tertiary, #10b981);\n }\n .tool-usage-kind.kind-write {\n color: var(--md-sys-color-on-primary, #ffffff);\n background: var(--md-sys-color-primary, #1e293b);\n }\n .tool-usage-kind.kind-unknown {\n color: var(--md-sys-color-on-error, #ffffff);\n background: var(--md-sys-color-error, #b91c1c);\n }\n /* ํŒ๋‹จ ํŒŒ์ดํ”„๋ผ์ธ โ€” ํ›‘์–ด ์ฝ๋Š” ๋ชฉ๋ก. ๋ฐฐ์ง€๋กœ ๊ฒฐ๊ณผ๋ฅผ ๊ตฌ๋ถ„ํ•˜๊ณ  ์›๋ณธ์€ ๋ˆŒ๋Ÿฌ์„œ ๋ณธ๋‹ค. */\n .tool-usages.has-problem {\n border-color: var(--md-sys-color-error, #dc2626);\n }\n .tool-usages-counts .tu-flag {\n font-weight: 650;\n }\n .tool-usages-counts .tu-flag.bad {\n color: var(--md-sys-color-error, #dc2626);\n }\n .tu-turn {\n list-style: none;\n margin: 4px 0 2px;\n padding: 0 8px;\n font-size: 9.5px;\n font-weight: 650;\n letter-spacing: 0.04em;\n color: var(--md-sys-color-outline, #94a3b8);\n text-transform: uppercase;\n }\n .tool-usage-head {\n cursor: pointer;\n align-items: center;\n }\n .tool-usage-item.outcome-rejected,\n .tool-usage-item.outcome-error {\n border-left-color: var(--md-sys-color-error, #dc2626);\n }\n .tool-usage-item.outcome-proposed {\n border-left-color: var(--md-sys-color-primary, #0f766e);\n }\n .tool-usage-item.outcome-folded {\n opacity: 0.7;\n }\n .tu-badge {\n flex-shrink: 0;\n padding: 0 5px;\n border-radius: 999px;\n font-size: 9px;\n font-weight: 700;\n line-height: 15px;\n background: var(--md-sys-color-surface-container-high, #e2e8f0);\n color: var(--md-sys-color-on-surface-variant, #475569);\n }\n .tu-badge.rejected,\n .tu-badge.error {\n background: var(--md-sys-color-error-container, #fef2f2);\n color: var(--md-sys-color-error, #dc2626);\n }\n .tu-badge.proposed {\n background: var(--md-sys-color-primary, #0f766e);\n color: var(--md-sys-color-on-primary, #fff);\n }\n /* ํ•œ ์ค„ ์š”์•ฝ โ€” ๋„˜์น˜๋ฉด ์ž๋ฅธ๋‹ค. ๋ชฉ๋ก์€ ํ›‘๋Š” ๊ณณ์ด๊ณ  ์ฝ๋Š” ๊ณณ์ด ์•„๋‹ˆ๋‹ค. */\n .tu-line {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--md-sys-color-on-surface-variant, #475569);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 9.5px;\n }\n .tu-more {\n --md-icon-size: 13px;\n flex-shrink: 0;\n color: var(--md-sys-color-outline, #94a3b8);\n }\n\n .tool-usage-args,\n .tool-usage-result {\n margin: 2px 0 0;\n padding: 4px 6px;\n background: var(--md-sys-color-surface-container-high, rgba(15, 23, 42, 0.04));\n border-radius: 3px;\n font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace;\n font-size: 10px;\n line-height: 1.4;\n white-space: pre-wrap;\n overflow-x: auto;\n color: var(--md-sys-color-on-surface, #0f172a);\n max-height: 180px;\n overflow-y: auto;\n }\n .tool-usage-args {\n border-left: 2px solid var(--md-sys-color-outline-variant, #cbd5e1);\n }\n .tool-usage-result {\n border-left: 2px solid var(--md-sys-color-outline, #94a3b8);\n }\n\n /* โ”€โ”€ Hover actions (assistant ๋ฉ”์‹œ์ง€๋งŒ, Material icon button) โ”€โ”€ */\n .msg-actions {\n display: flex;\n gap: 2px;\n margin-top: 2px;\n padding: 0;\n opacity: 0;\n transition: opacity 0.15s;\n pointer-events: none;\n }\n .msg-wrap:hover .msg-actions,\n .msg-wrap:focus-within .msg-actions {\n opacity: 1;\n pointer-events: auto;\n }\n .msg-actions .msg-action {\n width: 22px;\n height: 22px;\n padding: 0;\n background: transparent;\n border: 0;\n border-radius: 5px;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: var(--md-sys-color-outline, #94a3b8);\n transition:\n background 0.12s,\n color 0.12s;\n }\n .msg-actions .msg-action:hover:not(:disabled) {\n background: var(--md-sys-color-surface-container-high, #e2e8f0);\n color: var(--md-sys-color-on-surface, #0f172a);\n }\n .msg-actions .msg-action:disabled {\n opacity: 0.4;\n cursor: default;\n }\n .msg-actions .msg-action.confirmed {\n color: var(--md-sys-color-tertiary, #10b981);\n }\n .msg-actions .msg-action md-icon {\n --md-icon-size: 14px;\n }\n\n /* โ”€โ”€ Error banner โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .error {\n color: var(--md-sys-color-on-error-container, #b91c1c);\n padding: 7px 11px;\n background: var(--md-sys-color-error-container, #fef2f2);\n border: 1px solid var(--md-sys-color-error, #fee2e2);\n border-radius: 8px;\n margin: 0 16px 8px;\n font-size: 10.5px;\n line-height: 1.5;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n }\n .error .error-text {\n flex: 1;\n }\n .error .retry-btn {\n flex-shrink: 0;\n padding: 3px 8px;\n font-size: 10px;\n font-family: inherit;\n letter-spacing: inherit;\n background: var(--md-sys-color-error, #b91c1c);\n color: var(--md-sys-color-on-error, #ffffff);\n border: 0;\n border-radius: 6px;\n cursor: pointer;\n transition: opacity 0.15s;\n width: auto;\n height: auto;\n }\n .error .retry-btn:hover {\n opacity: 0.88;\n }\n\n /* โ”€โ”€ Composer (actions + input ํ†ตํ•ฉ ์˜์—ญ) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .composer {\n position: relative;\n border-top: 1px solid var(--md-sys-color-outline-variant, #f1f5f9);\n background: var(--md-sys-color-surface, #ffffff);\n display: flex;\n flex-direction: column;\n transition: background 0.15s, border-color 0.15s;\n }\n /* The wide box and a table's rows cover the conversation, inside the dock - the page beside it stays. */\n .messages.covered {\n flex: 0 0 0;\n padding: 0;\n overflow: hidden;\n visibility: hidden;\n }\n .composer.wide,\n .composer.previewing {\n flex: 1 1 auto;\n min-height: 0;\n }\n .composer.wide .input-row {\n flex: 1;\n min-height: 0;\n align-items: stretch;\n }\n .composer.wide .input-row > :not(.textarea-wrap) {\n align-self: flex-end;\n }\n .composer.wide textarea {\n min-height: 0;\n }\n .composer-size {\n margin-left: auto;\n }\n /* Named above the send button, out of the row - it takes no width from the box. */\n .composer.wide .input-row {\n position: relative;\n }\n .send-shortcut {\n position: absolute;\n right: 14px;\n bottom: 48px;\n font-size: 10px;\n color: var(--md-sys-color-outline, #64748b);\n white-space: nowrap;\n pointer-events: none;\n }\n /* A finger has no Ctrl or โŒ˜ - the send button is the way. */\n @media (pointer: coarse) {\n .send-shortcut {\n display: none;\n }\n }\n .table-preview {\n flex: 1;\n min-height: 0;\n display: flex;\n flex-direction: column;\n margin: 4px 14px;\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n border-radius: 8px;\n background: var(--md-sys-color-surface, #ffffff);\n overflow: hidden;\n }\n .table-preview-head {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 8px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n flex-wrap: wrap;\n }\n .table-preview-head > md-icon {\n --md-icon-size: 18px;\n color: var(--md-sys-color-primary, #0284c7);\n }\n .table-preview-name {\n font-weight: 500;\n color: var(--md-sys-color-on-surface, #0f172a);\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .table-preview-shape {\n color: var(--md-sys-color-on-surface-variant, #475569);\n margin-right: auto;\n }\n .table-preview-body {\n flex: 1;\n min-height: 0;\n overflow: auto;\n }\n .table-preview-body table {\n border-collapse: collapse;\n font-size: 11px;\n }\n .table-preview-body th,\n .table-preview-body td {\n border-bottom: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n padding: 4px 8px;\n text-align: left;\n white-space: nowrap;\n color: var(--md-sys-color-on-surface, #0f172a);\n }\n .table-preview-body th {\n position: sticky;\n left: 0;\n font-weight: 400;\n text-align: right;\n color: var(--md-sys-color-on-surface-variant, #475569);\n background: var(--md-sys-color-surface-container, #f1f5f9);\n }\n .attachment-open {\n all: unset;\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n flex: 1;\n cursor: pointer;\n border-radius: 6px;\n }\n .attachment-open:focus-visible {\n outline: 2px solid var(--md-sys-color-primary, #0284c7);\n outline-offset: 2px;\n }\n .attachment-chip.open {\n border-color: var(--md-sys-color-primary, #0284c7);\n }\n .composer.drag-over {\n background: var(--md-sys-color-surface-container, #f1f5f9);\n border-top-color: var(--md-sys-color-primary, #0284c7);\n }\n .drag-drop-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(255, 255, 255, 0.94);\n backdrop-filter: blur(2px);\n z-index: 10;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 6px;\n border: 2px dashed var(--md-sys-color-primary, #0284c7);\n border-radius: 4px;\n color: var(--md-sys-color-primary, #0284c7);\n font-size: 13px;\n font-weight: 500;\n pointer-events: none;\n }\n .drag-drop-overlay md-icon {\n --md-icon-size: 28px;\n }\n .attachment-strip {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 6px 14px 2px;\n max-height: 120px;\n overflow-y: auto;\n }\n .attachment-chip {\n display: flex;\n align-items: center;\n gap: 6px;\n background: var(--md-sys-color-surface-container, #f1f5f9);\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n border-radius: 8px;\n padding: 3px 6px 3px 4px;\n max-width: 220px;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n }\n .attachment-thumb {\n width: 28px;\n height: 28px;\n object-fit: cover;\n border-radius: 4px;\n flex: none;\n }\n .attachment-icon {\n --md-icon-size: 20px;\n color: var(--md-sys-color-primary, #0284c7);\n flex: none;\n }\n .attachment-meta {\n display: flex;\n flex-direction: column;\n min-width: 0;\n flex: 1;\n }\n .attachment-name {\n font-size: 11px;\n font-weight: 500;\n color: var(--md-sys-color-on-surface, #0f172a);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .attachment-size {\n font-size: 9px;\n color: var(--md-sys-color-outline, #64748b);\n }\n .attachment-remove {\n all: unset;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n cursor: pointer;\n color: var(--md-sys-color-outline, #64748b);\n transition: background 0.15s, color 0.15s;\n flex: none;\n }\n .attachment-remove:hover {\n background: var(--md-sys-color-surface-container-highest, #cbd5e1);\n color: var(--md-sys-color-error, #ef4444);\n }\n .attachment-remove md-icon {\n --md-icon-size: 14px;\n }\n .msg-attachments {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-top: 8px;\n }\n .msg-attachment-img-wrap {\n border-radius: 8px;\n overflow: hidden;\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n background: var(--md-sys-color-surface-container-lowest, #ffffff);\n max-width: 240px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n display: flex;\n flex-direction: column;\n }\n .msg-attachment-img-wrap img {\n max-width: 100%;\n max-height: 160px;\n object-fit: cover;\n display: block;\n }\n .msg-attachment-label {\n padding: 4px 8px;\n font-size: 10px;\n color: var(--md-sys-color-on-surface-variant, #64748b);\n background: var(--md-sys-color-surface-container, #f8fafc);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n border-top: 1px solid var(--md-sys-color-outline-variant, #f1f5f9);\n }\n .msg-attachment-file-chip {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 10px;\n border-radius: 8px;\n background: var(--md-sys-color-surface-container, #f8fafc);\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n font-size: 11px;\n color: var(--md-sys-color-on-surface, #0f172a);\n }\n .msg-attachment-file-chip md-icon {\n --md-icon-size: 18px;\n color: var(--md-sys-color-primary, #0284c7);\n }\n\n /* โ”€โ”€ Mini action row (๋ฉ”์‹œ์ง€ ์‹œ์ž‘ ํ›„) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n .actions-row {\n display: flex;\n gap: 6px;\n padding: 6px 14px 4px;\n flex-wrap: wrap;\n align-items: center;\n }\n /* Material 3 assist-chip ํ†ค โ€” height 24, font label-small */\n .action {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 5px;\n height: 24px;\n padding: 0 10px;\n font-size: 11px;\n font-family: inherit;\n letter-spacing: inherit;\n line-height: 1;\n color: var(--md-sys-color-on-surface-variant, #475569);\n background: transparent;\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n border-radius: 8px;\n cursor: pointer;\n transition:\n background 0.15s,\n border-color 0.15s,\n color 0.15s;\n width: auto;\n vertical-align: middle;\n }\n .action:hover {\n background: var(--md-sys-color-surface-container, #f8fafc);\n border-color: var(--md-sys-color-outline, #cbd5e1);\n color: var(--md-sys-color-on-surface, #0f172a);\n }\n .action:active {\n transform: scale(0.97);\n }\n .action md-icon {\n --md-icon-size: 14px;\n opacity: 0.7;\n }\n\n /* โ”€โ”€ Inline examples (action row ์˜ \"์˜ˆ์‹œ\" ํ† ๊ธ€ ์‹œ) โ”€โ”€โ”€โ”€ */\n .inline-examples {\n padding: 4px 16px 0;\n display: flex;\n flex-direction: column;\n gap: 3px;\n }\n .inline-examples .ex-row {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n }\n .inline-examples .ex-row .ex-label {\n font-size: 9px;\n color: var(--md-sys-color-outline, #94a3b8);\n letter-spacing: 0.05em;\n text-transform: uppercase;\n margin-right: 2px;\n align-self: center;\n font-weight: 600;\n }\n .inline-examples .ex {\n all: unset;\n cursor: pointer;\n padding: 2px 8px;\n font-size: 10px;\n color: var(--md-sys-color-on-surface, #0f172a);\n background: var(--md-sys-color-surface-container, #f8fafc);\n border: 1px solid var(--md-sys-color-outline-variant, #eef2f6);\n border-radius: 10px;\n transition: background 0.15s;\n }\n .inline-examples .ex:hover {\n background: var(--md-sys-color-surface-container-high, #f1f5f9);\n }\n\n /* โ”€โ”€ Input area โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */\n /* border-top ์€ .composer ๊ฐ€ ๋‹ด๋‹น (actions-row ๊ฐ€ ๊ฐ™์€ wrapper ์•ˆ) */\n .input-row {\n display: flex;\n gap: 8px;\n padding: 6px 14px 10px;\n background: transparent;\n align-items: flex-end;\n }\n /* ๋ฉ”์‹œ์ง€ ์‹œ์ž‘ ์ „ โ€” actions-row ๊ฐ€ ์—†์„ ๋•Œ๋Š” input-row ๊ฐ€ ์ง์ ‘ border-top */\n .composer.no-actions .input-row {\n padding-top: 10px;\n }\n\n /* mention popup โ€” textarea wrapper ๊ฐ€ relative ์ปจํ…์ŠคํŠธ, popup ์ด textarea\n ์™€ ์ •ํ™•ํžˆ ๊ฐ™์€ ํญ/์ขŒํ‘œ (์ขŒ์šฐ ๋ ์ •๋ ฌ). send ๋ฒ„ํŠผ ์˜์—ญ์€ ์ œ์™ธ. */\n .textarea-wrap {\n flex: 1;\n position: relative;\n display: flex;\n min-width: 0;\n }\n .textarea-wrap textarea {\n flex: 1;\n width: 100%;\n }\n .mention-popup {\n bottom: calc(100% + 4px);\n left: 0;\n right: 0;\n }\n\n textarea {\n flex: 1;\n padding: 8px 12px;\n border: 1px solid var(--md-sys-color-outline-variant, #e2e8f0);\n border-radius: 12px;\n font: inherit;\n letter-spacing: inherit;\n resize: none;\n /* The resting height of one line as it stood; the box grows from here by composerHeight (shared-dock.md ยง10). */\n box-sizing: border-box;\n min-height: 54px;\n outline: none;\n transition:\n border-color 0.2s,\n box-shadow 0.2s;\n background: var(--md-sys-color-surface, #ffffff);\n color: var(--md-sys-color-on-surface, #0f172a);\n }\n textarea::placeholder {\n color: var(--md-sys-color-outline, #94a3b8);\n }\n textarea:focus {\n border-color: var(--md-sys-color-outline, #cbd5e1);\n box-shadow: 0 0 0 3px var(--md-sys-color-primary-container, rgba(15, 23, 42, 0.08));\n }\n textarea:disabled {\n background: var(--md-sys-color-surface-container, #f8fafc);\n color: var(--md-sys-color-outline, #94a3b8);\n cursor: not-allowed;\n }\n\n /* ๋ณด๋‚ด๊ธฐ ์ „์— ๋ณด์ด๋Š” ์ดˆ๋Œ€ ์•ˆ๋‚ด โ€” ๋ˆ„๋ฅด๊ธฐ ์ „์— ์•Œ์•„์•ผ ํ•˜๋Š” ์‚ฌ์‹ค์ด๋‹ค. */\n .invite-notice {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 0 2px 4px;\n color: var(--md-sys-color-on-surface-variant, #475569);\n font-size: 11.5px;\n }\n\n .invite-notice md-icon {\n --md-icon-size: 15px;\n }\n\n /* โ”€โ”€ Send button โ€” ChatGPT ์Šคํƒ€์ผ ์›ํ˜• โ†‘ (.input-row ์•ˆ์˜ button ๋งŒ) โ”€โ”€โ”€ */\n .input-row > button {\n width: 32px;\n height: 32px;\n padding: 0;\n background: var(--md-sys-color-primary, #1e293b);\n color: var(--md-sys-color-on-primary, #ffffff);\n border: 0;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition:\n background 0.15s,\n transform 0.1s,\n opacity 0.15s;\n flex-shrink: 0;\n align-self: flex-end;\n margin-bottom: 2px;\n }\n /*\n ๋ฐฉ์— ๋งํ•˜๋Š” ์ž๋ฆฌ๋Š” **๋‘ ๋ฒˆ์งธ ํ–‰๋™**์ด๋‹ค โ€” ์ด ํ™”๋ฉด์˜ ์ฒซ ํ–‰๋™์€ ์–ด์‹œ์Šคํ„ดํŠธ์—๊ฒŒ ๋ฌป๋Š” ๊ฒƒ์ด๋‹ค.\n ๊ฐ™์€ ๋ฌด๊ฒŒ๋กœ ๋‘๋ฉด ๋ฌด์—‡์ด ๊ธฐ๋ณธ์ธ์ง€ ํ™”๋ฉด์ด ๋งํ•˜์ง€ ์•Š๊ฒŒ ๋œ๋‹ค(ADR-0070 A15 ์˜ ์ž๋ฆฌ ๋‘˜).\n */\n .input-row > button.say-to-room {\n background: var(--md-sys-color-surface-container-highest, #e2e8f0);\n color: var(--md-sys-color-on-surface-variant, #475569);\n }\n\n .input-row > button:disabled {\n background: var(--md-sys-color-surface-container-highest, #e2e8f0);\n color: var(--md-sys-color-outline, #94a3b8);\n cursor: not-allowed;\n }\n .input-row > button:hover:not(:disabled) {\n opacity: 0.88;\n }\n .input-row > button:active:not(:disabled) {\n transform: scale(0.94);\n }\n .input-row > button md-icon {\n --md-icon-size: 18px;\n }\n .input-row > button .spinner {\n width: 12px;\n height: 12px;\n border: 1.8px solid currentColor;\n border-right-color: transparent;\n border-radius: 50%;\n animation: spin 0.7s linear infinite;\n }\n @keyframes spin {\n to {\n transform: rotate(360deg);\n }\n }\n `\n ]\n\n connectedCallback() {\n super.connectedCallback()\n // ์ฒซ ๋งˆ์šดํŠธ ์‹œ sessionId ๊ฐ€ ์ด๋ฏธ set ๋ผ์žˆ์–ด๋„ loadHistory ๋Š” ์ฒซ render ํ›„ updated()\n // ๊ฐ€ ์ฒ˜๋ฆฌ โ€” ๋‹จ์ผ ์ง„์ž…์ ์œผ๋กœ ์ผ๊ด€ (์ด์ „์—” connectedCallback ๊ณผ updated ์–‘์ชฝ์ด ํ˜ธ์ถœ โ†’\n // ๋™์‹œ fetch race ๋ฐœ์ƒ).\n /* ๋ชจ๋“œ๊ฐ€ ์ด๋ฏธ ๋ถ™์–ด ์žˆ์œผ๋ฉด ๋ฌด์—‡์„ ์ฃผ๋Š”์ง€ ๋จผ์ € ๋ฌป๋Š”๋‹ค โ€” ๋ฐ”๋€” ๋•Œ๋Š” updated ๊ฐ€ ๋‹ค์‹œ ๋ฌป๋Š”๋‹ค. */\n if (this.mode?.kind) this.loadModeView()\n if (this.subject) this.onSubjectChanged()\n /*\n * Put back after the dock was closed: what is being written stays, the conversation is read again and its\n * broadcast and presence start again - they were stopped when it was taken out.\n */\n if (this.hasUpdated && this.sessionId) {\n this.loadHistory()\n this._startPresence()\n this._startMessageSubscription()\n }\n }\n\n /**\n * ํ™”๋ฉด์ด ๋ณด์—ฌ ์ฃผ๋Š” ๊ฒƒ์˜ ์ข…๋ฅ˜๊ฐ€ ๋ฐ”๋€Œ์—ˆ๋‹ค โ€” ์„ค ์ˆ˜ ์žˆ๋Š” ๋Œ€ํ™”๋ฅผ ๋‹ค์‹œ ๋ฌป๊ณ , ์ง€๋‚œ๋ฒˆ ๊ณ ๋ฅธ ๊ฒƒ์„ ๋˜์‚ด๋ฆฐ๋‹ค.\n *\n * ๋˜์‚ด๋ฆฌ๋Š” ๊ฒƒ์€ **๊ณ ๋ฅธ ๋Œ€ํ™”**์ด์ง€ ์„ธ์…˜์ด ์•„๋‹ˆ๋‹ค. ์„ธ์…˜์€ ์ž๊ธฐ๊ฐ€ ์–ด๋А ๋Œ€ํ™”์˜€๋Š”์ง€ ์ด๋ฏธ ์•Œ๊ณ , ๋‹ค๋ฅธ\n * ๋Œ€ํ™”๋กœ ๊ฐ€๋ฉด ๊ทธ๋•Œ ์ƒˆ๋กœ ๋‚œ๋‹ค(ADR-0072 A17 โ‘ ).\n */\n private async onSubjectChanged() {\n await this.loadModeChoices()\n if (this.modeChoices.length < 2 || !this.subject || !this.mode) return\n\n const kind = pickInitialMode(this.mode.kind, this.modeChoices, this.rememberedMode(this.subject))\n if (kind && kind !== this.mode.kind) this.askHostForMode(kind)\n }\n\n updated(changed: Map<string, any>) {\n if (changed.has('input') || changed.has('composerWide') || changed.has('previewAttachmentId') || changed.has('attachments')) this.fitComposer()\n\n /*\n * The subject changed, so the conversation is over.\n *\n * A conversation about station 3 is not a conversation about station 7. Leaving the old one\n * on screen means the user reads an answer about a screen they are no longer looking at,\n * and every host that met this wrote its own guard: plant re-checked the context on each\n * send and threw when it had moved, twin closed its session when the anchor changed. The\n * mode carries an id, so the component can do it once, here.\n *\n * The host still owns `sessionId`; it hears `assistant-mode-changed` and decides whether\n * this subject gets a stored session of its own.\n */\n /* ๋ณด๋Š” ๊ฒƒ์˜ ์ข…๋ฅ˜๊ฐ€ ๋ฐ”๋€Œ๋ฉด ์„ค ์ˆ˜ ์žˆ๋Š” ๋Œ€ํ™”๋„ ๋‹ฌ๋ผ์ง„๋‹ค โ€” ๋ณด๋“œ์—์„œ ํ˜„์žฅ์œผ๋กœ ๋„˜์–ด๊ฐ„ ์ž๋ฆฌ. */\n if (changed.has('subject')) this.onSubjectChanged()\n\n if (changed.has('mode') && isDifferentConversation(changed.get('mode'), this.mode)) {\n /* What this conversation offers is the new mode's; ask before drawing the panel again. */\n this.modeView = undefined\n this.rebuildMentionCaches()\n this.loadModeView()\n this.lines = []\n this.pickedMentions.clear()\n this.pickedUserMentions.clear()\n this.cachedUserCandidates = []\n this.errorMessage = undefined\n this.input = ''\n this._seenMessageIds.clear()\n this.dispatchEvent(\n new CustomEvent('assistant-mode-changed', {\n detail: { mode: this.mode },\n bubbles: true,\n composed: true\n })\n )\n }\n\n if (changed.has('sessionId') && this.adoptingSession) {\n this.adoptingSession = false\n this._startPresence()\n this._startMessageSubscription()\n } else if (changed.has('sessionId')) {\n // sessionId ๊ฐ€ ๋ฐ”๋€Œ๋ฉด (set / unset / ๋‹ค๋ฅธ ๋ณด๋“œ ์ „ํ™˜) ์ด์ „ ์„ธ์…˜์˜ ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ\n // ์ปจํ…์ŠคํŠธ ์ •๋ฆฌ โ€” lines / pickedMentions / errorMessage / input ๋ชจ๋‘ ์ƒˆ์ง€ ์•Š๋„๋ก.\n // ๋ณด๋“œ ๋‹จ์œ„ ๊ฒฉ๋ฆฌ (ChatSession 1:1 boardId) ๊ฐ€ ๊นจ์ง€๋Š” ํšŒ๊ท€ ๋ฐฉ์ง€.\n this.lines = []\n this.pickedMentions.clear()\n this.pickedUserMentions.clear()\n this.cachedUserCandidates = []\n this.errorMessage = undefined\n this.input = ''\n this.participants = []\n this._seenMessageIds.clear() // ์„ธ์…˜ ์ „ํ™˜ โ€” ์—์ฝ” dedup ์ปจํ…์ŠคํŠธ ๋ฆฌ์…‹\n if (this.sessionId) {\n this.loadHistory()\n this._startPresence() // C4: roster ๋กœ๋“œ + heartbeat ์‹œ์ž‘\n this._startMessageSubscription() // C4: ๋ฉ”์‹œ์ง€ ์‹ค์‹œ๊ฐ„ ๋ฐฉ์†ก ๊ตฌ๋…\n } else {\n this._stopPresence()\n this._stopMessageSubscription()\n }\n }\n /* Send carried questions only after subject, mode and session cleanup has completed. */\n if (this.autoAsk && assistantAutoAskKey(this.autoAsk, this.autoAskRequestId) !== this._autoAsked && (this.sessionId || this.prepareSession) && !this.busy) {\n this._autoAsked = assistantAutoAskKey(this.autoAsk, this.autoAskRequestId)\n this.input = this.autoAsk\n void this.send()\n }\n\n /* A draft fills the input and waits for the person โ€” it is never sent from here. */\n const draft = assistantDraftDecision({\n draft: this.draft,\n draftRequestId: this.draftRequestId,\n drafted: this._drafted,\n typed: this.input,\n autoAsk: this.autoAsk,\n autoAskRequestId: this.autoAskRequestId\n })\n if (draft.consumed) this._drafted = draft.consumed\n if (draft.fill) {\n this.input = this.draft!\n this.updateComplete.then(() => (this.renderRoot.querySelector('textarea') as HTMLTextAreaElement | null)?.focus())\n }\n\n\n // ์ž๋™ ์Šคํฌ๋กค\n const ms = this.renderRoot.querySelector('.messages') as HTMLElement | null\n if (ms) ms.scrollTop = ms.scrollHeight\n }\n\n disconnectedCallback() {\n this._stopPresence()\n this._stopMessageSubscription()\n if (this.elapsedTimer) {\n clearInterval(this.elapsedTimer)\n this.elapsedTimer = undefined\n }\n super.disconnectedCallback()\n }\n\n // โ”€โ”€ C4 presence/roster โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n private _startPresence() {\n this._stopPresence()\n this._loadParticipants()\n this._touchPresence() // ์ฆ‰์‹œ 1ํšŒ โ€” ๋‚ด online ์ฆ‰์‹œ ๋ฐ˜์˜\n this._heartbeatTimer = setInterval(() => {\n this._touchPresence()\n this._loadParticipants()\n this._presenceTick++ // online ํŒ์ • ์žฌํ‰๊ฐ€(์‹œ๊ฐ„ ๊ฒฝ๊ณผ)\n }, PRESENCE_HEARTBEAT_MS)\n }\n\n private _stopPresence() {\n if (this._heartbeatTimer) {\n clearInterval(this._heartbeatTimer)\n this._heartbeatTimer = undefined\n }\n }\n\n // โ”€โ”€ C4 ๊ทธ๋ฃน์ฑ— โ€” ๋ฉ”์‹œ์ง€ ์‹ค์‹œ๊ฐ„ ๋ฐฉ์†ก ๊ตฌ๋… โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n private _startMessageSubscription() {\n this._stopMessageSubscription()\n if (!this.sessionId) return\n try {\n this._messageSub = client\n .subscribe({ query: CHAT_MESSAGE_SUBSCRIPTION, variables: { sessionId: this.sessionId } })\n .subscribe({\n next: ({ data }: any) => this._onRemoteMessage(data?.chatMessageActivity),\n error: () => {\n /* ๊ตฌ๋… ์—๋Ÿฌ๋Š” ์ฑ„ํŒ… ๋ณธ ๊ธฐ๋Šฅ ๋ฌด์˜ํ–ฅ โ€” ํžˆ์Šคํ† ๋ฆฌ ์ฟผ๋ฆฌ๋กœ ํด๋ฐฑ */\n }\n })\n } catch {\n /* ๊ตฌ๋… ๋ฏธ์ง€์› ํ™˜๊ฒฝ โ€” ์กฐ์šฉํžˆ ์Šคํ‚ต */\n }\n }\n\n private _stopMessageSubscription() {\n if (this._messageSub) {\n try {\n this._messageSub.unsubscribe()\n } catch {\n /* ์ด๋ฏธ ๋‹ซํž˜ */\n }\n this._messageSub = undefined\n }\n }\n\n /** ์„œ๋ฒ„ ChatMessage โ†’ ChatLine. */\n private _msgToLine(m: any): ChatLine {\n return remoteMessageToLine(m) as ChatLine\n }\n\n /**\n * ์›๊ฒฉ(๋ฐฉ์†ก) ๋ฉ”์‹œ์ง€ ์ˆ˜์‹  โ€” ์—์ฝ”ยท์ค‘๋ณต์€ id ๋กœ ์ฐจ๋‹จ, ์‹ ๊ทœ๋Š” transcript ์— append.\n * ์ž๊ธฐ ๋ฐœ์‹  ๋ฉ”์‹œ์ง€์˜ id ๋Š” ์ „์†ก reconcile ์—์„œ ์ด๋ฏธ _seenMessageIds ์— ๋“ฑ๋ก๋จ.\n */\n private _onRemoteMessage(m: any) {\n const next = receiveRemoteMessage(this.lines as any, this._seenMessageIds, m)\n if (!next) return\n this._seenMessageIds = next.seen\n this.lines = next.lines as ChatLine[]\n }\n\n /**\n * ์ „์†กํ•œ optimistic ๋ผ์ธ์„ ์„œ๋ฒ„ id ๋กœ reconcile (index ๋น„์˜์กด โ€” _localId ๋กœ ํƒ์ƒ‰).\n * ์—์ฝ”๊ฐ€ ์‘๋‹ต๋ณด๋‹ค ๋จผ์ € ๋„์ฐฉํ•ด ์ด๋ฏธ append ๋์œผ๋ฉด optimistic ์ค‘๋ณต ๋ผ์ธ์„ ์ œ๊ฑฐํ•œ๋‹ค.\n */\n private _reconcileSentLine(localId: string, serverId: string | undefined, patch: Partial<ChatLine>) {\n const next = reconcileSentLine(this.lines as any, this._seenMessageIds, localId, serverId, patch as any)\n this._seenMessageIds = next.seen\n this.lines = next.lines as ChatLine[]\n }\n\n private async _loadParticipants() {\n if (!this.sessionId) return\n try {\n const result = await client.query({\n query: CHAT_PARTICIPANTS_QUERY,\n variables: { sessionId: this.sessionId },\n fetchPolicy: 'network-only'\n })\n this.participants = result.data?.chatSessionParticipants ?? []\n } catch {\n /* roster ๋กœ๋“œ ์‹คํŒจ๋Š” ์ฑ„ํŒ… ๋ณธ ๊ธฐ๋Šฅ ๋ฌด์˜ํ–ฅ โ€” ์กฐ์šฉํžˆ ๋ฌด์‹œ */\n }\n }\n\n private async _touchPresence() {\n if (!this.sessionId) return\n try {\n await client.mutate({ mutation: TOUCH_PRESENCE_MUTATION, variables: { sessionId: this.sessionId } })\n } catch {\n /* heartbeat ์‹คํŒจ ๋ฌด์‹œ */\n }\n }\n\n /** lastSeenAt ์ด TTL ์ด๋‚ด๋ฉด online. (_presenceTick ์˜์กด์œผ๋กœ ์ฃผ๊ธฐ ์žฌํ‰๊ฐ€.) */\n private _isOnline(lastSeenAt?: string): boolean {\n void this._presenceTick\n if (!lastSeenAt) return false\n const t = new Date(lastSeenAt).getTime()\n if (!Number.isFinite(t)) return false\n const age = Date.now() - t\n return age >= 0 ? age <= PRESENCE_TTL_MS : true\n }\n\n private async loadHistory() {\n if (!this.sessionId) return\n try {\n const result = await client.query({\n query: CHAT_MESSAGES_QUERY,\n variables: { sessionId: this.sessionId, limit: 200, offset: 0 },\n fetchPolicy: 'network-only'\n })\n const msgs = result.data?.chatMessages ?? []\n /* ์„œ๋ฒ„ ์ด๋ ฅ์„ ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์˜ค๋ฉด ํ™”๋ฉด์— ์ „๋ถ€ ๋ณด์ธ๋‹ค โ†’ ์ ‘์€ ์ง€์  ํ•ด์ œ(์•ˆ ํ•˜๋ฉด ํ™”๋ฉด๊ณผ ์—์ด์ „ํŠธ ๋ฌธ๋งฅ์ด\n * ์–ด๊ธ‹๋‚œ ์ฑ„ ๋‚จ๋Š”๋‹ค). ์ „์†ก ํ›„์—๋Š” ํ•ด์ œํ•˜์ง€ ์•Š๋Š”๋‹ค โ€” ์ ‘ํžŒ ํ™”๋ฉด์ด ๊ทธ๋Œ€๋กœ์ด๋ฏ€๋กœ ๊ณ„์† ์ˆจ๊ฒจ์•ผ ํ•œ๋‹ค. */\n this._truncateAfterId = undefined\n this.lines = msgs.map((m: any) => this._msgToLine(m))\n // ๋กœ๋“œ๋œ ๋ฉ”์‹œ์ง€ id ๋ฅผ seen ์— ๋“ฑ๋ก โ€” ์ดํ›„ ๋ฐฉ์†ก ์—์ฝ” dedup ๊ธฐ์ค€.\n this._seenMessageIds = new Set<string>(msgs.map((m: any) => m.id).filter(Boolean))\n } catch (e: any) {\n this.errorMessage = `${i18next.t('ai-assistant.text.failed-to-load-history')}: ${e.message ?? e}`\n }\n }\n\n render() {\n const hasMessages = this.lines.length > 0\n return html`\n ${this.toastMessage\n ? html`<div class=\"toast show\">${this.toastMessage}</div>`\n : nothing}\n ${this.renderModeSubject()}\n ${this.renderSessionTabs()}\n ${this.renderRoster()}\n <div class=\"messages ${this.composerWide || this.previewedTable ? 'covered' : ''}\" @click=${this.onBubbleClick}>\n ${!hasMessages ? this.renderEmpty() : nothing}\n ${(() => {\n const myEmail = this._myEmail\n return this.lines.map((line, idx) => {\n const prev = this.lines[idx - 1]\n const showLabel = line.role === 'assistant' && (!prev || prev.role !== 'assistant')\n /* ๊ทธ๋ฃน์ฑ—: ๋‹ค๋ฅธ ์ฐธ์—ฌ์ž์˜ user ๋ฉ”์‹œ์ง€๋Š” ์ขŒ์ธก + ๋ณด๋‚ธ์ด ์ด๋ฆ„ ํ‘œ์‹œ(์—ฐ์† ๋™์ผ ๋ฐœ์‹ ์ž๋Š” 1ํšŒ๋งŒ).\n * ํŒ์ •์€ email ๋น„๊ต. **๋‚ด email ์„ ๋ชจ๋ฅผ ๋•Œ๋Š” '๋‚จ'์œผ๋กœ ๋‹จ์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค** โ€” ๋‚ด ๋ฐœํ™”๋ฅผ ๋‚จ์˜ ๊ฒƒ์œผ๋กœ\n * ์ž˜๋ชป ๋ณด์—ฌ์ฃผ๋Š” ์ชฝ์ด ๋” ํ•ด๋กญ๋‹ค(๋กœ๊ทธ์ธ ์ •๋ณด๊ฐ€ ์•„์ง ์•ˆ ์˜จ ์ˆœ๊ฐ„ ๋“ฑ). ๋‚ด email ์„ ์•„๋Š” ์ƒํƒœ์—์„œ\n * ๋ฐœ์‹ ์ž email ์ด ๋‹ค๋ฅด๊ฑฐ๋‚˜ ๋น„์–ด ์žˆ์œผ๋ฉด ๋‹ค๋ฅธ ๊ณ„์ •์œผ๋กœ ๋ณธ๋‹ค. */\n const isOther = line.role === 'user' && !!myEmail && line.senderEmail !== myEmail\n const prevSameSender = !!prev && prev.role === 'user' && prev.senderEmail === line.senderEmail\n const showSenderLabel = isOther && !prevSameSender\n const content = (line.content ?? '').trim()\n /* A \"requested\" row is the card's state, shown on the card - as a line it would only be the machine's key. */\n if (line.role === 'system' && parseProposalRequestLine(content)) return nothing\n /*\n * ๊ฐ€๋ ค์ง„ ์ค„์€ ์–ด์‹œ์Šคํ„ดํŠธ์˜ ๋ง์ด ์•„๋‹ˆ๋‹ค โ€” ๋งˆํฌ๋‹ค์šด์œผ๋กœ ๊ทธ๋ฆฌ์ง€ ์•Š๊ณ , ๋ณต์‚ฌยท์žฌ์‹คํ–‰ ๊ฐ™์€ ์†์žก์ด๋„\n * ๋‹ฌ์ง€ ์•Š๋Š”๋‹ค(ADR-0073 ํŒ์ • 1). ๊ทธ ์†์žก์ด๋“ค์€ ์žˆ์ง€๋„ ์•Š์€ ๋‹ต์„ ๋‹ค๋ฃฌ๋‹ค.\n */\n const isMarkdown = line.role !== 'system' && content.length > 0 && !line.redacted\n const showActions = line.role !== 'system' && !line.pending && content.length > 0 && !line.redacted\n return html`\n ${showLabel\n ? html`<div class=\"msg-label\">${i18next.t('ai-assistant.label.ai')}</div>`\n : showSenderLabel\n ? html`<div class=\"msg-label sender\">${line.senderName || i18next.t('ai-assistant.label.participant')}</div>`\n : nothing}\n <div class=\"msg-wrap ${line.role} ${isOther ? 'other' : ''}\">\n <div\n class=\"msg ${line.role} ${isOther ? 'other' : ''} ${line.pending ? 'pending' : ''} ${line.systemOpen\n ? 'open'\n : ''} ${line.redacted ? 'redacted' : ''}\">\n ${line.pending\n ? html`<span class=\"typing-dots\"><span></span><span></span><span></span></span>`\n : line.redacted\n ? html`<div class=\"redacted-body\"><md-icon>lock</md-icon><span>${content}</span></div>`\n : isMarkdown\n ? html`<div class=\"md-body\">${unsafeHTML(renderMarkdown(content))}</div>`\n : line.role === 'system'\n ? html`<span\n class=\"sys-text\"\n title=${i18next.t('ai-assistant.text.toggle-system-note', { defaultValue: 'click to expand' })}\n @click=${() => this.toggleSystemNote(idx)}\n >${content}</span\n >`\n : content}\n ${line.attachments && line.attachments.length > 0\n ? html`\n <div class=\"msg-attachments\">\n ${line.attachments.map(att => {\n /* A stored file opens through the conversation's own route (ยง9-3); a fresh one shows its local copy. */\n const href = att.url || att.base64 || (att.id && this.sessionId ? chatAttachmentUrl(this.sessionId, att.id) : '')\n /* By type - a text file carries base64 too, and drew as a broken image (found on :3700). */\n return att.type?.startsWith('image/') || att.url?.startsWith('data:image/') || att.base64?.startsWith('data:image/')\n ? html`\n <a class=\"msg-attachment-img-wrap\" title=${att.name} href=${href} target=\"_blank\" rel=\"noopener\">\n <img src=${href} alt=${att.name} />\n <span class=\"msg-attachment-label\">${att.name}</span>\n </a>\n `\n : html`\n <a class=\"msg-attachment-file-chip\" title=${att.name} href=${href || nothing} target=\"_blank\" rel=\"noopener\">\n <md-icon>description</md-icon>\n <span>${att.name}</span>\n </a>\n `\n })}\n </div>\n `\n : nothing}\n ${line.patchId\n ? html`\n <div class=\"summary ${this.revertedPatchIds.has(line.patchId) ? 'reverted' : ''}\">\n <md-icon>check_circle</md-icon>\n <span class=\"summary-text\">\n ${this.revertedPatchIds.has(line.patchId)\n ? i18next.t('ai-assistant.text.reverted')\n : i18next.t('ai-assistant.text.applied-changes')}\n </span>\n <button\n class=\"revert-btn\"\n ?disabled=${this.revertedPatchIds.has(line.patchId)}\n @click=${() => line.patchId && this.onRevertClick(line.patchId)}>\n ${i18next.t('ai-assistant.button.revert')}\n </button>\n </div>\n `\n : nothing}\n ${line.followUp\n ? html`<div class=\"followup\">${unsafeHTML(renderMarkdown(line.followUp.trim()))}</div>`\n : nothing}\n ${line.proposals && line.proposals.length > 0 ? this.renderProposals(line) : nothing}\n ${line.groundingWarnings && line.groundingWarnings.length > 0\n ? this.renderGroundingWarning(line)\n : nothing}\n ${line.toolUsages && line.toolUsages.length > 0\n ? this.renderToolUsages(idx, line)\n : nothing}\n </div>\n ${showActions ? this.renderMessageActions(idx, line, content) : nothing}\n </div>\n `\n })\n })()}\n </div>\n ${this.errorMessage\n ? html`\n <div class=\"error\">\n <span class=\"error-text\">${this.errorMessage}</span>\n ${this.lastFailedInput\n ? html`\n <button class=\"retry-btn\" @click=${this.retryLastSend}>\n ${i18next.t('ai-assistant.button.retry')}\n </button>\n `\n : nothing}\n </div>\n `\n : nothing}\n ${this.renderFoldNotice()}\n <div\n class=\"composer ${this.dragOver ? 'drag-over' : ''} ${this.composerWide ? 'wide' : ''} ${this.previewedTable ? 'previewing' : ''}\"\n @dragover=${(e: DragEvent) => this.onComposerDragOver(e)}\n @dragleave=${(e: DragEvent) => this.onComposerDragLeave(e)}\n @drop=${(e: DragEvent) => this.onComposerDrop(e)}\n @paste=${(e: ClipboardEvent) => this.onComposerPaste(e)}>\n ${this.dragOver\n ? html`\n <div class=\"drag-drop-overlay\">\n <md-icon>cloud_upload</md-icon>\n <span>${i18next.t('ai-assistant.text.drop-files-here', { defaultValue: 'Drop images or files here' })}</span>\n </div>\n `\n : nothing}\n <div class=\"actions-row\">\n <input\n id=\"chat-file-input\"\n type=\"file\"\n multiple\n accept=${this.usesAttachmentPolicy ? acceptOf(this.modeView?.attachments) : 'image/*'}\n style=\"display: none\"\n @change=${(e: Event) => {\n const input = e.target as HTMLInputElement\n if (input.files?.length) {\n this.onAttachFiles(input.files)\n input.value = ''\n }\n }}\n />\n ${this.acceptsAttachments\n ? html`<button\n type=\"button\"\n class=\"action\"\n @click=${() => this.renderRoot.querySelector<HTMLInputElement>('#chat-file-input')?.click()}\n title=${i18next.t('ai-assistant.tooltip.attach-file', { defaultValue: 'attach an image (drag & drop or paste supported)' })}>\n <md-icon>attach_file</md-icon>\n ${i18next.t('ai-assistant.button.attach', { defaultValue: 'Attach' })}\n </button>`\n : nothing}\n ${hasMessages\n ? html`\n <button\n type=\"button\"\n class=\"action\"\n @click=${() => (this.examplesOpen = !this.examplesOpen)}\n title=${i18next.t('ai-assistant.text.show-examples-tooltip')}>\n <md-icon>${this.examplesOpen ? 'close' : 'lightbulb'}</md-icon>\n ${this.examplesOpen\n ? i18next.t('ai-assistant.button.close')\n : i18next.t('ai-assistant.button.examples')}\n </button>\n `\n : nothing}\n <button\n type=\"button\"\n class=\"action composer-size\"\n aria-pressed=${this.composerWide ? 'true' : 'false'}\n @click=${() => this.setComposerWide(!this.composerWide)}>\n <md-icon>${this.composerWide ? 'close_fullscreen' : 'open_in_full'}</md-icon>\n ${this.composerWide\n ? i18next.t('ai-assistant.button.write-narrow', { defaultValue: 'Narrow' })\n : i18next.t('ai-assistant.button.write-wide', { defaultValue: 'Write wide' })}\n </button>\n </div>\n ${this.renderTablePreview()}\n ${this.examplesOpen ? this.renderInlineExamples() : nothing}\n ${this.attachments.length > 0\n ? html`\n <div class=\"attachment-strip\">\n ${this.attachments.map(\n att => html`\n <div class=\"attachment-chip ${att.id === this.previewAttachmentId ? 'open' : ''}\" title=${att.name}>\n ${att.table\n ? html`<button\n type=\"button\"\n class=\"attachment-open\"\n aria-expanded=${att.id === this.previewAttachmentId ? 'true' : 'false'}\n @click=${() => (this.previewAttachmentId = att.id === this.previewAttachmentId ? null : att.id)}>\n <md-icon class=\"attachment-icon\">table_chart</md-icon>\n <span class=\"attachment-meta\">\n <span class=\"attachment-name\">${att.name}</span>\n <span class=\"attachment-size\">${this.tableShape(att.table)}</span>\n </span>\n </button>`\n : html`${att.type.startsWith('image/')\n ? html`<img class=\"attachment-thumb\" src=${att.url} alt=${att.name} />`\n : html`<md-icon class=\"attachment-icon\">description</md-icon>`}\n <div class=\"attachment-meta\">\n <span class=\"attachment-name\">${att.name}</span>\n <span class=\"attachment-size\">${formatFileSize(att.size)}</span>\n </div>`}\n <button\n type=\"button\"\n class=\"attachment-remove\"\n title=${i18next.t('ai-assistant.button.remove-attachment', { defaultValue: 'Remove attachment' })}\n @click=${() => this.removeAttachment(att.id)}>\n <md-icon>close</md-icon>\n </button>\n </div>\n `\n )}\n </div>\n `\n : nothing}\n ${this.renderInviteNotice()}\n <div class=\"input-row\">\n <div class=\"textarea-wrap\">\n <textarea\n .value=${this.input}\n @input=${(e: Event) => this.onTextareaInput(e)}\n @keydown=${(e: KeyboardEvent) => this.onKeyDown(e)}\n @blur=${() => {\n // ํฌ์ปค์Šค๋ฅผ popup item ์œผ๋กœ ์˜ฎ๊ธฐ๋Š” click ๋ณด๋‹ค blur ๊ฐ€ ๋จผ์ € โ€” popup item ์˜\n // mousedown.preventDefault() ๊ฐ€ ์ฒ˜๋ฆฌํ•˜์ง€๋งŒ ์•ˆ์ „๋ง์œผ๋กœ ์งง์€ ์ง€์—ฐ ํ›„ ๋‹ซ๊ธฐ.\n setTimeout(() => this.closeMentionPopup(), 150)\n }}\n ?disabled=${this.busy}\n rows=\"1\"\n placeholder=${this.conversation.placeholder ??\n this.placeholder ??\n i18next.t('ai-assistant.text.input-placeholder')}></textarea>\n ${this.mentionOpen\n ? html`\n <ox-mention-popup\n class=\"mention-popup\"\n .results=${this.mentionResults}\n .activeIndex=${this.mentionActiveIndex}\n .overflow=${this.mentionOverflow}\n @mention-active-change=${(e: CustomEvent) => {\n // ๋งˆ์šฐ์Šค hover โ€” keyboard nav ์™€ ๋™์ผํ•˜๊ฒŒ select + centerTo\n const idx = e.detail?.index\n if (typeof idx === 'number' && idx >= 0 && idx < this.mentionResults.length) {\n this.mentionActiveIndex = idx\n this.previewActiveCandidate()\n }\n }}\n @mention-select=${(e: CustomEvent) =>\n this.applyMention(e.detail.candidate)}></ox-mention-popup>\n `\n : nothing}\n </div>\n ${/*\n ๋‘ ์ž๋ฆฌ๋‹ค โ€” ์–ด์‹œ์Šคํ„ดํŠธ์—๊ฒŒ ๋ฌป๋Š” ์ž๋ฆฌ์™€ **๋ฐฉ์— ๋งํ•˜๋Š” ์ž๋ฆฌ**. ๋ˆ„๋ฅธ ์ž๋ฆฌ๊ฐ€ ๊ทธ ๋ง์˜ ๋Œ€์ƒ์„\n ์ •ํ•˜๊ณ , ์„œ๋ฒ„๋Š” ์–ด๋А ๋ฌธ์ด ๋ถˆ๋ ธ๋Š”์ง€๋กœ ๊ทธ ์‚ฌ์‹ค์„ ์ €์žฅํ•œ๋‹ค(ADR-0070 A15 ๊ฒฐ์ • โ‘ ).\n\n **๋ฐฉ์— ์‚ฌ๋žŒ์ด ์žˆ์„ ๋•Œ๋งŒ ๋ณด์ธ๋‹ค.** ํ˜ผ์ž ์“ฐ๋Š” ๋Œ€ํ™”์—์„œ ใ€Œ๋ฐฉ์— ๋งํ•˜๊ธฐใ€๋Š” ์•„๋ฌด์—๊ฒŒ๋„ ํ•˜์ง€ ์•Š๋Š”\n ๋ง์ด๊ณ , ๋ˆ„๋ฅผ ์ผ์ด ์—†๋Š” ๋‹จ์ถ”๋Š” ๋ฌด์—‡์ด ๊ธฐ๋ณธ์ธ์ง€ ํ๋ฆฐ๋‹ค. ์กฐ๊ฑด์€ ์ฐธ์—ฌ์ž ๋ชฉ๋ก๊ณผ ๊ฐ™๋‹ค(๋‘˜ ์ด์ƒ) โ€”\n ๋‘˜์งธ ์‚ฌ๋žŒ์€ ๋ฉ˜์…˜์œผ๋กœ ๋“ค์–ด์˜ค๊ณ , ๊ทธ ์ˆœ๊ฐ„ ์ด ์ž๋ฆฌ๋„ ํ•จ๊ป˜ ์„ ๋‹ค.\n */ ''}\n ${this.sessionId && this.participants.length >= 2\n ? html`\n <button\n class=\"say-to-room\"\n ?disabled=${this.busy || !this.input.trim()}\n @click=${() => this.sayToRoom()}\n title=${i18next.t('ai-assistant.text.say-to-room-tooltip', {\n defaultValue: 'say this to the people here โ€” the assistant does not answer'\n })}>\n <md-icon>forum</md-icon>\n </button>\n `\n : nothing}\n ${this.composerWide\n ? html`<span class=\"send-shortcut\">${i18next.t('ai-assistant.text.send-shortcut', { key: sendShortcut(navigator.platform), defaultValue: '{key} to send' })}</span>`\n : nothing}\n <button\n ?disabled=${this.busy || !!this.sendBlocked || (!this.input.trim() && this.attachments.length === 0)}\n @click=${this.send}\n title=${this.sendBlocked ||\n (this.composerWide\n ? i18next.t('ai-assistant.text.send-tooltip-wide', { key: sendShortcut(navigator.platform), defaultValue: 'Send ({key})' })\n : i18next.t('ai-assistant.text.send-tooltip'))}>\n ${this.busy\n ? html`<span class=\"spinner\"></span>`\n : html`<md-icon>arrow_upward</md-icon>`}\n </button>\n </div>\n </div>\n `\n }\n\n /**\n * ๋ฐฉ์— ๋งํ•œ๋‹ค โ€” ์–ด์‹œ์Šคํ„ดํŠธ๋Š” ๋‹ตํ•˜์ง€ ์•Š๋Š”๋‹ค.\n *\n * ์ €์žฅ๋˜๋Š” ๋Œ€ํ™”๊ฐ€ ์žˆ์„ ๋•Œ๋งŒ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์„ธ์…˜์ด ์—†๋Š” ์ฆ‰์„ ์งˆ๋ฌธ์—๋Š” ใ€Œ๋ฐฉใ€์ด ์—†๋‹ค โ€” ๊ทธ ์ž๋ฆฌ์—์„œ\n * ํ•œ ๋ง์€ ๋ˆ„๊ตฌ์—๊ฒŒ๋„ ๋‚จ์ง€ ์•Š๋Š”๋‹ค.\n */\n private async sayToRoom() {\n const body = this.input.trim()\n if (!body || this.busy) return\n if (!this.sessionId) {\n /* ๋งํ•  ๋ฐฉ์ด ์—†๋‹ค๋Š” ์‚ฌ์‹ค์„ ๋งํ•œ๋‹ค โ€” ์กฐ์šฉํžˆ ๋ฒ„๋ฆฌ๋ฉด ์‚ฌ๋žŒ์€ ๋งํ–ˆ๋‹ค๊ณ  ๋ฏฟ๋Š”๋‹ค. */\n this.errorMessage = i18next.t('ai-assistant.text.no-room-yet', {\n defaultValue: 'this conversation is not saved yet, so there is nobody else in it to talk to'\n })\n return\n }\n\n const localId = `local-${++this._localSeq}-r`\n this.lines = [...this.lines, { role: 'user', content: body, _localId: localId, senderEmail: this._myEmail }]\n this.input = ''\n this.busy = true\n try {\n const result = await client.mutate({\n mutation: SAY_TO_ROOM_MUTATION,\n variables: { sessionId: this.sessionId, content: body }\n })\n /* ๋ฐฉ์†ก ์—์ฝ”์™€ ๊ฒน์น˜์ง€ ์•Š๊ฒŒ ์„œ๋ฒ„ id ๋กœ ๋งž์ถ˜๋‹ค โ€” ๋ณด๋‚ธ ๋ง์ด ๋‘ ์ค„๋กœ ๋ณด์ด์ง€ ์•Š๊ฒŒ. */\n this._reconcileSentLine(localId, result.data?.sayToRoom ?? undefined, {})\n } catch (error) {\n this.lines = this.lines.filter(line => line._localId !== localId)\n this.input = body\n this.errorMessage = error instanceof Error ? error.message : String(error)\n } finally {\n this.busy = false\n }\n }\n\n /**\n * ๋ณด๋‚ด๊ธฐ ์ „์— ๋งํ•œ๋‹ค โ€” ใ€Œ์ด ์‚ฌ๋žŒ์€ ์ด ๋Œ€ํ™”์— ๋“ค์–ด์˜ต๋‹ˆ๋‹คใ€(ADR-0071 ๊ฒฐ์ • 1 โ‘ฃ).\n *\n * ๋ฉ˜์…˜์€ ์‚ฌ๋žŒ์„ ๋ถˆ๋Ÿฌ๋“ค์ธ๋‹ค. ๋ˆ„๋ฅธ ๋’ค์— ์•Œ๋ฉด ์ด๋ฏธ ๋“ค์–ด์™€ ์žˆ๊ณ , ํ˜‘์˜์˜ ๊ณต๊ฐœ ๋ฒ”์œ„๋Š” ๋˜๋Œ๋ฆฌ๊ธฐ ์–ด๋ ค์šด\n * ์ข…๋ฅ˜์˜ ์ผ์ด๋‹ค. ๊ทธ๋ž˜์„œ **์•„์ง ๋ณด๋‚ด์ง€ ์•Š์€ ์ƒํƒœ์—์„œ** ๋ˆ„๊ฐ€ ๋“ค์–ด์˜ค๊ฒŒ ๋˜๋Š”์ง€ ๋ณด์ธ๋‹ค.\n *\n * ์ดˆ๋Œ€ํ•  ์ˆ˜ ์—†๋Š” ์ž๋ฆฌ(๋ณด๊ธฐ ๊ถŒํ•œ ยท ์•„์ง ์ฐธ์—ฌ์ž๊ฐ€ ์•„๋‹˜)๋ผ๋ฉด ๊ทธ ์‚ฌ์‹ค์„ ๋งํ•œ๋‹ค โ€” ๋ˆŒ๋ €๋Š”๋ฐ ์•„๋ฌด ์ผ๋„\n * ์ผ์–ด๋‚˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ๋‚˜์˜๋‹ค.\n */\n private renderInviteNotice() {\n if (!this.sessionId) return nothing\n\n const here = new Set(this.participants.map(p => p.user?.id).filter(Boolean) as string[])\n const incoming = [...this.pickedUserMentions.entries()]\n .filter(([token, userId]) => this.input.includes(`@${token}`) && !here.has(userId))\n .map(([token]) => token)\n if (incoming.length === 0) return nothing\n\n const myRole = this.participants.find(p => p.user?.id && p.user.id === this._myUserId)?.role\n const mayInvite = myRole === 'owner' || myRole === 'member'\n const names = incoming.map(token => `@${token}`).join(', ')\n\n return html`\n <div class=\"invite-notice\">\n <md-icon>person_add</md-icon>\n <span>\n ${mayInvite\n ? i18next.t('ai-assistant.text.will-be-invited', {\n names,\n defaultValue: '{names} will join this conversation when you send'\n })\n : i18next.t('ai-assistant.text.cannot-invite', {\n names,\n defaultValue: '{names} will not join โ€” only the people already in this conversation can bring someone in'\n })}\n </span>\n </div>\n `\n }\n\n private get previewedTable(): ChatAttachment | undefined {\n return this.previewAttachmentId ? this.attachments.find(a => a.id === this.previewAttachmentId && a.table) : undefined\n }\n\n private tableShape(table: NonNullable<ChatAttachment['table']>) {\n return i18next.t('ai-assistant.text.table-shape', { rows: table.rows.length, columns: table.columns, defaultValue: '{rows} rows ร— {columns} columns' })\n }\n\n /*\n The rows of a pasted table, over the conversation - numbered as the file numbers them, which is the number the\n entry card names. Every row: the paste is held under the mode's limit already.\n */\n private renderTablePreview() {\n const att = this.previewedTable\n if (!att?.table) return nothing\n const { rows, columns } = att.table\n return html`\n <div\n class=\"table-preview\"\n role=\"region\"\n aria-label=${att.name}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.stopPropagation()\n this.previewAttachmentId = null\n }\n }}>\n <div class=\"table-preview-head\">\n <md-icon>table_chart</md-icon>\n <span class=\"table-preview-name\">${att.name}</span>\n <span class=\"table-preview-shape\">${this.tableShape(att.table)}</span>\n <button type=\"button\" class=\"action\" @click=${() => this.tableToWords(att.id)}>\n <md-icon>notes</md-icon>\n ${i18next.t('ai-assistant.button.table-to-words', { defaultValue: 'Put in as words' })}\n </button>\n <button type=\"button\" class=\"action\" @click=${() => (this.previewAttachmentId = null)}>\n <md-icon>close</md-icon>\n ${i18next.t('ai-assistant.button.close')}\n </button>\n </div>\n <div class=\"table-preview-body\">\n <table>\n ${rows.map(\n (row, i) => html`<tr>\n <th scope=\"row\">${i + 1}</th>\n ${Array.from({ length: columns }, (_, c) => html`<td>${row[c] ?? ''}</td>`)}\n </tr>`\n )}\n </table>\n </div>\n </div>\n `\n }\n\n private onKeyDown(e: KeyboardEvent) {\n /*\n The Enter that ends a Korean (or Japanese, Chinese) syllable belongs to the input method - sending on it\n sends the line without its last syllable, which then lands in the emptied box.\n */\n if (e.isComposing || e.keyCode === 229) return\n // Mention popup ํ™œ์„ฑ ์‹œ โ€” ํ™”์‚ดํ‘œ/Enter/Tab/Esc ๊ฐ€๋กœ์ฑ„์„œ popup ๋„ค๋น„๊ฒŒ์ด์…˜\n if (this.mentionOpen) {\n if (e.key === 'ArrowDown') {\n e.preventDefault()\n if (this.mentionResults.length > 0) {\n this.mentionActiveIndex =\n (this.mentionActiveIndex + 1) % this.mentionResults.length\n this.previewActiveCandidate()\n }\n return\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault()\n if (this.mentionResults.length > 0) {\n this.mentionActiveIndex =\n (this.mentionActiveIndex - 1 + this.mentionResults.length) %\n this.mentionResults.length\n this.previewActiveCandidate()\n }\n return\n }\n if (e.key === 'Enter' || e.key === 'Tab') {\n if (this.mentionResults.length > 0) {\n e.preventDefault()\n this.applyMention(this.mentionResults[this.mentionActiveIndex].candidate)\n return\n }\n // ๋งค์นญ 0๊ฐœ๋ฉด popup ๋‹ซ๊ณ  ์ผ๋ฐ˜ ๋™์ž‘ fall through\n this.closeMentionPopup()\n }\n if (e.key === 'Escape') {\n e.preventDefault()\n this.closeMentionPopup()\n return\n }\n }\n const action = composerKeyAction(e, this.composerWide)\n if (action === 'narrow') {\n /* The Escape that narrows the box is spent here - the floating dock closes on the next one. */\n e.preventDefault()\n e.stopPropagation()\n this.setComposerWide(false)\n } else if (action === 'send') {\n e.preventDefault()\n if (!this.busy) this.send()\n }\n }\n\n /** input ์ด๋ฒคํŠธ โ€” value ์ฆ‰์‹œ ๋ฐ˜์˜ + popup ๊ฐฑ์‹ ์€ 150ms ๋””๋ฐ”์šด์Šค (F-Finder ์™€ ๋™์ผ).\n * big board ์—์„œ ๋งค keystroke filter ๋น„์šฉ ์ ˆ๊ฐ + ํ•œ๊ตญ์–ด IME ์กฐํ•ฉ ์ค‘ ๊นœ๋นก์ž„ ์™„ํ™”. */\n private onTextareaInput(e: Event) {\n const ta = e.target as HTMLTextAreaElement\n this.input = ta.value\n if (this.inputDebounceTimer) clearTimeout(this.inputDebounceTimer)\n this.inputDebounceTimer = setTimeout(() => {\n this.refreshMentionPopup(ta)\n }, 150)\n }\n\n /** ํ˜„์žฌ cursor ์œ„์น˜๋ฅผ ๋ณด๊ณ  mention popup ํ™œ์„ฑ/๋น„ํ™œ์„ฑ + ํ›„๋ณด ๊ฐฑ์‹ .\n * `#` (์ปดํฌ๋„ŒํŠธ) / `@` (์นดํƒˆ๋กœ๊ทธ) / `/` (slash ํ…œํ”Œ๋ฆฟ) ํ•œ ๋ฒˆ์— ํ•˜๋‚˜๋งŒ ํ™œ์„ฑ. */\n private refreshMentionPopup(ta: HTMLTextAreaElement) {\n const cursor = ta.selectionStart ?? ta.value.length\n\n const triggers: Array<'#' | '@' | '/'> = ['#', '@', '/']\n let chosen: { hashPos: number; query: string; trigger: '#' | '@' | '/' } | null =\n null\n for (const t of triggers) {\n const ctx = extractMentionContext(ta.value, cursor, t)\n if (!ctx) continue\n if (!chosen || ctx.hashPos > chosen.hashPos) {\n chosen = { ...ctx, trigger: t }\n }\n }\n\n if (!chosen) {\n if (this.mentionOpen) this.closeMentionPopup()\n return\n }\n\n const wasOpen = this.mentionOpen\n const cap = 50\n let results: FilterResult[]\n if (chosen.trigger === '#' && this.searchProvider && chosen.query) {\n // ํ˜ธ์ŠคํŠธ์˜ SceneSearchEngine ์œ„์ž„ โ€” F-Finder ์™€ ๋™์ผ ๊ฒ€์ƒ‰ ๋ฃฐ. cap ๋งŒ chat ์ธก์—์„œ ์ ์šฉ.\n results = this.searchProvider(chosen.query).slice(0, cap)\n } else if (chosen.trigger === '@') {\n // `@` = ๋„๋ฉ”์ธ ์‚ฌ์šฉ์ž ๋ฉ˜์…˜. host ๊ฐ€ userProvider set ํ–ˆ์œผ๋ฉด query โ†’ users ๋น„๋™๊ธฐ fetch.\n // userProvider ๋ฏธ์„ค์ • / ๊ฒฐ๊ณผ ์—†์Œ โ†’ ๋นˆ popup (๋ฉ€ํ‹ฐ์œ ์ € ๋ฏธ์‚ฌ์šฉ ํ™˜๊ฒฝ).\n // async ๋ผ ์ฆ‰์‹œ ๋ฐ˜ํ™˜์€ ๋นˆ ๊ฒฐ๊ณผ; await ํ›„ ๋‹ค์‹œ set ํ•˜๋Š” ํŒจํ„ด.\n results = this.cachedUserCandidates\n ? filterMentionCandidates(this.cachedUserCandidates, chosen.query, cap)\n : []\n // ๋น„๋™๊ธฐ ๊ฐฑ์‹  โ€” ๊ฒฐ๊ณผ ๋„์ฐฉํ•˜๋ฉด popup ๋‹ค์‹œ ๊ฐฑ์‹ \n this.refreshUserCandidatesAsync(chosen.query, chosen.hashPos)\n } else {\n let all: MentionCandidate[]\n if (chosen.trigger === '#') {\n // ๋นˆ query ์˜ # ๋˜๋Š” searchProvider ๋ฏธ์„ค์ • โ€” ๋กœ์ปฌ enumeration ์œผ๋กœ ์ „์ฒด ํ›„๋ณด ํ‘œ์‹œ\n const liveBoard = this.boardProvider ? this.boardProvider() : this.currentBoard\n all = buildMentionCandidates(liveBoard?.components ?? [])\n } else {\n // `/` = ์นดํƒˆ๋กœ๊ทธ + slash ํ…œํ”Œ๋ฆฟ ํ†ตํ•ฉ (Notion `/` ํŒจํ„ด). ๋‘˜ ๋‹ค \"์‚ฝ์ž… ๊ฐ€๋Šฅ ํ•ญ๋ชฉ\".\n all = [...this.cachedCatalogCandidates, ...this.cachedSlashCandidates]\n }\n results = filterMentionCandidates(all, chosen.query, cap)\n }\n // overflow ๊ณ„์‚ฐ โ€” ์ „์ฒด ๋งค์นญ ์ค‘ cap ์œผ๋กœ ์ž˜๋ ค๋‚˜๊ฐ„ ์ˆ˜ (popup 'N more' ํ‘œ๊ธฐ)\n // (cap ์ž˜๋ผ์„œ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ, ์ „์ฒด ์นด์šดํŠธ๋Š” ์ž์œ  ๊ฒ€์ƒ‰ ์‹œ ์•Œ๊ธฐ ์–ด๋ ค์›€.\n // ์—„๊ฒฉํ•œ overflow ์ถ”์  ๋Œ€์‹  results.length === cap ์ด๋ฉด ์ถ”์ • ํ‘œ์‹œ)\n const overflow = results.length === cap ? 0 : 0\n this.mentionResults = results\n this.mentionOverflow = overflow\n this.mentionActiveIndex = 0\n this.mentionHashPos = chosen.hashPos\n this.mentionTrigger = chosen.trigger\n this.mentionOpen = true\n\n // ์ฒซ open ์‹œ โ€” ์‚ฌ์šฉ์ž selection ์Šค๋ƒ…์ƒท (์ทจ์†Œ ์‹œ ์›๋ณต์šฉ)\n if (!wasOpen && chosen.trigger === '#') {\n this.originalSelectedRefids = (this.selectedRefids ?? []).slice()\n }\n // ๋งค์นญ๋œ ํ›„๋ณด outline ๋งŒ ๊ฐฑ์‹  โ€” ์นด๋ฉ”๋ผ/์„ ํƒ ๋ณ€๊ฒฝ์€ commit (Enter/click) ์‹œ์ ์—๋งŒ.\n this.highlightMatchedCandidates()\n }\n\n /**\n * ํ˜ธ์ŠคํŠธ๊ฐ€ ๋ชฉ๋ก์„ ์ฃผ์ง€ ์•Š์„ ๋•Œ ์ด ๋„๋ฉ”์ธ์˜ ์‚ฌ์šฉ์ž๋ฅผ ์ง์ ‘ ๋ฌป๋Š”๋‹ค.\n *\n * ์‹คํŒจ๋Š” ๋นˆ ๋ชฉ๋ก์ด๋‹ค โ€” ๋ฉ˜์…˜์„ ๋ชป ๊ณ ๋ฅด๋Š” ๊ฒƒ์ด์ง€ ๋Œ€ํ™”๊ฐ€ ๋ง‰ํž ์ผ์€ ์•„๋‹ˆ๋‹ค.\n */\n private async fetchDomainUsers(query: string): Promise<Array<{ id: string; name?: string | null; email?: string | null }>> {\n try {\n const result = await client.query({\n query: DOMAIN_USERS_FOR_MENTION_QUERY,\n variables: { query },\n fetchPolicy: 'network-only'\n })\n return result.data?.domainUsersForMention ?? []\n } catch {\n return []\n }\n }\n\n /** `@` query ์— ๋Œ€ํ•œ userProvider ๋น„๋™๊ธฐ ํ˜ธ์ถœ โ€” ์‘๋‹ต ๋„์ฐฉ ์‹œ popup ๊ฒฐ๊ณผ ๊ฐฑ์‹ .\n * race ๋ฐฉ์ง€: token ์œผ๋กœ ์ตœ์‹  ํ˜ธ์ถœ ์‹๋ณ„ (๋Šฆ๊ฒŒ ๋„์ฐฉํ•œ ์‘๋‹ต ๋ฌด์‹œ). */\n private async refreshUserCandidatesAsync(query: string, hashPos: number) {\n const token = ++this.userFetchToken\n try {\n const users = this.userProvider\n ? await Promise.resolve(this.userProvider(query))\n : await this.fetchDomainUsers(query)\n if (token !== this.userFetchToken) return // ๋” ์ตœ์‹  ํ˜ธ์ถœ์ด ์žˆ์Œ\n // popup ์ด ๋‹ซํ˜”๊ฑฐ๋‚˜ trigger / hashPos ๊ฐ€ ๋ฐ”๋€Œ๋ฉด ๋ฌด์‹œ\n if (!this.mentionOpen || this.mentionTrigger !== '@' || this.mentionHashPos !== hashPos) {\n return\n }\n this.cachedUserCandidates = buildUserCandidates(users)\n this.mentionResults = filterMentionCandidates(\n this.cachedUserCandidates,\n query,\n 50\n )\n this.mentionActiveIndex = 0\n } catch (e) {\n // ์กฐ์šฉํžˆ ๋ฌด์‹œ โ€” ์‚ฌ์šฉ์ž ์ž…๋ ฅ ํ๋ฆ„ ๋ฐฉํ•ด X. ๋””๋ฒ„๊ทธ ์‹œ console ํ™•์ธ ๊ฐ€๋Šฅ.\n console.warn('[board-ai-chat] userProvider failed:', e)\n }\n }\n\n /** popup ํ›„๋ณด๋“ค outline highlight โ€” ์นด๋ฉ”๋ผ/์„ ํƒ ๋ณ€๊ฒฝ ์—†์Œ.\n * ํƒ€์ดํ•‘ ์งํ›„ (refreshMentionPopup) ์—์„œ ํ˜ธ์ถœ โ€” ์‚ฌ์šฉ์ž๊ฐ€ active ๋ฅผ ๋ช…์‹œ ์ด๋™ํ•˜์ง€\n * ์•Š์€ ์ƒํƒœ์ด๋ฏ€๋กœ ์ž„์˜์˜ ์ฒซ ํ•ญ๋ชฉ์„ ์„ ํƒํ•˜๊ฑฐ๋‚˜ ์นด๋ฉ”๋ผ ์ด๋™์‹œํ‚ค์ง€ ์•Š์Œ.\n * # trigger ์ผ ๋•Œ๋งŒ ํ™œ์„ฑ. */\n private highlightMatchedCandidates() {\n if (this.mentionTrigger !== '#') return\n const allRefids: number[] = []\n for (const r of this.mentionResults) {\n if (typeof r.candidate.refid === 'number') allRefids.push(r.candidate.refid)\n }\n this.dispatchActions([{ action: 'highlightComponents', refids: allRefids }])\n }\n\n /** active ํ›„๋ณด live preview โ€” ์‚ฌ์šฉ์ž๊ฐ€ โ†‘โ†“ ํ‚ค / popup ๋งˆ์šฐ์Šค hover ๋กœ ๋ช…์‹œ์ ์œผ๋กœ\n * active ๋ฅผ ์˜ฎ๊ธด ์‹œ์ ์— ํ˜ธ์ถœ. F-Finder ๋™๊ธ‰ 3-action: highlight + select + centerTo.\n * centerTo ๋Š” 150ms ๋””๋ฐ”์šด์Šค โ€” ๋น ๋ฅธ nav ์‹œ ์นด๋ฉ”๋ผ ์• ๋‹ˆ๋ฉ”์ด์…˜ race ๋ฐฉ์ง€.\n * # trigger ์ผ ๋•Œ๋งŒ ํ™œ์„ฑ. */\n private previewActiveCandidate() {\n if (this.mentionTrigger !== '#') return\n const allRefids: number[] = []\n for (const r of this.mentionResults) {\n if (typeof r.candidate.refid === 'number') allRefids.push(r.candidate.refid)\n }\n const active = this.mentionResults[this.mentionActiveIndex]\n const activeRefid =\n active && typeof active.candidate.refid === 'number'\n ? active.candidate.refid\n : undefined\n\n const actions: any[] = [{ action: 'highlightComponents', refids: allRefids }]\n if (typeof activeRefid === 'number') {\n actions.push({ action: 'selectComponents', refids: [activeRefid] })\n }\n this.dispatchActions(actions)\n\n if (this.centerDebounceTimer) clearTimeout(this.centerDebounceTimer)\n if (typeof activeRefid === 'number') {\n this.centerDebounceTimer = setTimeout(() => {\n this.dispatchActions([\n { action: 'centerToComponent', refid: activeRefid, animated: true }\n ])\n }, 150)\n }\n }\n\n private dispatchActions(actions: any[]) {\n this.dispatchEvent(\n new CustomEvent('scene-action-execute', {\n detail: { actions, sessionId: this.sessionId },\n bubbles: true,\n composed: true\n })\n )\n }\n\n /** ๋ฉ”์‹œ์ง€ ๋ฒ„๋ธ”์˜ `<span class=\"mention\">#token</span>` ํด๋ฆญ โ€” ์ปดํฌ๋„ŒํŠธ๋กœ select + centerTo.\n * resolve ๋ฃฐ์€ pure helper `resolveMentionToken` ์— ์œ„์ž„ (๋‹จ์œ„ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ). */\n private onBubbleClick = (e: Event) => {\n const target = e.target as HTMLElement | null\n if (!target?.classList?.contains('mention')) return\n e.preventDefault()\n const text = (target.textContent || '').trim()\n const token = text.startsWith('#') ? text.slice(1) : text\n if (!token) return\n\n const refid = resolveMentionToken(token, {\n persistedRefid: target.getAttribute('data-refid'),\n searchProvider: this.searchProvider,\n board: this.boardProvider ? this.boardProvider() : this.currentBoard\n })\n\n if (typeof refid === 'number') {\n this.dispatchActions([\n { action: 'selectComponents', refids: [refid] },\n { action: 'centerToComponent', refid, animated: true }\n ])\n } else {\n this.showToast(\n i18next.t('ai-assistant.text.mention-not-found', {\n token,\n defaultValue: `#${token} not found`\n })\n )\n }\n }\n\n /** popup ๋‹ซ๊ธฐ. commit=false (์ทจ์†Œ) ๋ฉด # ์˜ ๊ฒฝ์šฐ:\n * - highlight ์ •๋ฆฌ (highlightComponents [])\n * - ์›๋ž˜ selection ์œผ๋กœ ์›๋ณต\n * commit=true (ํ™•์ •) ๋ฉด ํ˜„์žฌ preview ์ƒํƒœ ์œ ์ง€ + highlight ๋งŒ ์ •๋ฆฌ. */\n private closeMentionPopup(commit = false) {\n if (!this.mentionOpen) return\n const wasHashTrigger = this.mentionTrigger === '#'\n this.mentionOpen = false\n this.mentionResults = []\n this.mentionOverflow = 0\n this.mentionActiveIndex = 0\n this.mentionHashPos = -1\n\n if (wasHashTrigger) {\n // popup ๋‹ซํž˜ โ†’ highlight ํ•ญ์ƒ ์ •๋ฆฌ (ํ™•์ •/์ทจ์†Œ ๋ชจ๋‘)\n const cleanupActions: any[] = [{ action: 'highlightComponents', refids: [] }]\n if (!commit) {\n // ์ทจ์†Œ โ€” ์›๋ž˜ selection ์œผ๋กœ ์›๋ณต\n cleanupActions.push({\n action: 'selectComponents',\n refids: this.originalSelectedRefids\n })\n }\n this.dispatchActions(cleanupActions)\n }\n }\n\n /** ํ›„๋ณด 1๊ฐœ๋ฅผ textarea ์— ์ ์šฉ + popup ๋‹ซ๊ณ  cursor ์žฌ๋ฐฐ์น˜. */\n private applyMention(candidate: MentionCandidate) {\n const ta = this.renderRoot.querySelector('textarea') as HTMLTextAreaElement | null\n if (!ta || this.mentionHashPos < 0) {\n this.closeMentionPopup()\n return\n }\n const cursor = ta.selectionStart ?? ta.value.length\n const r = applyMentionSelection(\n ta.value,\n cursor,\n this.mentionHashPos,\n candidate,\n this.mentionTrigger\n )\n this.input = r.text\n // # trigger + refid ๋ณด์œ  ํ›„๋ณด โ€” commit ์‹œ์ ์—๋งŒ select + centerTo (์‚ฌ์šฉ์ž ์˜๋„ ํ™•์ • ์ˆœ๊ฐ„).\n // ๋™์‹œ์— picks ๋กœ ๊ธฐ๋ก: textarea ์—๋Š” ๊นจ๋—ํ•œ #label, server ์—๋Š” ์ •ํ™•ํ•œ refid ์ „๋‹ฌ.\n if (\n this.mentionTrigger === '#' &&\n typeof candidate.refid === 'number'\n ) {\n this.pickedMentions.set(candidate.label, candidate.refid)\n this.dispatchActions([\n { action: 'selectComponents', refids: [candidate.refid] },\n { action: 'centerToComponent', refid: candidate.refid, animated: true }\n ])\n } else if (\n this.mentionTrigger === '@' &&\n typeof candidate.userId === 'string' &&\n candidate.userId.length > 0\n ) {\n // @user ๋ฉ˜์…˜ โ€” userId ๋ฐ•์ œ. ๋ณด๋“œ ์•ก์…˜์€ ๋ฐœ์‚ฌ ์•ˆ ํ•จ (์‚ฌ์šฉ์ž๋Š” ์ปดํฌ๋„ŒํŠธ ์•„๋‹˜).\n this.pickedUserMentions.set(candidate.label, candidate.userId)\n }\n this.closeMentionPopup(true) // commit โ€” preview selection ์œ ์ง€, highlight ๋งŒ ์ •๋ฆฌ\n requestAnimationFrame(() => {\n const ta2 = this.renderRoot.querySelector('textarea') as HTMLTextAreaElement | null\n ta2?.focus()\n ta2?.setSelectionRange(r.cursorPos, r.cursorPos)\n })\n }\n\n // โ”€โ”€ Empty state with onboarding guide โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\n /** ์˜ˆ์‹œ ๊ทธ๋ฃน โ€” i18n ํ‚ค. localize mixin ์ด ์–ธ์–ด ๋ณ€๊ฒฝ ์‹œ ์ž๋™ ์žฌ๋ Œ๋”. */\n /**\n * ํ™”๋ฉด์— ๊ทธ๋ฆด ์˜ˆ์‹œ โ€” ํ˜ธ์ŠคํŠธ๊ฐ€ ์ค€ ๊ฒƒ์ด ์žˆ์œผ๋ฉด ๊ทธ๊ฒƒ, ์—†์œผ๋ฉด ๋ณด๋“œ ๊ธฐ๋ณธ๊ฐ’(i18n ํ‚ค๋ฅผ ์—ฌ๊ธฐ์„œ ํ‘ผ๋‹ค).\n *\n * ๋‘ ์ž๋ฆฌ(๋นˆ ํ™”๋ฉด ยท ์ ‘ํžŒ ์ค„)๊ฐ€ ๊ฐ™์€ ๊ฐ’์„ ์จ์•ผ ํ•œ๋‹ค. ์ „์—๋Š” ๋‘˜์ด ๊ฐ๊ฐ `EXAMPLE_GROUPS` ๋ฅผ ์ง์ ‘\n * ์ฝ์—ˆ๊ณ , ๊ทธ๋Ÿฌ๋ฉด ํ˜ธ์ŠคํŠธ ๊ฐ’์„ ํ•œ์ชฝ๋งŒ ๋ฐ˜์˜ํ•˜๋Š” ์ƒํƒœ๊ฐ€ ๋งŒ๋“ค์–ด์งˆ ์ˆ˜ ์žˆ์—ˆ๋‹ค.\n */\n private get exampleGroups(): Array<{ label: string; items: string[] }> {\n /*\n * ๋Œ€ํ™”๊ฐ€ ์ž๊ธฐ ์˜ˆ์‹œ๋ฅผ ๊ฐ€์ง€๋ฉด ๊ทธ๊ฒƒ์ด ๋จผ์ €๋‹ค โ€” ์ž๋ฆฌํ‘œยท`/` ์™€ ๊ฐ™์€ ์ฐจ๋ก€(ADR-0061 ๊ฒฐ์ • 7). host ์†์„ฑ์€\n * ๋Œ€ํ™”๋ฅผ ๋ชจ๋ฅด๋ฏ€๋กœ, ํ•œ ํ™”๋ฉด์— ๋Œ€ํ™”๊ฐ€ ๋‘˜ ์„œ๋ฉด ํ•œ์ชฝ์— ๋งž๋Š” ๊ธ€์ด ๋‹ค๋ฅธ ์ชฝ์—๋„ ๋œฌ๋‹ค.\n */\n if (this.modeView?.examples?.length) return this.modeView.examples\n if (this.examples?.length) return this.examples\n return OxAssistantChat.EXAMPLE_GROUPS.map(group => ({\n label: i18next.t(group.labelKey),\n items: group.itemKeys.map(key => i18next.t(key))\n }))\n }\n\n /** ์ด ํ‘œ๋ฉด์ด ์‹ค์ œ๋กœ ์“ธ ์ˆ˜ ์žˆ๋Š” ํŠธ๋ฆฌ๊ฑฐ โ€” ํŒ์ •์€ `chat-triggers.ts` ๊ฐ€ ํ•˜๊ณ  ์—ฌ๊ธฐ์„œ๋Š” ์‚ฌ์‹ค๋งŒ ์ฝ๋Š”๋‹ค. */\n private get triggerChips(): TriggerChip[] {\n return availableTriggers({\n hasMentionableThings: !!(this.boardProvider || this.currentBoard || this.knownTypes?.length),\n hasSession: !!this.sessionId,\n slashTemplateCount: this.conversation.slashTemplates.length\n })\n }\n\n private static readonly EXAMPLE_GROUPS: Array<{\n labelKey: string\n itemKeys: string[]\n }> = [\n {\n labelKey: 'ai-assistant.label.create',\n itemKeys: [\n 'ai-assistant.example.create-monitoring-dashboard',\n 'ai-assistant.example.create-welcome-screen'\n ]\n },\n {\n labelKey: 'ai-assistant.label.edit',\n itemKeys: [\n 'ai-assistant.example.edit-align-distribute',\n 'ai-assistant.example.edit-resize-board'\n ]\n },\n {\n labelKey: 'ai-assistant.label.style',\n itemKeys: [\n 'ai-assistant.example.style-dark-mode',\n 'ai-assistant.example.style-rounded-shadow'\n ]\n }\n ]\n\n /** ๋ณด๋“œ์˜ ์„ธ์…˜ ํƒญ โ€” ๋‹ค์ค‘ ์„ธ์…˜ ํ™œ์„ฑํ™” ์‹œ ํŒจ๋„ ์ƒ๋‹จ. host ๊ฐ€ sessions ๋น„์›Œ๋‘๋ฉด ํ‘œ์‹œ X.\n * ๋ ˆ์ด๋ธ”์€ session.name ์šฐ์„ , ์—†์œผ๋ฉด fallback \"์„ธ์…˜ N\". */\n /**\n * ์ด ๋Œ€ํ™”์˜ **์ฃผ์–ด** โ€” ๊ฐ™์€ ํ™”๋ฉด ์œ„์— ๋‘ ๋Œ€ํ™”๊ฐ€ ์„ค ๋•Œ๋งŒ ๋‚˜์˜จ๋‹ค(ADR-0072 A17 โ‘ ).\n *\n * ํ•˜๋‚˜๋ฟ์ด๋ฉด ์•„๋ฌด๊ฒƒ๋„ ๊ทธ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค. ๊ณ ๋ฅผ ๊ฒƒ์ด ์—†๋Š” ๊ณ ๋ฅด๊ฐœ๋Š” ์ž๋ฆฌ๋งŒ ์ฐจ์ง€ํ•˜๊ณ , ์‚ฌ๋žŒ์—๊ฒŒ ใ€Œ๋ฌด์–ธ๊ฐ€\n * ๊ณ ๋ฅผ ๊ฒƒ์ด ์žˆ๋‹คใ€๋Š” ์ž˜๋ชป๋œ ์‹ ํ˜ธ๋ฅผ ์ค€๋‹ค.\n *\n * โ”€โ”€ ์™œ ํƒญ ์ค„์ด ์•„๋‹Œ๊ฐ€ (UX ๋ ˆ์ธ, 2026-09-18) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ์ฒ˜์Œ์—๋Š” ์นฉ ์ค„์— `role=\"tablist\"` ๋ฅผ ๋‹ฌ์•˜๋‹ค. ๋ฐ”๋กœ ์•„๋ž˜๊ฐ€ ์„ธ์…˜ ํƒญ์ด๊ณ  ๊ทธ์ชฝ๋„ tablist ๋ผ์„œ, ํ™”๋ฉด\n * ๋‚ญ๋…๊ธฐ๋กœ ๋“ค์œผ๋ฉด ใ€Œํƒญ ๋ชฉ๋ก, ๋Œ€ํ™”ใ€ ๋‹ค์Œ์— ใ€Œํƒญ ๋ชฉ๋ก, Conversation historyใ€ ๊ฐ€ ์ด์–ด์กŒ๋‹ค โ€” ๊ณ ๋ฅด๋Š”\n * ์ถ•์ด ๋‘˜์ธ๋ฐ ๋‘˜ ๋‹ค ใ€Œํƒญใ€์ด๋ผ๊ณ  ๋งํ•œ๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ ARIA ํƒญ์€ ์ขŒ์šฐ ํ™”์‚ดํ‘œ ์ด๋™๊ณผ `tabpanel` ์ด ํ•จ๊ป˜\n * ์žˆ์–ด์•ผ ์„ฑ๋ฆฝํ•˜๊ณ , ๋‘˜ ๋‹ค ์—†์œผ๋ฉด ๋‚ญ๋…๊ธฐ๋Š” ใ€Œ2 ์ค‘ 1๋ฒˆ์งธ ํƒญใ€์ด๋ผ ๋งํ•˜๊ณ  ํ™”์‚ดํ‘œ๋Š” ์•„๋ฌด ์ผ๋„ ์•ˆ ํ•œ๋‹ค.\n *\n * ๋ฌด๊ฒŒ๋„ ๋‹ค๋ฅด๋‹ค. ์„ธ์…˜์€ ใ€Œ์–ด๋А ์ง€๋‚œ ๋Œ€ํ™”๋ƒใ€์ด๊ณ  ๋ชจ๋“œ๋Š” ใ€Œ์ด ๋Œ€ํ™”๊ฐ€ ๋ฌด์—‡์— ๋Œ€ํ•œ ๊ฒƒ์ด๋ƒใ€์ด๋‹ค. ๊ฐ™์€\n * ๋ฌด๊ฒŒ๋กœ ๊ทธ๋ฆฌ๋ฉด ์–ด๋А ์ชฝ์ด ํ™”์ œ๋ฅผ ๋ฐ”๊พธ๊ณ  ์–ด๋А ์ชฝ์ด ์‹คํƒ€๋ž˜๋ฅผ ๋ฐ”๊พธ๋Š”์ง€ ๊ตฌ๋ณ„๋˜์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ž˜์„œ ์ง€๊ธˆ\n * ๋Œ€ํ™”๊ฐ€ ์ œ๋ชฉ ๊ตต๊ธฐ๋กœ ์„œ๊ณ , ๋ฐ”๊ฟ€ ์ž๋ฆฌ๋Š” ๊ทธ ์˜†์— ๋ถ™๋Š”๋‹ค.\n *\n * โ”€โ”€ ์™œ ๋„ํฌ ์ œ๋ชฉ ์ค„๋กœ ์•ˆ ์˜ฌ๋ฆฌ๋‚˜ (UX ๋ ˆ์ธ ํŒ์ •, 2026-09-18) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ๋„ํฌ ์ œ๋ชฉ์€ ใ€Œ์ง€๊ธˆ ์–ด๋””์— ์žˆ๋‚˜ใ€(์ด ๋„ํ˜• ยท ์ด ํ˜„์žฅ ยท ์ด ์Šคํ…Œ์ด์…˜ ํ™”๋ฉด)์ด๊ณ  ์ด ์ค„์€ ใ€Œ์ด ๋Œ€ํ™”๊ฐ€\n * ๋ฌด์—‡์— ๋Œ€ํ•œ ๊ฒƒ์ด๋ƒใ€์ด๋‹ค. ๋Œ€ํ™”์˜ ์ฃผ์–ด๋Š” ๋Œ€ํ™” ์•ˆ์— ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์„ธ ๋„ํฌ๊ฐ€ ๊ฐ์ž ๊ทธ๋ฆฌ๋ฉด ์„ธ ๋ฒŒ์ด ๋˜๊ณ \n * ๊ทธ ์„ธ ๋ฒŒ์€ ๊ฐˆ๋ฆฐ๋‹ค โ€” `modeChoices` ๋ฅผ ์•„๋Š” ๊ฒƒ๋„ ์—ฌ๊ธฐ๋‹ค. ์˜ฌ๋ฆฌ๋ฉด ๋ชฉ๋ก๊ณผ ๊ณ ๋ฅธ ๊ฒƒ์ด ์„ธ ์ž๋ฆฌ๋กœ ๋‚˜๊ฐ”๋‹ค\n * ๋Œ์•„์˜จ๋‹ค.\n */\n private renderModeSubject() {\n if (this.modeChoices.length < 2) return nothing\n\n const current = this.modeChoices.find(choice => choice.kind === this.mode?.kind)\n const others = this.modeChoices.filter(choice => choice.kind !== this.mode?.kind)\n\n return html`\n <div class=\"mode-subject\">\n <span class=\"mode-now\">${current?.label ?? this.mode?.kind ?? ''}</span>\n ${others.length === 1\n ? html`\n <button\n class=\"mode-switch\"\n title=${i18next.t('ai-assistant.text.switch-conversation', { name: others[0].label })}\n aria-label=${i18next.t('ai-assistant.text.switch-conversation', { name: others[0].label })}\n ?disabled=${this.busy}\n @click=${() => this.onModePick(others[0].kind)}>\n ${others[0].label}\n </button>\n `\n : html`\n <select\n class=\"mode-select\"\n aria-label=${i18next.t('ai-assistant.label.conversation')}\n ?disabled=${this.busy}\n @change=${(event: Event) => this.onModePick((event.target as HTMLSelectElement).value)}>\n ${this.modeChoices.map(\n choice => html`<option value=${choice.kind} ?selected=${choice.kind === this.mode?.kind}>${choice.label}</option>`\n )}\n </select>\n `}\n </div>\n `\n }\n\n private renderSessionTabs() {\n if (!this.sessions || this.sessions.length === 0) return nothing\n return html`\n <ox-assistant-session-toolbar style=\"padding:8px 12px\" .sessions=${this.sessions}\n .sessionId=${this.sessionId || ''} .disabled=${this.busy}\n @assistant-session-select=${(event: CustomEvent) => { event.stopPropagation(); this._onSessionTabClick(event.detail.sessionId) }}\n @assistant-session-reset=${(event: Event) => { event.stopPropagation(); this._onSessionCreateClick() }}\n ></ox-assistant-session-toolbar>\n `\n }\n\n /** C4 roster โ€” ์„ธ์…˜ ์ฐธ์—ฌ์ž + online ํ‘œ์‹œ. ์ฐธ์—ฌ์ž 2๋ช… ๋ฏธ๋งŒ์ด๋ฉด ์ˆจ๊น€(ํ˜ผ์ž๋ฉด ์˜๋ฏธ ์—†์Œ). */\n private renderRoster() {\n if (!this.sessionId || this.participants.length < 2) return nothing\n const online = this.participants.filter(p => this._isOnline(p.lastSeenAt)).length\n return html`\n <div class=\"roster\" role=\"group\" aria-label=\"participants\">\n <span class=\"roster-count\" title=${`${online} online / ${this.participants.length} total`}>\n <md-icon>group</md-icon>${online}/${this.participants.length}\n </span>\n ${this.participants.map(p => {\n const name = p.user?.name || p.user?.id || '?'\n const on = this._isOnline(p.lastSeenAt)\n return html`<span\n class=\"roster-chip ${on ? 'online' : 'offline'}\"\n title=${`${name} ยท ${p.role}${on ? ' ยท online' : ''}`}>\n <span class=\"roster-dot\"></span>${initials(name)}\n </span>`\n })}\n </div>\n `\n }\n\n private _onSessionTabClick(sessionId: string) {\n if (sessionId === this.sessionId) return\n this.dispatchEvent(\n new CustomEvent('session-switch', {\n detail: { sessionId },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private _onSessionCreateClick = () => {\n if (this.busy || this.lines.length === 0) return\n this.dispatchEvent(\n new CustomEvent('session-create', {\n bubbles: true,\n composed: true\n })\n )\n }\n\n private renderEmpty() {\n return html`\n <div class=\"empty\">\n <div class=\"header\">\n <md-icon class=\"icon\">auto_awesome</md-icon>\n <!-- ๋Œ€ํ™”๊ฐ€ ์ž๊ธฐ ๊ธ€์„ ๊ฐ€์ง€๋ฉด ๊ทธ๊ฒƒ์ด ๋จผ์ €๋‹ค โ€” host ์†์„ฑ์€ ๋Œ€ํ™”๋ฅผ ๋ชจ๋ฅธ๋‹ค. -->\n <div class=\"title\">\n ${this.modeView?.intro?.title ?? this.intro?.title ?? i18next.t('ai-assistant.text.empty-title')}\n </div>\n <div class=\"subtitle\">\n ${this.modeView?.intro?.subtitle ?? this.intro?.subtitle ?? i18next.t('ai-assistant.text.empty-subtitle')}\n </div>\n </div>\n\n ${this.triggerChips.length > 0\n ? html`\n <div class=\"trigger-row\">\n <div class=\"trigger-row-label\">${i18next.t('ai-assistant.text.triggers-heading')}</div>\n <div class=\"trigger-chips\">\n ${this.triggerChips.map(\n trigger => html`\n <button\n class=\"trigger-chip\"\n title=${i18next.t(trigger.tooltipKey)}\n @click=${() => this.insertTrigger(trigger.char)}>\n <span class=\"trigger-char\">${trigger.char}</span>\n <span class=\"trigger-desc\">${i18next.t(trigger.labelKey)}</span>\n </button>\n `\n )}\n </div>\n </div>\n `\n : ''}\n\n ${this.exampleGroups.map(\n group => html`\n <div class=\"group\">\n <div class=\"group-label\">${group.label}</div>\n ${group.items.map(\n text => html`\n <button class=\"example\" @click=${() => this.useExample(text)}>\n ${text}<span class=\"arrow\">โ†’</span>\n </button>\n `\n )}\n </div>\n `\n )}\n\n <div class=\"footer\">\n <span class=\"badge\">${i18next.t('ai-assistant.label.korean-supported')}</span>\n <span class=\"badge\">${i18next.t('ai-assistant.label.multi-command')}</span>\n <span class=\"badge\">${i18next.t('ai-assistant.label.review-able')}</span>\n ${this.conversation.footerNotice\n ? html`<br />${this.conversation.footerNotice}`\n : ''}\n </div>\n </div>\n `\n }\n\n /** trigger chip ํด๋ฆญ โ€” textarea ์— trigger ๋ฌธ์ž ์‚ฝ์ž… + focus + popup ์ž๋™ ํ™œ์„ฑ. */\n private insertTrigger(trigger: '#' | '@' | '/') {\n // ์ž…๋ ฅ ๋์— ๊ณต๋ฐฑ์ด ์—†์œผ๋ฉด ๊ณต๋ฐฑ ์ถ”๊ฐ€ ํ›„ trigger โ€” ์ž์—ฐ์Šค๋Ÿฌ์šด ์œ„์น˜\n const needsSpace = this.input.length > 0 && !/\\s$/.test(this.input)\n this.input = this.input + (needsSpace ? ' ' : '') + trigger\n requestAnimationFrame(() => {\n const ta = this.renderRoot.querySelector('textarea') as HTMLTextAreaElement | null\n if (!ta) return\n ta.focus()\n ta.setSelectionRange(ta.value.length, ta.value.length)\n // popup refresh โ€” onTextareaInput ์ด ๋””๋ฐ”์šด์Šค ํ›„ ํ˜ธ์ถœ๋˜์ง€๋งŒ ์ง์ ‘ ํ˜ธ์ถœ๋กœ ์ฆ‰๊ฐ ๋ฐ˜์˜\n this.refreshMentionPopup(ta)\n })\n }\n\n /** ์˜ˆ์‹œ ํด๋ฆญ โ€” ์ž…๋ ฅ์ฐฝ์— ์ฑ„์šฐ๊ณ  ํฌ์ปค์Šค (์‚ฌ์šฉ์ž๊ฐ€ ์ˆ˜์ • ํ›„ ์ „์†ก ๊ฐ€๋Šฅ) */\n private useExample(text: string) {\n this.input = text\n this.examplesOpen = false\n requestAnimationFrame(() => {\n const ta = this.renderRoot.querySelector('textarea') as HTMLTextAreaElement | null\n ta?.focus()\n ta?.setSelectionRange(text.length, text.length)\n })\n }\n\n // โ”€โ”€ Mini actions โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\n private renderInlineExamples() {\n return html`\n <div class=\"inline-examples\">\n ${this.exampleGroups.map(\n group => html`\n <div class=\"ex-row\">\n <span class=\"ex-label\">${group.label}</span>\n ${group.items.map(t => html`<button class=\"ex\" @click=${() => this.useExample(t)}>${t}</button>`)}\n </div>\n `\n )}\n </div>\n `\n }\n\n // โ”€โ”€ Retry (์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\n private async retryLastSend() {\n if (!this.lastFailedInput) return\n this.input = this.lastFailedInput\n this.errorMessage = undefined\n this.lastFailedInput = undefined\n await this.send()\n }\n\n // โ”€โ”€ Per-message hover action row โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\n /**\n * ๋ฉ”์‹œ์ง€๋ณ„ hover ์•ก์…˜ โ€” ํ…์ŠคํŠธ chip ์œผ๋กœ ๋ช…ํ™•.\n * user : ์•ก์…˜ row ์ž์ฒด X (์ž๊ธฐ ๋ฉ”์‹œ์ง€์— ์‹œ๊ฐ ๋…ธ์ด์ฆˆ X โ€” ํŽธ์ง‘์€ input ์œ„ \"์ƒˆ ๋Œ€ํ™”\" ํ๋ฆ„ ๋˜๋Š” ๋งˆ์šฐ์Šค ๋”๋ธ”ํด๋ฆญ)\n * assistant : ๋ณต์‚ฌ + ์žฌ์ƒ์„ฑ + (patch ์ ์šฉ๋œ ๊ฒฝ์šฐ๋งŒ) ๋˜๋Œ๋ฆฌ๊ธฐ\n * system : ์—†์Œ\n */\n private renderMessageActions(idx: number, line: ChatLine, content: string) {\n if (line.role !== 'assistant') return nothing\n\n const isCopied = this.copiedIdx === idx\n // revert ๋Š” ์ธ๋ผ์ธ patch chip (๋ฉ”์‹œ์ง€ ์•ˆ) ํ•œ ๊ณณ์—๋งŒ โ€” hover ์•ก์…˜์—์„œ ์ œ์™ธ (์ค‘๋ณต ๋ฐฉ์ง€).\n return html`\n <div class=\"msg-actions\">\n <button\n class=\"msg-action ${isCopied ? 'confirmed' : ''}\"\n title=${isCopied\n ? i18next.t('ai-assistant.text.copied')\n : i18next.t('ai-assistant.button.copy')}\n @click=${() => this.copyMessage(idx, content)}>\n <md-icon>${isCopied ? 'check' : 'content_copy'}</md-icon>\n </button>\n <button\n class=\"msg-action\"\n ?disabled=${this.busy}\n title=${i18next.t('ai-assistant.button.regenerate')}\n @click=${() => this.regenerateAssistant(idx)}>\n <md-icon>refresh</md-icon>\n </button>\n </div>\n `\n }\n\n /**\n * \"๋Œ€ํ™”๊ฐ€ ๊ธธ์–ด์กŒ์Šต๋‹ˆ๋‹ค\" ์•ˆ๋‚ด โ€” **์‚ฌ์‹ค๋งŒ** ์•Œ๋ฆฌ๊ณ  ๊ฒฐ์ •์€ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋งก๊ธด๋‹ค.\n *\n * ์ฃผ์ œ๊ฐ€ ๋ฐ”๋€Œ์—ˆ๋Š”์ง€ ํŒ์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค: ํŒ์ •ํ•˜๋ฉด ์˜คํƒ์ด ์ƒ๊ธฐ๊ณ , ์˜คํƒ์ด ์ƒ๊ธฐ๋ฉด ์‚ฌ์šฉ์ž๋Š” ์•ˆ๋‚ด ์ž์ฒด๋ฅผ\n * ๋ฌด์‹œํ•œ๋‹ค(์ ‘์ง€ ๊ฒฝ๊ณ ์—์„œ ๋ฐฐ์šด ๊ฒƒ๊ณผ ๊ฐ™๋‹ค). ๊ทผ๊ฑฐ๋Š” \"์•ž๋ถ€๋ถ„์ด ํ”„๋กฌํ”„ํŠธ์—์„œ ์ ‘ํ˜”๋‹ค\" ๋Š” ๊ฐ๊ด€์  ์‚ฌ์‹ค๋ฟ์ด๋‹ค.\n *\n * ์™œ ์•Œ๋ ค์•ผ ํ•˜๋Š”๊ฐ€: ํ•œ ๋Œ€ํ™”์— ์ฃผ์ œ๊ฐ€ ์—ฌ๋Ÿฟ ์„ž์ด๋ฉด (1) ์˜› ๋งฅ๋ฝ์ด ์ƒˆ ๋‹ต์„ ์˜ค์—ผ์‹œํ‚ค๊ณ  (2) ์š”์•ฝ์ด\n * ๋ญ‰๊ฐœ์ง€๊ณ  (3) ๋ชฉ๋ก์˜ ๋Œ€ํ™” ์ด๋ฆ„์ด ๊ฑฐ์ง“๋ง์ด ๋œ๋‹ค. ๊ทธ๊ฑธ ์•„๋Š” ์‚ฌ๋žŒ์€ ์‚ฌ์šฉ์ž๋ฟ์ด๋‹ค.\n */\n private renderFoldNotice() {\n const folded = this.historyFolded\n if (!folded || this.foldNoticeDismissed) return nothing\n return html`\n <div class=\"fold-notice\">\n <md-icon>unfold_less</md-icon>\n <span class=\"fn-text\">\n ${folded.summarized\n ? i18next.t('ai-assistant.text.history-folded-summarized', {\n count: folded.omitted,\n defaultValue: 'this conversation grew long โ€” the earlier {count} messages were folded into a summary. a new conversation is better for a different topic.'\n })\n : i18next.t('ai-assistant.text.history-folded', {\n count: folded.omitted,\n defaultValue: 'this conversation grew long โ€” the earlier {count} messages were left out. a new conversation is better for a different topic.'\n })}\n </span>\n <button class=\"fn-new\" @click=${this.startNewFromNotice}>\n ${i18next.t('ai-assistant.button.new-chat')}\n </button>\n <button class=\"fn-close\" title=${i18next.t('ai-assistant.button.close')} @click=${() => (this.foldNoticeDismissed = true)}>\n <md-icon>close</md-icon>\n </button>\n </div>\n `\n }\n\n /**\n * ์ƒˆ ๋Œ€ํ™”๋กœ โ€” **๋งฅ๋ฝ์„ ์˜ฎ๊ธฐ์ง€ ์•Š๋Š”๋‹ค.** ์ฃผ์ œ๋ฅผ ๋ฐ”๊พธ๋ ค๊ณ  ์ƒˆ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ, ์˜ฎ๊ธฐ๋ฉด ๊ทธ ์ด์œ ๊ฐ€\n * ์‚ฌ๋ผ์ง„๋‹ค(์Šน๊ฒฉ์€ ์ด์–ด๊ฐ€๋ ค๋Š” ๊ฒƒ์ด๊ณ  ์ด๊ฑด ๋Š์œผ๋ ค๋Š” ๊ฒƒ์ด๋‹ค). ์„ธ์…˜ ์ƒ์„ฑ์€ ํ˜ธ์ŠคํŠธ์˜ ๋ชซ์ด๋‹ค.\n */\n private startNewFromNotice = () => {\n this.foldNoticeDismissed = true\n this.dispatchEvent(new CustomEvent('assistant-start-new-session', { bubbles: true, composed: true }))\n }\n\n /**\n * ์กฐ์น˜ ์ œ์•ˆ ์นด๋“œ โ€” AI ๋Š” ์ œ์•ˆ๊นŒ์ง€, **์‹คํ–‰์€ ์‚ฌ์šฉ์ž**.\n *\n * ์™œ ์นด๋“œ์ธ๊ฐ€: ๋˜๋Œ๋ฆด ์ˆ˜ ์—†๋Š” ํ˜„์žฅ ๋ช…๋ น์„ ๋ฌธ์žฅ ์† ๋งํฌ๋กœ ํ˜๋ฆฌ๋ฉด ์‹ค์ˆ˜๋กœ ๋ˆŒ๋ฆฐ๋‹ค. ๋ฌด์—‡์„ยท์™œ ํ•˜๋Š”์ง€\n * ํ•œ ์ค„๋กœ ๋ณด์ด๊ณ  ์‹คํ–‰์ด **๋ถ„๋ช…ํ•œ ํ•œ ๋ฒˆ์˜ ํ–‰๋™**์ด์–ด์•ผ ํ•œ๋‹ค.\n * ์‹คํ–‰ ๊ฒฐ๊ณผ๋Š” ํ˜ธ์ŠคํŠธ๊ฐ€ **๋Œ€ํ™”์— ๊ธฐ๋ก**ํ•œ๋‹ค โ€” ๋ˆ„๊ฐ€ ๋ฌด์—‡์„ ์‹คํ–‰ํ–ˆ๋Š”์ง€๊ฐ€ ํ˜‘์˜ ์ด๋ ฅ์— ๋‚จ์•„์•ผ ํ•œ๋‹ค.\n */\n private renderProposals(line: ChatLine) {\n const items = line.proposals ?? []\n if (items.length === 0) return nothing\n /* The card's state is the conversation's rows - read once for every card of this line. */\n const outcomes = this.proposalOutcomes\n const requested = this.proposalRequests\n /* A data entry card replaced by a newer one for the same record cannot be entered (design/ai/data-entry.md ยง5). */\n const latestEntry = items.some(isEntryProposal) ? latestEntryKeys(this.lines.map(one => one.proposals ?? [])) : undefined\n return html`\n <div class=\"proposals\">\n ${items.map(p => {\n const key = this.proposalKey(p)\n /* A workspace card opens the page; it runs nothing (design/ai/workspace.md ยง4). */\n if (isWorkspaceProposal(p)) return this.renderWorkspaceCard(p, key)\n /* A screen card opens the application's list with the question's conditions; it runs nothing (design/ai/read-targets.md ยง5). */\n if (isOpenPageProposal(p)) return this.renderOpenPageCard(p)\n const card = proposalCardState(key, { outcomes, requested, sentHere: this.sentProposals.has(key) })\n const entry = isEntryProposal(p)\n const replaced = entry && latestEntry?.get(entryGroupOf(p)) !== key && card.state === 'ready'\n const ready = entry ? entryReadyCount(p) : 0\n const sent = card.state !== 'ready' || replaced || (entry && ready === 0)\n /*\n Follow-up chips are the host's words, never this component's. The fallback that used\n to live here named a 3D modeller's operations in hardcoded Korean, and it reached the\n plant and twin chats too.\n */\n const rawChoices: any[] = Array.isArray(p.choices) ? p.choices : this.conversation.proposalChoices\n\n return html`\n <div class=\"proposal ${sent ? 'sent' : ''}\">\n <md-icon>${p.icon || (p.source ? 'view_in_ar' : 'bolt')}</md-icon>\n <span class=\"pbody\">\n <span class=\"plabel\">${entry ? entryTitle(p, (key, options) => i18next.t(key, options) as string) : p.label || p.command}</span>\n ${p.reason ? html`<span class=\"preason\">${p.reason}</span>` : nothing}\n </span>\n ${/*\n The run button and the follow-up chips answer different questions โ€” \"is there\n something to apply\" and \"what else could I ask for\" โ€” and they used to share one\n ternary on `rawChoices.length`. A proposal that carried chips lost its button, so\n the one action the card exists for became unreachable while the model kept\n telling people to press it.\n */ ''}\n ${card.state === 'unconfirmed'\n ? html`\n <span class=\"preason\">${i18next.t('ai-assistant.text.proposal-unconfirmed', { defaultValue: 'sent earlier - no answer received' })}</span>\n <button class=\"run\" @click=${() => this.checkProposal(p, key)}>\n ${i18next.t('ai-assistant.button.check-proposal', { defaultValue: 'check result' })}\n </button>\n `\n : html`\n <button\n class=\"run\"\n ?disabled=${sent}\n @click=${() => this.executeProposal(p, key)}>\n ${replaced\n ? i18next.t('ai-assistant.entry.replaced', { defaultValue: 'replaced by a newer card' })\n : card.state !== 'ready'\n ? this.proposalStateText(key)\n : entry\n ? ready\n ? isChangeProposal(p)\n ? i18next.t('ai-assistant.entry.change', { defaultValue: 'change {count} records', count: ready })\n : i18next.t('ai-assistant.entry.enter', { defaultValue: 'enter {count} rows', count: ready })\n : i18next.t('ai-assistant.entry.nothing-to-enter', { defaultValue: 'nothing to enter' })\n : i18next.t('ai-assistant.button.run-proposal', { defaultValue: 'run' })}\n </button>\n `}\n ${/*\n Drawn only where the host has said it staged this candidate, in the host's own\n words. Not knowing is not a claim: with no word from the host, nothing is drawn.\n This badge used to read \"there are chips\" as \"the model is in the 3D viewer\" and\n say so, in a component that plant and twin also use.\n */ ''}\n ${this.stagedProposals.has(key) && this.conversation.stagedNotice ? html`\n <span class=\"staged-badge\">\n <md-icon>check_circle</md-icon>\n <span>${this.conversation.stagedNotice}</span>\n </span>\n ` : nothing}\n </div>\n ${entry ? html`<ox-assistant-entry-review .proposal=${p}></ox-assistant-entry-review>` : nothing}\n ${entry && this.sessionId && offersWorkspaceReview(p)\n ? html`<button\n class=\"workspace-review\"\n @click=${() =>\n this.dispatchEvent(new CustomEvent('assistant-open-page', { detail: { href: entryReviewAddress(this.sessionId!, key) }, bubbles: true, composed: true }))}\n >\n <md-icon>open_in_full</md-icon>\n <span>${i18next.t('ai-assistant.entry.review-in-workspace', { defaultValue: 'review in the workspace' })}</span>\n </button>`\n : nothing}\n ${rawChoices.length ? html`\n <div class=\"proposal-choices\" role=\"group\" aria-label=${i18next.t('ai-assistant.text.proposal-choices', { defaultValue: 'follow-up choices' })}>\n ${rawChoices.map((c: any) => html`\n <button\n class=\"choice-chip ${c.primary ? 'primary' : ''}\"\n title=${c.prompt || c.label}\n @click=${() => this.onChoiceClick(c, p, key)}>\n ${c.icon ? html`<md-icon>${c.icon}</md-icon>` : nothing}\n <span>${c.label}</span>\n </button>\n `)}\n </div>\n ` : nothing}\n `\n })}\n </div>\n `\n }\n\n /** The screen card - which list, the conditions the screen does not take, and the way to open it. */\n private renderOpenPageCard(p: any) {\n const note = openPageNote(p, (key, options) => String(i18next.t(key, options)))\n const open = () => this.dispatchEvent(new CustomEvent('assistant-open-page', { detail: { href: p.href }, bubbles: true, composed: true }))\n return html`\n <div class=\"proposal workspace\">\n <md-icon>${p.icon || 'open_in_new'}</md-icon>\n <span class=\"pbody\">\n <span class=\"plabel\">${p.label}</span>\n ${note ? html`<span class=\"preason\">${note}</span>` : nothing}\n </span>\n <button class=\"run\" @click=${open}>${i18next.t('ai-assistant.screen.open', { defaultValue: 'open the screen' })}</button>\n </div>\n `\n }\n\n /** The AI ์ž‘์—…ํŒ card - what it holds, which version, and the way to open it. The person opens it; the model does not. */\n private renderWorkspaceCard(p: any, key: string) {\n const { version, of } = versionOfCard(this.lines.map(one => one.proposals ?? []), p.workspace.name, key)\n const contents = Object.entries(p.contents ?? {})\n .map(([kind, count]) => String(i18next.t(`ai-assistant.workspace.contains-${kind}`, { defaultValue: `${kind} {count}`, count: Number(count) } as any)))\n .join(' ยท ')\n const open = () => {\n if (!this.sessionId) return\n /* The page is the application's; navigate is the shell's, reached by an event so this component stays standalone. */\n this.dispatchEvent(new CustomEvent('assistant-open-page', { detail: { href: workspaceAddress(this.sessionId, p.workspace.name, version) }, bubbles: true, composed: true }))\n }\n return html`\n <div class=\"proposal workspace\">\n <md-icon>${p.icon || 'dashboard'}</md-icon>\n <span class=\"pbody\">\n <span class=\"plabel\">${p.workspace.title}</span>\n <span class=\"preason\">${[contents, of > 1 ? i18next.t('ai-assistant.workspace.version', { defaultValue: 'version {version} of {of}', version, of }) : ''].filter(Boolean).join(' ยท ')}</span>\n </span>\n <button class=\"run\" ?disabled=${!this.sessionId} @click=${open}>${i18next.t('ai-assistant.workspace.open', { defaultValue: 'open in workspace' })}</button>\n </div>\n `\n }\n\n /**\n * ๋ˆŒ๋ฆฐ ์นด๋“œ๊ฐ€ ๋งํ•˜๋Š” ๊ฒƒ โ€” **ํ˜ธ์ŠคํŠธ๊ฐ€ ํ•œ ์ผ**์ด๊ณ , ์•„์ง ๋ชจ๋ฅด๋ฉด ๋ชจ๋ฅธ๋‹ค๊ณ  ๋งํ•œ๋‹ค.\n *\n * ์˜ˆ์ „์—๋Š” ๋ˆ„๋ฅธ ์ˆœ๊ฐ„ ใ€Œ์‹คํ–‰๋จใ€์ด์—ˆ๋‹ค. 09-18 ํŠธ์œˆ์—์„œ ์•„๋ฌด ์ผ๋„ ์ผ์–ด๋‚˜์ง€ ์•Š์€ ์ฑ„ ใ€Œโœ“ ๋ฐ˜์˜ํ–ˆ์Šต๋‹ˆ๋‹คใ€๊ฐ€\n * ๋–ด๋‹ค(ADR-0070 A12-a).\n */\n private proposalStateText(key: string): string {\n const outcome = this.proposalOutcomes.get(key)\n\n if (!outcome) {\n /* ๋‹ต์ด ์˜ค๊ธฐ ์ „ โ€” ์•„๋Š” ์‚ฌ์‹ค์€ ใ€Œ๋ณด๋ƒˆ๊ณ  ์•„์ง ๋‹ต์ด ์—†๋‹คใ€๋ฟ์ด๋‹ค. ๊ฒฝ๊ณผ ์‹œ๊ฐ„์„ ํ•จ๊ป˜ ๋ณด์ธ๋‹ค. */\n const since = this.proposalSentAt.get(key)\n const seconds = since ? Math.max(0, Math.round((Date.now() - since) / 1000)) : 0\n return i18next.t('ai-assistant.text.proposal-waiting', {\n seconds,\n defaultValue: 'sending โ€” {seconds}s, no answer yet'\n })\n }\n\n const counted =\n typeof outcome.applied === 'number' && typeof outcome.total === 'number' && outcome.total > 0\n ? i18next.t('ai-assistant.text.proposal-applied-count', {\n applied: outcome.applied,\n total: outcome.total,\n defaultValue: ' {applied} of {total}'\n })\n : ''\n\n /* ์‚ฌ์œ ๋Š” ํ˜ธ์ŠคํŠธ๊ฐ€ ์ค€ ์ฝ”๋“œ ๊ทธ๋Œ€๋กœ๋‹ค โ€” ๋ฌธ์žฅ์œผ๋กœ ๋ฐ”๊พธ์ง€ ์•Š๋Š”๋‹ค(ADR-0042). */\n const reason = outcome.errorCode ? ` (${outcome.errorCode})` : ''\n\n const verdict = i18next.t(`ai-assistant.verdict.${outcome.verdict}`, {\n defaultValue:\n outcome.verdict === 'accepted'\n ? 'done'\n : outcome.verdict === 'refused'\n ? 'refused'\n : outcome.verdict === 'declined'\n ? 'cancelled'\n : 'could not run'\n })\n\n return `${verdict}${counted}${reason}`\n }\n\n private onChoiceClick(choice: any, proposal: any, key: string) {\n if (choice.action === 'save') {\n this.dispatchEvent(\n new CustomEvent('assistant-choice', {\n detail: { action: 'save', choice, proposal, sessionId: this.sessionId },\n bubbles: true,\n composed: true\n })\n )\n this.executeProposal(proposal, key)\n return\n }\n\n if (choice.action === 'prompt' && choice.prompt) {\n this.input = choice.prompt\n this.dispatchEvent(\n new CustomEvent('assistant-choice', {\n detail: { action: 'prompt', choice, proposal, sessionId: this.sessionId },\n bubbles: true,\n composed: true\n })\n )\n void this.send()\n return\n }\n\n this.dispatchEvent(\n new CustomEvent('assistant-choice', {\n detail: { action: choice.action || 'custom', choice, proposal, sessionId: this.sessionId },\n bubbles: true,\n composed: true\n })\n )\n }\n\n /**\n * ์ œ์•ˆ ์‹๋ณ„ ํ‚ค โ€” ๊ฐ™์€ ์กฐ์น˜๋ฅผ ๋‘ ๋ฒˆ ์‹คํ–‰ํ•˜์ง€ ์•Š๋„๋ก **ํšจ๊ณผ**(๋ช…๋ นยท๋Œ€์ƒยท์ธ์ž)๋กœ๋งŒ ๋งŒ๋“ ๋‹ค.\n *\n * ์ธ์ž๋Š” **ํ‚ค ์ˆœ์„œ๋ฅผ ์ •๋ ฌ**ํ•ด ์ง๋ ฌํ™”ํ•œ๋‹ค: ๊ฐ™์€ ์ธ์ž๋ฅผ ๋‹ค๋ฅธ ์ˆœ์„œ๋กœ ๋ฐ›์•˜์„ ๋ฟ์ธ๋ฐ ํ‚ค๊ฐ€ ๋‹ฌ๋ผ์ง€๋ฉด\n * ํ•œ ์นด๋“œ๋ฅผ ์‹คํ–‰ํ•œ ๋’ค์—๋„ ๋‹ค๋ฅธ ์นด๋“œ๊ฐ€ ์‚ด์•„ ์žˆ์–ด **๊ฐ™์€ ๋ช…๋ น์ด ๋‘ ๋ฒˆ ๋‚˜๊ฐ„๋‹ค**(์‹ค์ œ๋กœ ๊ทธ๋žฌ๋‹ค).\n * ์„ค๋ช… ๋ฌธ๊ตฌ(labelยทreason)๋Š” ํ‚ค์— ๋„ฃ์ง€ ์•Š๋Š”๋‹ค โ€” ๋ฌธ๊ตฌ๊ฐ€ ๋‹ฌ๋ผ๋„ ๊ฐ™์€ ์กฐ์น˜๋‹ค.\n */\n private proposalKey(p: any): string {\n const stable = (v: any): string => {\n if (v === null || typeof v !== 'object') return JSON.stringify(v ?? null)\n if (Array.isArray(v)) return `[${v.map(stable).join(',')}]`\n return `{${Object.keys(v)\n .sort()\n .map(k => `${JSON.stringify(k)}:${stable(v[k])}`)\n .join(',')}}`\n }\n /*\n * ์„œ๋ฒ„๊ฐ€ ์‹ค์–ด ๋ณด๋‚ธ ํ‚ค๊ฐ€ ์ •๋ณธ์ด๋‹ค โ€” ๋ฌด์—‡์ด ๊ฐ™์€ ์กฐ์น˜์ธ๊ฐ€๋Š” ์ œ์•ˆ์„ ๋งŒ๋“  ์ชฝ์ด ์•ˆ๋‹ค(ADR-0061 ๊ฒฐ์ •\n * 7 ๋’ค ์ •๋ฆฌ). ์˜ˆ์ „์—๋Š” ์—ฌ๊ธฐ์„œ `command|instanceId|args` ๋กœ ๋‹ค์‹œ ์…Œ๋Š”๋ฐ, ๋ช…๋ น์ด ์—†๋Š” ์ œ์•ˆ(์„ ์–ธ ยท\n * ์ƒˆ ํŠธ์œˆ ์ดˆ์•ˆ)์€ ๊ทธ ์…‹์ด ๋ชจ๋‘ ๋น„์–ด **์„œ๋กœ ๋‹ค๋ฅธ ์ œ์•ˆ์ด ํ•œ ์นด๋“œ๋กœ ์ ‘ํ˜”๊ณ **, ํ•˜๋‚˜๋ฅผ ๋ˆ„๋ฅด๋ฉด ๋‚˜๋จธ์ง€๊ฐ€\n * ํ•จ๊ป˜ ใ€Œ์š”์ฒญ๋จใ€์ด ๋๋‹ค.\n */\n if (typeof p?.key === 'string' && p.key) return p.key\n try {\n return `${p?.tool ?? ''}|${p?.command ?? ''}|${p?.instanceId ?? ''}|${stable(p?.args)}|${stable(p?.ops)}`\n } catch {\n return `${p?.tool ?? ''}|${p?.command ?? ''}|${p?.instanceId ?? ''}`\n }\n }\n\n /**\n * ์‹คํ–‰์€ ํ˜ธ์ŠคํŠธ๊ฐ€ ํ•œ๋‹ค โ€” ์ด ์ปดํฌ๋„ŒํŠธ๋Š” ๋„๋ฉ”์ธ(ํŠธ์œˆ ๋ช…๋ น ์ฑ„๋„)์„ ๋ชจ๋ฅธ๋‹ค.\n * ํ™•์ธ ๋Œ€ํ™”ยท๋ช…๋ น ์ „์†กยท๊ฒฐ๊ณผ ๊ธฐ๋ก์€ ํ˜ธ์ŠคํŠธ์˜ ๋ชซ์ด๊ณ , ์—ฌ๊ธฐ์„œ๋Š” ์ค‘๋ณต ํด๋ฆญ๋งŒ ๋ง‰๋Š”๋‹ค.\n */\n /**\n * ๋ˆ„๋ฅธ ์‹œ๊ฐ โ€” ใ€Œ๋ณด๋‚ด๋Š” ์ค‘ใ€ ์˜†์˜ ๊ฒฝ๊ณผ ์‹œ๊ฐ„์šฉ.\n *\n * ์‹œ๊ฐ„์œผ๋กœ ์‹คํŒจ๋ฅผ ํŒ์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค(ADR-0070 A12-a ๊ฒฐ์ • โ‘ก). ์•„๋Š” ์‚ฌ์‹ค์€ ใ€Œ์•„์ง ๋‹ต์„ ๋ฐ›์ง€ ๋ชปํ–ˆ๋‹คใ€\n * ํ•˜๋‚˜์ด๊ณ , ์‹œ๊ฐ„์ด ์ง€๋‚ฌ๋‹ค๊ณ  ์‹คํŒจ๋กœ ๋ฐ”๊พธ๋ฉด ๊ทธ๊ฒƒ์ด ์ง€์–ด๋‚ธ ์›์ธ์ด๋‹ค.\n */\n private proposalSentAt = new Map<string, number>()\n\n private elapsedTimer?: ReturnType<typeof setInterval>\n\n private async executeProposal(p: any, key: string) {\n if (this.sentProposals.has(key)) return\n this.sentProposals = new Set(this.sentProposals).add(key)\n this.proposalSentAt.set(key, Date.now())\n this._startElapsedTicker()\n\n /*\n * The server records the request first and answers whether this conversation has taken the proposal\n * already (ADR-0097 Q-D4 โ‘ฃ). Only a granted request reaches the host. A refused one - taken in another\n * window, or before a refresh - leaves the card to the rows; a failed one leaves it as it was, and the\n * error is said by the client's own error line. Either way the host is not asked.\n */\n if (this.sessionId) {\n let granted = false\n try {\n granted = await this.requestProposal(key)\n } catch {\n granted = false\n }\n if (!granted) {\n const left = new Set(this.sentProposals)\n left.delete(key)\n this.sentProposals = left\n this.proposalSentAt.delete(key)\n return\n }\n }\n\n this.dispatchEvent(\n new CustomEvent('assistant-proposal-execute', {\n /*\n * `proposalKey` ๋ฅผ ํ•จ๊ป˜ ์ค€๋‹ค โ€” ํ˜ธ์ŠคํŠธ๊ฐ€ `reportProposalOutcome` ์œผ๋กœ ๋‹ตํ•  ๋•Œ ์“ฐ๋Š” ์ด๋ฆ„์ด๋‹ค.\n * ํ˜ธ์ŠคํŠธ๊ฐ€ ์ž๊ธฐ ๊ทœ์น™์œผ๋กœ ํ‚ค๋ฅผ ๋‹ค์‹œ ๋งŒ๋“ค๋ฉด ์นด๋“œ๊ฐ€ ๋ชป ์ฐพ๋Š” ๋‹ต์ด ์ƒ๊ธด๋‹ค(์›๋ณธ์€ ํ•˜๋‚˜).\n */\n detail: { proposal: p, sessionId: this.sessionId, proposalKey: key },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private async requestProposal(key: string): Promise<boolean> {\n const result = await client.mutate({\n mutation: gql`\n mutation ($id: String!, $key: String!) {\n requestProposal(sessionId: $id, proposalKey: $key)\n }\n `,\n variables: { id: this.sessionId, key }\n })\n if (result.errors?.length) throw new Error(result.errors[0].message)\n return result.data?.requestProposal === true\n }\n\n /**\n * \"Check result\" on a card that was requested and never answered: the host is asked what happened\n * (`AssistantSurface.proposalOutcome`), never to run it again. The dock reports what it learns.\n */\n private checkProposal(p: any, key: string) {\n this.dispatchEvent(\n new CustomEvent('assistant-proposal-check', {\n detail: { proposal: p, sessionId: this.sessionId, proposalKey: key },\n bubbles: true,\n composed: true\n })\n )\n }\n\n /** Keys whose run was requested - from the conversation's rows, like the outcomes. */\n private get proposalRequests(): Set<string> {\n const requested = new Set<string>()\n for (const line of this.lines) {\n if (line.role !== 'system') continue\n const key = parseProposalRequestLine(line.content ?? '')\n if (key) requested.add(key)\n }\n return requested\n }\n\n /**\n * ํ˜ธ์ŠคํŠธ๊ฐ€ ๋ฌด์—‡์„ ํ–ˆ๋Š”์ง€ โ€” ๋Œ€ํ™”์— ๋‚จ์€ `system` ํ–‰์—์„œ ์ฝ๋Š”๋‹ค(ADR-0070 A12-a ๊ฒฐ์ • โ‘ ).\n *\n * ์นด๋“œ๊ฐ€ ์ž๊ธฐ ๊ธฐ์–ต์œผ๋กœ ์ƒํƒœ๋ฅผ ๋“ค๊ณ  ์žˆ์œผ๋ฉด ์ƒˆ๋กœ ๊ณ ์น˜๋Š” ์ˆœ๊ฐ„ ์‚ฌ๋ผ์ง€๊ณ , ๋‹ค๋ฅธ ์ฐฝ์—์„œ ์‹คํ–‰ํ•œ ๊ฒƒ์€\n * ์• ์ดˆ์— ๋ณด์ด์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ž˜์„œ ์ƒํƒœ์˜ ์ž๋ฆฌ๋Š” ์ด๋ ฅ์ด๋‹ค.\n */\n private get proposalOutcomes(): Map<string, ParsedProposalOutcome> {\n const outcomes = new Map<string, ParsedProposalOutcome>()\n for (const line of this.lines) {\n if (line.role !== 'system') continue\n const parsed = parseProposalOutcomeLine(line.content ?? '')\n if (parsed) outcomes.set(parsed.key, parsed)\n }\n return outcomes\n }\n\n /** ๊ฒฝ๊ณผ ์‹œ๊ฐ„์„ ๋ณด์ด๋Š” ๋™์•ˆ์—๋งŒ ๋ˆ๋‹ค โ€” ๋‹ต์ด ์˜ค๋ฉด ๋ฉˆ์ถ˜๋‹ค. */\n private _startElapsedTicker() {\n if (this.elapsedTimer) return\n this.elapsedTimer = setInterval(() => {\n const outcomes = this.proposalOutcomes\n const waiting = [...this.proposalSentAt.keys()].some(key => !outcomes.has(key))\n if (!waiting) {\n clearInterval(this.elapsedTimer)\n this.elapsedTimer = undefined\n return\n }\n this.requestUpdate()\n }, 1000)\n }\n\n /**\n * ์ ‘์ง€ ๊ฒฝ๊ณ  โ€” ๋‹ต์ด ์–ธ๊ธ‰ํ–ˆ์ง€๋งŒ **๊ทผ๊ฑฐ์— ์—†๋˜** ๋Œ€์ƒ์„ ์•Œ๋ฆฐ๋‹ค.\n *\n * ์™œ ๋‹ต์„ ์ง€์šฐ์ง€ ์•Š๋Š”๊ฐ€: ํŒ์ •์€ ์‹๋ณ„์ž ๋Œ€์กฐ๋ผ ํ™•์ •์ด ์•„๋‹ˆ๋‹ค(์˜ˆ: ์‚ฌ์šฉ์ž๊ฐ€ ํ™”๋ฉด์—์„œ ๋ณธ ์ด๋ฆ„์„\n * ๋Œ€ํ™” ๋ฐ–์—์„œ ์•Œ๊ณ  ๋งํ•œ ๊ฒฝ์šฐ). ๊ทธ๋ž˜์„œ ๋‹ต์€ ๊ทธ๋Œ€๋กœ ๋ณด์—ฌ์ฃผ๊ณ , ๊ฒ€์ฆ๋˜์ง€ ์•Š์•˜๋‹ค๋Š” ์‚ฌ์‹ค๋งŒ ๋ถ™์ธ๋‹ค โ€”\n * ์‚ฌ์šฉ์ž๊ฐ€ ๊ทธ ๋Œ€์ƒ์„ ์‹ค์ œ ์ž‘์—…์˜ ๊ทผ๊ฑฐ๋กœ ์‚ผ๊ธฐ ์ „์— ์•Œ์•„์•ผ ํ•˜๋Š” ์ •๋ณด๋‹ค.\n */\n private renderGroundingWarning(line: ChatLine) {\n const ids = line.groundingWarnings ?? []\n if (ids.length === 0) return nothing\n return html`\n <div class=\"grounding-warning\" role=\"note\">\n <md-icon>report</md-icon>\n <span>\n ${i18next.t('ai-assistant.text.ungrounded-mention', {\n defaultValue: 'Mentions an unverified target โ€” not present in the actual data:'\n })}\n <span class=\"ids\">${ids.join(', ')}</span>\n </span>\n </div>\n `\n }\n\n /**\n * \"AI ๊ฐ€ ์ด๋Ÿฐ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค\" fold-able ๋ฐ•์Šค.\n *\n * - ๊ธฐ๋ณธ ๋‹ซํž˜ (toolUsagesOpen=false). ํ—ค๋” ํด๋ฆญ ์‹œ toggle.\n * - ํŽผ์ณค์„ ๋•Œ ๋„๊ตฌ ๋ณ„๋กœ name + arguments + result + read/write ์ƒ‰์ƒ ๋ฐฐ์ง€.\n * - ๋””๋ฒ„๊ทธ / ์‹ ๋ขฐ๋„ ํ–ฅ์ƒ์šฉ โ€” ์‚ฌ์šฉ์ž๊ฐ€ \"์™œ ์ด๋ ‡๊ฒŒ ๋‹ตํ–ˆ์ง€\" ์˜๋ฌธ ๊ฐ€์งˆ ๋•Œ ์ฆ‰์‹œ ๊ฒ€์ฆ.\n */\n private renderToolUsages(idx: number, line: ChatLine) {\n const usages = line.toolUsages\n if (!usages || usages.length === 0) return nothing\n const open = !!line.toolUsagesOpen\n const readCount = usages.filter(u => u.kind === 'read').length\n const writeCount = usages.filter(u => u.kind === 'write').length\n const toolsLabel = i18next.t('ai-assistant.text.tools-used', { defaultValue: 'Tools used' })\n /* ๋ˆˆ์— ๊ฑธ๋ ค์•ผ ํ•˜๋Š” ๊ฒƒ์„ ๋จธ๋ฆฌ์ค„์— ์˜ฌ๋ฆฐ๋‹ค โ€” ๊ฑฐ์ ˆยท์ ‘ํž˜์ด ์žˆ์œผ๋ฉด ํŽผ์น˜๊ธฐ ์ „์— ๋ณด์ธ๋‹ค.\n * (์ด๋ฒˆ ์‚ฌ๊ณ ๋“ค์ด ์ „๋ถ€ ๊ทธ๊ฒƒ์ด์—ˆ๋‹ค: ์ธ์ž ๋น ์ง„ ํ˜ธ์ถœ์ด ๊ฑฐ์ ˆ๋๊ณ , ์ค‘๋ณต ์ œ์•ˆ์ด ์ ‘ํ˜”๋‹ค.) */\n const problems = usages.filter(u => u.outcome === 'rejected' || u.outcome === 'error').length\n const folded = usages.filter(u => u.outcome === 'folded').length\n return html`\n <div class=\"tool-usages ${open ? 'open' : ''} ${problems ? 'has-problem' : ''}\">\n <button\n class=\"tool-usages-header\"\n aria-expanded=${open}\n @click=${() => this.toggleToolUsages(idx)}>\n <md-icon class=\"tool-usages-icon\">${open ? 'expand_less' : 'account_tree'}</md-icon>\n <span class=\"tool-usages-summary\">\n <strong>${usages.length}</strong> ${toolsLabel}\n <span class=\"tool-usages-counts\">\n ยท read ${readCount} ยท write ${writeCount}${problems\n ? html` ยท <span class=\"tu-flag bad\">${i18next.t('ai-assistant.text.tool-rejected-count', {\n count: problems,\n defaultValue: 'rejected {count}'\n })}</span>`\n : nothing}${folded\n ? html` ยท <span class=\"tu-flag\">${i18next.t('ai-assistant.text.tool-folded-count', {\n count: folded,\n defaultValue: 'folded {count}'\n })}</span>`\n : nothing}\n </span>\n </span>\n <md-icon class=\"tool-usages-chevron\">${open ? 'expand_less' : 'expand_more'}</md-icon>\n </button>\n ${open\n ? html`\n <ol class=\"tool-usages-list\">\n ${usages.map((u, i) => this.renderToolStep(idx, u, i, usages[i - 1]))}\n </ol>\n `\n : nothing}\n </div>\n `\n }\n\n /** ์‹œ์Šคํ…œ ๊ธฐ๋ก ํŽผ์น˜๊ธฐ/์ ‘๊ธฐ โ€” ๊ณ์ค„์ด ๊ธธ์–ด๋„ ๋Œ€ํ™”๊ฐ€ ๊ฐ€๋ ค์ง€์ง€ ์•Š๊ฒŒ. */\n private toggleSystemNote(idx: number) {\n const next = [...this.lines]\n const line = next[idx]\n if (!line) return\n next[idx] = { ...line, systemOpen: !line.systemOpen }\n this.lines = next\n }\n\n /**\n * ํŒ๋‹จ ๊ณผ์ •์˜ ํ•œ ๋‹จ๊ณ„ โ€” ํ„ด ๊ตฌ๋ถ„ ยท ๋„๊ตฌ ยท ๋ฐฐ์ง€ ยท **ํ•œ ์ค„ ์š”์•ฝ**.\n *\n * ์›๋ณธ JSON ์„ ์ฒ˜์Œ๋ถ€ํ„ฐ ํŽผ์ณ ๋‘๋ฉด ๋ˆˆ์ด ํ๋ ค์ ธ ์ •์ž‘ ์ค‘์š”ํ•œ ๊ฒƒ(๋ฌด์—‡์ด ๊ฑฐ์ ˆ๋๋Š”์ง€, ๋ฌด์—‡์ด ์ ‘ํ˜”๋Š”์ง€)์ด\n * ์•ˆ ๋ณด์ธ๋‹ค. ํ•œ ์ค„๋กœ ์ค„์ด๊ณ  ์›๋ณธ์€ ํ•ญ๋ชฉ๋ณ„๋กœ ๋ˆŒ๋Ÿฌ์„œ ๋ณธ๋‹ค.\n */\n private renderToolStep(lineIdx: number, u: any, i: number, prev: any) {\n const outcome = u.outcome ?? 'ok'\n const openKey = `${lineIdx}:${i}`\n const open = this.openToolSteps.has(openKey)\n /* ํ„ด์ด ๋ฐ”๋€Œ๋ฉด ๊ตฌ๋ถ„์„  โ€” \"ํ•œ ํ„ด ์•ˆ์—์„œ ์ •์ •ํ–ˆ๋Š”์ง€, ๋‹ค์Œ ํ„ด์—์„œ ํ–ˆ๋Š”์ง€\" ๊ฐ€ ์ง„๋‹จ์˜ ์ ˆ๋ฐ˜์ด๋‹ค. */\n const newTurn = typeof u.iter === 'number' && (!prev || prev.iter !== u.iter)\n return html`\n ${newTurn\n ? html`<li class=\"tu-turn\">\n ${i18next.t('ai-assistant.text.tool-turn', { n: (u.iter ?? 0) + 1, defaultValue: 'decision {n}' })}\n </li>`\n : nothing}\n <li class=\"tool-usage-item kind-${u.kind} outcome-${outcome}\">\n <div class=\"tool-usage-head\" @click=${() => this.toggleToolStep(openKey)}>\n <span class=\"tool-usage-step\">${i + 1}.</span>\n <span class=\"tool-usage-name\">${u.name}</span>\n <span class=\"tu-badge ${outcome}\">${this.outcomeLabel(outcome, u.kind)}</span>\n <span class=\"tu-line\" title=${this.stepSummary(u)}>${this.stepSummary(u)}</span>\n <md-icon class=\"tu-more\">${open ? 'expand_less' : 'expand_more'}</md-icon>\n </div>\n ${open\n ? html`\n ${u.arguments && Object.keys(u.arguments).length > 0\n ? html`<pre class=\"tool-usage-args\">${this.formatJson(u.arguments)}</pre>`\n : nothing}\n <pre class=\"tool-usage-result\">${this.formatJson(u.result)}</pre>\n `\n : nothing}\n </li>\n `\n }\n\n /**\n * ๋ฐฐ์ง€ ๋ฌธ๊ตฌ โ€” ์ฝ”๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ ์‚ฌ๋žŒ ๋ง๋กœ.\n *\n * ๋๊นŒ์ง€ ๊ฐ„ ํ˜ธ์ถœ(ok)์€ ๋ฌด์—‡์„ ํ–ˆ๋Š”์ง€๋กœ ๋ถ€๋ฅธ๋‹ค โ€” ์ฝ๊ธฐ๋Š” ใ€Œ์กฐํšŒใ€, ์“ฐ๊ธฐ๋Š” ใ€Œ์ ์šฉใ€. ์ „์—๋Š” ok ๊ฐ€\n * ์–ธ์ œ๋‚˜ ใ€Œ์กฐํšŒใ€์˜€์–ด์„œ, ๋ณด๋“œ๋ฅผ ๋ฐ”๊พผ addComponent ๋„ ใ€Œreadใ€ ๋ฐฐ์ง€๋ฅผ ๋‹ฌ์•˜๋‹ค(๋จธ๋ฆฌ์ค„์€ write 2 ๋ผ๊ณ \n * ์„ธ๋Š”๋ฐ).\n */\n private outcomeLabel(outcome: string, kind?: string): string {\n if (outcome === 'ok' && kind === 'write') {\n return i18next.t('ai-assistant.text.outcome-applied', { defaultValue: 'applied' })\n }\n const map: Record<string, [string, string]> = {\n ok: ['ai-assistant.text.outcome-ok', 'read'],\n rejected: ['ai-assistant.text.outcome-rejected', 'rejected'],\n queued: ['ai-assistant.text.outcome-queued', 'to apply'],\n proposed: ['ai-assistant.text.outcome-proposed', 'proposed'],\n folded: ['ai-assistant.text.outcome-folded', 'duplicate'],\n error: ['ai-assistant.text.outcome-error', 'error']\n }\n const [key, fallback] = map[outcome] ?? map.ok\n return i18next.t(key, { defaultValue: fallback })\n }\n\n /**\n * ๊ฒฐ๊ณผ ํ•œ ์ค„ โ€” ๋ฌด์—‡์„ ์–ป์—ˆ๋Š”์ง€/์™œ ๋ง‰ํ˜”๋Š”์ง€๋งŒ. ๋ชฉ๋ก์—์„œ ํ›‘์–ด ์ฝ์„ ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.\n * ๊ฑฐ์ ˆ์ด๋ฉด ์‚ฌ์œ ๋ฅผ, ์กฐํšŒ๋ฉด ๋Œ€ํ‘œ์ ์ธ ๊ฐœ์ˆ˜๋ฅผ, ์ œ์•ˆ์ด๋ฉด ๋ฌด์—‡์„ ์ œ์•ˆํ–ˆ๋Š”์ง€.\n */\n private stepSummary(u: any): string {\n const r = u?.result\n if (!r || typeof r !== 'object') return typeof r === 'string' ? r.slice(0, 80) : ''\n if (u.outcome === 'rejected' || u.outcome === 'error') {\n return String(r.errorCode || r.error || r.issues?.[0]?.message || '').slice(0, 80)\n }\n if (u.outcome === 'proposed' || u.outcome === 'folded') {\n return [r.command, r.args && Object.keys(r.args).length ? this.formatJson(r.args) : '']\n .filter(Boolean)\n .join(' ')\n .slice(0, 80)\n }\n /* ์กฐํšŒ ๊ฒฐ๊ณผ โ€” ๋ฐฐ์—ด ๊ธธ์ด๊ฐ€ ์žˆ๋Š” ํ•„๋“œ๋ฅผ ๊ณจ๋ผ \"๋ฌด์—‡์ด ๋ช‡ ๊ฐœ\" ๋กœ ์š”์•ฝํ•œ๋‹ค(์ „์ฒด ๋คํ”„ ๊ธˆ์ง€). */\n const counts = Object.keys(r)\n .filter(k => Array.isArray(r[k]) && r[k].length > 0)\n .slice(0, 2)\n .map(k => `${k} ${r[k].length}`)\n if (counts.length) return counts.join(' ยท ')\n const keys = Object.keys(r).slice(0, 4)\n return keys.map(k => (typeof r[k] === 'object' ? k : `${k} ${r[k]}`)).join(' ยท ').slice(0, 80)\n }\n\n private toggleToolStep(key: string) {\n const next = new Set(this.openToolSteps)\n next.has(key) ? next.delete(key) : next.add(key)\n this.openToolSteps = next\n }\n\n private toggleToolUsages(idx: number) {\n const next = [...this.lines]\n const line = next[idx]\n if (!line) return\n next[idx] = { ...line, toolUsagesOpen: !line.toolUsagesOpen }\n this.lines = next\n }\n\n private formatJson(value: any): string {\n try {\n return JSON.stringify(value, null, 2)\n } catch {\n return String(value)\n }\n }\n\n // โ”€โ”€ Per-message actions โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\n private async copyMessage(idx: number, content: string) {\n try {\n // ํด๋ฆฝ๋ณด๋“œ์—๋Š” marker ์ œ๊ฑฐ๋œ ๊นจ๋—ํ•œ ํ…์ŠคํŠธ\n await navigator.clipboard.writeText(stripMentionRefids(content))\n this.copiedIdx = idx\n this.showToast(i18next.t('ai-assistant.text.copied'))\n setTimeout(() => {\n if (this.copiedIdx === idx) this.copiedIdx = undefined\n }, 1500)\n } catch {\n // clipboard ๊ถŒํ•œ ์—†๊ฑฐ๋‚˜ ๋น„-secure context โ€” ์กฐ์šฉํžˆ ๋ฌด์‹œ\n }\n }\n\n private showToast(message: string) {\n this.toastMessage = message\n setTimeout(() => {\n if (this.toastMessage === message) this.toastMessage = undefined\n }, 1500)\n }\n\n /**\n * ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€ ํŽธ์ง‘ โ€” ํ•ด๋‹น ๋ฉ”์‹œ์ง€ + ์ดํ›„ ๋ชจ๋‘ UI ์—์„œ ์ œ๊ฑฐํ•˜๊ณ  ์ž…๋ ฅ์ฐฝ์— ์ฑ„์›€.\n * ์„œ๋ฒ„ ์˜์† history ๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€ (๋‹ค์Œ send ์‹œ ์ƒˆ ๋ฉ”์‹œ์ง€๋กœ ์ถ”๊ฐ€).\n */\n /** ํŽธ์ง‘์œผ๋กœ ์ ‘์€ ์ง€์  โ€” ๋งˆ์ง€๋ง‰์œผ๋กœ ๋‚จ๊ธด **์„œ๋ฒ„ ๋ฉ”์‹œ์ง€ id**. ์„œ๋ฒ„ ์ด๋ ฅ์€ ์œ ์ง€๋˜๋ฏ€๋กœ ์ด๊ฑธ ํ•จ๊ป˜\n * ๋ณด๋‚ด์•ผ ์ ‘์€ ๋ง์ด ์—์ด์ „ํŠธ ๋ฌธ๋งฅ์— ๋˜์‚ด์•„๋‚˜์ง€ ์•Š๋Š”๋‹ค(์„œ๋ฒ„ buildLlmHistory ๊ฐ€ ๊ทธ ๋’ค๋ฅผ ๋ฒ„๋ฆฐ๋‹ค). */\n private _truncateAfterId?: string\n\n private editUserMessage(idx: number, content: string) {\n // textarea ์—๋Š” marker ์ œ๊ฑฐ๋œ ๊นจ๋—ํ•œ ํ…์ŠคํŠธ โ€” ์‚ฌ์šฉ์ž๊ฐ€ raw `{refid:N}` ๋ณด์ง€ ์•Š๊ฒŒ.\n // ๋‹ค์‹œ send ์‹œ popup pickedMentions ๊ธฐ๋ฐ˜์œผ๋กœ marker ์žฌ์ฃผ์ž….\n const cleaned = stripMentionRefids(content)\n /* ๋‚จ๊ธธ ๋งˆ์ง€๋ง‰ ์ค„์˜ ์„œ๋ฒ„ id โ€” ์—†์œผ๋ฉด(์•„์ง ์˜์† ์•ˆ ๋œ ์ค„๋ฟ) ์ง€์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค(์„œ๋ฒ„๊ฐ€ ์ „๋ถ€ ์œ ์ง€). */\n this._truncateAfterId = this.lines\n .slice(0, idx)\n .reverse()\n .find(l => !!l.id)?.id\n this.lines = this.lines.slice(0, idx)\n this.input = cleaned\n requestAnimationFrame(() => {\n const ta = this.renderRoot.querySelector('textarea') as HTMLTextAreaElement | null\n ta?.focus()\n ta?.setSelectionRange(cleaned.length, cleaned.length)\n })\n }\n\n /**\n * AI ์‘๋‹ต ์žฌ์ƒ์„ฑ โ€” ํ•ด๋‹น assistant ๋ฉ”์‹œ์ง€ + ์ดํ›„ ์ œ๊ฑฐํ•˜๊ณ , ์ง์ „ user ๋ฉ”์‹œ์ง€๋ฅผ ๋‹ค์‹œ send.\n */\n private async regenerateAssistant(idx: number) {\n if (this.busy) return\n // ์ง์ „ user ๋ฉ”์‹œ์ง€ ์ฐพ๊ธฐ\n let userIdx = idx - 1\n while (userIdx >= 0 && this.lines[userIdx].role !== 'user') userIdx--\n if (userIdx < 0) return\n // textarea ์—๋Š” marker ์ œ๊ฑฐ๋œ ๊นจ๋—ํ•œ ๋ณธ๋ฌธ. send() ๊ฐ€ ๋ณธ๋ฌธ์„ ๋‹ค์‹œ line ์œผ๋กœ push ํ•˜๋Š”๋ฐ,\n // pickedMentions ๋Š” ์ง์ „ send ์—์„œ ๋น„์›Œ์กŒ์œผ๋ฏ€๋กœ ์ƒˆ line ์—๋Š” marker ์—†์Œ โ€” ํด๋ฆญ ์‹œ\n // runtime fallback resolver ๊ฐ€ ์ฒ˜๋ฆฌ. (์˜์†๋œ ์›๋ณธ user ๋ฉ”์‹œ์ง€์˜ marker ๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€)\n const userContent = stripMentionRefids(this.lines[userIdx].content)\n // assistant ๋ฉ”์‹œ์ง€ + ์ดํ›„ ์ œ๊ฑฐ\n this.lines = this.lines.slice(0, idx)\n this.input = userContent\n await this.send()\n }\n\n // โ”€โ”€ Patch revert โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n\n private onRevertClick(patchId: string) {\n if (this.revertedPatchIds.has(patchId)) return\n this.revertedPatchIds = new Set([...this.revertedPatchIds, patchId])\n // ํ˜ธ์ŠคํŠธ (board-modeller-page) ์—๊ฒŒ revert ์š”์ฒญ โ€” ํ˜ธ์ŠคํŠธ๊ฐ€ snapshot ๋ณต์› + ์„œ๋ฒ„ mutation ํ˜ธ์ถœ\n this.dispatchEvent(\n new CustomEvent('board-edit-revert', {\n detail: { patchId },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private async send() {\n if (this.sendBlocked) { this.errorMessage = this.sendBlocked; return }\n const text = this.input.trim()\n const attachmentsToSend = [...this.attachments]\n if ((!text && attachmentsToSend.length === 0) || this.busy) return\n this.attachments = []\n /* What was written wide is sent to be answered - the conversation comes back to show it. */\n this.composerWide = false\n this.previewAttachmentId = null\n\n const promptText = text || (attachmentsToSend.length > 0\n ? (attachmentsToSend[0].type.startsWith('image/')\n ? i18next.t('ai-assistant.text.attached-image-ask', { defaultValue: 'here is an image โ€” go by it.' })\n : i18next.t('ai-assistant.text.attached-file-ask', { defaultValue: 'here is a file โ€” take a look.' }))\n : '')\n if (!this.sessionId && this.prepareSession) {\n this.busy = true\n try {\n await this.prepareSession(id => { this.adoptingSession = true; this.sessionId = id })\n await this.updateComplete\n } catch (error) {\n this.errorMessage = error instanceof Error ? error.message : String(error)\n this.busy = false\n return\n }\n this.busy = false\n }\n\n /* The neutral door takes stored files by id: upload them to the conversation first (ยง9-2). */\n let attachmentIds: string[] | undefined\n if (attachmentsToSend.length > 0 && this.usesAttachmentPolicy) {\n if (!this.sessionId) {\n this.errorMessage = i18next.t('ai-assistant.text.attachments-need-session', { defaultValue: 'attachments need a saved conversation.' })\n this.attachments = attachmentsToSend\n return\n }\n this.busy = true\n try {\n const uploaded = await client.mutate({\n mutation: ATTACH_TO_CONVERSATION_MUTATION,\n variables: { sessionId: this.sessionId, files: attachmentsToSend.map(a => a.file), kind: this.conversation.kind },\n /* The shell's client sends multipart only when asked - without it a File travels as {} and is refused. */\n context: { hasUpload: true }\n })\n if (uploaded.errors?.length) throw new Error(uploaded.errors.map(error => error.message).join('\\n'))\n attachmentIds = (uploaded.data?.attachToConversation ?? []).map((file: any) => file.id)\n } catch (error) {\n this.errorMessage = error instanceof Error ? error.message : String(error)\n this.attachments = attachmentsToSend\n this.busy = false\n return\n }\n this.busy = false\n }\n\n let requestContext: AssistantRequestContext\n let liveBoard: any\n let requestBase: any\n try {\n const provided = this.contextProvider?.() || {}\n requestContext = structuredClone({ hostContext: this.conversation.hostContext, ...provided })\n liveBoard = structuredClone(this.boardProvider ? this.boardProvider() : this.currentBoard)\n requestBase = { version: 1, sessionId: this.sessionId, hostContext: requestContext.hostContext,\n modelFingerprint: assistantModelFingerprint(liveBoard) }\n } catch (error) {\n this.errorMessage = error instanceof Error ? error.message : String(error)\n this.attachments = attachmentsToSend\n return\n }\n\n // pickedMentions / pickedUserMentions ์—์„œ ํ˜„์žฌ ํ…์ŠคํŠธ์— ์‹ค์ œ #/@ token ์œผ๋กœ\n // ๋“ฑ์žฅํ•˜๋Š” ๊ฒƒ๋งŒ ์ถ”์ถœ โ€” ์ง€์šด ํ† ํฐ ์ œ์™ธ. inline ๋งˆ์ปค๋กœ content ์— ์ฃผ์ž….\n const mentions: Array<{ token: string; refid: number }> = []\n for (const [token, refid] of this.pickedMentions.entries()) {\n if (promptText.includes(`#${token}`)) mentions.push({ token, refid })\n }\n const userMentions: Array<{ token: string; userId: string }> = []\n for (const [token, userId] of this.pickedUserMentions.entries()) {\n if (promptText.includes(`@${token}`)) userMentions.push({ token, userId })\n }\n let enrichedContent = injectMentionRefids(promptText, mentions)\n enrichedContent = injectMentionUserIds(enrichedContent, userMentions)\n\n // optimistic ๋ผ์ธ์— ์ž„์‹œ ํ•ธ๋“ค โ€” ๋ฐฉ์†ก ์—์ฝ”์™€์˜ reconcile ์„ index ๋น„์˜์กด์œผ๋กœ.\n const userLocalId = `local-${++this._localSeq}-u`\n const asstLocalId = `local-${++this._localSeq}-a`\n\n this.lines = [\n ...this.lines,\n {\n role: 'user',\n content: enrichedContent,\n attachments: attachmentsToSend.map(a => ({\n name: a.name,\n size: a.size,\n type: a.type,\n url: a.url,\n base64: a.base64\n })),\n _localId: userLocalId,\n senderEmail: this._myEmail\n }\n ]\n this.input = ''\n this.busy = true\n this.errorMessage = undefined\n\n // ๊ฐ€์งœ pending ์‘๋‹ต ํ‘œ์‹œ (UX ๋ถ€๋“œ๋Ÿฝ๊ฒŒ)\n this.lines = [...this.lines, { role: 'assistant', content: '', pending: true, _localId: asstLocalId }]\n\n try {\n if (attachmentsToSend.length > 0 && !attachmentIds) {\n requestContext.hostContext = {\n ...requestContext.hostContext,\n attachments: attachmentsToSend.map(a => ({\n name: a.name,\n size: a.size,\n mediaType: a.type,\n data: a.base64\n })),\n image: attachmentsToSend.find(a => a.type.startsWith('image/'))\n ? {\n name: attachmentsToSend.find(a => a.type.startsWith('image/'))!.name,\n mediaType: attachmentsToSend.find(a => a.type.startsWith('image/'))!.type,\n data: attachmentsToSend.find(a => a.type.startsWith('image/'))!.base64\n }\n : undefined\n }\n }\n // LLM ์œผ๋กœ ๋ณด๋‚ผ history โ€” user/assistant ๋งŒ (system ์€ ๋ฐฑ์—”๋“œ๊ฐ€ ์ž๋™ ํ•ฉ๋ฅ˜).\n // pending placeholder ์™€ system ์€ ์ œ์™ธ (index ๋น„์˜์กด โ€” ๋ฐฉ์†ก append ์™€ ๋ฌด๊ด€).\n const history = this.lines\n .filter(l => !l.pending && l._localId !== asstLocalId && l.role !== 'system')\n .map(l => ({ role: l.role, content: l.content }))\n\n // ๋ผ์ด๋ธŒ ๋ณด๋“œ ์šฐ์„  โ€” ํ˜ธ์ŠคํŠธ์˜ ์บ”๋ฒ„์Šค๊ฐ€ ์‚ฌ์šฉ์ž ์ˆ˜์ž‘์—… ํŽธ์ง‘์„ ๋“ค๊ณ  ์žˆ์„ ์ˆ˜ ์žˆ์Œ.\n // boardProvider ๊ฐ€ ์žˆ์œผ๋ฉด send ์‹œ์ ์— ๊ทธ๊ฒƒ์„ pull, ์—†์œผ๋ฉด ์ •์  currentBoard.\n // mentions ๋Š” ์œ„์—์„œ ์ด๋ฏธ ๊ณ„์‚ฐํ•ด user line ์— thread โ€” ๊ทธ๋Œ€๋กœ mutation ์ž…๋ ฅ์œผ๋กœ ์žฌ์‚ฌ์šฉ.\n const neutral = this.conversation.chatEndpoint === 'assistantChat'\n const result = await client.mutate({\n mutation: neutral ? ASSISTANT_CHAT_MUTATION : BOARD_AI_CHAT_MUTATION,\n variables: {\n input: neutral\n ? buildAssistantChatInput({\n sessionId: this.sessionId,\n history,\n mode: { kind: this.conversation.kind!, target: this.conversation.target },\n truncateAfterMessageId: this._truncateAfterId,\n hostContext: requestContext.hostContext,\n attachmentIds\n })\n : buildChatMutationInput({\n sessionId: this.sessionId,\n history,\n liveBoard,\n scopes: this.scopes,\n truncateAfterMessageId: this._truncateAfterId,\n hostContext: requestContext.hostContext,\n /* The board door still takes its categories from the element โ€” it declares no mode. */\n toolCategories: this.toolCategories,\n boardTools: this.boardTools,\n requireGroundingTools: this.requireGroundingTools,\n knownTypes: this.knownTypes,\n categories: this.categories,\n componentSchemas: this.componentSchemas,\n selectedRefids: this.selectedRefids ?? [],\n mentions,\n /* With a declared mode the server owns persona and tools; the board door still carries the board. */\n mode: this.conversation.kind ? { kind: this.conversation.kind, target: this.conversation.target } : undefined\n })\n }\n })\n\n /*\n * Apollo๊ฐ€ errorPolicy: all ๋กœ ์‘๋‹ตํ•˜๋ฉด data๋Š” ๋น„๊ณ  GraphQL ์˜ค๋ฅ˜๋Š” result.errors ์— ๋‚จ๋Š”๋‹ค.\n * ์ด๋ฅผ ํ™•์ธํ•˜์ง€ ์•Š์œผ๋ฉด ์‹ค์ œ ์„œ๋ฒ„ ์‚ฌ์œ (์˜ˆ: Figure ํ›„๋ณด์˜ ๋งˆ์ง€๋ง‰ ๊ฒ€์ฆ ์‚ฌ์œ )๋ฅผ ๋ฒ„๋ฆฌ๊ณ \n * \"์‘๋‹ต์ด ๋น„์–ด์žˆ์Šต๋‹ˆ๋‹ค\"๋ผ๋Š” ๊ฑฐ์ง“ ์˜ค๋ฅ˜๋ฅผ ๋ณด์—ฌ ์ค€๋‹ค.\n */\n if (result.errors?.length) {\n throw new Error(result.errors.map(error => error.message).join('\\n'))\n }\n\n const out = neutral ? result.data?.assistantChat : result.data?.boardAIChat\n if (!out) throw new Error(i18next.t('ai-assistant.text.empty-response'))\n\n /* ๋Œ€ํ™”๊ฐ€ ๊ธธ์–ด์กŒ๋‹ค๋Š” ์„œ๋ฒ„ ๋ณด๊ณ  โ€” ๋‹ซ์ง€ ์•Š์•˜๋‹ค๋ฉด ์•ˆ๋‚ด๋ฅผ ๋„์šด๋‹ค. */\n this.historyFolded = out.historyFolded ?? undefined\n\n // ์ „์†ก ์„ฑ๊ณต โ€” picks ์ •๋ฆฌ (๋‹ค์Œ ๋ฉ”์‹œ์ง€๋ถ€ํ„ฐ๋Š” ์ƒˆ picks ๋งŒ)\n this.pickedMentions.clear()\n this.pickedUserMentions.clear()\n\n // optimistic ๋ผ์ธ์„ ์„œ๋ฒ„ id ๋กœ reconcile (๋ฐฉ์†ก ์—์ฝ”์™€ ์ค‘๋ณต ๋ฐฉ์ง€, index ๋น„์˜์กด).\n // ์‚ฌ์šฉ์ž ๋ผ์ธ: enrich ๋œ ๋ณธ๋ฌธ ์œ ์ง€, id ๋งŒ ๋ถ€์—ฌ. AI ๋ผ์ธ: pending โ†’ ์‹ค์ œ ์‘๋‹ต.\n this._reconcileSentLine(userLocalId, out.userMessageId, {})\n this._reconcileSentLine(asstLocalId, out.assistantMessageId, {\n role: 'assistant',\n content: out.reply,\n patchSummary: out.patch?.summary,\n followUp: out.followUp || undefined,\n patchId: out.patchId || undefined,\n toolUsages: Array.isArray(out.toolUsages) ? out.toolUsages : undefined,\n groundingWarnings: Array.isArray(out.groundingWarnings) ? out.groundingWarnings : undefined,\n proposals: Array.isArray(out.proposals) ? out.proposals : undefined,\n pending: false\n })\n\n // ์ œ์•ˆ ์ž๋™ ํ”„๋ฆฌ๋ทฐ ์ „ํŒŒ (3D ๋ทฐ์–ด ์ž๋™ ๋ฐ˜์˜)\n if (Array.isArray(out.proposals) && out.proposals.length > 0) {\n for (const p of out.proposals) {\n if (p?.source || p?.autoStage) {\n this.dispatchEvent(\n new CustomEvent('assistant-proposal-preview', {\n detail: { proposal: p, sessionId: out.sessionId },\n bubbles: true,\n composed: true\n })\n )\n }\n }\n }\n\n // ํ˜ธ์ŠคํŠธ๋กœ patch ์ด๋ฒคํŠธ ์ „ํŒŒ\n if (out.patch) {\n this.dispatchEvent(\n new CustomEvent('scene-edit-patch', {\n detail: {\n patch: out.patch,\n requestBase,\n summary: out.patch.summary,\n confidence: out.patch.confidence,\n patchId: out.patchId,\n sessionId: out.sessionId\n },\n bubbles: true,\n composed: true\n })\n )\n }\n // ํ˜ธ์ŠคํŠธ๋กœ ephemeral scene ์กฐ์ž‘ actions ์ „ํŒŒ (selection / view / mode)\n if (Array.isArray(out.actions) && out.actions.length > 0) {\n this.dispatchEvent(\n new CustomEvent('scene-action-execute', {\n detail: { actions: out.actions, sessionId: out.sessionId, requestBase },\n bubbles: true,\n composed: true\n })\n )\n }\n if (out.followUp) {\n this.dispatchEvent(\n new CustomEvent('chat-followup', {\n detail: { question: out.followUp },\n bubbles: true,\n composed: true\n })\n )\n }\n } catch (e: any) {\n // pending(AI) placeholder ๋งŒ ์ œ๊ฑฐ โ€” ์‚ฌ์šฉ์ž ๋ผ์ธ์€ ๋ณด์กด(์žฌ์‹œ๋„). index ๋น„์˜์กด.\n this.lines = this.lines.filter(l => l._localId !== asstLocalId)\n this.errorMessage = e?.message ?? String(e)\n this.lastFailedInput = text\n } finally {\n this.busy = false\n }\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ox-assistant-chat': OxAssistantChat\n }\n}\n"]}