@things-factory/ai-assistant 10.1.112 โ 10.1.114
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/components/assistant-chat.ts +19 -0
- package/client/utils/open-page.ts +21 -0
- package/dist-client/components/assistant-chat.d.ts +2 -0
- package/dist-client/components/assistant-chat.js +19 -0
- package/dist-client/components/assistant-chat.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/utils/open-page.d.ts +5 -0
- package/dist-client/utils/open-page.js +19 -0
- package/dist-client/utils/open-page.js.map +1 -0
- package/dist-server/service/assistant-mode/resolve.d.ts +1 -0
- package/dist-server/service/assistant-mode/resolve.js +2 -1
- package/dist-server/service/assistant-mode/resolve.js.map +1 -1
- package/dist-server/service/assistant-mode/types.d.ts +2 -0
- package/dist-server/service/assistant-mode/types.js.map +1 -1
- package/dist-server/service/chat-session/attachment-tool-result.d.ts +28 -0
- package/dist-server/service/chat-session/attachment-tool-result.js +9 -0
- package/dist-server/service/chat-session/attachment-tool-result.js.map +1 -0
- package/dist-server/service/chat-session/attachment-tools.js +4 -5
- package/dist-server/service/chat-session/attachment-tools.js.map +1 -1
- package/dist-server/service/data-read/list-read.d.ts +36 -0
- package/dist-server/service/data-read/list-read.js +64 -0
- package/dist-server/service/data-read/list-read.js.map +1 -0
- package/dist-server/service/data-read/read-target.d.ts +109 -0
- package/dist-server/service/data-read/read-target.js +189 -0
- package/dist-server/service/data-read/read-target.js.map +1 -0
- package/dist-server/service/data-read/read-tools.d.ts +228 -0
- package/dist-server/service/data-read/read-tools.js +197 -0
- package/dist-server/service/data-read/read-tools.js.map +1 -0
- package/dist-server/service/index.d.ts +3 -0
- package/dist-server/service/index.js +7 -1
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/server/service/assistant-mode/resolve.ts +3 -2
- package/server/service/assistant-mode/types.ts +2 -0
- package/server/service/chat-session/attachment-tool-result.test.ts +26 -0
- package/server/service/chat-session/attachment-tool-result.ts +18 -0
- package/server/service/chat-session/attachment-tools.ts +4 -5
- package/server/service/data-read/data-read.test.ts +229 -0
- package/server/service/data-read/list-read.ts +98 -0
- package/server/service/data-read/read-target.ts +230 -0
- package/server/service/data-read/read-tools.ts +212 -0
- package/server/service/index.ts +4 -0
- package/test/open-page.test.ts +31 -0
- package/translations/en.json +14 -0
- package/translations/ja.json +14 -0
- package/translations/ko.json +14 -0
- package/translations/ms.json +14 -0
- package/translations/zh.json +14 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant-chat.js","sourceRoot":"","sources":["../../client/components/assistant-chat.ts"],"names":[],"mappings":"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QAC3E,eAAe;QACf,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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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'\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 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 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 * ๋ฐ์์ ๋ฃ์ด ์ค ์ง๋ฌธ์ ์๋ ์ ์กํ๋ค(์ค๋ฅ ํ ์คํธ์ \"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"]}
|