@lynn123411/dsh-chat-translate 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/client/index.ts", "../src/client/translate/client-cache.ts", "../src/client/translate/api.ts", "../src/client/translate/mount.ts", "../src/client/translate/viewport-observer.ts", "../src/client/translate/lazy.ts", "../src/client/translate/observer.ts", "../src/client/settings/ui.tsx", "../src/client/settings/store.ts", "../src/client/settings/styles.ts"],
4
+ "sourcesContent": ["import { chatTranslateObserver } from './translate/observer.ts';\nimport { setupSettingsUi } from './settings/ui.tsx';\n\n/** Client plugin name, shared with the browser bundle id. */\nexport const name = 'dsh-chat-translate';\n\n/** Declare dependency on slots for settings section */\nexport const inject = ['slots'];\n\ninterface ClientContext {\n effect(factory: () => void | (() => void), label: string): void;\n get?(serviceName: string): any;\n slots?: any;\n}\n\n/**\n * Mount the tool-call / think-summary translation observer and the settings UI.\n * @param ctx - DSH browser client context.\n */\nexport function apply(ctx: ClientContext): void {\n // 1. Mount tool title / think summary translation observer (current session only)\n ctx.effect(() => chatTranslateObserver.start(document), 'dsh-chat-translate: title translate observer');\n\n // 2. Mount settings UI section\n ctx.effect(() => setupSettingsUi(ctx), 'dsh-chat-translate: settings section');\n}\n\nexport { chatTranslateObserver } from './translate/observer.ts';\nexport { setupSettingsUi } from './settings/ui.tsx';\nexport { NonDestructiveTranslationMount } from './translate/mount.ts';\nexport { StreamDebounceViewportObserver } from './translate/viewport-observer.ts';\nexport { clientCache } from './translate/client-cache.ts';\nexport { lazyQueue } from './translate/lazy.ts';\nexport { settingsStore } from './settings/store.ts';\n", "const CACHE_KEY = 'dsh-chat-translate:cache';\nconst MAX_LOCAL_ENTRIES = 500;\n/** Entries older than this are treated as expired. */\nconst TTL_MS = 7 * 24 * 60 * 60 * 1000; // 7 days\n\ninterface CacheEntry {\n t: number; // epoch ms; 0 = legacy entry without timestamp\n v: string;\n}\n\nexport class ClientCache {\n // Map preserves insertion order in JS, enabling true LRU semantics.\n private memCache = new Map<string, CacheEntry>();\n private dirty = false;\n private saveTimer: number | null = null;\n\n constructor() {\n this.load();\n }\n\n private load(): void {\n if (typeof localStorage === 'undefined') return;\n try {\n const raw = localStorage.getItem(CACHE_KEY);\n if (raw) {\n const obj = JSON.parse(raw);\n if (obj && typeof obj === 'object') {\n for (const [k, entry] of Object.entries(obj)) {\n if (typeof entry === 'string') {\n // Legacy entry from an older release.\n this.memCache.set(k, { t: 0, v: entry });\n } else if (entry && typeof entry === 'object' && typeof (entry as CacheEntry).v === 'string') {\n this.memCache.set(k, entry as CacheEntry);\n }\n }\n }\n }\n } catch {\n // Ignore parse failure\n }\n }\n\n get(text: string): string | undefined {\n const key = text.trim().toLowerCase();\n const entry = this.memCache.get(key);\n if (entry === undefined) return undefined;\n // Drop dirty fallback entries where value equals key\n if (entry.v && entry.v.trim().toLowerCase() === key) {\n this.memCache.delete(key);\n this.dirty = true;\n this.scheduleSave();\n return undefined;\n }\n if (entry.t > 0 && Date.now() - entry.t > TTL_MS) {\n this.memCache.delete(key);\n this.dirty = true;\n this.scheduleSave();\n return undefined;\n }\n // True LRU: Re-insert to move to the end (most recently used)\n this.memCache.delete(key);\n this.memCache.set(key, entry);\n return entry.v;\n }\n\n set(text: string, translated: string): void {\n const key = text.trim().toLowerCase();\n if (this.memCache.has(key)) {\n this.memCache.delete(key);\n } else if (this.memCache.size >= MAX_LOCAL_ENTRIES) {\n // Evict least recently used (first item in Map)\n const oldestKey = this.memCache.keys().next().value;\n if (oldestKey !== undefined) {\n this.memCache.delete(oldestKey);\n }\n }\n this.memCache.set(key, { t: Date.now(), v: translated });\n this.dirty = true;\n this.scheduleSave();\n }\n\n private scheduleSave(): void {\n if (this.saveTimer !== null || typeof window === 'undefined') return;\n this.saveTimer = window.setTimeout(() => {\n this.saveTimer = null;\n this.flushSync();\n }, 2000);\n }\n\n flushSync(): void {\n if (!this.dirty || typeof localStorage === 'undefined') return;\n this.dirty = false;\n try {\n const obj: Record<string, CacheEntry> = {};\n for (const [k, v] of this.memCache.entries()) {\n obj[k] = v;\n }\n localStorage.setItem(CACHE_KEY, JSON.stringify(obj));\n } catch {\n // Ignore quota error\n }\n }\n\n clear(): void {\n this.memCache.clear();\n this.dirty = true;\n this.flushSync();\n }\n\n size(): number {\n return this.memCache.size;\n }\n}\n\nexport const clientCache = new ClientCache();", "export interface TranslateItemResult {\n original: string;\n translated: string;\n channel: string;\n cached: boolean;\n}\n\nexport interface TranslateBatchOptions {\n signal?: AbortSignal;\n timeoutMs?: number;\n}\n\nexport async function requestTranslateBatch(\n texts: string[],\n options: TranslateBatchOptions = {}\n): Promise<TranslateItemResult[]> {\n if (!Array.isArray(texts) || texts.length === 0) return [];\n \n // Filter out empty or whitespace-only texts\n const validTexts = texts.map((t) => (typeof t === 'string' ? t : ''));\n if (validTexts.length === 0) return [];\n\n const controller = new AbortController();\n const timeoutId = options.timeoutMs\n ? setTimeout(() => controller.abort(), options.timeoutMs)\n : null;\n\n const effectiveSignal = options.signal\n ? (options.signal.aborted ? options.signal : controller.signal)\n : controller.signal;\n\n if (options.signal) {\n options.signal.addEventListener('abort', () => controller.abort(), { once: true });\n }\n\n try {\n const res = await fetch('/api/dsh-chat-translate/translate', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ texts: validTexts }),\n signal: effectiveSignal,\n });\n\n if (res.ok) {\n const data = (await res.json()) as { ok: boolean; results?: TranslateItemResult[]; error?: string };\n if (data.ok && Array.isArray(data.results) && data.results.length > 0) {\n return data.results;\n } else if (data.error) {\n console.warn(`[dsh-chat-translate] \u7FFB\u8BD1\u63A5\u53E3\u9519\u8BEF: ${data.error}`);\n }\n } else {\n console.warn(`[dsh-chat-translate] \u7FFB\u8BD1\u8BF7\u6C42\u5931\u8D25 (HTTP ${res.status})`);\n }\n } catch (err: any) {\n if (err?.name === 'AbortError') {\n // Intentionally aborted\n }\n } finally {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n }\n\n // Host route unreachable or error \u2014 leave the original text untouched\n return validTexts.map((t) => ({\n original: t,\n translated: t,\n channel: 'fallback-client',\n cached: false,\n }));\n}\n\nexport async function fetchServerConfig(): Promise<any> {\n try {\n const res = await fetch('/api/dsh-chat-translate/config');\n if (!res.ok) return null;\n const json = await res.json();\n return json.config;\n } catch {\n return null;\n }\n}\n\nexport async function updateServerConfig(updates: any): Promise<any> {\n try {\n const res = await fetch('/api/dsh-chat-translate/config', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(updates),\n });\n if (!res.ok) return null;\n const json = await res.json();\n return json.config;\n } catch {\n return null;\n }\n}\n\nexport async function testServerChannel(channel: string): Promise<{ ok: boolean; latencyMs: number; error?: string }> {\n try {\n const res = await fetch('/api/dsh-chat-translate/test-channel', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ channel }),\n });\n return await res.json();\n } catch (err: any) {\n return { ok: false, latencyMs: 0, error: err?.message || String(err) };\n }\n}\n\n/** Persist the translation API key into ~/.dsh/.credentials.yaml via the host. */\nexport async function saveCredentials(\n apiKey: string\n): Promise<{ ok: boolean; configured?: boolean; error?: string }> {\n try {\n const res = await fetch('/api/dsh-chat-translate/credentials', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ apiKey }),\n });\n return await res.json();\n } catch (err: any) {\n return { ok: false, error: err?.message || String(err) };\n }\n}", "/**\n * Non-destructive translation DOM mount mechanism.\n *\n * Preserves the original React Fiber tree, event listeners, and nested DOM nodes\n * by wrapping them in a hidden container (<span class=\"dsh-tidy-original-hidden\">)\n * rather than destroying them with `element.textContent = translated`.\n *\n * Displays the translated text in a companion container (<span class=\"dsh-tidy-translated-block\">).\n * Clicking the translation toggles between original and translated text in-place.\n */\n\nexport const CLASS_ORIGINAL_HIDDEN = 'dsh-tidy-original-hidden';\nexport const CLASS_ORIGINAL_SHOWN = 'dsh-tidy-original-shown';\nexport const CLASS_TRANSLATED_BLOCK = 'dsh-tidy-translated-block';\n\nexport interface MountOptions {\n originalText?: string;\n isThink?: boolean;\n interactive?: boolean;\n}\n\nexport class NonDestructiveTranslationMount {\n /**\n * Mounts a translated string onto the target element non-destructively.\n */\n static mount(\n element: HTMLElement,\n translated: string,\n options: MountOptions = {}\n ): void {\n if (!element || !element.ownerDocument) return;\n const doc = element.ownerDocument;\n\n // Check if already mounted\n let transWrapper = element.querySelector<HTMLElement>(`:scope > .${CLASS_TRANSLATED_BLOCK}`);\n let origWrapper = element.querySelector<HTMLElement>(\n `:scope > .${CLASS_ORIGINAL_HIDDEN}, :scope > .${CLASS_ORIGINAL_SHOWN}`\n );\n\n if (transWrapper && origWrapper) {\n // Update existing translation\n transWrapper.textContent = translated;\n element.dataset.tidyTranslated = 'true';\n if (options.isThink) element.dataset.tidyThink = 'true';\n if (options.originalText) element.dataset.original = options.originalText;\n return;\n }\n\n const originalText = options.originalText ?? this.extractVisibleText(element);\n\n // Create wrapper for original children\n origWrapper = doc.createElement('span');\n origWrapper.className = CLASS_ORIGINAL_HIDDEN;\n origWrapper.style.display = 'none';\n\n // Move all existing child nodes into origWrapper\n while (element.firstChild) {\n origWrapper.appendChild(element.firstChild);\n }\n\n // Create translation block\n transWrapper = doc.createElement('span');\n transWrapper.className = CLASS_TRANSLATED_BLOCK;\n transWrapper.textContent = translated;\n\n // Interactive bilingual toggle\n const interactive = options.interactive !== false;\n if (interactive) {\n\n const showOriginal = (e: MouseEvent): void => {\n e.stopPropagation();\n if (!origWrapper || !transWrapper) return;\n origWrapper.style.display = 'inline';\n origWrapper.className = CLASS_ORIGINAL_SHOWN;\n transWrapper.style.display = 'none';\n };\n\n const showTranslated = (e: MouseEvent): void => {\n e.stopPropagation();\n if (!origWrapper || !transWrapper) return;\n origWrapper.style.display = 'none';\n origWrapper.className = CLASS_ORIGINAL_HIDDEN;\n transWrapper.style.display = 'inline';\n };\n\n transWrapper.addEventListener('click', showOriginal);\n origWrapper.addEventListener('click', showTranslated);\n }\n\n // Append both to target element\n element.appendChild(transWrapper);\n element.appendChild(origWrapper);\n\n element.dataset.tidyTranslated = 'true';\n element.dataset.original = originalText;\n if (options.isThink) {\n element.dataset.tidyThink = 'true';\n }\n }\n\n /**\n * Unmounts translation and restores original DOM nodes completely.\n */\n static unmount(element: HTMLElement): void {\n if (!element) return;\n\n const origWrapper = element.querySelector<HTMLElement>(\n `:scope > .${CLASS_ORIGINAL_HIDDEN}, :scope > .${CLASS_ORIGINAL_SHOWN}`\n );\n const transWrapper = element.querySelector<HTMLElement>(`:scope > .${CLASS_TRANSLATED_BLOCK}`);\n\n if (origWrapper) {\n // Move all original children back to element\n while (origWrapper.firstChild) {\n element.insertBefore(origWrapper.firstChild, origWrapper);\n }\n origWrapper.remove();\n }\n\n if (transWrapper) {\n transWrapper.remove();\n }\n\n // Fallback if no wrapper was created but text was modified directly\n if (!origWrapper && element.dataset.original) {\n element.textContent = element.dataset.original;\n }\n\n delete element.dataset.tidyTranslated;\n delete element.dataset.original;\n delete element.dataset.tidyThink;\n }\n\n /**\n * Checks if an element has non-destructive translation mounted.\n */\n static isMounted(element: HTMLElement): boolean {\n return (\n element.dataset.tidyTranslated === 'true' &&\n !!element.querySelector(`:scope > .${CLASS_TRANSLATED_BLOCK}`)\n );\n }\n\n /**\n * Gets the original text recorded on the element or contained in origWrapper.\n */\n static getOriginal(element: HTMLElement): string | undefined {\n if (element.dataset.original) return element.dataset.original;\n const origWrapper = element.querySelector<HTMLElement>(\n `:scope > .${CLASS_ORIGINAL_HIDDEN}, :scope > .${CLASS_ORIGINAL_SHOWN}`\n );\n return origWrapper ? origWrapper.textContent?.trim() : undefined;\n }\n\n /**\n * Extracts text content excluding our own translation wrappers.\n */\n static extractVisibleText(element: HTMLElement): string {\n const origWrapper = element.querySelector<HTMLElement>(\n `:scope > .${CLASS_ORIGINAL_HIDDEN}, :scope > .${CLASS_ORIGINAL_SHOWN}`\n );\n if (origWrapper) {\n return origWrapper.textContent?.trim() || '';\n }\n const transWrapper = element.querySelector<HTMLElement>(`:scope > .${CLASS_TRANSLATED_BLOCK}`);\n if (transWrapper) {\n return transWrapper.textContent?.trim() || '';\n }\n return element.textContent?.trim() || '';\n }\n}", "/**\n * StreamDebounceViewportObserver\n *\n * Combines:\n * 1. True IntersectionObserver for viewport visibility detection (rootMargin: '150px 0px').\n * 2. Typing/streaming debounce (default 400ms) to avoid translating partial streaming sentences.\n * 3. Batch queuing to group multiple visible elements into efficient batch requests.\n */\n\nexport interface ViewportObserverOptions {\n rootMargin?: string;\n debounceMs?: number;\n onVisibleBatch: (items: Array<{ element: HTMLElement; text: string; isThink?: boolean }>) => void;\n}\n\nexport class StreamDebounceViewportObserver {\n private intersectionObserver: IntersectionObserver | null = null;\n private streamingTimers = new WeakMap<HTMLElement, number>();\n private pendingQueue: Array<{ element: HTMLElement; text: string; isThink?: boolean }> = [];\n private batchFlushTimer: number | null = null;\n private options: Required<Omit<ViewportObserverOptions, 'onVisibleBatch'>> & {\n onVisibleBatch: ViewportObserverOptions['onVisibleBatch'];\n };\n\n constructor(options: ViewportObserverOptions) {\n this.options = {\n rootMargin: options.rootMargin ?? '150px 0px',\n debounceMs: options.debounceMs ?? 400,\n onVisibleBatch: options.onVisibleBatch,\n };\n this.initIntersectionObserver();\n }\n\n private initIntersectionObserver(): void {\n if (typeof window === 'undefined' || typeof IntersectionObserver === 'undefined') {\n return;\n }\n\n this.intersectionObserver = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.isIntersecting && entry.target instanceof HTMLElement) {\n const el = entry.target;\n // Stop observing once it enters viewport and is queued\n this.intersectionObserver?.unobserve(el);\n const text = el.dataset.tidyPendingText || el.textContent?.trim() || '';\n const isThink = el.dataset.tidyPendingThink === 'true';\n if (text) {\n delete el.dataset.tidyPendingText;\n delete el.dataset.tidyPendingThink;\n this.enqueueBatch(el, text, isThink);\n }\n }\n }\n },\n {\n root: null, // viewport\n rootMargin: this.options.rootMargin,\n threshold: 0,\n }\n );\n }\n\n /**\n * Observe an element with streaming debounce.\n * If streaming updates characterData repeatedly within debounceMs, the timer resets.\n */\n observeWithDebounce(element: HTMLElement, text: string, immediate = false, isThink = false): void {\n if (!element || !text) return;\n\n // Clear any active streaming timer for this element\n const existingTimer = this.streamingTimers.get(element);\n if (existingTimer !== undefined) {\n clearTimeout(existingTimer);\n this.streamingTimers.delete(element);\n }\n\n if (immediate || this.options.debounceMs <= 0) {\n this.registerForViewport(element, text, isThink);\n return;\n }\n\n const timer = window.setTimeout(() => {\n this.streamingTimers.delete(element);\n if (element.isConnected) {\n // Read latest text content after streaming settles\n const latestText = element.textContent?.trim() || text;\n this.registerForViewport(element, latestText, isThink);\n }\n }, this.options.debounceMs);\n\n this.streamingTimers.set(element, timer);\n }\n\n private registerForViewport(element: HTMLElement, text: string, isThink = false): void {\n if (!element.isConnected) return;\n\n if (!this.intersectionObserver) {\n // Fallback if IntersectionObserver is unsupported: enqueue immediately\n this.enqueueBatch(element, text, isThink);\n return;\n }\n\n element.dataset.tidyPendingText = text;\n if (isThink) element.dataset.tidyPendingThink = 'true';\n this.intersectionObserver.observe(element);\n }\n\n private enqueueBatch(element: HTMLElement, text: string, isThink = false): void {\n this.pendingQueue.push({ element, text, isThink });\n if (this.batchFlushTimer === null && typeof window !== 'undefined') {\n this.batchFlushTimer = window.setTimeout(() => {\n this.batchFlushTimer = null;\n this.flushQueue();\n }, 50);\n }\n }\n\n private flushQueue(): void {\n if (this.pendingQueue.length === 0) return;\n const batch = [...this.pendingQueue];\n this.pendingQueue = [];\n this.options.onVisibleBatch(batch);\n }\n\n unobserve(element: HTMLElement): void {\n const timer = this.streamingTimers.get(element);\n if (timer !== undefined) {\n clearTimeout(timer);\n this.streamingTimers.delete(element);\n }\n delete element.dataset.tidyPendingText;\n delete element.dataset.tidyPendingThink;\n if (this.intersectionObserver) {\n this.intersectionObserver.unobserve(element);\n }\n }\n\n disconnect(): void {\n if (this.batchFlushTimer !== null) {\n clearTimeout(this.batchFlushTimer);\n this.batchFlushTimer = null;\n }\n this.pendingQueue = [];\n if (this.intersectionObserver) {\n this.intersectionObserver.disconnect();\n this.initIntersectionObserver();\n }\n }\n}\n", "import { clientCache } from './client-cache.ts';\nimport { requestTranslateBatch } from './api.ts';\nimport { NonDestructiveTranslationMount } from './mount.ts';\nimport { StreamDebounceViewportObserver } from './viewport-observer.ts';\n\ntype TranslateTask = {\n element: HTMLElement;\n text: string;\n isThink?: boolean;\n};\n\nclass LazyTranslationQueue {\n private enabled = true;\n private viewportObserver: StreamDebounceViewportObserver;\n\n constructor() {\n this.viewportObserver = new StreamDebounceViewportObserver({\n rootMargin: '150px 0px',\n debounceMs: 400,\n onVisibleBatch: (items) => this.handleVisibleBatch(items),\n });\n }\n\n setEnabled(enabled: boolean): void {\n this.enabled = enabled;\n if (!enabled) {\n this.viewportObserver.disconnect();\n }\n }\n\n observe(element: HTMLElement, text: string, immediate = false, isThink = false): void {\n if (!this.enabled || !element.isConnected) return;\n\n // 1. If cached, apply immediately non-destructively\n const cached = clientCache.get(text);\n if (cached) {\n this.applyTranslation(element, cached, text, isThink);\n return;\n }\n\n // 2. Delegate to streaming-debounced viewport observer\n this.viewportObserver.observeWithDebounce(element, text, immediate, isThink);\n }\n\n private async handleVisibleBatch(items: TranslateTask[]): Promise<void> {\n if (!this.enabled || items.length === 0) return;\n\n // Document order: translations appear in reading order (top-to-bottom),\n // never out-of-order even when IntersectionObserver fires entries randomly.\n const sorted = [...items].sort((a, b) => {\n if (a.element === b.element) return 0;\n const pos = a.element.compareDocumentPosition(b.element);\n return pos & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;\n });\n\n // Group elements by text to deduplicate API requests\n const textMap = new Map<string, Array<{ element: HTMLElement; isThink?: boolean }>>();\n for (const item of sorted) {\n if (!item.element.isConnected) continue;\n\n const cached = clientCache.get(item.text);\n if (cached) {\n this.applyTranslation(item.element, cached, item.text, item.isThink);\n continue;\n }\n\n const list = textMap.get(item.text) || [];\n list.push({ element: item.element, isThink: item.isThink });\n textMap.set(item.text, list);\n }\n\n const uniqueTexts = Array.from(textMap.keys());\n if (uniqueTexts.length === 0) return;\n\n const results = await requestTranslateBatch(uniqueTexts);\n\n for (const res of results) {\n if (\n res.translated &&\n res.translated.trim() &&\n res.channel !== 'fallback' &&\n res.channel !== 'fallback-client' &&\n res.translated.trim() !== res.original.trim()\n ) {\n clientCache.set(res.original, res.translated);\n const entries = textMap.get(res.original) || [];\n for (const entry of entries) {\n if (entry.element.isConnected && this.enabled) {\n this.applyTranslation(entry.element, res.translated, res.original, entry.isThink);\n }\n }\n } else if (res.channel === 'fallback' || res.channel === 'fallback-client') {\n console.debug(`[dsh-chat-translate] \u7FFB\u8BD1\u672A\u6210\u529F (\u964D\u7EA7\u4FDD\u7559\u539F\u6587): \"${res.original.slice(0, 40)}\"`);\n }\n }\n }\n\n private applyTranslation(element: HTMLElement, translated: string, original: string, isThink?: boolean): void {\n if (!element.isConnected || !this.enabled) return;\n NonDestructiveTranslationMount.mount(element, translated, {\n originalText: original,\n isThink: isThink || element.dataset.tidyThink === 'true',\n });\n }\n\n disconnect(): void {\n this.viewportObserver.disconnect();\n }\n}\n\nexport const lazyQueue = new LazyTranslationQueue();", "import { clientCache } from './client-cache.ts';\nimport { lazyQueue } from './lazy.ts';\nimport { NonDestructiveTranslationMount } from './mount.ts';\n\nconst TOOL_TITLE_SELECTOR = '[class*=\"summary\"]';\n\n/**\n * Current-session scroll container (the conversation layout re-renders this\n * whole subtree when the active session changes), falling back to the chat\n * flow. Both are emitted by the DSH web UI.\n */\nconst SESSION_ROOT_SELECTOR = '[data-conversation-scroll], [data-chat-flow]';\n\n/** How often (ms) we re-check that the observed root is still the live one. */\nconst ROOT_CHECK_INTERVAL_MS = 3000;\n\nfunction isToolSummarySpan(span: HTMLElement): boolean {\n if (!span || span.nodeType !== 1) return false;\n if (span.hasAttribute('aria-hidden')) return false;\n\n // Never match parent rows or containers that contain title, leading icon, chevron or nested summary\n if (span.querySelector?.('[class*=\"title\"], [class*=\"leading\"], [class*=\"chevron\"], [class*=\"sep\"], [class*=\"summary\"]')) {\n return false;\n }\n\n const cls = span.className || '';\n if (/title|leading|icon|badge|chevron|separator|sep\\b|row\\b|root\\b|card\\b/i.test(cls)) return false;\n\n // Never translate fold toggle (\"\u5C55\u5F00\"/\"\u6536\u8D77\") or Think card's own title badge (\"Think\"/\"\u601D\u8003\")\n const rawToggle = (span.textContent || '').trim();\n if (\n rawToggle.length <= 12 &&\n /^(\u5C55\u5F00|\u6536\u8D77|\u5C55\u5F00\u5168\u90E8|\u6536\u8D77\u5168\u90E8|Expand|Collapse|Show more|Show less|Think|\u601D\u8003)$/i.test(rawToggle)\n ) {\n return false;\n }\n if (rawToggle === 'Think' || rawToggle === '\u601D\u8003') return false;\n if (\n span.closest('button, [role=\"button\"]') &&\n rawToggle.length <= 12 &&\n /\u5C55\u5F00|\u6536\u8D77|Expand|Collapse|Think|\u601D\u8003/i.test(rawToggle)\n ) {\n return false;\n }\n\n // Must belong to tool call or think block card\n if (\n span.closest(\n '[data-chat-call-id], [data-slot=\"tool.call.toolview\"], [data-sample], [data-variant], [data-tool], [data-disclosure-row]'\n )\n ) {\n return true;\n }\n return false;\n}\n\nexport class ChatTranslateObserver {\n private observer: MutationObserver | null = null;\n private rootElement: HTMLElement | null = null;\n private rootCheckTimer: number | null = null;\n private isEnabled = true;\n\n constructor() {\n this.handleMutations = this.handleMutations.bind(this);\n }\n\n setEnabled(enabled: boolean): void {\n this.isEnabled = enabled;\n if (enabled) {\n lazyQueue.setEnabled(true);\n this.start();\n } else {\n this.restoreOriginals();\n this.disconnect();\n lazyQueue.setEnabled(false);\n }\n }\n\n private restoreOriginals(): void {\n const scope = this.rootElement ?? document;\n const spans = scope.querySelectorAll<HTMLElement>('[data-tidy-translated=\"true\"]');\n for (const span of spans) {\n NonDestructiveTranslationMount.unmount(span);\n }\n }\n\n /**\n * The active session's scroll container. Only the currently-viewed session\n * is translated; switching sessions replaces this subtree and the observer\n * naturally follows the new content.\n */\n private isVisible(el: HTMLElement): boolean {\n if (el.hasAttribute('hidden')) return false;\n if (el.style.display === 'none') return false;\n try {\n return el.getClientRects().length > 0;\n } catch {\n return true;\n }\n }\n\n private findRoot(documentRef: Document): HTMLElement {\n if (!documentRef.body) {\n return documentRef.documentElement;\n }\n const candidates = documentRef.querySelectorAll<HTMLElement>(SESSION_ROOT_SELECTOR);\n for (const el of candidates) {\n if (this.isVisible(el)) {\n return el;\n }\n }\n return documentRef.body;\n }\n\n start(documentRef: Document = document): () => void {\n if (!this.isEnabled || typeof window === 'undefined') {\n return () => {};\n }\n\n const findAndObserveRoot = () => {\n const root = this.findRoot(documentRef);\n\n this.rootElement = root;\n\n // 1. Initial scan of existing tool elements\n this.scanContainer(root);\n\n // 2. Setup MutationObserver\n if (!this.observer) {\n this.observer = new MutationObserver(this.handleMutations);\n this.observer.observe(root, {\n childList: true,\n subtree: true,\n attributes: true,\n characterData: true,\n attributeFilter: ['data-state', 'data-tool', 'data-variant', 'data-sample', 'aria-expanded'],\n });\n }\n };\n\n findAndObserveRoot();\n\n // Defense: if the observed root is detached or hidden (e.g. the user\n // switched to another view), re-probe for the live session container.\n this.scheduleRootCheck();\n\n return () => {\n this.disconnect();\n };\n }\n\n private scheduleRootCheck(): void {\n if (this.rootCheckTimer !== null || typeof window === 'undefined') return;\n this.rootCheckTimer = window.setInterval(() => {\n if (this.rootElement && this.rootElement.isConnected && this.isVisible(this.rootElement)) {\n return;\n }\n this.restart();\n }, ROOT_CHECK_INTERVAL_MS);\n }\n\n private restart(): void {\n if (typeof window === 'undefined') return;\n const wasEnabled = this.isEnabled;\n this.disconnect();\n if (wasEnabled) {\n this.start();\n }\n }\n\n private handleMutations(mutations: MutationRecord[]): void {\n if (!this.isEnabled) return;\n\n for (const mutation of mutations) {\n if (mutation.type === 'childList') {\n for (let i = 0; i < mutation.addedNodes.length; i++) {\n const node = mutation.addedNodes[i];\n if (node instanceof HTMLElement) {\n if (\n node.classList?.contains('dsh-tidy-translated-block') ||\n node.classList?.contains('dsh-tidy-original-hidden') ||\n node.classList?.contains('dsh-tidy-original-shown')\n ) {\n continue;\n }\n this.scanNode(node);\n }\n }\n } else if (mutation.type === 'attributes') {\n const target = mutation.target;\n if (target instanceof HTMLElement) {\n if (\n target.classList?.contains('dsh-tidy-translated-block') ||\n target.classList?.contains('dsh-tidy-original-hidden') ||\n target.classList?.contains('dsh-tidy-original-shown')\n ) {\n continue;\n }\n this.scanNode(target);\n }\n } else if (mutation.type === 'characterData') {\n const parent = mutation.target.parentElement;\n if (parent instanceof HTMLElement) {\n if (\n parent.classList?.contains('dsh-tidy-translated-block') ||\n parent.classList?.contains('dsh-tidy-original-hidden') ||\n parent.classList?.contains('dsh-tidy-original-shown')\n ) {\n continue;\n }\n this.scanNode(parent);\n }\n }\n }\n }\n\n private scanContainer(container: HTMLElement): void {\n const spans = container.querySelectorAll<HTMLElement>(TOOL_TITLE_SELECTOR);\n spans.forEach((span) => {\n if (isToolSummarySpan(span)) {\n this.processSpan(span);\n }\n });\n }\n\n private scanNode(node: HTMLElement): void {\n if (node.matches?.(TOOL_TITLE_SELECTOR) && isToolSummarySpan(node)) {\n this.processSpan(node);\n }\n\n const spans = node.querySelectorAll<HTMLElement>(TOOL_TITLE_SELECTOR);\n spans.forEach((span) => {\n if (isToolSummarySpan(span)) {\n this.processSpan(span);\n }\n });\n }\n\n private processSpan(span: HTMLElement): void {\n if (NonDestructiveTranslationMount.isMounted(span)) {\n const original = NonDestructiveTranslationMount.getOriginal(span);\n if (original) {\n const cached = clientCache.get(original);\n if (cached) return;\n }\n return;\n }\n\n const text = NonDestructiveTranslationMount.extractVisibleText(span);\n if (!text) return;\n\n // Check fast client cache\n const cached = clientCache.get(text);\n if (cached) {\n NonDestructiveTranslationMount.mount(span, cached, {\n originalText: text,\n });\n return;\n }\n\n // Send to viewport lazy queue\n lazyQueue.observe(span, text);\n }\n\n disconnect(): void {\n if (this.rootCheckTimer !== null) {\n clearInterval(this.rootCheckTimer);\n this.rootCheckTimer = null;\n }\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n lazyQueue.disconnect();\n this.rootElement = null;\n }\n}\n\nexport const chatTranslateObserver = new ChatTranslateObserver();\n", "import { useState, useEffect } from 'react';\nimport * as React from 'react';\nimport { settingsStore, type ClientSettingsState } from './store.ts';\nimport { SETTINGS_CSS } from './styles.ts';\nlet stylesInjected = false;\nfunction ensureSettingsStyles(): void {\n if (stylesInjected || typeof document === 'undefined') return;\n const el = document.createElement('style');\n el.dataset.tidySettings = 'true';\n el.textContent = SETTINGS_CSS;\n document.head.appendChild(el);\n stylesInjected = true;\n}\n\nfunction Switch(props: { checked: boolean; onChange: () => void; label: string }): React.ReactElement {\n return (\n <button\n type=\"button\"\n className=\"dsh-tidy-switch\"\n role=\"switch\"\n aria-checked={props.checked}\n onClick={props.onChange}\n aria-label={props.label}\n />\n );\n}\n\nexport function TidySettingsPanel(): React.ReactElement {\n ensureSettingsStyles();\n\n const [state, setState] = useState<ClientSettingsState>(() => settingsStore.getState());\n const [testing, setTesting] = useState<{ channel: string; running: boolean; ok?: boolean; message?: string } | null>(null);\n const [apiKeyInput, setApiKeyInput] = useState('');\n const [savingKey, setSavingKey] = useState(false);\n const [keyMsg, setKeyMsg] = useState<{ ok: boolean; text: string } | null>(null);\n\n useEffect(() => {\n return settingsStore.subscribe(() => {\n setState(settingsStore.getState());\n });\n }, []);\n\n const runTest = async (channel: string): Promise<void> => {\n setTesting({ channel, running: true });\n const res = await settingsStore.testChannel(channel);\n const message = res.ok\n ? `\u8FDE\u63A5\u6B63\u5E38\uFF0C\u5EF6\u8FDF ${res.latencyMs}ms`\n : `\u5931\u8D25\uFF1A${res.error || '\u672A\u77E5\u9519\u8BEF'}`;\n setTesting({ channel, running: false, ok: res.ok, message });\n };\n\n const handleSaveKey = async (): Promise<void> => {\n setSavingKey(true);\n setKeyMsg(null);\n const res = await settingsStore.saveApiKey(apiKeyInput);\n setSavingKey(false);\n if (res.ok) {\n const cleared = !apiKeyInput.trim();\n setKeyMsg({\n ok: true,\n text: cleared\n ? '\u5DF2\u6E05\u9664 API Key\uFF08AI \u901A\u9053\u5C06\u4E0D\u53EF\u7528\uFF0CBing \u515C\u5E95\uFF09'\n : '\u5DF2\u4FDD\u5B58\u5230 ~/.dsh/.credentials.yaml\uFF0C\u7ACB\u5373\u751F\u6548',\n });\n setApiKeyInput('');\n } else {\n setKeyMsg({ ok: false, text: `\u4FDD\u5B58\u5931\u8D25\uFF1A${res.error || '\u672A\u77E5\u9519\u8BEF'}` });\n }\n };\n\n return (\n <div className=\"dsh-tidy-settings\">\n {/* 1. \u603B\u5F00\u5173 */}\n <div className=\"dsh-tidy-card\">\n <div className=\"dsh-tidy-title\">\n <span>\u5DE5\u5177\u8C03\u7528\u4E0E\u601D\u8003\u6458\u8981\u7FFB\u8BD1</span>\n <Switch\n checked={state.enabled}\n onChange={() => settingsStore.update({ enabled: !state.enabled })}\n label=\"\u542F\u7528\u5DE5\u5177\u8C03\u7528\u4E0E\u6458\u8981\u7FFB\u8BD1\"\n />\n </div>\n <div className=\"dsh-tidy-desc\">\n \u81EA\u52A8\u5C06\u5F53\u524D\u4F1A\u8BDD\u4E2D\u5DE5\u5177\u8C03\u7528\u6807\u9898\u4E0E\u601D\u8003\u6298\u53E0\u6458\u8981\uFF08\u5982 <code>Locate DSH home directory structure</code>\uFF09\u7FFB\u8BD1\u4E3A\u4E2D\u6587\uFF0C\n \u70B9\u51FB\u8BD1\u6587\u53EF\u539F\u5730\u5207\u6362\u539F\u6587/\u8BD1\u6587\u3002\u4EC5\u4F5C\u7528\u4E8E\u5F53\u524D\u67E5\u770B\u7684\u4F1A\u8BDD\uFF0C\u5BF9\u8BDD\u6B63\u6587\u6C38\u4E0D\u7FFB\u8BD1\u3002\n </div>\n </div>\n\n {state.enabled && (\n <>\n {/* 2. AI \u901A\u9053 */}\n <div className=\"dsh-tidy-card\">\n <div className=\"dsh-tidy-title\">\n <span>AI \u7FFB\u8BD1\uFF08OpenAI \u517C\u5BB9\u534F\u8BAE\uFF09</span>\n <Switch\n checked={state.aiEnabled}\n onChange={() => settingsStore.update({ aiEnabled: !state.aiEnabled })}\n label=\"\u542F\u7528 AI \u7FFB\u8BD1\u901A\u9053\"\n />\n </div>\n <div className=\"dsh-tidy-desc\">\n <span className={`dsh-tidy-badge ${state.aiConfigured ? 'dsh-tidy-badge-ok' : 'dsh-tidy-badge-warn'}`}>\n {state.aiConfigured ? '\u5DF2\u914D\u7F6E' : '\u672A\u914D\u7F6E'}\n </span>{' '}\n \u672A\u914D\u7F6E\u65F6 AI \u901A\u9053\u81EA\u52A8\u8DF3\u8FC7\uFF0C\u7531 Bing \u515C\u5E95\u3002\n </div>\n\n {state.aiEnabled && (\n <>\n <div className=\"dsh-tidy-row\">\n <div className=\"dsh-tidy-row-info\">\n <div className=\"dsh-tidy-row-title\">API Key</div>\n <div className=\"dsh-tidy-row-desc\">\n \u4FDD\u5B58\u81F3 <code>~/.dsh/.credentials.yaml</code> \u7684 <code>TRANSLATE_API_KEY</code>\uFF0C\u4FDD\u5B58\u540E\u7ACB\u5373\u751F\u6548\uFF1B\u7559\u7A7A\u4FDD\u5B58 = \u6E05\u9664\n </div>\n </div>\n <div className=\"dsh-tidy-input-row\">\n <input\n type=\"password\"\n className=\"dsh-tidy-input\"\n placeholder={state.aiConfigured ? '\u5DF2\u914D\u7F6E\uFF08\u5982\u9700\u66F4\u6362\u8BF7\u76F4\u63A5\u8F93\u5165\uFF09' : 'sk-...'}\n value={apiKeyInput}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setApiKeyInput(e.target.value)}\n style={{ width: '260px' }}\n aria-label=\"API Key\"\n />\n <button type=\"button\" className=\"dsh-tidy-btn\" disabled={savingKey} onClick={handleSaveKey}>\n {savingKey ? '\u4FDD\u5B58\u4E2D\u2026' : '\u4FDD\u5B58'}\n </button>\n </div>\n </div>\n {keyMsg && (\n <div className={`dsh-tidy-test-result ${keyMsg.ok ? 'ok' : 'fail'}`}>{keyMsg.text}</div>\n )}\n\n <div className=\"dsh-tidy-row\">\n <div className=\"dsh-tidy-row-info\">\n <div className=\"dsh-tidy-row-title\">Base URL</div>\n <div className=\"dsh-tidy-row-desc\">\n \u4EFB\u610F OpenAI \u517C\u5BB9\u670D\u52A1\u7AEF\u70B9\uFF0C\u5982 <code>https://api.openai.com/v1</code>\u3001{' '}\n <code>https://api.deepseek.com/v1</code>\n </div>\n </div>\n <input\n type=\"text\"\n className=\"dsh-tidy-input\"\n placeholder=\"https://api.openai.com/v1\"\n value={state.baseUrl}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n settingsStore.update({ baseUrl: e.target.value })\n }\n style={{ width: '260px' }}\n aria-label=\"AI Base URL\"\n />\n </div>\n <div className=\"dsh-tidy-row\">\n <div className=\"dsh-tidy-row-info\">\n <div className=\"dsh-tidy-row-title\">\u6A21\u578B</div>\n <div className=\"dsh-tidy-row-desc\">\n \u5982 <code>gpt-4o-mini</code>\u3001<code>deepseek-chat</code>\uFF1B\u7559\u7A7A\u89C6\u4E3A\u672A\u914D\u7F6E\n </div>\n </div>\n <input\n type=\"text\"\n className=\"dsh-tidy-input\"\n placeholder=\"gpt-4o-mini\"\n value={state.model}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n settingsStore.update({ model: e.target.value })\n }\n style={{ width: '260px' }}\n aria-label=\"AI \u6A21\u578B\"\n />\n </div>\n <div className=\"dsh-tidy-row\">\n <button\n type=\"button\"\n className=\"dsh-tidy-btn\"\n disabled={testing?.running}\n onClick={() => runTest('openai')}\n >\n {testing?.running ? '\u6D4B\u8BD5\u4E2D\u2026' : '\u6D4B\u8BD5 AI \u901A\u9053'}\n </button>\n {testing?.channel === 'openai' && !testing.running && (\n <span className={`dsh-tidy-test-result ${testing.ok ? 'ok' : 'fail'}`}>{testing.message}</span>\n )}\n </div>\n </>\n )}\n </div>\n\n {/* 3. Bing \u901A\u9053 */}\n <div className=\"dsh-tidy-card\">\n <div className=\"dsh-tidy-title\">\n <span>Bing \u7F51\u9875\u7FFB\u8BD1\uFF08\u514D Key \u515C\u5E95\uFF09</span>\n <Switch\n checked={state.bingEnabled}\n onChange={() => settingsStore.update({ bingEnabled: !state.bingEnabled })}\n label=\"\u542F\u7528 Bing \u7FFB\u8BD1\u901A\u9053\"\n />\n </div>\n <div className=\"dsh-tidy-desc\">\n \u5185\u7F6E\u514D Key \u7FFB\u8BD1\u901A\u9053\uFF0C\u65E0\u9700\u4EFB\u4F55\u914D\u7F6E\u3002AI \u672A\u914D\u7F6E\u6216\u8BF7\u6C42\u5931\u8D25\u65F6\u81EA\u52A8\u515C\u5E95\uFF1BAI \u4E0E Bing \u540C\u65F6\u5173\u95ED\u5219\u4E0D\u7FFB\u8BD1\u3002\n </div>\n </div>\n\n {/* 4. \u884C\u4E3A\u8BF4\u660E */}\n <div className=\"dsh-tidy-card\">\n <div className=\"dsh-tidy-row-title\">\u901A\u9053\u884C\u4E3A</div>\n <ul className=\"dsh-tidy-desc dsh-tidy-behavior-list\">\n <li>AI \u5F00\u542F\u4E14\u5DF2\u914D\u7F6E \u2192 AI \u4F18\u5148\u7FFB\u8BD1\uFF0C\u5931\u8D25\u81EA\u52A8\u964D\u7EA7 Bing</li>\n <li>AI \u5F00\u542F\u4F46\u672A\u914D\u7F6E + Bing \u5F00\u542F \u2192 \u7531 Bing \u7FFB\u8BD1</li>\n <li>AI \u5F00\u542F\u4F46\u672A\u914D\u7F6E + Bing \u5173\u95ED \u2192 \u4E0D\u7FFB\u8BD1</li>\n <li>AI \u5173\u95ED + Bing \u5F00\u542F \u2192 \u76F4\u63A5\u4F7F\u7528 Bing</li>\n <li>AI \u5173\u95ED + Bing \u5173\u95ED \u2192 \u4E0D\u7FFB\u8BD1</li>\n </ul>\n </div>\n\n {/* 5. \u5E76\u53D1\u63A7\u5236 */}\n <div className=\"dsh-tidy-card\">\n <div className=\"dsh-tidy-row\">\n <div className=\"dsh-tidy-row-info\">\n <div className=\"dsh-tidy-row-title\">\u6700\u5927\u7FFB\u8BD1\u5E76\u53D1\u6570</div>\n <div className=\"dsh-tidy-row-desc\">\n \u63A7\u5236\u89C6\u53E3\u6EDA\u52A8\u4E0E\u591A\u5DE5\u5177\u5361\u7247\u65F6\u7684\u6700\u5927\u5E76\u884C\u8BF7\u6C42\u6570\uFF08\u8303\u56F4 1-100\uFF0C\u63A8\u8350 3\uFF09\u3002\n </div>\n </div>\n <input\n type=\"number\"\n className=\"dsh-tidy-input\"\n min={1}\n max={100}\n step={1}\n value={state.concurrency}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => {\n const val = parseInt(e.target.value, 10);\n if (!Number.isFinite(val)) return;\n settingsStore.update({ concurrency: Math.min(Math.max(val, 1), 100) });\n }}\n style={{ width: '88px' }}\n aria-label=\"\u6700\u5927\u7FFB\u8BD1\u5E76\u53D1\u6570\"\n />\n </div>\n </div>\n </>\n )}\n </div>\n );\n}\n\nexport function setupSettingsUi(ctx: any): void {\n if (typeof window === 'undefined') return;\n try {\n const slots = ctx?.slots || (ctx?.get ? ctx.get('slots') : null);\n if (!slots || typeof slots.inject !== 'function') return;\n\n slots.inject('settings.section', () => {\n return slots.register(\n {\n name: 'settings.section',\n id: 'dsh-chat-translate',\n order: 5,\n label: () => '\u804A\u5929\u7FFB\u8BD1',\n },\n TidySettingsPanel\n );\n });\n } catch (err) {\n console.warn('[dsh-chat-translate] Failed to inject settings section:', err);\n }\n}\n", "import { fetchServerConfig, updateServerConfig, testServerChannel, saveCredentials } from '../translate/api.ts';\nimport { chatTranslateObserver } from '../translate/observer.ts';\n\nexport interface ClientSettingsState {\n enabled: boolean;\n concurrency: number;\n aiEnabled: boolean;\n bingEnabled: boolean;\n baseUrl: string;\n model: string;\n aiConfigured: boolean;\n}\n\nconst LS_PREFIX = 'dsh-chat-translate:';\nexport const LS_ENABLED = `${LS_PREFIX}enabled`;\nexport const LS_CONCURRENCY = `${LS_PREFIX}concurrency`;\nexport const LS_AI_ENABLED = `${LS_PREFIX}aiEnabled`;\nexport const LS_BING_ENABLED = `${LS_PREFIX}bingEnabled`;\nexport const LS_BASE_URL = `${LS_PREFIX}baseUrl`;\nexport const LS_MODEL = `${LS_PREFIX}model`;\n\nconst DEFAULT_STATE: ClientSettingsState = {\n enabled: true,\n concurrency: 3,\n aiEnabled: true,\n bingEnabled: true,\n baseUrl: '',\n model: '',\n aiConfigured: false,\n};\n\nclass SettingsStore {\n private state: ClientSettingsState = { ...DEFAULT_STATE };\n\n private listeners = new Set<() => void>();\n private storageListener: ((e: StorageEvent) => void) | null = null;\n private pushTimer: number | null = null;\n private pushSeq = 0;\n private userTouched = false;\n\n constructor() {\n this.loadFromLocalStorage();\n this.initStorageListener();\n this.syncFromServer();\n }\n\n private loadFromLocalStorage(): void {\n if (typeof localStorage === 'undefined') return;\n try {\n const enabledRaw = localStorage.getItem(LS_ENABLED);\n if (enabledRaw !== null) {\n this.state.enabled = enabledRaw === 'true';\n }\n const concurrencyRaw = localStorage.getItem(LS_CONCURRENCY);\n if (concurrencyRaw !== null) {\n const c = parseInt(concurrencyRaw, 10);\n if (Number.isFinite(c) && c >= 1 && c <= 100) {\n this.state.concurrency = c;\n }\n }\n const aiRaw = localStorage.getItem(LS_AI_ENABLED);\n if (aiRaw !== null) {\n this.state.aiEnabled = aiRaw === 'true';\n }\n const bingRaw = localStorage.getItem(LS_BING_ENABLED);\n if (bingRaw !== null) {\n this.state.bingEnabled = bingRaw === 'true';\n }\n const baseUrlRaw = localStorage.getItem(LS_BASE_URL);\n if (baseUrlRaw !== null) {\n this.state.baseUrl = baseUrlRaw;\n }\n const modelRaw = localStorage.getItem(LS_MODEL);\n if (modelRaw !== null) {\n this.state.model = modelRaw;\n }\n } catch {\n // Ignore storage access errors\n }\n try {\n chatTranslateObserver.setEnabled(this.state.enabled);\n } catch {}\n }\n\n private initStorageListener(): void {\n if (typeof window === 'undefined' || typeof window.addEventListener !== 'function') return;\n this.storageListener = (e: StorageEvent) => {\n if (!e.key || !e.key.startsWith(LS_PREFIX)) return;\n let changed = false;\n if (e.key === LS_ENABLED && e.newValue !== null) {\n const val = e.newValue === 'true';\n if (this.state.enabled !== val) {\n this.state.enabled = val;\n chatTranslateObserver.setEnabled(val);\n changed = true;\n }\n } else if (e.key === LS_CONCURRENCY && e.newValue !== null) {\n const c = parseInt(e.newValue, 10);\n if (Number.isFinite(c) && c >= 1 && c <= 100 && this.state.concurrency !== c) {\n this.state.concurrency = c;\n changed = true;\n }\n } else if (e.key === LS_AI_ENABLED && e.newValue !== null) {\n const val = e.newValue === 'true';\n if (this.state.aiEnabled !== val) {\n this.state.aiEnabled = val;\n changed = true;\n }\n } else if (e.key === LS_BING_ENABLED && e.newValue !== null) {\n const val = e.newValue === 'true';\n if (this.state.bingEnabled !== val) {\n this.state.bingEnabled = val;\n changed = true;\n }\n } else if (e.key === LS_BASE_URL && e.newValue !== null && this.state.baseUrl !== e.newValue) {\n this.state.baseUrl = e.newValue;\n changed = true;\n } else if (e.key === LS_MODEL && e.newValue !== null && this.state.model !== e.newValue) {\n this.state.model = e.newValue;\n changed = true;\n }\n if (changed) {\n this.notify();\n this.schedulePush();\n }\n };\n window.addEventListener('storage', this.storageListener);\n }\n\n private async syncFromServer(): Promise<void> {\n try {\n const config = await fetchServerConfig();\n if (config) {\n // If the user already edited something before the first server\n // snapshot arrived, keep their values \u2014 otherwise the echo would\n // overwrite the edit and (since no push is queued for it) it would be\n // lost forever. aiConfigured is a server-derived status, always safe.\n const touched = this.userTouched;\n this.state = {\n enabled: !touched && typeof config.enabled === 'boolean' ? config.enabled : this.state.enabled,\n concurrency:\n !touched && typeof config.concurrency === 'number' && Number.isFinite(config.concurrency)\n ? config.concurrency\n : this.state.concurrency,\n aiEnabled: !touched && typeof config.aiEnabled === 'boolean' ? config.aiEnabled : this.state.aiEnabled,\n bingEnabled: !touched && typeof config.bingEnabled === 'boolean' ? config.bingEnabled : this.state.bingEnabled,\n baseUrl: !touched && typeof config.baseUrl === 'string' ? config.baseUrl : this.state.baseUrl,\n model: !touched && typeof config.model === 'string' ? config.model : this.state.model,\n aiConfigured: typeof config.aiConfigured === 'boolean' ? config.aiConfigured : this.state.aiConfigured,\n };\n chatTranslateObserver.setEnabled(this.state.enabled);\n this.notify();\n }\n } catch {\n // Host route may be unavailable during early boot \u2014 keep local defaults.\n }\n }\n\n getState(): ClientSettingsState {\n return { ...this.state };\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n private notify(): void {\n this.listeners.forEach((l) => {\n try {\n l();\n } catch {}\n });\n }\n\n /**\n * Debounced server push: fast typing in the baseUrl/model/concurrency inputs\n * collapses into a single POST (300ms trailing). A monotonic sequence number\n * ensures an out-of-order older response never overwrites newer state.\n */\n private schedulePush(): void {\n if (this.pushTimer !== null || typeof window === 'undefined') return;\n this.pushTimer = window.setTimeout(() => {\n this.pushTimer = null;\n this.pushToServer();\n }, 300);\n }\n\n private async pushToServer(): Promise<void> {\n const seq = ++this.pushSeq;\n const sent = {\n enabled: this.state.enabled,\n concurrency: this.state.concurrency,\n aiEnabled: this.state.aiEnabled,\n bingEnabled: this.state.bingEnabled,\n baseUrl: this.state.baseUrl,\n model: this.state.model,\n };\n try {\n const updated = await updateServerConfig(sent);\n if (!updated || seq !== this.pushSeq) return; // superseded by a newer push\n // Per-field echo guard: only write back fields the user has NOT edited\n // since this request was sent. Otherwise a slow response could clobber a\n // newer local edit (a later push is already queued with the new value).\n this.state = {\n ...this.state,\n enabled:\n this.state.enabled === sent.enabled && typeof updated.enabled === 'boolean'\n ? updated.enabled\n : this.state.enabled,\n concurrency:\n this.state.concurrency === sent.concurrency && typeof updated.concurrency === 'number'\n ? updated.concurrency\n : this.state.concurrency,\n aiEnabled:\n this.state.aiEnabled === sent.aiEnabled && typeof updated.aiEnabled === 'boolean'\n ? updated.aiEnabled\n : this.state.aiEnabled,\n bingEnabled:\n this.state.bingEnabled === sent.bingEnabled && typeof updated.bingEnabled === 'boolean'\n ? updated.bingEnabled\n : this.state.bingEnabled,\n baseUrl:\n this.state.baseUrl === sent.baseUrl && typeof updated.baseUrl === 'string'\n ? updated.baseUrl\n : this.state.baseUrl,\n model:\n this.state.model === sent.model && typeof updated.model === 'string'\n ? updated.model\n : this.state.model,\n aiConfigured: typeof updated.aiConfigured === 'boolean' ? updated.aiConfigured : this.state.aiConfigured,\n };\n this.notify();\n } catch {\n // Host route may be unavailable \u2014 keep local state.\n }\n }\n\n async update(partial: Partial<ClientSettingsState>): Promise<void> {\n this.userTouched = true;\n let sanitizedConcurrency = this.state.concurrency;\n if (typeof partial.concurrency === 'number') {\n if (Number.isFinite(partial.concurrency)) {\n sanitizedConcurrency = Math.min(Math.max(Math.round(partial.concurrency), 1), 100);\n }\n }\n\n this.state = {\n ...this.state,\n ...partial,\n concurrency: sanitizedConcurrency,\n };\n\n if (typeof partial.enabled === 'boolean') {\n try {\n localStorage.setItem(LS_ENABLED, String(partial.enabled));\n } catch {}\n chatTranslateObserver.setEnabled(partial.enabled);\n }\n if (typeof partial.concurrency === 'number' && Number.isFinite(partial.concurrency)) {\n try {\n localStorage.setItem(LS_CONCURRENCY, String(sanitizedConcurrency));\n } catch {}\n }\n if (typeof partial.aiEnabled === 'boolean') {\n try {\n localStorage.setItem(LS_AI_ENABLED, String(partial.aiEnabled));\n } catch {}\n }\n if (typeof partial.bingEnabled === 'boolean') {\n try {\n localStorage.setItem(LS_BING_ENABLED, String(partial.bingEnabled));\n } catch {}\n }\n if (typeof partial.baseUrl === 'string') {\n try {\n localStorage.setItem(LS_BASE_URL, partial.baseUrl);\n } catch {}\n }\n if (typeof partial.model === 'string') {\n try {\n localStorage.setItem(LS_MODEL, partial.model);\n } catch {}\n }\n\n this.notify();\n this.schedulePush();\n }\n\n async testChannel(channel: string): Promise<{ ok: boolean; latencyMs: number; error?: string }> {\n return testServerChannel(channel);\n }\n\n /** Persist the API key via the host and refresh the server-derived status. */\n async saveApiKey(apiKey: string): Promise<{ ok: boolean; error?: string }> {\n const res = await saveCredentials(apiKey);\n if (res.ok) {\n await this.syncFromServer();\n }\n return { ok: Boolean(res.ok), error: res.error };\n }\n\n /** Re-pull the server config (e.g. after the API key changed). */\n async refreshFromServer(): Promise<void> {\n await this.syncFromServer();\n }\n\n dispose(): void {\n if (this.pushTimer !== null && typeof window !== 'undefined') {\n clearTimeout(this.pushTimer);\n this.pushTimer = null;\n }\n if (this.storageListener && typeof window !== 'undefined') {\n window.removeEventListener('storage', this.storageListener);\n this.storageListener = null;\n }\n this.listeners.clear();\n }\n}\n\nexport const settingsStore = new SettingsStore();\n", "export const SETTINGS_CSS = String.raw`\n.dsh-tidy-settings {\n display: flex;\n flex-direction: column;\n gap: 16px;\n max-width: 580px;\n padding-bottom: 32px;\n color: var(--dsw-alias-label-primary, inherit);\n font-family: inherit;\n}\n\n.dsh-tidy-card {\n border: 1px solid var(--dsw-alias-border-l2, rgba(128, 128, 128, 0.2));\n border-radius: 12px;\n padding: 16px 18px;\n background: var(--dsw-alias-bg-card, rgba(128, 128, 128, 0.05));\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.dsh-tidy-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary, inherit);\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.dsh-tidy-desc {\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-secondary, rgba(128, 128, 128, 0.8));\n}\n\n.dsh-tidy-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 14px;\n padding: 8px 0;\n}\n\n.dsh-tidy-row + .dsh-tidy-row {\n border-top: 1px solid var(--dsw-alias-border-l3, rgba(128, 128, 128, 0.1));\n}\n\n.dsh-tidy-row-info {\n flex: 1;\n min-width: 0;\n}\n\n.dsh-tidy-row-title {\n font-size: 13px;\n font-weight: 500;\n}\n\n.dsh-tidy-row-desc {\n font-size: 11px;\n color: var(--dsw-alias-label-secondary, rgba(128, 128, 128, 0.7));\n margin-top: 2px;\n line-height: 1.4;\n}\n\n/* Switch */\n.dsh-tidy-switch {\n position: relative;\n width: 38px;\n height: 22px;\n flex: none;\n cursor: pointer;\n border-radius: 999px;\n border: none;\n background: rgba(128, 128, 128, 0.3);\n transition: background 0.15s ease;\n padding: 0;\n outline: none;\n}\n\n.dsh-tidy-switch[aria-checked=\"true\"] {\n background: #3b82f6;\n}\n\n.dsh-tidy-switch::after {\n content: \"\";\n position: absolute;\n top: 2px;\n left: 2px;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: #ffffff;\n transition: transform 0.15s ease;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);\n}\n\n.dsh-tidy-switch[aria-checked=\"true\"]::after {\n transform: translateX(16px);\n}\n\n/* Inputs */\n.dsh-tidy-input-group {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.dsh-tidy-label {\n font-size: 12px;\n font-weight: 500;\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.dsh-tidy-input-row {\n display: flex;\n gap: 8px;\n}\n\n.dsh-tidy-input {\n flex: 1;\n min-width: 0;\n padding: 8px 12px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2, rgba(128, 128, 128, 0.25));\n background: var(--dsw-alias-bg-input, rgba(0, 0, 0, 0.05));\n color: inherit;\n font-size: 12px;\n outline: none;\n transition: border-color 0.15s;\n}\n\n.dsh-tidy-input:focus {\n border-color: #3b82f6;\n}\n\n.dsh-tidy-btn {\n padding: 6px 14px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2, rgba(128, 128, 128, 0.3));\n background: transparent;\n color: inherit;\n font-size: 12px;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n}\n\n.dsh-tidy-btn:hover {\n background: rgba(128, 128, 128, 0.1);\n border-color: rgba(128, 128, 128, 0.5);\n}\n\n.dsh-tidy-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.dsh-tidy-badge {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 500;\n}\n\n.dsh-tidy-badge-ok {\n background: rgba(34, 197, 94, 0.15);\n color: #22c55e;\n}\n\n.dsh-tidy-badge-none {\n background: rgba(156, 163, 175, 0.15);\n color: #9ca3af;\n}\n\n.dsh-tidy-badge-warn {\n background: rgba(245, 158, 11, 0.15);\n color: #f59e0b;\n}\n\n.dsh-tidy-test-result {\n font-size: 12px;\n margin-left: 10px;\n}\n\n.dsh-tidy-test-result.ok {\n color: #22c55e;\n}\n\n.dsh-tidy-test-result.fail {\n color: #ef4444;\n}\n\n.dsh-tidy-behavior-list {\n padding-left: 18px;\n margin: 4px 0 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n/* Priority list */\n.dsh-tidy-priority-list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.dsh-tidy-priority-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n border-radius: 8px;\n background: rgba(128, 128, 128, 0.06);\n border: 1px solid var(--dsw-alias-border-l3, rgba(128, 128, 128, 0.12));\n}\n\n.dsh-tidy-priority-name {\n font-size: 12px;\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.dsh-tidy-order-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: #3b82f6;\n color: #ffffff;\n font-size: 11px;\n font-weight: 600;\n}\n\n.dsh-tidy-btn-group {\n display: flex;\n gap: 4px;\n}\n\n.dsh-tidy-icon-btn {\n width: 26px;\n height: 26px;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 6px;\n border: 1px solid rgba(128, 128, 128, 0.2);\n background: transparent;\n color: inherit;\n cursor: pointer;\n font-size: 12px;\n}\n\n.dsh-tidy-icon-btn:hover:not(:disabled) {\n background: rgba(128, 128, 128, 0.15);\n}\n\n.dsh-tidy-icon-btn:disabled {\n opacity: 0.3;\n cursor: default;\n}\n\n/* Slider / Select */\n.dsh-tidy-select {\n padding: 6px 10px;\n border-radius: 8px;\n border: 1px solid var(--dsw-alias-border-l2, rgba(128, 128, 128, 0.3));\n background: var(--dsw-alias-bg-input, rgba(0, 0, 0, 0.05));\n color: inherit;\n font-size: 12px;\n outline: none;\n}\n`;\n"],
5
+ "mappings": "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gB,IAAI,cAAc;;;AClUxC,IAAM,eAAe,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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",
6
+ "names": ["cached"]
7
+ }