@klarkxy/dsh-model-picker 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"client.inner.cjs","names":["useRef","useState","useId","useMemo","rankByName","observeStickyMenuGroups","createPortal","MenuSurface","IconChevronRightOutlineRegular","Input","IconCloseFillRegular","IconCheckOutlineRegular","MenuGroup","isValidElement","cloneElement","IconDataOutlineRegular","StateDot","IconChevronDownOutlineRegular","useState","useRef","useMemo","useCallback","useSyncExternalStore","Toast","IconWarningOutlineRegular"],"sources":["../../dsh-model-route/src/menu.ts","../../dsh-model-route/src/ui.tsx","../../dsh-model-route/src/model-picker.ts","../src/effort-preference.ts","../src/client.tsx"],"sourcesContent":["/**\n * Pure menu helpers over parsed catalog choices: provider grouping, display\n * names and search filtering. Pure and browser-safe like the rest of the core\n * entry — no React, no host imports. The popover component lives in `./ui.tsx`.\n */\nimport type { ModelMenuChoice } from './catalog.ts'\n\n/** Localize standard effort ids only when the provider has not supplied a display name. */\nexport function modelMenuEffortLabel(effort: { id: string; name: string }, locale?: string): string {\n if (effort.name !== effort.id) return effort.name\n const labels: Record<string, readonly [string, string]> = {\n off: ['关闭', 'Off'], none: ['无', 'None'], minimal: ['最低', 'Minimal'], low: ['低', 'Low'],\n medium: ['中', 'Medium'], high: ['高', 'High'], xhigh: ['极高', 'Extra high'],\n max: ['最高', 'Maximum'], ultra: ['超高', 'Ultra'],\n }\n return labels[effort.id]?.[locale?.toLowerCase().startsWith('zh') ? 0 : 1] ?? effort.name\n}\n\n/** One provider group in the menu, in catalog order, after applying the search query. */\nexport interface ModelMenuGroup {\n readonly provider: string\n /** Provider display name, from the catalog group or split from the \"Provider / Model\" label. */\n readonly name: string\n readonly items: readonly ModelMenuChoice[]\n}\n\n/** The short model label shown inside a provider group. */\nexport function modelMenuShortName(choice: ModelMenuChoice): string {\n const sep = choice.label.indexOf(' / ')\n return sep > 0 ? choice.label.slice(sep + 3) : choice.model\n}\n\n/** Group catalog choices by provider and filter them by a case-insensitive query. */\nexport function groupModelMenuChoices(choices: readonly ModelMenuChoice[], query: string): ModelMenuGroup[] {\n const needle = query.trim().toLowerCase()\n const matched = needle\n ? choices.filter(choice => choice.label.toLowerCase().includes(needle)\n || choice.model.toLowerCase().includes(needle)\n || choice.provider.toLowerCase().includes(needle)\n // The provider display name is a separate search channel: a catalog may\n // name a provider differently from its id, and callers search by name.\n || (choice.providerLabel?.toLowerCase().includes(needle) ?? false))\n : choices\n const groups: Array<{ provider: string; name: string; items: ModelMenuChoice[] }> = []\n for (const choice of matched) {\n const sep = choice.label.indexOf(' / ')\n const name = choice.providerLabel ?? (sep > 0 ? choice.label.slice(0, sep) : choice.provider)\n const last = groups.at(-1)\n if (last && last.provider === choice.provider) last.items.push(choice)\n else groups.push({ provider: choice.provider, name, items: [choice] })\n }\n return groups\n}\n","/**\n * ModelMenu: the standard editor of one model-route field — the visible half\n * of the x-model-route contract. A feature plugin's settings page renders it\n * for its own marked field; the model hub renders one per detected field.\n *\n * It is a plugin-side copy of the host's composer model picker\n * (dsh-client-ui-model-selection's ModelSelect), rebuilt from the official\n * primitives and the published bundle's behavior: one card that opens on the\n * root pane (Model / Effort cells), drills into the provider-grouped,\n * searchable model list or the effort list, and Escapes back before closing.\n * Sticky group headings, subsequence ranking, highlight walking and focus\n * hand-back all match the host. SYNC POINT: when the host's ModelSelect or\n * ModelSelect.module.css changes, this copy must be re-transcribed; styles\n * below may only reference allowlisted theme tokens (the --dsw-* set plus the\n * host's --ds-* motion tokens), never literal colors.\n *\n * It statically imports the primitives, so only browser clients should load\n * this entry; host code and node tests use the core entry (`./index.ts`).\n */\nimport { cloneElement, isValidElement, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, type CSSProperties, type ReactNode } from 'react'\nimport { createPortal } from 'react-dom'\nimport {\n IconCheckOutlineRegular, IconChevronRightOutlineRegular, IconCloseFillRegular, Input, MenuGroup, MenuSurface,\n observeStickyMenuGroups, rankByName,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nexport { useModelCatalog, ModelCatalogStatus } from './catalog-ui.tsx'\nexport type { UseModelCatalogOptions, ModelCatalogState, ModelCatalogStatusProps } from './catalog-ui.tsx'\nimport type { ModelMenuChoice } from './catalog.ts'\nimport { groupModelMenuChoices, modelMenuEffortLabel, modelMenuShortName } from './menu.ts'\n\n/** Extra rows rendered above the model groups (e.g. a plugin's \"follow\"/\"off\" modes). */\nexport interface ModelMenuLeadingItem {\n readonly id: string\n readonly label: ReactNode\n readonly selected?: boolean\n}\n\nexport interface ModelMenuProps {\n /** Active host locale, supplied by the owning plugin's live locale subscription. */\n readonly locale?: string\n readonly open: boolean\n readonly onOpenChange: (open: boolean) => void\n /** Trigger rendered in place; the menu anchors to it and returns focus to it. */\n readonly anchor: ReactNode\n readonly choices: readonly ModelMenuChoice[]\n readonly selected?: { readonly provider: string; readonly model: string }\n readonly onPick: (route: { provider: string; model: string }) => void\n readonly leading?: readonly ModelMenuLeadingItem[]\n readonly onPickLeading?: (id: string) => void\n /** Effort pane rows; the root Effort cell is hidden while this is empty. */\n readonly efforts?: ReadonlyArray<{ id: string; name: string }>\n readonly selectedEffort?: string\n readonly onPickEffort?: (effort: string | undefined) => void\n /** Root-cell labels and the values shown trailing them. */\n readonly modelLabel?: string\n readonly modelValue?: string\n readonly effortLabel?: string\n readonly effortValue?: string\n readonly defaultEffortLabel?: string\n readonly searchPlaceholder?: string\n readonly emptyLabel?: string\n readonly clearSearchLabel?: string\n /** Pane the menu opens on; default 'root'. 'model' opens the searchable model list directly. */\n readonly initialPane?: 'root' | 'model'\n /** Show the model search row even when the catalog has four or fewer choices. */\n readonly alwaysShowSearch?: boolean\n /**\n * Render the declared reasoning efforts as a discrete slider inside the model\n * pane. Additive: the effort list and the root Effort cell stay for the\n * default (false) mode, and only the caller-supplied effort rows are shown.\n */\n readonly reasoningSlider?: boolean\n /**\n * Optional banner rendered at the top of the menu card, above the search and\n * list — e.g. a directory status/error row. Pure library-local React content,\n * not a cross-factory data contract.\n */\n readonly menuHeader?: ReactNode\n /** Disable every action after opening; by default a true value also closes\n * the menu (closeOnDisable). */\n readonly disabled?: boolean\n /**\n * Submission in progress. Keeps the menu open (unlike `disabled`) and still\n * allows opening/closing and typing in search, but disables selection rows\n * and blocks repeated model/leading/effort/slider submissions.\n */\n readonly busy?: boolean\n /**\n * Close the card after a model pick. Default true (drill menus dismiss).\n * The composer picker sets false so a selection does not unmount the open\n * list — search and scroll belong to that card.\n */\n readonly closeOnPick?: boolean\n /**\n * Close the open card when `disabled` rises. Default true — a hard lock\n * dismisses. Keep-open callers (the composer picker) set false: an owner's\n * save-state \"disabled\" pulse gates actions without unmounting the open\n * list, and Escape/outside presses still dismiss while disabled.\n */\n readonly closeOnDisable?: boolean\n readonly className?: string\n /** Extra class on the portaled menu card, which renders under document.body. */\n readonly listClassName?: string\n}\n\ntype Pane = 'root' | 'model' | 'effort'\n\n/** Unplaced portal card: hidden but laid out at a fixed origin so measurements are real. */\nconst MEASURE_STYLE: CSSProperties = { visibility: 'hidden', left: 0, top: 0 }\n\nexport function ModelMenu(props: ModelMenuProps) {\n const language = props.locale?.toLowerCase().startsWith('zh') ? 'zh' : 'en'\n const copy = language === 'zh'\n ? { model: '模型', effort: '思考强度', default: '默认', search: '搜索模型…', empty: '没有匹配的模型', clear: '清除搜索' }\n : { model: 'Model', effort: 'Reasoning', default: 'Default', search: 'Search models…', empty: 'No matching models', clear: 'Clear search' }\n const {\n open, onOpenChange, anchor, choices, selected, onPick,\n leading = [], onPickLeading, efforts = [], selectedEffort, onPickEffort,\n modelLabel = copy.model, modelValue = '—', effortLabel = copy.effort, effortValue, defaultEffortLabel = copy.default,\n searchPlaceholder = copy.search, emptyLabel = copy.empty, clearSearchLabel = copy.clear,\n initialPane = 'root', alwaysShowSearch = false, reasoningSlider = false,\n menuHeader, disabled = false, busy = false, closeOnPick = true, closeOnDisable = true,\n className, listClassName,\n } = props\n const rootRef = useRef<HTMLSpanElement | null>(null)\n const openRef = useRef(open)\n openRef.current = open\n const pendingOpenRef = useRef(false)\n const pendingRestoreFocus = useRef(false)\n const [requestedOpen, setRequestedOpen] = useState(false)\n const menuRef = useRef<HTMLDivElement | null>(null)\n const groupsRef = useRef<HTMLDivElement | null>(null)\n const searchRef = useRef<HTMLInputElement | null>(null)\n const itemRefs = useRef<Array<HTMLButtonElement | null>>([])\n const paneFocus = useRef<Pane | 'drill' | null>(null)\n const [pane, setPane] = useState<Pane>('root')\n const [query, setQuery] = useState('')\n const [highlightedIndex, setHighlightedIndex] = useState<number | null>(null)\n /* Keyboard arrows only. Mouse focus and a rebuilt choices array must not scroll. */\n const [keyNav, setKeyNav] = useState(0)\n const [menuPos, setMenuPos] = useState<CSSProperties | null>(null)\n const id = useId()\n const showSearch = alwaysShowSearch || choices.length > 4\n const effortRows = useMemo(() => [{ id: '', name: defaultEffortLabel }, ...efforts.map(effort => ({ ...effort, name: modelMenuEffortLabel(effort, language) }))], [defaultEffortLabel, efforts, language])\n /* The official ranks each provider group by a case-insensitive ordered\n * subsequence (prefix hits first, then alignment score, then catalog order);\n * groups left empty by the query drop out. */\n const filteredGroups = useMemo(() => groupModelMenuChoices(choices, '').map(group => ({\n ...group,\n items: rankByName(group.items.map(choice => ({\n choice,\n name: modelMenuShortName(choice),\n // The match surface deliberately carries the provider id, provider display\n // name, model id and the full \"Provider / Model\" label — never only the\n // possibly-truncated short model name — so provider and model-id searches\n // resolve while the rendered name stays short.\n label: [choice.provider, choice.providerLabel, choice.model, choice.label].filter(Boolean).join(' '),\n })), showSearch ? query.trim() : ''),\n })).filter(group => group.items.length > 0), [choices, query, showSearch])\n const visibleModels = useMemo(() => filteredGroups.flatMap(group => group.items.map(item => item.choice)), [filteredGroups])\n const currentVisibleIndex = visibleModels.findIndex(choice => choice.provider === selected?.provider && choice.model === selected.model)\n const activeModelIndex = Math.min(highlightedIndex ?? Math.max(0, currentVisibleIndex), visibleModels.length - 1)\n const changeOpen = (next: boolean): void => {\n if (openRef.current === next) return\n openRef.current = next\n onOpenChange(next)\n }\n const requestOpen = (): void => {\n if (open || pendingOpenRef.current) return\n pendingOpenRef.current = true\n pendingRestoreFocus.current = false\n setRequestedOpen(true)\n }\n const close = (restoreFocus = false): void => {\n const active = document.activeElement\n pendingRestoreFocus.current = restoreFocus && (active === document.body\n || rootRef.current?.contains(active) === true || menuRef.current?.contains(active) === true)\n changeOpen(false)\n }\n const drill = (next: Pane): void => {\n setQuery('')\n setHighlightedIndex(null)\n paneFocus.current = 'drill'\n setPane(next)\n }\n /** Leave a drilled pane for the entry pane, handing the keyboard back to it.\n * A root entry refocuses the cell that opened the pane; a search-first\n * (model) entry refocuses that pane's own intent. */\n const back = (from: Pane): void => {\n paneFocus.current = initialPane === 'root' ? from : 'drill'\n setPane(initialPane)\n }\n const moveFocus = (offset: number): void => {\n const items = itemRefs.current.filter((item): item is HTMLButtonElement => item !== null && !item.disabled)\n if (!items.length) return\n const active = items.findIndex(item => item === document.activeElement)\n items[active === -1 ? (offset > 0 ? 0 : items.length - 1) : (active + offset + items.length) % items.length]?.focus()\n }\n\n // A selection can synchronously disable its trigger while the owner writes.\n // Retry on the owner's next render, once the native button can take focus.\n useLayoutEffect(() => {\n if (open || !pendingRestoreFocus.current) return\n const active = document.activeElement\n if (active !== document.body && !rootRef.current?.contains(active)) {\n pendingRestoreFocus.current = false\n return\n }\n const trigger = rootRef.current?.querySelector('button')\n if (!trigger || trigger.disabled) return\n trigger.focus()\n if (document.activeElement === trigger) pendingRestoreFocus.current = false\n })\n useEffect(() => {\n if (open || !pendingRestoreFocus.current) return\n const cancelOutside = (event: Event): void => {\n if (event.target instanceof Node && !rootRef.current?.contains(event.target)) pendingRestoreFocus.current = false\n }\n document.addEventListener('focusin', cancelOutside)\n document.addEventListener('pointerdown', cancelOutside)\n return () => {\n document.removeEventListener('focusin', cancelOutside)\n document.removeEventListener('pointerdown', cancelOutside)\n }\n })\n\n useEffect(() => {\n if (!requestedOpen) return\n pendingOpenRef.current = false\n setRequestedOpen(false)\n // The caller's trigger handler may also update the controlled open prop.\n // Check the committed state before supplying the missing open callback.\n if (!open) changeOpen(true)\n }, [requestedOpen, open])\n\n useEffect(() => {\n if (!open) return\n // A consumer may open directly at the model pane (a search-first picker).\n // The root cells stay reachable with Escape; the default stays 'root' and\n // leaves the trigger's keyboard focus intent untouched.\n setPane(initialPane)\n if (initialPane === 'model') paneFocus.current = 'drill'\n setQuery('')\n setHighlightedIndex(null)\n }, [open, initialPane])\n // A consumer that becomes busy/locked after opening must not leave actions\n // available. With closeOnDisable a true value also closes the card (the\n // trigger owns the disabled look); without it the open card stays mounted\n // and only dismissal stays available.\n useEffect(() => {\n if (disabled && open && closeOnDisable) changeOpen(false)\n }, [disabled, open, closeOnDisable])\n useEffect(() => {\n if (!open) return\n const closeOutside = (event: MouseEvent): void => {\n const target = event.target as Node\n if (rootRef.current?.contains(target) || menuRef.current?.contains(target)) return\n changeOpen(false)\n }\n /* The span's React onKeyDown already sees Escape from inside the menu —\n * portal rows bubble through the React tree. What it cannot see is focus\n * that is no longer in the tree at all: a disabled rise ejects the\n * focused row's focus to document.body, and Escape there never reaches\n * the span. This listener keeps dismissal reachable for that focus; the\n * openRef check means it never double-acts after the in-tree handler. */\n const escapeOutside = (event: KeyboardEvent): void => {\n if (event.key !== 'Escape' || event.defaultPrevented || event.isComposing) return\n if (!openRef.current) return\n event.preventDefault()\n if (pane !== initialPane) back(pane)\n else close(true)\n }\n document.addEventListener('mousedown', closeOutside)\n document.addEventListener('keydown', escapeOutside)\n return () => {\n document.removeEventListener('mousedown', closeOutside)\n document.removeEventListener('keydown', escapeOutside)\n }\n }, [open, onOpenChange, pane, initialPane])\n /* Focus intent after a pane change: the model pane takes the search field when\n * it has one, every other drill takes the checked row, and going back takes\n * the cell that opened the pane. */\n useEffect(() => {\n const intent = paneFocus.current\n // MenuSurface forwards the measurement visibility:hidden style. Browsers\n // refuse focus there, so keep intent until placement has made it visible.\n if (!open || menuPos === null || intent === null) return\n // Reopening resets a previously drilled pane in a separate commit. Entry\n // and return intent belong to the root cells, never the outgoing rows.\n if (intent !== 'drill' && pane !== 'root') return\n paneFocus.current = null\n if (intent === 'drill') {\n if (pane === 'model' && showSearch) { searchRef.current?.focus(); return }\n (menuRef.current?.querySelector<HTMLButtonElement>('[role=\"menuitemradio\"][aria-checked=\"true\"]:not([disabled])')\n ?? itemRefs.current.find(item => item !== null && !item.disabled))?.focus()\n return\n }\n itemRefs.current[intent === 'effort' ? 1 : 0]?.focus()\n }, [open, pane, showSearch, menuPos])\n useEffect(() => {\n const viewport = groupsRef.current\n if (viewport === null) return\n return observeStickyMenuGroups(viewport)\n }, [open, pane, filteredGroups])\n /* Scroll when the model pane opens, or when a keyboard arrow moves the\n * highlight. `visibleModels` is a new array whenever a directory snapshot\n * replaces `current` and the caller rebuilds equivalent choices — depending\n * on that array jumped scrollTop. Search may replace the rows; a model\n * click must not. */\n const modelPaneOpen = open && pane === 'model'\n const scrollSignal = !modelPaneOpen ? 'closed' : keyNav === 0 ? 'open' : `key:${keyNav}`\n const scrollSignalRef = useRef<string | null>(null)\n useLayoutEffect(() => {\n if (!modelPaneOpen || activeModelIndex < 0) {\n if (!modelPaneOpen) scrollSignalRef.current = null\n return\n }\n if (scrollSignalRef.current === scrollSignal) return\n scrollSignalRef.current = scrollSignal\n itemRefs.current[leading.length + activeModelIndex]?.scrollIntoView({ block: 'nearest' })\n }, [modelPaneOpen, scrollSignal, activeModelIndex, leading.length])\n /* The card hangs above the trigger, right-aligned, inside 12px viewport\n * margins — the official placement formula, re-run on scroll and resize. */\n useLayoutEffect(() => {\n if (!open) { setMenuPos(null); return }\n const place = (): void => {\n const rect = rootRef.current?.getBoundingClientRect()\n if (!rect) return\n const margin = 12, lw = menuRef.current?.offsetWidth ?? 0, lh = menuRef.current?.offsetHeight ?? 0\n let x = rect.right - lw, y = rect.top - 8 - lh\n if (lw > 0) x = Math.min(Math.max(x, margin), window.innerWidth - lw - margin)\n if (lh > 0) y = Math.min(Math.max(y, margin), window.innerHeight - lh - margin)\n setMenuPos(prev => (prev && prev.left === x && prev.top === y ? prev : { left: x, top: y }))\n }\n place()\n window.addEventListener('scroll', place, true)\n window.addEventListener('resize', place)\n return () => {\n window.removeEventListener('scroll', place, true)\n window.removeEventListener('resize', place)\n }\n }, [open, pane, choices, query])\n\n function onKeyDown(event: React.KeyboardEvent): void {\n if (event.defaultPrevented || event.nativeEvent.isComposing) return\n // Escape dismisses even while actions are disabled — a save lock gates\n // selection, not closing. A drilled pane backs out to the entry pane\n // first; the entry pane closes outright.\n if (event.key === 'Escape' && open) {\n event.preventDefault()\n if (pane !== initialPane) back(pane)\n else close(true)\n return\n }\n if (disabled) return\n if (!open && ['Enter', ' ', 'ArrowDown', 'ArrowUp'].includes(event.key)) {\n const button = event.target instanceof Element ? event.target.closest('button') : null\n if (!(button instanceof HTMLButtonElement) || button.disabled || !rootRef.current?.contains(button)) return\n // Prevent the native Enter/Space click from opening a second time.\n event.preventDefault()\n paneFocus.current = 'model'\n requestOpen()\n return\n }\n if (!open) return\n if (pane === 'model' && showSearch && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {\n event.preventDefault()\n if (visibleModels.length > 0) {\n setHighlightedIndex((activeModelIndex + (event.key === 'ArrowDown' ? 1 : -1) + visibleModels.length) % visibleModels.length)\n setKeyNav(n => n + 1)\n searchRef.current?.focus()\n }\n return\n }\n if (pane === 'model' && showSearch && event.target instanceof HTMLInputElement && (event.key === 'Enter' || (event.key === 'Tab' && !event.shiftKey))) {\n if (event.key === 'Tab' && visibleModels.length === 0) return\n event.preventDefault()\n const highlighted = visibleModels[activeModelIndex]\n // A submission in progress must not be repeated by Enter/Tab.\n if (highlighted && !busy) { onPick({ provider: highlighted.provider, model: highlighted.model }); if (closeOnPick) close(true) }\n return\n }\n if (event.key === 'Tab') {\n if (event.shiftKey) {\n event.preventDefault()\n if (pane !== initialPane) back(pane)\n else close(true)\n return\n }\n const focused = document.activeElement\n const rows = itemRefs.current.filter((item): item is HTMLButtonElement => item !== null)\n if (focused instanceof HTMLButtonElement && rows.includes(focused)) {\n event.preventDefault()\n focused.click()\n return\n }\n if (pane === 'model' && showSearch) {\n event.preventDefault()\n setHighlightedIndex(null)\n searchRef.current?.focus()\n }\n return\n }\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault()\n moveFocus(event.key === 'ArrowDown' ? 1 : -1)\n }\n }\n\n function onBlur(event: React.FocusEvent): void {\n const related = event.relatedTarget\n // A target already detached from the document (the menu re-rendering the\n // focused row) is inside for this purpose — never a dismissal.\n if (related instanceof Node\n && (rootRef.current?.contains(related) || menuRef.current?.contains(related)\n || !related.isConnected)) return\n // Keep-open mode never closes on a blur that has no connected next focus:\n // disabling the picked row, or a blur whose target raced a re-render, is\n // not the user dismissing the card. Outside presses, Escape, and focus\n // landing in a real outside node still close.\n if (!closeOnPick && !(related instanceof Node)) return\n // Disabling the focused row while a selection is in flight blurs it with\n // no next target. That is not a dismissal — closing here unmounts the card.\n if (busy && related == null) return\n if (open) changeOpen(false)\n }\n\n itemRefs.current = []\n let itemIndex = 0\n let modelIndex = 0\n const itemRef = () => {\n const at = itemIndex++\n return (node: HTMLButtonElement | null): void => { itemRefs.current[at] = node }\n }\n\n const menu = open && typeof document !== 'undefined'\n ? createPortal(\n <MenuSurface\n ref={menuRef}\n id={`${id}-menu`}\n className={`dsh-model-menu-menu${listClassName ? ` ${listClassName}` : ''}`}\n style={menuPos ?? MEASURE_STYLE}\n role={pane === 'model' ? 'group' : 'menu'}\n aria-label={modelLabel}\n lang={language}\n >\n {menuHeader ? <div className=\"dsh-model-menu-header\">{menuHeader}</div> : null}\n {pane === 'root' ? <>\n <button ref={itemRef()} type=\"button\" role=\"menuitem\" className=\"dsh-model-menu-cell\" disabled={disabled} onClick={() => drill('model')}>\n <span className=\"dsh-model-menu-cellLabel\">{modelLabel}</span>\n <span className=\"dsh-model-menu-cellValue\">{modelValue}</span>\n <IconChevronRightOutlineRegular className=\"dsh-model-menu-cellChevron\" />\n </button>\n {efforts.length > 0 && !reasoningSlider ? <button ref={itemRef()} type=\"button\" role=\"menuitem\" className=\"dsh-model-menu-cell\" disabled={disabled} onClick={() => drill('effort')}>\n <span className=\"dsh-model-menu-cellLabel\">{effortLabel}</span>\n <span className=\"dsh-model-menu-cellValue\">{effortValue ?? effortRows.find(row => row.id === (selectedEffort ?? ''))?.name ?? defaultEffortLabel}</span>\n <IconChevronRightOutlineRegular className=\"dsh-model-menu-cellChevron\" />\n </button> : null}\n </> : null}\n {pane === 'model' ? <>\n {showSearch ? <div className=\"dsh-model-menu-searchRow\">\n <Input\n ref={searchRef}\n disabled={disabled}\n className={`dsh-model-menu-search${query !== '' ? ' dsh-model-menu-searchWithQuery' : ''}`}\n type=\"text\"\n role=\"searchbox\"\n aria-label={searchPlaceholder}\n aria-controls={`${id}-models`}\n aria-activedescendant={activeModelIndex < 0 ? undefined : `${id}-model-${activeModelIndex}`}\n placeholder={searchPlaceholder}\n value={query}\n onChange={event => { setQuery(event.target.value); setHighlightedIndex(0) }}\n />\n {query !== '' ? <button type=\"button\" className=\"dsh-model-menu-searchClear\" aria-label={clearSearchLabel} disabled={disabled}\n onClick={() => { setQuery(''); setHighlightedIndex(null); searchRef.current?.focus() }}>\n <IconCloseFillRegular />\n </button> : null}\n </div> : null}\n <div ref={groupsRef} id={`${id}-models`} className=\"dsh-model-menu-groups scrollable\" role=\"menu\" aria-label={modelLabel}\n hidden={filteredGroups.length === 0}>\n {leading.length > 0 ? <div className=\"dsh-model-menu-leading\">\n {leading.map(item => (\n <button key={item.id} ref={itemRef()} type=\"button\" role=\"menuitemradio\" aria-checked={item.selected === true} disabled={disabled || busy}\n className={`dsh-model-menu-option${item.selected === true ? ' dsh-model-menu-selected' : ''}`}\n onClick={() => { if (disabled || busy) return; onPickLeading?.(item.id); if (closeOnPick) close(true) }}>\n <span className=\"dsh-model-menu-optionCopy\"><span className=\"dsh-model-menu-modelName\">{item.label}</span></span>\n <span className=\"dsh-model-menu-check\">{item.selected === true ? <IconCheckOutlineRegular /> : null}</span>\n </button>\n ))}\n </div> : null}\n {filteredGroups.map(group => (\n <MenuGroup key={group.provider} label={group.name}>\n {group.items.map(item => {\n const index = modelIndex++\n const choice = item.choice\n const checked = selected?.provider === choice.provider && selected.model === choice.model\n return <button\n key={`${choice.provider}/${choice.model}`}\n ref={itemRef()}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={checked}\n id={`${id}-model-${index}`}\n tabIndex={showSearch ? -1 : 0}\n disabled={disabled || busy}\n onFocus={() => setHighlightedIndex(index)}\n data-highlighted={index === activeModelIndex ? '' : undefined}\n className={`dsh-model-menu-option dsh-model-menu-modelOption${checked ? ' dsh-model-menu-selected' : ''}${index === activeModelIndex ? ' dsh-model-menu-optionActive' : ''}`}\n onMouseMove={index === activeModelIndex ? undefined : () => {\n if (showSearch) setHighlightedIndex(index)\n else itemRefs.current[leading.length + index]?.focus()\n }}\n title={choice.label}\n onClick={() => { if (disabled || busy) return; onPick({ provider: choice.provider, model: choice.model }); if (closeOnPick) close(true) }}\n >\n <span className=\"dsh-model-menu-optionCopy\"><span className=\"dsh-model-menu-modelName\">{modelMenuShortName(choice)}</span></span>\n <span className=\"dsh-model-menu-check\">{checked ? <IconCheckOutlineRegular /> : null}</span>\n </button>\n })}\n </MenuGroup>\n ))}\n </div>\n {reasoningSlider && efforts.length > 0 && filteredGroups.length > 0\n ? <EffortSlider label={effortLabel} rows={effortRows} selected={selectedEffort ?? ''} disabled={disabled} busy={busy}\n onPick={value => onPickEffort?.(value)} />\n : null}\n {filteredGroups.length === 0 ? <div className=\"dsh-model-menu-empty\" role=\"status\">{emptyLabel}</div> : null}\n </> : null}\n {pane === 'effort' ? <>\n {effortRows.map(row => {\n const checked = (selectedEffort ?? '') === row.id\n return <button key={row.id || '__default'} ref={itemRef()} type=\"button\" role=\"menuitemradio\" aria-checked={checked} disabled={disabled || busy}\n className={`dsh-model-menu-option${checked ? ' dsh-model-menu-selected' : ''}`}\n onClick={() => { if (disabled || busy) return; onPickEffort?.(row.id || undefined); if (closeOnPick) close(true) }}>\n <span className=\"dsh-model-menu-optionCopy\"><span className=\"dsh-model-menu-modelName\">{row.name}</span></span>\n <span className=\"dsh-model-menu-check\">{checked ? <IconCheckOutlineRegular /> : null}</span>\n </button>\n })}\n </> : null}\n </MenuSurface>,\n document.body,\n )\n : null\n const trigger = isValidElement<Record<string, unknown>>(anchor)\n ? cloneElement(anchor, { 'aria-haspopup': 'menu', 'aria-expanded': open, 'aria-controls': open ? `${id}-menu` : undefined, 'aria-disabled': disabled || undefined })\n : anchor\n return <span ref={rootRef} className={`dsh-model-menu-root${className ? ` ${className}` : ''}`} onKeyDown={onKeyDown} onBlur={onBlur}\n onClick={event => {\n if (disabled || event.defaultPrevented) return\n const button = event.target instanceof Element ? event.target.closest('button') : null\n if (!(button instanceof HTMLButtonElement) || button.disabled || !rootRef.current?.contains(button)) return\n requestOpen()\n }}\n onMouseDown={event => { if (event.target instanceof Element && menuRef.current?.contains(event.target) && event.target.closest('button') !== null) event.preventDefault() }}>\n {trigger}{menu}\n </span>\n}\n\n/**\n * Discrete reasoning-effort slider shown under the model list in enhanced mode.\n *\n * A native range input (`step=1`) over exactly the rows the caller supplies —\n * the default row plus each effort the selected model advertises — so it can\n * never invent a level. It previews locally while dragging or arrowing and\n * commits only when the gesture ends (pointer up, key up, or blur), so a drag\n * does not write on every step. The menu stays open, so adjusting the effort\n * never loses the model selection or the search query.\n *\n * The input itself stays the entire interaction and accessibility surface —\n * keyboard, ARIA, disabled and the native step snapping all come from it —\n * while the track, gradient fill and thumb below are decorative layers painted\n * from the `--_p` percentage the preview position sets on the rail. Value\n * changes only update that custom property, so the CSS transitions animate\n * between levels without remounting nodes or restarting an animation.\n */\nfunction EffortSlider(props: {\n readonly label: string\n readonly rows: ReadonlyArray<{ id: string; name: string }>\n readonly selected: string\n readonly disabled?: boolean\n readonly busy?: boolean\n readonly onPick: (effort: string | undefined) => void\n}) {\n const { label, rows, selected, disabled = false, busy = false, onPick } = props\n const active = Math.max(0, rows.findIndex(row => row.id === selected))\n const [position, setPosition] = useState(active)\n const positionRef = useRef(position)\n // A committed selection from the owner resets the preview.\n useEffect(() => { positionRef.current = active; setPosition(active) }, [active])\n const preview = (next: number): void => {\n positionRef.current = next\n setPosition(next)\n }\n // Commit once per gesture: pointer up, key up, or leaving the control. A\n // submission already in flight must not be repeated.\n const commit = (): void => {\n if (disabled || busy) return\n const row = rows[positionRef.current]\n if (row !== undefined) onPick(row.id === '' ? undefined : row.id)\n }\n const max = Math.max(0, rows.length - 1)\n const percent = max > 0 ? Math.round((position / max) * 100) : 0\n return <div className=\"dsh-model-menu-sliderGroup\" role=\"group\" aria-label={label}>\n <div className=\"dsh-model-menu-sliderHead\">\n <span className=\"dsh-model-menu-sliderTitle\">{label}</span>\n <span className=\"dsh-model-menu-sliderValue\">{rows[position]?.name}</span>\n </div>\n <div className=\"dsh-model-menu-sliderRail\" style={{ '--_p': percent } as CSSProperties}>\n <input\n type=\"range\"\n className=\"dsh-model-menu-sliderInput\"\n min={0}\n max={max}\n step={1}\n value={position}\n disabled={disabled}\n aria-label={label}\n aria-disabled={disabled || busy || undefined}\n aria-valuetext={rows[position]?.name}\n onChange={event => {\n // Read the event target, not currentTarget: a synthetic change event may\n // carry a detached `{ value }` target, while a real range event targets\n // the input itself. Both must preview the same position.\n const value = Number((event.target as HTMLInputElement).value)\n if (Number.isFinite(value)) preview(value)\n }}\n onPointerUp={commit}\n onKeyUp={commit}\n onBlur={commit}\n />\n <span className=\"dsh-model-menu-sliderTrack\" aria-hidden=\"true\">\n <span className=\"dsh-model-menu-sliderFill\"><span className=\"dsh-model-menu-sliderFillBar\" /></span>\n <span className=\"dsh-model-menu-sliderNodes\">\n {rows.map((row, index) => (\n <span key={row.id || '__default'} data-covered={index <= position ? '' : undefined}\n className=\"dsh-model-menu-sliderNode\" style={{ '--_n': max > 0 ? Math.round((index / max) * 100) : 0 } as CSSProperties} />\n ))}\n </span>\n </span>\n <span className=\"dsh-model-menu-sliderThumb\" aria-hidden=\"true\" />\n </div>\n </div>\n}\n\n/**\n * ModelMenu styles, transcribed from the official ModelSelect.module.css (the\n * published dsh-client-ui-model-selection bundle): card capped at\n * min(360px, 100vh - 96px), 34px option cells at 13/18 with 5px 7px padding,\n * 34px root cells at 13/20, a borderless 12px search row with a clear button,\n * sticky group headings (MenuGroup's own CSS), and the l1-stroke prominent\n * elevation at portal z-index 1100. The trigger mirrors the composer's 28px\n * model pill, chevron rotating open. MenuSurface paints fill and backdrop.\n * Only allowlisted --dsw- and --ds- theme tokens may appear here — a literal\n * color is a bug.\n */\nexport const modelMenuCss = `\n.dsh-model-menu-root { min-width: 0; position: relative; display: inline-flex; }\n.dsh-model-menu-trigger {\n border-radius: var(--dsw-radius-sm);\n min-width: 0;\n max-width: min(360px, 45cqw);\n height: 28px;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n background: none;\n border: none;\n outline: none;\n align-items: center;\n gap: 4px;\n padding: 0 4px 0 8px;\n font-size: 13px;\n font-weight: 400;\n line-height: 20px;\n display: flex;\n}\n.dsh-model-menu-trigger:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }\n.dsh-model-menu-trigger:focus-visible:not([data-selection-focus]) { box-shadow: 0 0 0 var(--dsw-focus-ring-width) var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary)); }\n.dsh-model-menu-trigger:disabled { color: var(--dsw-alias-label-dimmed); cursor: default; }\n.dsh-model-menu-triggerLabel { text-overflow: ellipsis; white-space: nowrap; min-width: 0; overflow: hidden; }\n.dsh-model-menu-triggerEffort { text-overflow: ellipsis; white-space: nowrap; min-width: 0; color: var(--dsw-alias-label-caption); flex-shrink: 1000; overflow: hidden; }\n.dsh-model-menu-chevron { color: var(--dsw-alias-label-caption); flex: none; transition: transform var(--ds-transition-duration) var(--ds-ease-in-out); }\n.dsh-model-menu-chevronOpen { transform: rotate(180deg); }\n/* Portal overlay: the host publishes no z-index token, so the card keeps the\n * native menu layer's 1100 verbatim. */\n.dsh-model-menu-menu {\n z-index: 1100;\n --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);\n width: max-content;\n min-width: min(240px, 100vw - 32px);\n max-width: min(420px, 100vw - 32px);\n max-height: min(360px, 100vh - 96px);\n box-shadow: var(--dsw-elevation-prominent);\n color: var(--dsw-alias-label-primary);\n --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);\n --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);\n border: 0;\n flex-direction: column;\n padding: 4px;\n display: flex;\n position: fixed;\n overflow: hidden;\n}\n.dsh-model-menu-status, .dsh-model-menu-empty { color: var(--dsw-alias-label-tertiary); padding: 8px; font-size: 12px; line-height: 18px; }\n.dsh-model-menu-header { flex: none; padding: 2px 2px 4px; }\n.dsh-model-menu-searchRow { flex-shrink: 0; margin: 2px 0 3px; position: relative; }\n.dsh-model-menu-searchRow .dsh-model-menu-search { border-radius: var(--dsw-radius-md); background: none; border: 0 solid transparent; height: auto; padding: 5px 7px; display: flex; }\n.dsh-model-menu-searchRow .dsh-model-menu-search:focus-within { border-color: transparent; }\n.dsh-model-menu-searchWithQuery { padding-right: 34px; }\n.dsh-model-menu-searchRow .dsh-model-menu-search input { padding: 0; font-size: 12px; line-height: normal; }\n.dsh-model-menu-searchRow .dsh-model-menu-search input::placeholder { color: var(--dsw-alias-label-caption); }\n/* The clear button is a circle by geometry (border-radius: 50%), a shape the\n * radius token scale does not describe. */\n.dsh-model-menu-searchClear {\n width: 24px;\n height: 24px;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n background: none;\n border: none;\n border-radius: 50%;\n justify-content: center;\n align-items: center;\n padding: 0;\n display: inline-flex;\n position: absolute;\n top: 50%;\n right: 4px;\n transform: translateY(-50%);\n}\n.dsh-model-menu-searchClear:hover, .dsh-model-menu-searchClear:focus-visible { background: var(--dsw-alias-interactive-bg-hover); outline: none; }\n.dsh-model-menu-groups { min-height: 0; overflow-y: auto; }\n.dsh-model-menu-leading { border-bottom: 0.5px solid var(--dsw-alias-border-l2); margin-bottom: 3px; padding-bottom: 3px; }\n.dsh-model-menu-option {\n box-sizing: border-box;\n border-radius: var(--dsw-radius-md);\n width: auto;\n min-width: 100%;\n min-height: 34px;\n color: inherit;\n text-align: left;\n cursor: pointer;\n background: none;\n border: none;\n outline: none;\n align-items: center;\n gap: 6px;\n padding: 5px 7px;\n display: flex;\n}\n.dsh-model-menu-option:not(.dsh-model-menu-modelOption):hover:not(:disabled),\n.dsh-model-menu-option:focus-visible,\n.dsh-model-menu-optionActive:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }\n.dsh-model-menu-modelOption:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }\n.dsh-model-menu-selected { background: none; }\n.dsh-model-menu-option:disabled { color: var(--dsw-alias-label-dimmed); cursor: default; }\n.dsh-model-menu-optionCopy { flex-direction: column; flex: 1; min-width: 0; display: flex; }\n.dsh-model-menu-modelName { color: inherit; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 400; line-height: 18px; overflow: hidden; }\n.dsh-model-menu-check { color: var(--dsw-alias-label-primary); flex: 0 0 14px; place-items: center; display: grid; }\n.dsh-model-menu-check svg { width: 14px; height: 14px; }\n.dsh-model-menu-cell {\n box-sizing: border-box;\n border-radius: var(--dsw-radius-md);\n width: auto;\n min-width: 100%;\n height: 34px;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n text-align: left;\n background: none;\n border: none;\n outline: none;\n align-items: center;\n gap: 6px;\n padding: 0 8px;\n font-size: 13px;\n line-height: 20px;\n display: flex;\n}\n.dsh-model-menu-cell:hover, .dsh-model-menu-cell:focus-visible { background: var(--dsw-alias-interactive-bg-hover); }\n.dsh-model-menu-cellLabel { white-space: nowrap; flex: none; }\n.dsh-model-menu-cellValue { text-overflow: ellipsis; white-space: nowrap; text-align: right; min-width: 0; color: var(--dsw-alias-label-tertiary); flex: auto; overflow: hidden; }\n.dsh-model-menu-cellChevron { width: 12px; height: 12px; color: var(--dsw-alias-menu-icon); flex: none; }\n/* Discrete reasoning-effort slider under the model list (enhanced mode).\n * The painted control is layered over a fully functional native range input:\n * the input stays on top, transparent, and owns pointer/keyboard/ARIA, while\n * the decorative track, fill and thumb render beneath it at pointer-events:\n * none. Position lives in one custom property (--_p, 0–100) on the rail, so\n * the only animated work a level change triggers is a clip-path/left\n * transition — no keyframes, no element churn. */\n.dsh-model-menu-sliderGroup { border-top: 0.5px solid var(--dsw-alias-border-l2); flex: none; margin-top: 4px; padding: 6px 8px 8px; }\n.dsh-model-menu-sliderHead { align-items: baseline; justify-content: space-between; gap: 8px; margin: 0 2px 4px; display: flex; }\n.dsh-model-menu-sliderTitle { color: var(--dsw-alias-label-tertiary); font-size: 12px; line-height: 18px; }\n.dsh-model-menu-sliderValue { color: var(--dsw-alias-label-primary); font-size: 13px; font-weight: 600; line-height: 20px; transition: color var(--ds-transition-duration) var(--ds-ease-in-out); }\n.dsh-model-menu-sliderRail { position: relative; direction: ltr; height: 38px; margin-top: 2px; }\n.dsh-model-menu-sliderRail:has(:disabled) { opacity: 0.45; }\n.dsh-model-menu-sliderInput {\n appearance: none;\n -webkit-appearance: none;\n box-sizing: border-box;\n border: 0;\n cursor: pointer;\n direction: ltr;\n opacity: 0;\n margin: 0;\n padding: 0;\n width: 100%;\n height: 100%;\n position: absolute;\n inset: 0;\n z-index: 1;\n touch-action: pan-y;\n}\n.dsh-model-menu-sliderInput:disabled { cursor: default; }\n/* The transparent input must keep the painted thumb's geometry: an\n * appearance:none webkit thumb defaults to 16px, which would shift the\n * end-point positions 7px off the decorative 30px disc and misplace the\n * native drag hit target. Track gets the full rail height so the whole band\n * maps to values identically. */\n.dsh-model-menu-sliderInput::-webkit-slider-runnable-track { width: 100%; height: 100%; }\n.dsh-model-menu-sliderInput::-webkit-slider-thumb { appearance: none; -webkit-appearance: none; width: 30px; height: 30px; margin: 0; }\n.dsh-model-menu-sliderInput::-moz-range-track { width: 100%; height: 100%; }\n.dsh-model-menu-sliderInput::-moz-range-thumb { width: 30px; height: 30px; margin: 0; border: 0; }\n.dsh-model-menu-sliderTrack {\n pointer-events: none;\n border-radius: 999px;\n width: 100%;\n height: 26px;\n background: var(--dsw-alias-interactive-bg-hover);\n box-shadow: inset 0 0 0 0.5px var(--dsw-alias-border-l2);\n position: absolute;\n inset-inline: 0;\n top: 50%;\n transform: translateY(-50%);\n /* No overflow:hidden — it would clip the fill's drop-shadow glow; the bar's\n * own clip-path already supplies the rounded reveal shape. */\n}\n/* The accent ramp paints the full track width once and is revealed by an\n * animated clip-path, so raising the effort unwraps more of the spectrum\n * instead of squashing the same gradient into a narrower bar. The glow lives\n * on the un-clipped parent: a filter on the clipped element itself would be\n * clipped away with it. */\n.dsh-model-menu-sliderFill {\n display: block;\n height: 100%;\n filter: drop-shadow(0 0 5px var(--dsw-alias-state-business-primary));\n transition: filter var(--ds-transition-duration) var(--ds-ease-in-out);\n}\n.dsh-model-menu-sliderInput:hover:not(:disabled) ~ .dsh-model-menu-sliderTrack .dsh-model-menu-sliderFill,\n.dsh-model-menu-sliderInput:active:not(:disabled) ~ .dsh-model-menu-sliderTrack .dsh-model-menu-sliderFill {\n filter: drop-shadow(0 0 9px var(--dsw-alias-state-business-primary));\n}\n/* The fill stops at the thumb's center, not at the track edge — at a 30px\n * thumb the end stops sit 15px in from each side, matching the node dots. */\n.dsh-model-menu-sliderFillBar {\n display: block;\n height: 100%;\n background: linear-gradient(90deg,\n var(--dsw-alias-state-business-primary),\n var(--dsw-alias-state-success-primary),\n var(--dsw-alias-state-warn-primary),\n var(--dsw-alias-state-error-primary));\n clip-path: inset(0 calc(100% - 15px - (100% - 30px) * var(--_p, 0) / 100) 0 0 round 999px);\n transition: clip-path var(--ds-transition-duration) var(--ds-ease-in-out);\n}\n/* Stop dots: one per declared row (default + every advertised effort), evenly\n * spread across the band between the two thumb-center extremes (inset 15px,\n * i.e. half the 30px thumb). --_n is 0-100 along that band. A covered dot\n * reads as a pale pin through the gradient; an uncovered one stays a neutral\n * notch on the empty track. */\n.dsh-model-menu-sliderNodes {\n pointer-events: none;\n display: block;\n position: absolute;\n inset-inline: 15px;\n inset-block: 0;\n}\n.dsh-model-menu-sliderNode {\n pointer-events: none;\n box-sizing: border-box;\n width: 4px;\n height: 4px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--dsw-alias-label-secondary) 35%, transparent);\n position: absolute;\n left: calc(var(--_n, 0) * 1%);\n top: 50%;\n transform: translate(-50%, -50%);\n transition: background-color var(--ds-transition-duration) var(--ds-ease-in-out),\n transform var(--ds-transition-duration) var(--ds-ease-in-out);\n}\n.dsh-model-menu-sliderNode[data-covered] { background: color-mix(in srgb, var(--dsw-alias-label-primary) 60%, transparent); }\n.dsh-model-menu-sliderThumb {\n pointer-events: none;\n box-sizing: border-box;\n border-radius: 50%;\n width: 30px;\n height: 30px;\n background: var(--dsw-alias-button-primary-fill);\n border: 0.5px solid var(--dsw-alias-border-l4);\n box-shadow: 0 0 0 3px var(--dsw-alias-interactive-bg-hover), var(--dsw-elevation-soft);\n position: absolute;\n left: calc((100% - 30px) * var(--_p, 0) / 100);\n top: 50%;\n transform: translateY(-50%) scale(0.92);\n transition: left var(--ds-transition-duration) var(--ds-ease-in-out),\n transform var(--ds-transition-duration) var(--ds-ease-in-out),\n box-shadow var(--ds-transition-duration) var(--ds-ease-in-out);\n}\n.dsh-model-menu-sliderInput:hover:not(:disabled) ~ .dsh-model-menu-sliderThumb { transform: translateY(-50%) scale(1); }\n.dsh-model-menu-sliderInput:active:not(:disabled) ~ .dsh-model-menu-sliderThumb {\n transform: translateY(-50%) scale(1.1);\n box-shadow: 0 0 0 4px var(--dsw-alias-interactive-bg-hover), 0 0 12px var(--dsw-alias-state-business-primary);\n}\n.dsh-model-menu-sliderInput:focus-visible ~ .dsh-model-menu-sliderThumb {\n box-shadow: 0 0 0 3px var(--dsw-alias-interactive-bg-hover),\n 0 0 0 calc(3px + var(--dsw-focus-ring-width)) var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));\n}\n@media (prefers-reduced-motion: reduce) {\n .dsh-model-menu-sliderFill, .dsh-model-menu-sliderFillBar, .dsh-model-menu-sliderThumb,\n .dsh-model-menu-sliderNode, .dsh-model-menu-sliderValue { transition: none; }\n}\n`\n","/**\n * Shared `klarkxy.model-picker` Factory contract.\n *\n * `@klarkxy/dsh-model-picker` registers one root-scoped Component Factory under\n * this name: a searchable model picker with a reasoning-effort slider, built on\n * the same ModelMenu recipe this package ships. Feature plugins opt in by\n * calling `renderFactorySlot('klarkxy.model-picker', props, options)` inside a\n * slot component; when no definition is registered the renderer resolves the\n * caller's `options.fallback`, so each consumer keeps its own native menu as\n * the fallback and gains the shared picker only while the plugin is installed.\n *\n * This entry is pure types and constants — no React, no host imports — so a\n * consumer can `import type` the declaration and the input/local props without\n * depending on the business plugin at runtime. The `SlotFactoryMap` merge is\n * what makes the `renderFactorySlot`/`registerFactory` calls type-check on\n * both sides; import it for the types only.\n */\nimport type { ModelMenuChoice, ModelCatalogFailure } from './catalog.ts'\nimport type { HostObservable } from '@deepseek-ai/dsh-client-ui-slots'\n\n/** Registered Factory name — the `renderFactorySlot`/`registerFactory` key. */\nexport const MODEL_PICKER_FACTORY = 'klarkxy.model-picker'\n/** The one caller-selectable local position: the trigger rendered in place. */\nexport const MODEL_PICKER_ANCHOR_SLOT = 'anchor'\n\n/** Extra row the picker renders above the model groups (pure data; no React). */\nexport interface ModelPickerLeadingItem {\n readonly id: string\n readonly label: string\n readonly selected?: boolean\n}\n\n/** Status banner data the picker renders inside the menu header, above the groups. */\nexport interface ModelPickerStatus {\n /** Whole-request failure text; renders with a retry action. */\n readonly error?: string | null\n /** Advisory row (e.g. the saved route left the catalog); rendered warn-toned, no retry. */\n readonly warning?: string\n /** Whether the owner is loading or selecting (dims the banner). */\n readonly busy?: boolean\n /** Provider-local failures; still usable groups stay selectable. */\n readonly failures?: readonly ModelCatalogFailure[]\n /** Reload action the banner's retry buttons call. */\n readonly retry?: () => void\n}\n\n/**\n * Occurrence input (`renderFactorySlot` `props`). Everything here is data or\n * callbacks — React content travels through the `anchor` local slot instead.\n */\nexport interface ModelPickerProps {\n /** Active UI language; `'zh*'` selects the built-in Chinese copy. */\n readonly locale?: string\n /** Flat catalog choices (grouped internally by provider). */\n readonly choices: readonly ModelMenuChoice[]\n /** Current selection highlight. */\n readonly selected?: { readonly provider: string; readonly model: string }\n /** Model pick; the picker closes after the callback runs. */\n readonly onPick: (route: { provider: string; model: string }) => void\n /** Extra rows above the model groups (e.g. a \"follow default\" row). */\n readonly leading?: readonly ModelPickerLeadingItem[]\n /** Leading-row pick; `undefined` keeps the menu open. */\n readonly onPickLeading?: (id: string) => void\n /** Declared reasoning-effort rows; the slider is hidden while empty. */\n readonly efforts?: ReadonlyArray<{ id: string; name: string }>\n /** Current effort id; `''`/undefined marks the provider-default row. */\n readonly selectedEffort?: string\n /** Effort pick; the menu stays open. `undefined` = provider default. */\n readonly onPickEffort?: (effort: string | undefined) => void\n /** Disables the trigger and every menu action. */\n readonly disabled?: boolean\n /** Trigger caption; the default anchor falls back to localized \"Select model\". */\n readonly triggerLabel?: string\n /** Current effort caption shown after the trigger label (\"model · high\"). */\n readonly triggerEffortLabel?: string\n /** Extra class on the default trigger button. */\n readonly triggerClassName?: string\n /** Show a spinner instead of the chevron while a selection settles. */\n readonly busy?: boolean\n /** Extra class on the portaled menu card. */\n readonly listClassName?: string\n /** Menu opens on the searchable model pane ('model') or the root cells. */\n readonly initialPane?: 'root' | 'model'\n /** Show the search row even for a small catalog. */\n readonly alwaysShowSearch?: boolean\n /** Show the reasoning-effort slider under the model list (default true here). */\n readonly reasoningSlider?: boolean\n /** Status banner rendered inside the menu header (load failures, retry). */\n readonly status?: ModelPickerStatus\n /** Menu open-state changes; the owner may react (e.g. refresh the catalog). */\n readonly onOpenChange?: (open: boolean) => void\n /** Copy overrides; every key is optional. */\n readonly modelLabel?: string\n readonly modelValue?: string\n readonly effortLabel?: string\n readonly defaultEffortLabel?: string\n readonly searchPlaceholder?: string\n readonly emptyLabel?: string\n readonly clearSearchLabel?: string\n readonly retryLabel?: string\n}\n\n/** Props one `anchor` local component receives (plus the framework kit). */\nexport interface ModelPickerAnchorProps {\n /** Mirror of `aria-expanded`; true while the menu is open. */\n readonly open: boolean\n /** Disabled state passed down by the owner. */\n readonly disabled: boolean\n /** Whether a selection is settling; the default anchor shows a spinner. */\n readonly busy: boolean\n /** Resolved trigger caption. */\n readonly label: string\n /** Resolved effort caption appended to the caption, if any. */\n readonly effortLabel?: string\n /** Extra class on the trigger element. */\n readonly className?: string\n /** Anchored-popup marker the picker stamps on the trigger (always 'menu'). */\n readonly 'aria-haspopup'?: 'menu'\n /** Mirror of `open`, for ARIA-compliant custom anchors. */\n readonly 'aria-expanded'?: boolean\n /** Menu element id while the menu is mounted. */\n readonly 'aria-controls'?: string\n /** Resolved accessible name for the trigger. */\n readonly 'aria-label'?: string\n /** Set when the picker is disabled; custom anchors may read it instead of `disabled`. */\n readonly 'aria-disabled'?: boolean\n}\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface SlotFactoryMap {\n /**\n * Reusable model picker: one searchable provider-grouped model list plus an\n * optional reasoning-effort slider. Consumers call `renderFactorySlot` with\n * `ModelPickerProps`; `options.slots.anchor` may supply a custom trigger\n * component typed `ModelPickerAnchorProps`, and `options.fallback` is the\n * menu rendered while no `klarkxy.model-picker` definition is registered.\n */\n 'klarkxy.model-picker': {\n scope: 'root'\n props: ModelPickerProps\n /** Occurrence inject face: the active-locale observable bound as a hook. */\n inject: { hooks: { activeLocale: HostObservable<{ active: string }> } }\n slots: {\n anchor: {\n scope: 'root'\n props: ModelPickerAnchorProps\n }\n }\n locale: 'model-picker'\n }\n }\n interface LocaleNamespaceMap {\n /** Copy owned by @klarkxy/dsh-model-picker. */\n 'model-picker':\n | 'trigger.fallback' | 'trigger.aria' | 'trigger.ariaEffort'\n | 'menu.model' | 'menu.effort' | 'effort.providerDefault'\n | 'search.placeholder' | 'search.clear' | 'search.empty' | 'empty.models'\n | 'status.loading' | 'error.action' | 'action.retry' | 'warning.unroutable'\n }\n}\n","/**\n * Effort preference — a small client-side memory for explicit reasoning-effort\n * picks, keyed by provider+model route.\n *\n * Why it exists: the Host already persists the complete default selection —\n * `sessionController.selectModel` records the Session selection and calls\n * `ctx.agentDefaultModel.saveSelection(selected)` in the background, and the\n * `agentDefaultModel` Config carries `provider`, `model` and an optional\n * `reasoningEffort` field. A Session with no recorded selection follows that\n * saved default through live `AgentOptions` accessors\n * (`dsh-api-session-controller/agent.js` `agentOptions()`), so a new Session\n * inherits the effort only while the default keeps it.\n *\n * The gap is a model switch: the picker's pick submits provider+model only\n * (native semantics — the adapter resolves its own default effort), which\n * makes `saveSelection` write a config WITHOUT `reasoningEffort`; the default\n * effort is erased and the next new Session loses it. Remembering the last\n * successful explicit effort per route and re-attaching it to later model\n * picks restores \"new Session inherits the last human setting\" without\n * touching Host code, Host events, or existing Sessions — the memory only\n * shapes what THIS surface submits.\n *\n * Rules (matching the Host contract):\n * - Only successful explicit picks are remembered. A failed `select` must\n * never update memory — nothing was recorded or saved.\n * - Choosing \"Default\" (effort `undefined`) clears the route's entry; the\n * model then follows the adapter default, never a forced prior pick.\n * - A remembered effort is re-applied only when the catalog declares it for\n * that exact route: a model that advertises no `efforts` never receives an\n * explicit effort, so \"不支援 High 的模型不會收到 High\".\n * - No persistence to disk and no Host calls: the memory lasts for the page\n * lifetime; across reloads the Host's own saved default already carries\n * the effort forward.\n * - Reads never mutate; this module never triggers an LLM call and never\n * touches subagent model choices.\n */\n\n/** One selectable route. */\nexport interface EffortRoute {\n provider: string\n model: string\n}\n\n/** A selection request: the same shape `directory.select` accepts. */\nexport interface EffortSelection extends EffortRoute {\n reasoningEffort?: string\n}\n\n/** The subset of catalog metadata the memory validates against. */\nexport interface RouteReasoning {\n /** Effort ids the model declares (`model.reasoning.efforts[].id`). */\n efforts?: readonly string[]\n}\n\n/** Normalized select result: `{ ok: true }` or `{ ok: false }`. */\nexport type SelectResult = { ok: boolean; error?: unknown } | undefined\n\ntype SelectFn = (selection: EffortSelection) => Promise<SelectResult> | SelectResult\n\nconst keyOf = (route: EffortRoute): string => JSON.stringify([route.provider, route.model])\n\n/**\n * In-memory per-route effort memory. One instance is shared by the composer\n * seat and any face that submits through `submit`, so a slider pick made in\n * one surface is what the next model pick re-attaches.\n */\nexport class EffortPreference {\n /** route key → remembered explicit effort (a cleared route has no entry). */\n private readonly efforts = new Map<string, string>()\n\n /** The remembered explicit effort for one route, or undefined. */\n effortFor(route: EffortRoute): string | undefined {\n return this.efforts.get(keyOf(route))\n }\n\n /**\n * Record one confirmed pick. `undefined` clears the route's entry —\n * \"Default\" is an explicit choice too, and must not be overridden later.\n * Callers invoke this only after the Host accepted the selection.\n */\n remember(route: EffortRoute, effort: string | undefined): void {\n const key = keyOf(route)\n if (effort === undefined) this.efforts.delete(key)\n else this.efforts.set(key, effort)\n }\n\n /**\n * Effort to attach to a fresh pick of `route`: the remembered value when\n * the catalog still declares it for that route, else undefined (the pick\n * then follows the adapter default). Validation is per-route — a model\n * without declared efforts can never inherit an effort remembered for it.\n */\n resolve(route: EffortRoute, reasoning: RouteReasoning | undefined): string | undefined {\n const effort = this.efforts.get(keyOf(route))\n if (effort === undefined) return undefined\n return reasoning?.efforts?.includes(effort) ? effort : undefined\n }\n\n /**\n * Submit helper for a MODEL pick: merge the remembered effort into\n * `selection` when no effort is already present and the target route still\n * supports it, call `select`, and remember the resolved effort only on\n * success. On failure memory is untouched and the result is returned\n * verbatim.\n *\n * This is NOT the right verb for the slider's \"Default\" row: a caller\n * clearing an effort must submit through `select` directly and call\n * `remember(route, undefined)` only after success — routing the clear\n * through `submit` would just re-attach the remembered effort.\n */\n async submit(\n selection: EffortSelection,\n reasoning: RouteReasoning | undefined,\n select: SelectFn,\n ): Promise<SelectResult> {\n const effort = selection.reasoningEffort ?? this.resolve(selection, reasoning)\n const intent: EffortSelection = effort === undefined ? { provider: selection.provider, model: selection.model } : { ...selection, reasoningEffort: effort }\n const result = await select(intent)\n /* Only a confirmed `ok: true` updates memory. `undefined` is NOT success:\n * the seat's fallback select resolves undefined for an unavailable\n * directory, and recording a pick the Host never saw would invent a\n * preference. */\n if (result?.ok !== true) return result\n this.remember(intent, intent.reasoningEffort)\n return result\n }\n}\n","/**\n * Model picker, browser half.\n *\n * Two surfaces ride one component:\n *\n * - `klarkxy.model-picker` (root Factory): the searchable model picker with a\n * reasoning-effort slider that feature plugins mount through\n * `renderFactorySlot`. Its props are pure data and callbacks so consumers\n * never take a runtime dependency on this package — while the definition is\n * absent the renderer resolves the caller's `options.fallback`.\n * - `conversation.input.model` (single/session, priority -2): the composer\n * model seat, shadowing the shipped entry (priority 0) and a reasoning-slider\n * entry (priority -1). The ledger keeps every occupant, so unmounting this\n * entry restores the previous winner — the native or reference seat returns\n * automatically on disable/uninstall. The label child slot stays declared by\n * the shadowed native entry, which means only it may render it; like\n * reasoning-slider this seat renders the model name verbatim.\n *\n * The seat drives the same per-session ModelDirectory the native seat and the\n * /model popup share (catalog load, selection submission, pending/error\n * projection), so selection semantics stay host-owned.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore, type CSSProperties, type ReactNode } from 'react'\nimport type { Context } from '@deepseek-ai/cordis'\nimport type { FactoryComponentPropsOf, FactoryLocalComponent } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { ModelDirectoryState, ModelSelectInjected } from '@deepseek-ai/dsh-client-ui-model-selection/client'\n/* Type-only merges: client Context services and the composer slot contract. */\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-api-session-controller/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport { IconChevronDownOutlineRegular, IconDataOutlineRegular, IconWarningOutlineRegular, StateDot, Toast } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { modelMenuEffortLabel, type ModelMenuChoice } from '@klarkxy/dsh-model-route'\nimport { ModelMenu, modelMenuCss } from '@klarkxy/dsh-model-route/ui'\nimport {\n MODEL_PICKER_ANCHOR_SLOT, MODEL_PICKER_FACTORY,\n type ModelPickerAnchorProps, type ModelPickerProps,\n} from '@klarkxy/dsh-model-route/model-picker'\nimport { EffortPreference } from './effort-preference.ts'\n\nexport const name = 'dsh-model-picker-client'\nexport const inject = ['slots', 'locale', 'sessions'] as const\n\n/* The seat's cell: the native entry holds priority 0, reasoning-slider -1.\n * -2 makes this seat the winner while both are registered. */\nconst MODEL_SEAT_PRIORITY = -2\n\n/* --------------------------------------------------------------------------\n * Locale\n * ------------------------------------------------------------------------ */\n\nconst NS = 'model-picker'\nexport const dictZh = {\n 'trigger.fallback': '请选择模型',\n 'trigger.aria': '选择模型,当前 {model}',\n 'trigger.ariaEffort': '选择模型,当前 {model},推理等级 {effort}',\n 'menu.model': '模型',\n 'menu.effort': '推理等级',\n 'effort.providerDefault': '跟随模型默认',\n 'search.placeholder': '搜索模型…',\n 'search.clear': '清除搜索',\n 'search.empty': '没有匹配的模型。',\n 'empty.models': '暂无可用模型',\n 'status.loading': '正在刷新模型列表…',\n 'error.action': '模型操作失败:{message}',\n 'action.retry': '重试',\n 'warning.unroutable': '当前模型不在可用目录中',\n}\nexport const dictEn = {\n 'trigger.fallback': 'Select model',\n 'trigger.aria': 'Select model, current {model}',\n 'trigger.ariaEffort': 'Select model, current {model}, reasoning effort {effort}',\n 'menu.model': 'Model',\n 'menu.effort': 'Effort',\n 'effort.providerDefault': 'Default',\n 'search.placeholder': 'Search models…',\n 'search.clear': 'Clear search',\n 'search.empty': 'No matching models.',\n 'empty.models': 'No models available.',\n 'status.loading': 'Refreshing model list…',\n 'error.action': 'Model operation failed: {message}',\n 'action.retry': 'Retry',\n 'warning.unroutable': 'The selected model is not in the available catalog',\n}\ntype PickerKey = keyof typeof dictZh\ntype Translate = (key: PickerKey, params?: Record<string, unknown>) => string\n\nfunction template(text: string, params?: Record<string, unknown>): string {\n return params ? text.replace(/\\{(\\w+)\\}/g, (_, k: string) => String(params[k] ?? `{${k}}`)) : text\n}\n\n/** Copy resolver for tests and for faces that never got a framework `t`. */\nexport function pickerCopy(locale: string | undefined): Translate {\n const dict = locale?.toLowerCase().startsWith('zh') ? dictZh : dictEn\n return (key, params) => template(dict[key], params)\n}\n\n/* --------------------------------------------------------------------------\n * Styles — token whitelist only, scoped under .dsh-model-picker\n * ------------------------------------------------------------------------ */\n\nexport const modelPickerCss = `${modelMenuCss}\n.dsh-model-picker-status {\n display: flex; flex-direction: column; gap: 4px; flex: none;\n}\n.dsh-model-picker-statusRow {\n display: flex; align-items: center; justify-content: space-between; gap: 8px;\n border-radius: var(--dsw-radius-md); padding: 5px 7px;\n color: var(--dsw-alias-state-error-primary);\n background: var(--dsw-alias-interactive-bg-hover-danger);\n font-size: 12px; line-height: 18px;\n}\n.dsh-model-picker-statusRow[data-tone=\"warn\"] {\n color: var(--dsw-alias-label-secondary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-model-picker-statusText { min-width: 0; flex: 1; overflow-wrap: anywhere; }\n.dsh-model-picker-retry {\n color: inherit; font: inherit; font-weight: 600; cursor: pointer;\n background: none; border: none; padding: 0 2px; flex: none;\n}\n.dsh-model-picker-retry:hover:not(:disabled) { text-decoration: underline; }\n.dsh-model-picker-retry:disabled { opacity: 0.6; cursor: default; }\n.dsh-model-picker-triggerIcon { display: var(--dsh-composer-model-icon-display, none); flex: none; }\n`\n\n/* --------------------------------------------------------------------------\n * Catalog shape adapters\n * ------------------------------------------------------------------------ */\n\n/** Directory provider groups → flat ModelMenu choices. */\nexport function directoryChoices(groups: ModelDirectoryState['groups'], bound?: { provider: string; model: string }): ModelMenuChoice[] {\n const choices: ModelMenuChoice[] = []\n for (const group of groups) {\n const providerName = group.name || group.id\n for (const model of group.models) {\n choices.push({\n provider: group.id,\n model: model.id,\n label: `${providerName} / ${model.name || model.id}`,\n providerLabel: providerName,\n efforts: (model.reasoning?.efforts ?? []).map(effort => ({ id: effort.id, name: effort.name || effort.id })),\n })\n }\n }\n if (bound?.provider && bound.model && !choices.some(item => item.provider === bound.provider && item.model === bound.model)) {\n choices.push({ provider: bound.provider, model: bound.model, label: `${bound.provider} / ${bound.model}`, efforts: [] })\n }\n return choices\n}\n\nfunction reasoningOf(groups: ModelDirectoryState['groups'], provider: string, model: string) {\n return groups.find(group => group.id === provider)?.models.find(entry => entry.id === model)?.reasoning\n}\n\n/** Route key only when the saved model is absent from the catalog. Effort-only\n * snapshot updates must not change this — a new `current` object is not a new list. */\nfunction outsideCatalogKey(groups: ModelDirectoryState['groups'], current: { provider: string; model: string } | null): string {\n if (!current) return ''\n for (const group of groups) {\n if (group.id !== current.provider) continue\n if (group.models.some(model => model.id === current.model)) return ''\n }\n return `${current.provider}\\0${current.model}`\n}\n\n/* Model picks submit provider+model verbatim: the adapter resolves its own\n * default effort — see the native ModelSelect.choose path. */\n\n/* --------------------------------------------------------------------------\n * Default anchor (the trigger rendered in place of the caller's row)\n * ------------------------------------------------------------------------ */\n\nexport type AnchorComponent = (props: ModelPickerAnchorProps & Record<string, unknown>) => ReactNode\n\n/**\n * DOM attributes the anchor forwards: framework-stamped ARIA, identity and\n * style fields, and event handlers. Everything else in the local props —\n * injected kit members and hook objects — never reaches the DOM.\n */\nconst TRIGGER_FORWARD = /^(aria-|data-|id$|className$|style$|title$|role$|tabIndex$|on[A-Z])/\n\n/**\n * The trigger every occurrence gets unless the caller selects its own\n * `anchor` local component. It mirrors the composer's model pill: icon +\n * label + effort caption + chevron (spinner while busy).\n */\nfunction DefaultTrigger(props: ModelPickerAnchorProps & Record<string, unknown>): ReactNode {\n const { open, disabled, busy, label, effortLabel, className, ...rest } = props as ModelPickerAnchorProps & Record<string, unknown>\n const forward: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(rest)) if (TRIGGER_FORWARD.test(key)) forward[key] = value\n return <button\n type=\"button\"\n {...forward}\n className={`dsh-model-menu-trigger${className ? ` ${className}` : ''}`}\n disabled={disabled || undefined}\n title={effortLabel ? `${label} · ${effortLabel}` : label}\n >\n <IconDataOutlineRegular className=\"dsh-model-picker-triggerIcon\" size={16} />\n <span className=\"dsh-model-menu-triggerLabel\">{label}</span>\n {effortLabel !== undefined\n ? <span className=\"dsh-model-menu-triggerEffort\">{effortLabel}</span>\n : null}\n {busy\n ? <StateDot state=\"ongoing\" />\n : <IconChevronDownOutlineRegular className={`dsh-model-menu-chevron${open ? ' dsh-model-menu-chevronOpen' : ''}`} />}\n </button>\n}\n\n/* --------------------------------------------------------------------------\n * Factory definition component\n * ------------------------------------------------------------------------ */\n\ntype ModelPickerComponentProps = FactoryComponentPropsOf<'klarkxy.model-picker'>\n\n/**\n * One picker occurrence. `props` is the consumer's ModelPickerProps plus the\n * framework seats (`t`, `useFactorySlot`, injected hooks). Open state is per\n * occurrence; a `disabled` rise closes the menu and every pick is gated so a\n * busy or disabled picker can never select.\n */\nexport function ModelPicker(props: ModelPickerComponentProps): ReactNode {\n const { t, useFactorySlot, useActiveLocale, ...input } = props as ModelPickerComponentProps & ModelPickerProps\n const activeLocale = useActiveLocale ? String(useActiveLocale(snapshot => snapshot.active)) : 'en'\n const [open, setOpen] = useState(false)\n /* `disabled` locks the trigger and every menu action but must not close an\n * already-open card: consumers pulse it with their save state, and the\n * picker's contract keeps the menu mounted so a selection never loses the\n * search, scroll, or the open slider. `busy` (selecting/loading) is softer —\n * the menu stays open so a failure can surface; only actions are gated. */\n const disabled = input.disabled === true\n /* input.busy = an owner's in-flight submission (rows gated, menu stays).\n * status.busy = data loading — it renders a banner row, never a gate. */\n const busy = input.busy === true\n const gatedRef = useRef(disabled || busy)\n gatedRef.current = disabled || busy\n const setMenuOpenRef = useRef((next: boolean): void => {})\n setMenuOpenRef.current = (next: boolean): void => {\n if (disabled && next) return\n setOpen(next)\n input.onOpenChange?.(next)\n }\n const setMenuOpen = (next: boolean): void => setMenuOpenRef.current(next)\n\n const language = input.locale ?? activeLocale\n const selected = input.selected\n const selectedChoice = useMemo(\n () => input.choices.find(choice => choice.provider === selected?.provider && choice.model === selected.model),\n [input.choices, selected?.provider, selected?.model])\n const triggerLabel = input.triggerLabel ?? selectedChoice?.label ?? (selected ? `${selected.provider} / ${selected.model}` : t('trigger.fallback'))\n const effortRows = input.efforts ?? []\n const selectedEffort = input.selectedEffort ?? ''\n /* An unset effort shows the provider-default caption, matching the slider's\n * default row — never the resolved default's own name. */\n const triggerEffortLabel = input.triggerEffortLabel\n ?? (selectedEffort\n ? modelMenuEffortLabel(effortRows.find(row => row.id === selectedEffort) ?? { id: selectedEffort, name: selectedEffort }, language)\n : effortRows.length > 0 ? input.defaultEffortLabel ?? t('effort.providerDefault') : undefined)\n\n /* The status banner occupies the menu's own header seat: a retry row for the\n * whole-request error and one warn row per provider-local failure. The\n * loading row only renders while there is nothing to pick — a refresh of an\n * already-populated catalog stays silent so a background reload (e.g. the\n * settings/document-updated fan-out after every saved selection) never\n * re-lays out the menu or steals the slider's DOM. */\n const status = input.status\n const loading = status?.busy === true && input.choices.length === 0\n const menuHeader = status && (loading || status.error || status.warning || (status.failures?.length ?? 0) > 0)\n ? <div className=\"dsh-model-picker-status\" role={status.error ? 'alert' : 'status'}>\n {loading\n ? <div className=\"dsh-model-picker-statusRow\" data-tone=\"info\">\n <span className=\"dsh-model-picker-statusText\">{t('status.loading')}</span>\n </div>\n : null}\n {status.warning\n ? <div className=\"dsh-model-picker-statusRow\" data-tone=\"warn\">\n <span className=\"dsh-model-picker-statusText\">{status.warning}</span>\n </div>\n : null}\n {status.error\n ? <div className=\"dsh-model-picker-statusRow\">\n <span className=\"dsh-model-picker-statusText\">{t('error.action', { message: status.error })}</span>\n {status.retry ? <button type=\"button\" className=\"dsh-model-picker-retry\" disabled={disabled} onClick={() => status.retry?.()}>{input.retryLabel ?? t('action.retry')}</button> : null}\n </div>\n : null}\n {(status.failures ?? []).map(failure => <div key={failure.id} className=\"dsh-model-picker-statusRow\" data-tone=\"warn\">\n <span className=\"dsh-model-picker-statusText\">{failure.name || failure.id}: {failure.message}</span>\n {status.retry ? <button type=\"button\" className=\"dsh-model-picker-retry\" disabled={disabled} onClick={() => status.retry?.()}>{input.retryLabel ?? t('action.retry')}</button> : null}\n </div>)}\n </div>\n : undefined\n\n const gate = <A extends unknown[]>(fn: ((...args: A) => void) | undefined): ((...args: A) => void) =>\n (...args) => { if (!gatedRef.current) fn?.(...args) }\n\n const Anchor = useFactorySlot(MODEL_PICKER_ANCHOR_SLOT, DefaultTrigger as FactoryLocalComponent<'klarkxy.model-picker', 'anchor'>)\n const anchor = <Anchor\n open={open}\n disabled={disabled}\n busy={busy}\n label={triggerLabel}\n effortLabel={triggerEffortLabel}\n className={input.triggerClassName}\n aria-label={triggerEffortLabel\n ? t('trigger.ariaEffort', { model: triggerLabel, effort: triggerEffortLabel })\n : t('trigger.aria', { model: triggerLabel })}\n />\n\n return <>\n <style>{modelPickerCss}</style>\n <ModelMenu\n locale={language}\n open={open}\n onOpenChange={setMenuOpen}\n anchor={anchor}\n choices={input.choices}\n selected={input.selected}\n onPick={gate(input.onPick)}\n leading={input.leading ?? []}\n onPickLeading={gate(input.onPickLeading)}\n menuHeader={menuHeader}\n disabled={disabled}\n busy={busy}\n efforts={effortRows}\n selectedEffort={selectedEffort}\n onPickEffort={gate(input.onPickEffort)}\n modelLabel={input.modelLabel ?? t('menu.model')}\n modelValue={input.modelValue ?? triggerLabel}\n effortLabel={input.effortLabel ?? t('menu.effort')}\n defaultEffortLabel={input.defaultEffortLabel ?? t('effort.providerDefault')}\n searchPlaceholder={input.searchPlaceholder ?? t('search.placeholder')}\n emptyLabel={input.emptyLabel ?? (input.choices.length === 0 ? t('empty.models') : t('search.empty'))}\n clearSearchLabel={input.clearSearchLabel ?? t('search.clear')}\n initialPane={input.initialPane ?? 'model'}\n alwaysShowSearch={input.alwaysShowSearch ?? true}\n reasoningSlider={input.reasoningSlider ?? true}\n closeOnPick={false}\n closeOnDisable={false}\n listClassName={`dsh-model-picker${input.listClassName ? ` ${input.listClassName}` : ''}`}\n className=\"dsh-model-picker\"\n />\n </>\n}\n\n/* --------------------------------------------------------------------------\n * Composer seat\n * ------------------------------------------------------------------------ */\n\ninterface SeatProps {\n sessionId: string\n locked: boolean\n t: Translate\n}\n\n/** The seat's injected face equals the native ModelSelectInjected. */\ntype InjectedSeatProps = SeatProps & ModelSelectInjected & {\n renderFactorySlot?: (name: string, props: unknown, options?: { fallback?: ReactNode }) => ReactNode\n}\n\n/**\n * The composer model seat: the same injected face the native entry exposes,\n * rendered through the shared factory so the composer and every consumer\n * share one picker implementation. The bare ModelMenu below is the last-ditch\n * path for a missing factory — the seat never loses its control.\n */\nexport function ComposerModelSeat(props: InjectedSeatProps): ReactNode {\n const { t } = props\n const directory = props.directory\n /* Subscribe by directory identity. A fresh closure every render makes\n * useSyncExternalStore resubscribe on each pass; the snapshot itself stays\n * the store's cached value, so this is not what jumps the menu, but the\n * resubscribe is needless churn on the selection that already re-renders. */\n const subscribeDirectory = useCallback((onStoreChange: () => void) => directory.subscribe(onStoreChange), [directory])\n const snapshotDirectory = useCallback(() => directory.getSnapshot(), [directory])\n const state = useSyncExternalStore(subscribeDirectory, snapshotDirectory, snapshotDirectory)\n const [toast, setToast] = useState<{ seq: number; text: string } | null>(null)\n const toastSeq = useRef(0)\n const rootRef = useRef<HTMLSpanElement | null>(null)\n\n const groups = state.groups\n const current = state.current\n const outsideKey = outsideCatalogKey(groups, current)\n const choices = useMemo(() => directoryChoices(\n groups,\n outsideKey === '' ? undefined : { provider: outsideKey.slice(0, outsideKey.indexOf('\\0')), model: outsideKey.slice(outsideKey.indexOf('\\0') + 1) },\n ), [groups, outsideKey])\n const selectedChoice = choices.find(choice => choice.provider === current?.provider && choice.model === current.model)\n const reasoning = current ? reasoningOf(groups, current.provider, current.model) : undefined\n /* The slider offers only efforts the catalog actually advertises — a saved\n * effort the model no longer declares is displayed, never listed. */\n const efforts = useMemo(() => [...(selectedChoice?.efforts ?? [])], [selectedChoice])\n const busy = state.status === 'selecting' || state.pending !== null\n\n /* Mount and every open refresh the shared directory, mirroring the native\n * seat — without this the catalog may sit idle forever. */\n useEffect(() => { props.load() }, [props.load])\n const onMenuOpenChange = (next: boolean): void => { if (next) props.load() }\n\n const report = (error: { code: string; message: string }): void => {\n toastSeq.current += 1\n setToast({ seq: toastSeq.current, text: t('error.action', { message: `${error.code}: ${error.message}` }) })\n }\n const submit = (selection: { provider: string; model: string; reasoningEffort?: string }): void => {\n void props.select(selection).then(result => {\n if (result !== undefined && !result.ok) report(result.error)\n }).catch(error => report({ code: 'model-picker/error', message: error instanceof Error ? error.message : String(error) }))\n }\n /* A saved route that left the catalog stays displayable but is not\n * routable: the synthetic row is disabled so the user cannot \"select\" a\n * model the host cannot dispatch to — matching the native seat's posture. */\n const unroutable = state.routable === false && current !== null\n const pickModel = (route: { provider: string; model: string }): void => {\n if (current?.provider === route.provider && current.model === route.model) return\n if (unroutable && route.provider === current.provider && route.model === current.model) return\n /* Native semantics: switching models submits provider+model only and lets\n * the adapter apply its own default effort. */\n submit({ provider: route.provider, model: route.model })\n }\n const pickEffort = (effort: string | undefined): void => {\n if (!current) return\n if ((current.reasoningEffort ?? undefined) === effort) return\n submit({ provider: current.provider, model: current.model, ...(effort === undefined ? {} : { reasoningEffort: effort }) })\n }\n\n const modelName = selectedChoice\n ? (selectedChoice.label.split(' / ').slice(1).join(' / ') || selectedChoice.model)\n : current?.model ?? t('trigger.fallback')\n /* Trigger caption: a saved effort shows its label; nothing saved shows the\n * provider-default caption when the model declares efforts (matching the\n * slider's default row) or the retained caption when the model is gone. */\n const effortLabel = reasoning === undefined\n ? state.retainedEffort\n : current?.reasoningEffort !== undefined\n ? modelMenuEffortLabel(reasoning.efforts.find(row => row.id === current?.reasoningEffort) ?? { id: current?.reasoningEffort ?? '', name: current?.reasoningEffort ?? '' }, undefined)\n : reasoning.efforts.length > 0 || reasoning.defaultEffort !== undefined\n ? t('effort.providerDefault')\n : undefined\n\n if (!props.available) return null\n\n const fallback = <ModelMenuFallback\n t={t}\n state={state}\n choices={choices}\n efforts={efforts}\n savedEffort={current?.reasoningEffort}\n effortLabel={effortLabel}\n modelName={modelName}\n locked={props.locked}\n busy={busy}\n onPick={pickModel}\n onPickEffort={pickEffort}\n onOpen={onMenuOpenChange}\n onRetry={() => props.load()}\n />\n\n const pickerProps: ModelPickerProps = {\n choices,\n selected: current ? { provider: current.provider, model: current.model } : undefined,\n onPick: pickModel,\n efforts,\n selectedEffort: current?.reasoningEffort ?? '',\n onPickEffort: pickEffort,\n disabled: props.locked,\n busy,\n triggerLabel: modelName,\n triggerEffortLabel: effortLabel,\n onOpenChange: onMenuOpenChange,\n status: {\n error: state.error,\n busy: state.status === 'loading',\n warning: unroutable ? t('warning.unroutable') : undefined,\n failures: state.failures,\n retry: () => props.load(),\n },\n }\n\n return <span ref={rootRef} className=\"dsh-model-picker\">\n {props.renderFactorySlot ? props.renderFactorySlot(MODEL_PICKER_FACTORY, pickerProps, { fallback }) : fallback}\n {toast !== null && <Toast\n // Toast already renders through its own body portal; keying by seq\n // restarts the banner for a fresh error.\n key={toast.seq}\n text={toast.text}\n icon={<IconWarningOutlineRegular />}\n anchor={rootRef.current?.closest('[data-composer-card]') ?? rootRef.current}\n onDone={() => setToast(null)}\n />}\n </span>\n}\n\n/** Bare-menu fallback used only if the factory never registered. */\nfunction ModelMenuFallback(props: {\n t: Translate\n state: ModelDirectoryState\n choices: ModelMenuChoice[]\n efforts: { id: string; name: string }[]\n savedEffort: string | undefined\n effortLabel: string | undefined\n modelName: string\n locked: boolean\n busy: boolean\n onPick(route: { provider: string; model: string }): void\n onPickEffort(effort: string | undefined): void\n onOpen(next: boolean): void\n onRetry(): void\n}): ReactNode {\n const { t, state } = props\n const [open, setOpen] = useState(false)\n useEffect(() => { if (props.locked) setOpen(false) }, [props.locked])\n const gated = props.locked || props.busy\n const unroutable = state.routable === false && state.current !== null\n /* Same quiet-refresh rule as the factory face: the loading banner exists\n * for the initial (empty) load only. */\n const loading = state.status === 'loading' && props.choices.length === 0\n const menuHeader = (loading || state.error || unroutable || state.failures.length > 0)\n ? <div className=\"dsh-model-picker-status\" role={state.error ? 'alert' : 'status'}>\n {loading\n ? <div className=\"dsh-model-picker-statusRow\" data-tone=\"info\">\n <span className=\"dsh-model-picker-statusText\">{t('status.loading')}</span>\n </div>\n : null}\n {unroutable\n ? <div className=\"dsh-model-picker-statusRow\" data-tone=\"warn\">\n <span className=\"dsh-model-picker-statusText\">{t('warning.unroutable')}</span>\n </div>\n : null}\n {state.error\n ? <div className=\"dsh-model-picker-statusRow\">\n <span className=\"dsh-model-picker-statusText\">{t('error.action', { message: state.error })}</span>\n <button type=\"button\" className=\"dsh-model-picker-retry\" disabled={gated} onClick={props.onRetry}>{t('action.retry')}</button>\n </div>\n : null}\n {state.failures.map(failure => <div key={failure.id} className=\"dsh-model-picker-statusRow\" data-tone=\"warn\">\n <span className=\"dsh-model-picker-statusText\">{failure.name || failure.id}: {failure.message}</span>\n <button type=\"button\" className=\"dsh-model-picker-retry\" disabled={gated} onClick={props.onRetry}>{t('action.retry')}</button>\n </div>)}\n </div>\n : undefined\n return <>\n <style>{modelPickerCss}</style>\n <ModelMenu\n locale=\"en\"\n open={open && !props.locked}\n onOpenChange={next => {\n if (props.locked) return\n setOpen(next)\n if (next) props.onOpen(next)\n }}\n anchor={<DefaultTrigger open={open} disabled={gated} busy={props.busy} label={props.modelName} effortLabel={props.effortLabel} aria-label={props.effortLabel ? t('trigger.ariaEffort', { model: props.modelName, effort: props.effortLabel }) : t('trigger.aria', { model: props.modelName })} />}\n choices={props.choices}\n selected={state.current ? { provider: state.current.provider, model: state.current.model } : undefined}\n onPick={route => { if (!gated) props.onPick(route) }}\n menuHeader={menuHeader}\n disabled={props.locked}\n busy={props.busy}\n efforts={props.efforts}\n selectedEffort={props.savedEffort ?? ''}\n onPickEffort={effort => { if (!gated) props.onPickEffort(effort) }}\n modelLabel={t('menu.model')}\n modelValue={props.modelName}\n effortLabel={t('menu.effort')}\n defaultEffortLabel={t('effort.providerDefault')}\n searchPlaceholder={t('search.placeholder')}\n emptyLabel={t('empty.models')}\n clearSearchLabel={t('search.clear')}\n initialPane=\"model\"\n alwaysShowSearch\n reasoningSlider\n closeOnPick={false}\n listClassName=\"dsh-model-picker\"\n className=\"dsh-model-picker\"\n />\n </>\n}\n\n/* --------------------------------------------------------------------------\n * Plugin apply\n * ------------------------------------------------------------------------ */\n\n/**\n * Wrap one per-session `ModelDirectory.select` with the page-lifetime effort\n * memory: a cross-route pick with no explicit effort re-attaches the route's\n * last successful human pick (only while the catalog still declares it), and\n * every confirmed selection records its effort so the Host default save —\n * `sessionController.selectModel` persists the complete selection through\n * `agentDefaultModel.saveSelection` — keeps the effort for new Sessions that\n * follow the default. Memory updates strictly on `result.ok === true`; a\n * failure leaves the remembered route untouched. Exported for the wiring spec.\n */\nexport function createPreferredSelect(\n directory: { store: ModelSelectInjected['directory']; select: ModelSelectInjected['select'] },\n preference: EffortPreference,\n): ModelSelectInjected['select'] {\n return async selection => {\n const state = directory.store.getSnapshot()\n const current = state.current\n const sameRoute = current !== null && current.provider === selection.provider && current.model === selection.model\n let final = selection\n if (!sameRoute && selection.reasoningEffort === undefined) {\n const reasoning = state.groups\n .find(group => group.id === selection.provider)?.models\n .find(model => model.id === selection.model)?.reasoning\n const effort = preference.resolve(selection, reasoning === undefined ? undefined : { efforts: reasoning.efforts.map(row => row.id) })\n if (effort !== undefined) final = { ...selection, reasoningEffort: effort }\n }\n const result = await directory.select(final)\n if (result?.ok === true) preference.remember(final, final.reasoningEffort)\n return result\n }\n}\n\nexport function apply(ctx: Context): void {\n /* Page-lifetime memory of the last successful explicit effort per route.\n * Scoped to this apply: multiple client contexts (HMR, parallel roots)\n * each own their own. */\n const preference = new EffortPreference()\n\n ctx.effect(() => {\n /* The untyped single-locale form: the typed register demands every\n * installed language dictionary, while the plugin ships zh + en. */\n const zh = ctx.locale?.register(NS, 'zh', dictZh)\n const en = ctx.locale?.register(NS, 'en', dictEn)\n return () => { zh?.(); en?.() }\n })\n\n ctx.slots.registerFactory({\n name: MODEL_PICKER_FACTORY,\n scope: 'root',\n locale: NS,\n inject: () => ({ hooks: { activeLocale: ctx.locale } }),\n slots: { [MODEL_PICKER_ANCHOR_SLOT]: { scope: 'root' } },\n }, ModelPicker as never)\n\n /* The seat waits on the model-selection service instead of probing it once:\n * if the resolver plugin mounts later, this fiber re-runs and registers;\n * if it unloads, the seat entry is disposed and the native occupant shows. */\n ctx.inject(['modelDirectories'], scope => {\n const directories = scope.modelDirectories\n scope.slots.inject('conversation.input.model', () => scope.slots.register({\n name: 'conversation.input.model',\n priority: MODEL_SEAT_PRIORITY,\n locale: NS,\n inject: (sessionId): ModelSelectInjected => {\n const unavailable: ModelSelectInjected = {\n available: false,\n directory: {\n getSnapshot: () => EMPTY_STATE,\n subscribe: () => () => {},\n update: () => {},\n set: () => {},\n },\n load: () => {},\n resolveText: text => ctx.locale?.resolveText(text) ?? String(text),\n select: async () => undefined,\n }\n if (scope.sessions?.subagentAddress?.(sessionId) !== undefined) return unavailable\n try {\n const directory = directories.directoryFor(sessionId)\n return {\n available: true,\n directory: directory.store,\n load: () => { void directory.load().catch(() => {}) },\n resolveText: text => ctx.locale?.resolveText(text) ?? String(text),\n select: createPreferredSelect(directory, preference),\n }\n } catch {\n return unavailable\n }\n },\n }, ComposerModelSeat as never))\n })\n}\n\nconst EMPTY_STATE: ModelDirectoryState = { current: null, routable: null, groups: [], failures: [], status: 'idle', pending: null, error: null }\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.inner.cjs","names":["useRef","useState","useId","useMemo","rankByName","observeStickyMenuGroups","createPortal","MenuSurface","IconChevronRightOutlineRegular","Input","IconCloseFillRegular","IconCheckOutlineRegular","MenuGroup","isValidElement","cloneElement","IconDataOutlineRegular","StateDot","IconChevronDownOutlineRegular","useState","useRef","useMemo","useCallback","useSyncExternalStore","Toast","IconWarningOutlineRegular"],"sources":["../../dsh-model-route/src/menu.ts","../../dsh-model-route/src/ui.tsx","../../dsh-model-route/src/model-picker.ts","../src/effort-preference.ts","../../dsh-plugin-kit/src/log-shared.ts","../../dsh-plugin-kit/src/client-logger.ts","../src/client.tsx"],"sourcesContent":["/**\n * Pure menu helpers over parsed catalog choices: provider grouping, display\n * names and search filtering. Pure and browser-safe like the rest of the core\n * entry — no React, no host imports. The popover component lives in `./ui.tsx`.\n */\nimport type { ModelMenuChoice } from './catalog.ts'\n\n/** Localize standard effort ids only when the provider has not supplied a display name. */\nexport function modelMenuEffortLabel(effort: { id: string; name: string }, locale?: string): string {\n if (effort.name !== effort.id) return effort.name\n const labels: Record<string, readonly [string, string]> = {\n off: ['关闭', 'Off'], none: ['无', 'None'], minimal: ['最低', 'Minimal'], low: ['低', 'Low'],\n medium: ['中', 'Medium'], high: ['高', 'High'], xhigh: ['极高', 'Extra high'],\n max: ['最高', 'Maximum'], ultra: ['超高', 'Ultra'],\n }\n return labels[effort.id]?.[locale?.toLowerCase().startsWith('zh') ? 0 : 1] ?? effort.name\n}\n\n/** One provider group in the menu, in catalog order, after applying the search query. */\nexport interface ModelMenuGroup {\n readonly provider: string\n /** Provider display name, from the catalog group or split from the \"Provider / Model\" label. */\n readonly name: string\n readonly items: readonly ModelMenuChoice[]\n}\n\n/** The short model label shown inside a provider group. */\nexport function modelMenuShortName(choice: ModelMenuChoice): string {\n const sep = choice.label.indexOf(' / ')\n return sep > 0 ? choice.label.slice(sep + 3) : choice.model\n}\n\n/** Group catalog choices by provider and filter them by a case-insensitive query. */\nexport function groupModelMenuChoices(choices: readonly ModelMenuChoice[], query: string): ModelMenuGroup[] {\n const needle = query.trim().toLowerCase()\n const matched = needle\n ? choices.filter(choice => choice.label.toLowerCase().includes(needle)\n || choice.model.toLowerCase().includes(needle)\n || choice.provider.toLowerCase().includes(needle)\n // The provider display name is a separate search channel: a catalog may\n // name a provider differently from its id, and callers search by name.\n || (choice.providerLabel?.toLowerCase().includes(needle) ?? false))\n : choices\n const groups: Array<{ provider: string; name: string; items: ModelMenuChoice[] }> = []\n for (const choice of matched) {\n const sep = choice.label.indexOf(' / ')\n const name = choice.providerLabel ?? (sep > 0 ? choice.label.slice(0, sep) : choice.provider)\n const last = groups.at(-1)\n if (last && last.provider === choice.provider) last.items.push(choice)\n else groups.push({ provider: choice.provider, name, items: [choice] })\n }\n return groups\n}\n","/**\n * ModelMenu: the standard editor of one model-route field — the visible half\n * of the x-model-route contract. A feature plugin's settings page renders it\n * for its own marked field; the model hub renders one per detected field.\n *\n * It is a plugin-side copy of the host's composer model picker\n * (dsh-client-ui-model-selection's ModelSelect), rebuilt from the official\n * primitives and the published bundle's behavior: one card that opens on the\n * root pane (Model / Effort cells), drills into the provider-grouped,\n * searchable model list or the effort list, and Escapes back before closing.\n * Sticky group headings, subsequence ranking, highlight walking and focus\n * hand-back all match the host. SYNC POINT: when the host's ModelSelect or\n * ModelSelect.module.css changes, this copy must be re-transcribed; styles\n * below may only reference allowlisted theme tokens (the --dsw-* set plus the\n * host's --ds-* motion tokens), never literal colors.\n *\n * It statically imports the primitives, so only browser clients should load\n * this entry; host code and node tests use the core entry (`./index.ts`).\n */\nimport { cloneElement, isValidElement, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, type CSSProperties, type ReactNode } from 'react'\nimport { createPortal } from 'react-dom'\nimport {\n IconCheckOutlineRegular, IconChevronRightOutlineRegular, IconCloseFillRegular, Input, MenuGroup, MenuSurface,\n observeStickyMenuGroups, rankByName,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nexport { useModelCatalog, ModelCatalogStatus } from './catalog-ui.tsx'\nexport type { UseModelCatalogOptions, ModelCatalogState, ModelCatalogStatusProps } from './catalog-ui.tsx'\nimport type { ModelMenuChoice } from './catalog.ts'\nimport { groupModelMenuChoices, modelMenuEffortLabel, modelMenuShortName } from './menu.ts'\n\n/** Extra rows rendered above the model groups (e.g. a plugin's \"follow\"/\"off\" modes). */\nexport interface ModelMenuLeadingItem {\n readonly id: string\n readonly label: ReactNode\n readonly selected?: boolean\n}\n\nexport interface ModelMenuProps {\n /** Active host locale, supplied by the owning plugin's live locale subscription. */\n readonly locale?: string\n readonly open: boolean\n readonly onOpenChange: (open: boolean) => void\n /** Trigger rendered in place; the menu anchors to it and returns focus to it. */\n readonly anchor: ReactNode\n readonly choices: readonly ModelMenuChoice[]\n readonly selected?: { readonly provider: string; readonly model: string }\n readonly onPick: (route: { provider: string; model: string }) => void\n readonly leading?: readonly ModelMenuLeadingItem[]\n readonly onPickLeading?: (id: string) => void\n /** Effort pane rows; the root Effort cell is hidden while this is empty. */\n readonly efforts?: ReadonlyArray<{ id: string; name: string }>\n readonly selectedEffort?: string\n readonly onPickEffort?: (effort: string | undefined) => void\n /** Root-cell labels and the values shown trailing them. */\n readonly modelLabel?: string\n readonly modelValue?: string\n readonly effortLabel?: string\n readonly effortValue?: string\n readonly defaultEffortLabel?: string\n readonly searchPlaceholder?: string\n readonly emptyLabel?: string\n readonly clearSearchLabel?: string\n /** Pane the menu opens on; default 'root'. 'model' opens the searchable model list directly. */\n readonly initialPane?: 'root' | 'model'\n /** Show the model search row even when the catalog has four or fewer choices. */\n readonly alwaysShowSearch?: boolean\n /**\n * Render the declared reasoning efforts as a discrete slider inside the model\n * pane. Additive: the effort list and the root Effort cell stay for the\n * default (false) mode, and only the caller-supplied effort rows are shown.\n */\n readonly reasoningSlider?: boolean\n /**\n * Optional banner rendered at the top of the menu card, above the search and\n * list — e.g. a directory status/error row. Pure library-local React content,\n * not a cross-factory data contract.\n */\n readonly menuHeader?: ReactNode\n /** Disable every action after opening; by default a true value also closes\n * the menu (closeOnDisable). */\n readonly disabled?: boolean\n /**\n * Submission in progress. Keeps the menu open (unlike `disabled`) and still\n * allows opening/closing and typing in search, but disables selection rows\n * and blocks repeated model/leading/effort/slider submissions.\n */\n readonly busy?: boolean\n /**\n * Close the card after a model pick. Default true (drill menus dismiss).\n * The composer picker sets false so a selection does not unmount the open\n * list — search and scroll belong to that card.\n */\n readonly closeOnPick?: boolean\n /**\n * Close the open card when `disabled` rises. Default true — a hard lock\n * dismisses. Keep-open callers (the composer picker) set false: an owner's\n * save-state \"disabled\" pulse gates actions without unmounting the open\n * list, and Escape/outside presses still dismiss while disabled.\n */\n readonly closeOnDisable?: boolean\n readonly className?: string\n /** Extra class on the portaled menu card, which renders under document.body. */\n readonly listClassName?: string\n}\n\ntype Pane = 'root' | 'model' | 'effort'\n\n/** Unplaced portal card: hidden but laid out at a fixed origin so measurements are real. */\nconst MEASURE_STYLE: CSSProperties = { visibility: 'hidden', left: 0, top: 0 }\n\nexport function ModelMenu(props: ModelMenuProps) {\n const language = props.locale?.toLowerCase().startsWith('zh') ? 'zh' : 'en'\n const copy = language === 'zh'\n ? { model: '模型', effort: '思考强度', default: '默认', search: '搜索模型…', empty: '没有匹配的模型', clear: '清除搜索' }\n : { model: 'Model', effort: 'Reasoning', default: 'Default', search: 'Search models…', empty: 'No matching models', clear: 'Clear search' }\n const {\n open, onOpenChange, anchor, choices, selected, onPick,\n leading = [], onPickLeading, efforts = [], selectedEffort, onPickEffort,\n modelLabel = copy.model, modelValue = '—', effortLabel = copy.effort, effortValue, defaultEffortLabel = copy.default,\n searchPlaceholder = copy.search, emptyLabel = copy.empty, clearSearchLabel = copy.clear,\n initialPane = 'root', alwaysShowSearch = false, reasoningSlider = false,\n menuHeader, disabled = false, busy = false, closeOnPick = true, closeOnDisable = true,\n className, listClassName,\n } = props\n const rootRef = useRef<HTMLSpanElement | null>(null)\n const openRef = useRef(open)\n openRef.current = open\n const pendingOpenRef = useRef(false)\n const pendingRestoreFocus = useRef(false)\n const [requestedOpen, setRequestedOpen] = useState(false)\n const menuRef = useRef<HTMLDivElement | null>(null)\n const groupsRef = useRef<HTMLDivElement | null>(null)\n const searchRef = useRef<HTMLInputElement | null>(null)\n const itemRefs = useRef<Array<HTMLButtonElement | null>>([])\n const paneFocus = useRef<Pane | 'drill' | null>(null)\n const [pane, setPane] = useState<Pane>('root')\n const [query, setQuery] = useState('')\n const [highlightedIndex, setHighlightedIndex] = useState<number | null>(null)\n /* Keyboard arrows only. Mouse focus and a rebuilt choices array must not scroll. */\n const [keyNav, setKeyNav] = useState(0)\n const [menuPos, setMenuPos] = useState<CSSProperties | null>(null)\n const id = useId()\n const showSearch = alwaysShowSearch || choices.length > 4\n const effortRows = useMemo(() => [{ id: '', name: defaultEffortLabel }, ...efforts.map(effort => ({ ...effort, name: modelMenuEffortLabel(effort, language) }))], [defaultEffortLabel, efforts, language])\n /* The official ranks each provider group by a case-insensitive ordered\n * subsequence (prefix hits first, then alignment score, then catalog order);\n * groups left empty by the query drop out. */\n const filteredGroups = useMemo(() => groupModelMenuChoices(choices, '').map(group => ({\n ...group,\n items: rankByName(group.items.map(choice => ({\n choice,\n name: modelMenuShortName(choice),\n // The match surface deliberately carries the provider id, provider display\n // name, model id and the full \"Provider / Model\" label — never only the\n // possibly-truncated short model name — so provider and model-id searches\n // resolve while the rendered name stays short.\n label: [choice.provider, choice.providerLabel, choice.model, choice.label].filter(Boolean).join(' '),\n })), showSearch ? query.trim() : ''),\n })).filter(group => group.items.length > 0), [choices, query, showSearch])\n const visibleModels = useMemo(() => filteredGroups.flatMap(group => group.items.map(item => item.choice)), [filteredGroups])\n const currentVisibleIndex = visibleModels.findIndex(choice => choice.provider === selected?.provider && choice.model === selected.model)\n const activeModelIndex = Math.min(highlightedIndex ?? Math.max(0, currentVisibleIndex), visibleModels.length - 1)\n const changeOpen = (next: boolean): void => {\n if (openRef.current === next) return\n openRef.current = next\n onOpenChange(next)\n }\n const requestOpen = (): void => {\n if (open || pendingOpenRef.current) return\n pendingOpenRef.current = true\n pendingRestoreFocus.current = false\n setRequestedOpen(true)\n }\n const close = (restoreFocus = false): void => {\n const active = document.activeElement\n pendingRestoreFocus.current = restoreFocus && (active === document.body\n || rootRef.current?.contains(active) === true || menuRef.current?.contains(active) === true)\n changeOpen(false)\n }\n const drill = (next: Pane): void => {\n setQuery('')\n setHighlightedIndex(null)\n paneFocus.current = 'drill'\n setPane(next)\n }\n /** Leave a drilled pane for the entry pane, handing the keyboard back to it.\n * A root entry refocuses the cell that opened the pane; a search-first\n * (model) entry refocuses that pane's own intent. */\n const back = (from: Pane): void => {\n paneFocus.current = initialPane === 'root' ? from : 'drill'\n setPane(initialPane)\n }\n const moveFocus = (offset: number): void => {\n const items = itemRefs.current.filter((item): item is HTMLButtonElement => item !== null && !item.disabled)\n if (!items.length) return\n const active = items.findIndex(item => item === document.activeElement)\n items[active === -1 ? (offset > 0 ? 0 : items.length - 1) : (active + offset + items.length) % items.length]?.focus()\n }\n\n // A selection can synchronously disable its trigger while the owner writes.\n // Retry on the owner's next render, once the native button can take focus.\n useLayoutEffect(() => {\n if (open || !pendingRestoreFocus.current) return\n const active = document.activeElement\n if (active !== document.body && !rootRef.current?.contains(active)) {\n pendingRestoreFocus.current = false\n return\n }\n const trigger = rootRef.current?.querySelector('button')\n if (!trigger || trigger.disabled) return\n trigger.focus()\n if (document.activeElement === trigger) pendingRestoreFocus.current = false\n })\n useEffect(() => {\n if (open || !pendingRestoreFocus.current) return\n const cancelOutside = (event: Event): void => {\n if (event.target instanceof Node && !rootRef.current?.contains(event.target)) pendingRestoreFocus.current = false\n }\n document.addEventListener('focusin', cancelOutside)\n document.addEventListener('pointerdown', cancelOutside)\n return () => {\n document.removeEventListener('focusin', cancelOutside)\n document.removeEventListener('pointerdown', cancelOutside)\n }\n })\n\n useEffect(() => {\n if (!requestedOpen) return\n pendingOpenRef.current = false\n setRequestedOpen(false)\n // The caller's trigger handler may also update the controlled open prop.\n // Check the committed state before supplying the missing open callback.\n if (!open) changeOpen(true)\n }, [requestedOpen, open])\n\n useEffect(() => {\n if (!open) return\n // A consumer may open directly at the model pane (a search-first picker).\n // The root cells stay reachable with Escape; the default stays 'root' and\n // leaves the trigger's keyboard focus intent untouched.\n setPane(initialPane)\n if (initialPane === 'model') paneFocus.current = 'drill'\n setQuery('')\n setHighlightedIndex(null)\n }, [open, initialPane])\n // A consumer that becomes busy/locked after opening must not leave actions\n // available. With closeOnDisable a true value also closes the card (the\n // trigger owns the disabled look); without it the open card stays mounted\n // and only dismissal stays available.\n useEffect(() => {\n if (disabled && open && closeOnDisable) changeOpen(false)\n }, [disabled, open, closeOnDisable])\n useEffect(() => {\n if (!open) return\n const closeOutside = (event: MouseEvent): void => {\n const target = event.target as Node\n if (rootRef.current?.contains(target) || menuRef.current?.contains(target)) return\n changeOpen(false)\n }\n /* The span's React onKeyDown already sees Escape from inside the menu —\n * portal rows bubble through the React tree. What it cannot see is focus\n * that is no longer in the tree at all: a disabled rise ejects the\n * focused row's focus to document.body, and Escape there never reaches\n * the span. This listener keeps dismissal reachable for that focus; the\n * openRef check means it never double-acts after the in-tree handler. */\n const escapeOutside = (event: KeyboardEvent): void => {\n if (event.key !== 'Escape' || event.defaultPrevented || event.isComposing) return\n if (!openRef.current) return\n event.preventDefault()\n if (pane !== initialPane) back(pane)\n else close(true)\n }\n document.addEventListener('mousedown', closeOutside)\n document.addEventListener('keydown', escapeOutside)\n return () => {\n document.removeEventListener('mousedown', closeOutside)\n document.removeEventListener('keydown', escapeOutside)\n }\n }, [open, onOpenChange, pane, initialPane])\n /* Focus intent after a pane change: the model pane takes the search field when\n * it has one, every other drill takes the checked row, and going back takes\n * the cell that opened the pane. */\n useEffect(() => {\n const intent = paneFocus.current\n // MenuSurface forwards the measurement visibility:hidden style. Browsers\n // refuse focus there, so keep intent until placement has made it visible.\n if (!open || menuPos === null || intent === null) return\n // Reopening resets a previously drilled pane in a separate commit. Entry\n // and return intent belong to the root cells, never the outgoing rows.\n if (intent !== 'drill' && pane !== 'root') return\n paneFocus.current = null\n if (intent === 'drill') {\n if (pane === 'model' && showSearch) { searchRef.current?.focus(); return }\n (menuRef.current?.querySelector<HTMLButtonElement>('[role=\"menuitemradio\"][aria-checked=\"true\"]:not([disabled])')\n ?? itemRefs.current.find(item => item !== null && !item.disabled))?.focus()\n return\n }\n itemRefs.current[intent === 'effort' ? 1 : 0]?.focus()\n }, [open, pane, showSearch, menuPos])\n useEffect(() => {\n const viewport = groupsRef.current\n if (viewport === null) return\n return observeStickyMenuGroups(viewport)\n }, [open, pane, filteredGroups])\n /* Scroll when the model pane opens, or when a keyboard arrow moves the\n * highlight. `visibleModels` is a new array whenever a directory snapshot\n * replaces `current` and the caller rebuilds equivalent choices — depending\n * on that array jumped scrollTop. Search may replace the rows; a model\n * click must not. */\n const modelPaneOpen = open && pane === 'model'\n const scrollSignal = !modelPaneOpen ? 'closed' : keyNav === 0 ? 'open' : `key:${keyNav}`\n const scrollSignalRef = useRef<string | null>(null)\n useLayoutEffect(() => {\n if (!modelPaneOpen || activeModelIndex < 0) {\n if (!modelPaneOpen) scrollSignalRef.current = null\n return\n }\n if (scrollSignalRef.current === scrollSignal) return\n scrollSignalRef.current = scrollSignal\n itemRefs.current[leading.length + activeModelIndex]?.scrollIntoView({ block: 'nearest' })\n }, [modelPaneOpen, scrollSignal, activeModelIndex, leading.length])\n /* The card hangs above the trigger, right-aligned, inside 12px viewport\n * margins — the official placement formula, re-run on scroll and resize. */\n useLayoutEffect(() => {\n if (!open) { setMenuPos(null); return }\n const place = (): void => {\n const rect = rootRef.current?.getBoundingClientRect()\n if (!rect) return\n const margin = 12, lw = menuRef.current?.offsetWidth ?? 0, lh = menuRef.current?.offsetHeight ?? 0\n let x = rect.right - lw, y = rect.top - 8 - lh\n if (lw > 0) x = Math.min(Math.max(x, margin), window.innerWidth - lw - margin)\n if (lh > 0) y = Math.min(Math.max(y, margin), window.innerHeight - lh - margin)\n setMenuPos(prev => (prev && prev.left === x && prev.top === y ? prev : { left: x, top: y }))\n }\n place()\n window.addEventListener('scroll', place, true)\n window.addEventListener('resize', place)\n return () => {\n window.removeEventListener('scroll', place, true)\n window.removeEventListener('resize', place)\n }\n }, [open, pane, choices, query])\n\n function onKeyDown(event: React.KeyboardEvent): void {\n if (event.defaultPrevented || event.nativeEvent.isComposing) return\n // Escape dismisses even while actions are disabled — a save lock gates\n // selection, not closing. A drilled pane backs out to the entry pane\n // first; the entry pane closes outright.\n if (event.key === 'Escape' && open) {\n event.preventDefault()\n if (pane !== initialPane) back(pane)\n else close(true)\n return\n }\n if (disabled) return\n if (!open && ['Enter', ' ', 'ArrowDown', 'ArrowUp'].includes(event.key)) {\n const button = event.target instanceof Element ? event.target.closest('button') : null\n if (!(button instanceof HTMLButtonElement) || button.disabled || !rootRef.current?.contains(button)) return\n // Prevent the native Enter/Space click from opening a second time.\n event.preventDefault()\n paneFocus.current = 'model'\n requestOpen()\n return\n }\n if (!open) return\n if (pane === 'model' && showSearch && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {\n event.preventDefault()\n if (visibleModels.length > 0) {\n setHighlightedIndex((activeModelIndex + (event.key === 'ArrowDown' ? 1 : -1) + visibleModels.length) % visibleModels.length)\n setKeyNav(n => n + 1)\n searchRef.current?.focus()\n }\n return\n }\n if (pane === 'model' && showSearch && event.target instanceof HTMLInputElement && (event.key === 'Enter' || (event.key === 'Tab' && !event.shiftKey))) {\n if (event.key === 'Tab' && visibleModels.length === 0) return\n event.preventDefault()\n const highlighted = visibleModels[activeModelIndex]\n // A submission in progress must not be repeated by Enter/Tab.\n if (highlighted && !busy) { onPick({ provider: highlighted.provider, model: highlighted.model }); if (closeOnPick) close(true) }\n return\n }\n if (event.key === 'Tab') {\n if (event.shiftKey) {\n event.preventDefault()\n if (pane !== initialPane) back(pane)\n else close(true)\n return\n }\n const focused = document.activeElement\n const rows = itemRefs.current.filter((item): item is HTMLButtonElement => item !== null)\n if (focused instanceof HTMLButtonElement && rows.includes(focused)) {\n event.preventDefault()\n focused.click()\n return\n }\n if (pane === 'model' && showSearch) {\n event.preventDefault()\n setHighlightedIndex(null)\n searchRef.current?.focus()\n }\n return\n }\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault()\n moveFocus(event.key === 'ArrowDown' ? 1 : -1)\n }\n }\n\n function onBlur(event: React.FocusEvent): void {\n const related = event.relatedTarget\n // A target already detached from the document (the menu re-rendering the\n // focused row) is inside for this purpose — never a dismissal.\n if (related instanceof Node\n && (rootRef.current?.contains(related) || menuRef.current?.contains(related)\n || !related.isConnected)) return\n // Keep-open mode never closes on a blur that has no connected next focus:\n // disabling the picked row, or a blur whose target raced a re-render, is\n // not the user dismissing the card. Outside presses, Escape, and focus\n // landing in a real outside node still close.\n if (!closeOnPick && !(related instanceof Node)) return\n // Disabling the focused row while a selection is in flight blurs it with\n // no next target. That is not a dismissal — closing here unmounts the card.\n if (busy && related == null) return\n if (open) changeOpen(false)\n }\n\n itemRefs.current = []\n let itemIndex = 0\n let modelIndex = 0\n const itemRef = () => {\n const at = itemIndex++\n return (node: HTMLButtonElement | null): void => { itemRefs.current[at] = node }\n }\n\n const menu = open && typeof document !== 'undefined'\n ? createPortal(\n <MenuSurface\n ref={menuRef}\n id={`${id}-menu`}\n className={`dsh-model-menu-menu${listClassName ? ` ${listClassName}` : ''}`}\n style={menuPos ?? MEASURE_STYLE}\n role={pane === 'model' ? 'group' : 'menu'}\n aria-label={modelLabel}\n lang={language}\n >\n {menuHeader ? <div className=\"dsh-model-menu-header\">{menuHeader}</div> : null}\n {pane === 'root' ? <>\n <button ref={itemRef()} type=\"button\" role=\"menuitem\" className=\"dsh-model-menu-cell\" disabled={disabled} onClick={() => drill('model')}>\n <span className=\"dsh-model-menu-cellLabel\">{modelLabel}</span>\n <span className=\"dsh-model-menu-cellValue\">{modelValue}</span>\n <IconChevronRightOutlineRegular className=\"dsh-model-menu-cellChevron\" />\n </button>\n {efforts.length > 0 && !reasoningSlider ? <button ref={itemRef()} type=\"button\" role=\"menuitem\" className=\"dsh-model-menu-cell\" disabled={disabled} onClick={() => drill('effort')}>\n <span className=\"dsh-model-menu-cellLabel\">{effortLabel}</span>\n <span className=\"dsh-model-menu-cellValue\">{effortValue ?? effortRows.find(row => row.id === (selectedEffort ?? ''))?.name ?? defaultEffortLabel}</span>\n <IconChevronRightOutlineRegular className=\"dsh-model-menu-cellChevron\" />\n </button> : null}\n </> : null}\n {pane === 'model' ? <>\n {showSearch ? <div className=\"dsh-model-menu-searchRow\">\n <Input\n ref={searchRef}\n disabled={disabled}\n className={`dsh-model-menu-search${query !== '' ? ' dsh-model-menu-searchWithQuery' : ''}`}\n type=\"text\"\n role=\"searchbox\"\n aria-label={searchPlaceholder}\n aria-controls={`${id}-models`}\n aria-activedescendant={activeModelIndex < 0 ? undefined : `${id}-model-${activeModelIndex}`}\n placeholder={searchPlaceholder}\n value={query}\n onChange={event => { setQuery(event.target.value); setHighlightedIndex(0) }}\n />\n {query !== '' ? <button type=\"button\" className=\"dsh-model-menu-searchClear\" aria-label={clearSearchLabel} disabled={disabled}\n onClick={() => { setQuery(''); setHighlightedIndex(null); searchRef.current?.focus() }}>\n <IconCloseFillRegular />\n </button> : null}\n </div> : null}\n <div ref={groupsRef} id={`${id}-models`} className=\"dsh-model-menu-groups scrollable\" role=\"menu\" aria-label={modelLabel}\n hidden={filteredGroups.length === 0}>\n {leading.length > 0 ? <div className=\"dsh-model-menu-leading\">\n {leading.map(item => (\n <button key={item.id} ref={itemRef()} type=\"button\" role=\"menuitemradio\" aria-checked={item.selected === true} disabled={disabled || busy}\n className={`dsh-model-menu-option${item.selected === true ? ' dsh-model-menu-selected' : ''}`}\n onClick={() => { if (disabled || busy) return; onPickLeading?.(item.id); if (closeOnPick) close(true) }}>\n <span className=\"dsh-model-menu-optionCopy\"><span className=\"dsh-model-menu-modelName\">{item.label}</span></span>\n <span className=\"dsh-model-menu-check\">{item.selected === true ? <IconCheckOutlineRegular /> : null}</span>\n </button>\n ))}\n </div> : null}\n {filteredGroups.map(group => (\n <MenuGroup key={group.provider} label={group.name}>\n {group.items.map(item => {\n const index = modelIndex++\n const choice = item.choice\n const checked = selected?.provider === choice.provider && selected.model === choice.model\n return <button\n key={`${choice.provider}/${choice.model}`}\n ref={itemRef()}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={checked}\n id={`${id}-model-${index}`}\n tabIndex={showSearch ? -1 : 0}\n disabled={disabled || busy}\n onFocus={() => setHighlightedIndex(index)}\n data-highlighted={index === activeModelIndex ? '' : undefined}\n className={`dsh-model-menu-option dsh-model-menu-modelOption${checked ? ' dsh-model-menu-selected' : ''}${index === activeModelIndex ? ' dsh-model-menu-optionActive' : ''}`}\n onMouseMove={index === activeModelIndex ? undefined : () => {\n if (showSearch) setHighlightedIndex(index)\n else itemRefs.current[leading.length + index]?.focus()\n }}\n title={choice.label}\n onClick={() => { if (disabled || busy) return; onPick({ provider: choice.provider, model: choice.model }); if (closeOnPick) close(true) }}\n >\n <span className=\"dsh-model-menu-optionCopy\"><span className=\"dsh-model-menu-modelName\">{modelMenuShortName(choice)}</span></span>\n <span className=\"dsh-model-menu-check\">{checked ? <IconCheckOutlineRegular /> : null}</span>\n </button>\n })}\n </MenuGroup>\n ))}\n </div>\n {reasoningSlider && efforts.length > 0 && filteredGroups.length > 0\n ? <EffortSlider label={effortLabel} rows={effortRows} selected={selectedEffort ?? ''} disabled={disabled} busy={busy}\n onPick={value => onPickEffort?.(value)} />\n : null}\n {filteredGroups.length === 0 ? <div className=\"dsh-model-menu-empty\" role=\"status\">{emptyLabel}</div> : null}\n </> : null}\n {pane === 'effort' ? <>\n {effortRows.map(row => {\n const checked = (selectedEffort ?? '') === row.id\n return <button key={row.id || '__default'} ref={itemRef()} type=\"button\" role=\"menuitemradio\" aria-checked={checked} disabled={disabled || busy}\n className={`dsh-model-menu-option${checked ? ' dsh-model-menu-selected' : ''}`}\n onClick={() => { if (disabled || busy) return; onPickEffort?.(row.id || undefined); if (closeOnPick) close(true) }}>\n <span className=\"dsh-model-menu-optionCopy\"><span className=\"dsh-model-menu-modelName\">{row.name}</span></span>\n <span className=\"dsh-model-menu-check\">{checked ? <IconCheckOutlineRegular /> : null}</span>\n </button>\n })}\n </> : null}\n </MenuSurface>,\n document.body,\n )\n : null\n const trigger = isValidElement<Record<string, unknown>>(anchor)\n ? cloneElement(anchor, { 'aria-haspopup': 'menu', 'aria-expanded': open, 'aria-controls': open ? `${id}-menu` : undefined, 'aria-disabled': disabled || undefined })\n : anchor\n return <span ref={rootRef} className={`dsh-model-menu-root${className ? ` ${className}` : ''}`} onKeyDown={onKeyDown} onBlur={onBlur}\n onClick={event => {\n if (disabled || event.defaultPrevented) return\n const button = event.target instanceof Element ? event.target.closest('button') : null\n if (!(button instanceof HTMLButtonElement) || button.disabled || !rootRef.current?.contains(button)) return\n requestOpen()\n }}\n onMouseDown={event => { if (event.target instanceof Element && menuRef.current?.contains(event.target) && event.target.closest('button') !== null) event.preventDefault() }}>\n {trigger}{menu}\n </span>\n}\n\n/**\n * Discrete reasoning-effort slider shown under the model list in enhanced mode.\n *\n * A native range input (`step=1`) over exactly the rows the caller supplies —\n * the default row plus each effort the selected model advertises — so it can\n * never invent a level. It previews locally while dragging or arrowing and\n * commits only when the gesture ends (pointer up, key up, or blur), so a drag\n * does not write on every step. The menu stays open, so adjusting the effort\n * never loses the model selection or the search query.\n *\n * The input itself stays the entire interaction and accessibility surface —\n * keyboard, ARIA, disabled and the native step snapping all come from it —\n * while the track, gradient fill and thumb below are decorative layers painted\n * from the `--_p` percentage the preview position sets on the rail. Value\n * changes only update that custom property, so the CSS transitions animate\n * between levels without remounting nodes or restarting an animation.\n */\nfunction EffortSlider(props: {\n readonly label: string\n readonly rows: ReadonlyArray<{ id: string; name: string }>\n readonly selected: string\n readonly disabled?: boolean\n readonly busy?: boolean\n readonly onPick: (effort: string | undefined) => void\n}) {\n const { label, rows, selected, disabled = false, busy = false, onPick } = props\n const active = Math.max(0, rows.findIndex(row => row.id === selected))\n const [position, setPosition] = useState(active)\n const positionRef = useRef(position)\n // A committed selection from the owner resets the preview.\n useEffect(() => { positionRef.current = active; setPosition(active) }, [active])\n const preview = (next: number): void => {\n positionRef.current = next\n setPosition(next)\n }\n // Commit once per gesture: pointer up, key up, or leaving the control. A\n // submission already in flight must not be repeated.\n const commit = (): void => {\n if (disabled || busy) return\n const row = rows[positionRef.current]\n if (row !== undefined) onPick(row.id === '' ? undefined : row.id)\n }\n const max = Math.max(0, rows.length - 1)\n const percent = max > 0 ? Math.round((position / max) * 100) : 0\n return <div className=\"dsh-model-menu-sliderGroup\" role=\"group\" aria-label={label}>\n <div className=\"dsh-model-menu-sliderHead\">\n <span className=\"dsh-model-menu-sliderTitle\">{label}</span>\n <span className=\"dsh-model-menu-sliderValue\">{rows[position]?.name}</span>\n </div>\n <div className=\"dsh-model-menu-sliderRail\" style={{ '--_p': percent } as CSSProperties}>\n <input\n type=\"range\"\n className=\"dsh-model-menu-sliderInput\"\n min={0}\n max={max}\n step={1}\n value={position}\n disabled={disabled}\n aria-label={label}\n aria-disabled={disabled || busy || undefined}\n aria-valuetext={rows[position]?.name}\n onChange={event => {\n // Read the event target, not currentTarget: a synthetic change event may\n // carry a detached `{ value }` target, while a real range event targets\n // the input itself. Both must preview the same position.\n const value = Number((event.target as HTMLInputElement).value)\n if (Number.isFinite(value)) preview(value)\n }}\n onPointerUp={commit}\n onKeyUp={commit}\n onBlur={commit}\n />\n <span className=\"dsh-model-menu-sliderTrack\" aria-hidden=\"true\">\n <span className=\"dsh-model-menu-sliderFill\"><span className=\"dsh-model-menu-sliderFillBar\" /></span>\n <span className=\"dsh-model-menu-sliderNodes\">\n {rows.map((row, index) => (\n <span key={row.id || '__default'} data-covered={index <= position ? '' : undefined}\n className=\"dsh-model-menu-sliderNode\" style={{ '--_n': max > 0 ? Math.round((index / max) * 100) : 0 } as CSSProperties} />\n ))}\n </span>\n </span>\n <span className=\"dsh-model-menu-sliderThumb\" aria-hidden=\"true\" />\n </div>\n </div>\n}\n\n/**\n * ModelMenu styles, transcribed from the official ModelSelect.module.css (the\n * published dsh-client-ui-model-selection bundle): card capped at\n * min(360px, 100vh - 96px), 34px option cells at 13/18 with 5px 7px padding,\n * 34px root cells at 13/20, a borderless 12px search row with a clear button,\n * sticky group headings (MenuGroup's own CSS), and the l1-stroke prominent\n * elevation at portal z-index 1100. The trigger mirrors the composer's 28px\n * model pill, chevron rotating open. MenuSurface paints fill and backdrop.\n * Only allowlisted --dsw- and --ds- theme tokens may appear here — a literal\n * color is a bug.\n */\nexport const modelMenuCss = `\n.dsh-model-menu-root { min-width: 0; position: relative; display: inline-flex; }\n.dsh-model-menu-trigger {\n border-radius: var(--dsw-radius-sm);\n min-width: 0;\n max-width: min(360px, 45cqw);\n height: 28px;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n background: none;\n border: none;\n outline: none;\n align-items: center;\n gap: 4px;\n padding: 0 4px 0 8px;\n font-size: 13px;\n font-weight: 400;\n line-height: 20px;\n display: flex;\n}\n.dsh-model-menu-trigger:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }\n.dsh-model-menu-trigger:focus-visible:not([data-selection-focus]) { box-shadow: 0 0 0 var(--dsw-focus-ring-width) var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary)); }\n.dsh-model-menu-trigger:disabled { color: var(--dsw-alias-label-dimmed); cursor: default; }\n.dsh-model-menu-triggerLabel { text-overflow: ellipsis; white-space: nowrap; min-width: 0; overflow: hidden; }\n.dsh-model-menu-triggerEffort { text-overflow: ellipsis; white-space: nowrap; min-width: 0; color: var(--dsw-alias-label-caption); flex-shrink: 1000; overflow: hidden; }\n.dsh-model-menu-chevron { color: var(--dsw-alias-label-caption); flex: none; transition: transform var(--ds-transition-duration) var(--ds-ease-in-out); }\n.dsh-model-menu-chevronOpen { transform: rotate(180deg); }\n/* Portal overlay: the host publishes no z-index token, so the card keeps the\n * native menu layer's 1100 verbatim. */\n.dsh-model-menu-menu {\n z-index: 1100;\n --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);\n width: max-content;\n min-width: min(240px, 100vw - 32px);\n max-width: min(420px, 100vw - 32px);\n max-height: min(360px, 100vh - 96px);\n box-shadow: var(--dsw-elevation-prominent);\n color: var(--dsw-alias-label-primary);\n --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);\n --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);\n border: 0;\n flex-direction: column;\n padding: 4px;\n display: flex;\n position: fixed;\n overflow: hidden;\n}\n.dsh-model-menu-status, .dsh-model-menu-empty { color: var(--dsw-alias-label-tertiary); padding: 8px; font-size: 12px; line-height: 18px; }\n.dsh-model-menu-header { flex: none; padding: 2px 2px 4px; }\n.dsh-model-menu-searchRow { flex-shrink: 0; margin: 2px 0 3px; position: relative; }\n.dsh-model-menu-searchRow .dsh-model-menu-search { border-radius: var(--dsw-radius-md); background: none; border: 0 solid transparent; height: auto; padding: 5px 7px; display: flex; }\n.dsh-model-menu-searchRow .dsh-model-menu-search:focus-within { border-color: transparent; }\n.dsh-model-menu-searchWithQuery { padding-right: 34px; }\n.dsh-model-menu-searchRow .dsh-model-menu-search input { padding: 0; font-size: 12px; line-height: normal; }\n.dsh-model-menu-searchRow .dsh-model-menu-search input::placeholder { color: var(--dsw-alias-label-caption); }\n/* The clear button is a circle by geometry (border-radius: 50%), a shape the\n * radius token scale does not describe. */\n.dsh-model-menu-searchClear {\n width: 24px;\n height: 24px;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n background: none;\n border: none;\n border-radius: 50%;\n justify-content: center;\n align-items: center;\n padding: 0;\n display: inline-flex;\n position: absolute;\n top: 50%;\n right: 4px;\n transform: translateY(-50%);\n}\n.dsh-model-menu-searchClear:hover, .dsh-model-menu-searchClear:focus-visible { background: var(--dsw-alias-interactive-bg-hover); outline: none; }\n.dsh-model-menu-groups { min-height: 0; overflow-y: auto; }\n.dsh-model-menu-leading { border-bottom: 0.5px solid var(--dsw-alias-border-l2); margin-bottom: 3px; padding-bottom: 3px; }\n.dsh-model-menu-option {\n box-sizing: border-box;\n border-radius: var(--dsw-radius-md);\n width: auto;\n min-width: 100%;\n min-height: 34px;\n color: inherit;\n text-align: left;\n cursor: pointer;\n background: none;\n border: none;\n outline: none;\n align-items: center;\n gap: 6px;\n padding: 5px 7px;\n display: flex;\n}\n.dsh-model-menu-option:not(.dsh-model-menu-modelOption):hover:not(:disabled),\n.dsh-model-menu-option:focus-visible,\n.dsh-model-menu-optionActive:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }\n.dsh-model-menu-modelOption:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }\n.dsh-model-menu-selected { background: none; }\n.dsh-model-menu-option:disabled { color: var(--dsw-alias-label-dimmed); cursor: default; }\n.dsh-model-menu-optionCopy { flex-direction: column; flex: 1; min-width: 0; display: flex; }\n.dsh-model-menu-modelName { color: inherit; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 400; line-height: 18px; overflow: hidden; }\n.dsh-model-menu-check { color: var(--dsw-alias-label-primary); flex: 0 0 14px; place-items: center; display: grid; }\n.dsh-model-menu-check svg { width: 14px; height: 14px; }\n.dsh-model-menu-cell {\n box-sizing: border-box;\n border-radius: var(--dsw-radius-md);\n width: auto;\n min-width: 100%;\n height: 34px;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n text-align: left;\n background: none;\n border: none;\n outline: none;\n align-items: center;\n gap: 6px;\n padding: 0 8px;\n font-size: 13px;\n line-height: 20px;\n display: flex;\n}\n.dsh-model-menu-cell:hover, .dsh-model-menu-cell:focus-visible { background: var(--dsw-alias-interactive-bg-hover); }\n.dsh-model-menu-cellLabel { white-space: nowrap; flex: none; }\n.dsh-model-menu-cellValue { text-overflow: ellipsis; white-space: nowrap; text-align: right; min-width: 0; color: var(--dsw-alias-label-tertiary); flex: auto; overflow: hidden; }\n.dsh-model-menu-cellChevron { width: 12px; height: 12px; color: var(--dsw-alias-menu-icon); flex: none; }\n/* Discrete reasoning-effort slider under the model list (enhanced mode).\n * The painted control is layered over a fully functional native range input:\n * the input stays on top, transparent, and owns pointer/keyboard/ARIA, while\n * the decorative track, fill and thumb render beneath it at pointer-events:\n * none. Position lives in one custom property (--_p, 0–100) on the rail, so\n * the only animated work a level change triggers is a clip-path/left\n * transition — no keyframes, no element churn. */\n.dsh-model-menu-sliderGroup { border-top: 0.5px solid var(--dsw-alias-border-l2); flex: none; margin-top: 4px; padding: 6px 8px 8px; }\n.dsh-model-menu-sliderHead { align-items: baseline; justify-content: space-between; gap: 8px; margin: 0 2px 4px; display: flex; }\n.dsh-model-menu-sliderTitle { color: var(--dsw-alias-label-tertiary); font-size: 12px; line-height: 18px; }\n.dsh-model-menu-sliderValue { color: var(--dsw-alias-label-primary); font-size: 13px; font-weight: 600; line-height: 20px; transition: color var(--ds-transition-duration) var(--ds-ease-in-out); }\n.dsh-model-menu-sliderRail { position: relative; direction: ltr; height: 38px; margin-top: 2px; }\n.dsh-model-menu-sliderRail:has(:disabled) { opacity: 0.45; }\n.dsh-model-menu-sliderInput {\n appearance: none;\n -webkit-appearance: none;\n box-sizing: border-box;\n border: 0;\n cursor: pointer;\n direction: ltr;\n opacity: 0;\n margin: 0;\n padding: 0;\n width: 100%;\n height: 100%;\n position: absolute;\n inset: 0;\n z-index: 1;\n touch-action: pan-y;\n}\n.dsh-model-menu-sliderInput:disabled { cursor: default; }\n/* The transparent input must keep the painted thumb's geometry: an\n * appearance:none webkit thumb defaults to 16px, which would shift the\n * end-point positions 7px off the decorative 30px disc and misplace the\n * native drag hit target. Track gets the full rail height so the whole band\n * maps to values identically. */\n.dsh-model-menu-sliderInput::-webkit-slider-runnable-track { width: 100%; height: 100%; }\n.dsh-model-menu-sliderInput::-webkit-slider-thumb { appearance: none; -webkit-appearance: none; width: 30px; height: 30px; margin: 0; }\n.dsh-model-menu-sliderInput::-moz-range-track { width: 100%; height: 100%; }\n.dsh-model-menu-sliderInput::-moz-range-thumb { width: 30px; height: 30px; margin: 0; border: 0; }\n.dsh-model-menu-sliderTrack {\n pointer-events: none;\n border-radius: 999px;\n width: 100%;\n height: 26px;\n background: var(--dsw-alias-interactive-bg-hover);\n box-shadow: inset 0 0 0 0.5px var(--dsw-alias-border-l2);\n position: absolute;\n inset-inline: 0;\n top: 50%;\n transform: translateY(-50%);\n /* No overflow:hidden — it would clip the fill's drop-shadow glow; the bar's\n * own clip-path already supplies the rounded reveal shape. */\n}\n/* The accent ramp paints the full track width once and is revealed by an\n * animated clip-path, so raising the effort unwraps more of the spectrum\n * instead of squashing the same gradient into a narrower bar. The glow lives\n * on the un-clipped parent: a filter on the clipped element itself would be\n * clipped away with it. */\n.dsh-model-menu-sliderFill {\n display: block;\n height: 100%;\n filter: drop-shadow(0 0 5px var(--dsw-alias-state-business-primary));\n transition: filter var(--ds-transition-duration) var(--ds-ease-in-out);\n}\n.dsh-model-menu-sliderInput:hover:not(:disabled) ~ .dsh-model-menu-sliderTrack .dsh-model-menu-sliderFill,\n.dsh-model-menu-sliderInput:active:not(:disabled) ~ .dsh-model-menu-sliderTrack .dsh-model-menu-sliderFill {\n filter: drop-shadow(0 0 9px var(--dsw-alias-state-business-primary));\n}\n/* The fill stops at the thumb's center, not at the track edge — at a 30px\n * thumb the end stops sit 15px in from each side, matching the node dots. */\n.dsh-model-menu-sliderFillBar {\n display: block;\n height: 100%;\n background: linear-gradient(90deg,\n var(--dsw-alias-state-business-primary),\n var(--dsw-alias-state-success-primary),\n var(--dsw-alias-state-warn-primary),\n var(--dsw-alias-state-error-primary));\n clip-path: inset(0 calc(100% - 15px - (100% - 30px) * var(--_p, 0) / 100) 0 0 round 999px);\n transition: clip-path var(--ds-transition-duration) var(--ds-ease-in-out);\n}\n/* Stop dots: one per declared row (default + every advertised effort), evenly\n * spread across the band between the two thumb-center extremes (inset 15px,\n * i.e. half the 30px thumb). --_n is 0-100 along that band. A covered dot\n * reads as a pale pin through the gradient; an uncovered one stays a neutral\n * notch on the empty track. */\n.dsh-model-menu-sliderNodes {\n pointer-events: none;\n display: block;\n position: absolute;\n inset-inline: 15px;\n inset-block: 0;\n}\n.dsh-model-menu-sliderNode {\n pointer-events: none;\n box-sizing: border-box;\n width: 4px;\n height: 4px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--dsw-alias-label-secondary) 35%, transparent);\n position: absolute;\n left: calc(var(--_n, 0) * 1%);\n top: 50%;\n transform: translate(-50%, -50%);\n transition: background-color var(--ds-transition-duration) var(--ds-ease-in-out),\n transform var(--ds-transition-duration) var(--ds-ease-in-out);\n}\n.dsh-model-menu-sliderNode[data-covered] { background: color-mix(in srgb, var(--dsw-alias-label-primary) 60%, transparent); }\n.dsh-model-menu-sliderThumb {\n pointer-events: none;\n box-sizing: border-box;\n border-radius: 50%;\n width: 30px;\n height: 30px;\n background: var(--dsw-alias-button-primary-fill);\n border: 0.5px solid var(--dsw-alias-border-l4);\n box-shadow: 0 0 0 3px var(--dsw-alias-interactive-bg-hover), var(--dsw-elevation-soft);\n position: absolute;\n left: calc((100% - 30px) * var(--_p, 0) / 100);\n top: 50%;\n transform: translateY(-50%) scale(0.92);\n transition: left var(--ds-transition-duration) var(--ds-ease-in-out),\n transform var(--ds-transition-duration) var(--ds-ease-in-out),\n box-shadow var(--ds-transition-duration) var(--ds-ease-in-out);\n}\n.dsh-model-menu-sliderInput:hover:not(:disabled) ~ .dsh-model-menu-sliderThumb { transform: translateY(-50%) scale(1); }\n.dsh-model-menu-sliderInput:active:not(:disabled) ~ .dsh-model-menu-sliderThumb {\n transform: translateY(-50%) scale(1.1);\n box-shadow: 0 0 0 4px var(--dsw-alias-interactive-bg-hover), 0 0 12px var(--dsw-alias-state-business-primary);\n}\n.dsh-model-menu-sliderInput:focus-visible ~ .dsh-model-menu-sliderThumb {\n box-shadow: 0 0 0 3px var(--dsw-alias-interactive-bg-hover),\n 0 0 0 calc(3px + var(--dsw-focus-ring-width)) var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));\n}\n@media (prefers-reduced-motion: reduce) {\n .dsh-model-menu-sliderFill, .dsh-model-menu-sliderFillBar, .dsh-model-menu-sliderThumb,\n .dsh-model-menu-sliderNode, .dsh-model-menu-sliderValue { transition: none; }\n}\n`\n","/**\n * Shared `klarkxy.model-picker` Factory contract.\n *\n * `@klarkxy/dsh-model-picker` registers one root-scoped Component Factory under\n * this name: a searchable model picker with a reasoning-effort slider, built on\n * the same ModelMenu recipe this package ships. Feature plugins opt in by\n * calling `renderFactorySlot('klarkxy.model-picker', props, options)` inside a\n * slot component; when no definition is registered the renderer resolves the\n * caller's `options.fallback`, so each consumer keeps its own native menu as\n * the fallback and gains the shared picker only while the plugin is installed.\n *\n * This entry is pure types and constants — no React, no host imports — so a\n * consumer can `import type` the declaration and the input/local props without\n * depending on the business plugin at runtime. The `SlotFactoryMap` merge is\n * what makes the `renderFactorySlot`/`registerFactory` calls type-check on\n * both sides; import it for the types only.\n */\nimport type { ModelMenuChoice, ModelCatalogFailure } from './catalog.ts'\nimport type { HostObservable } from '@deepseek-ai/dsh-client-ui-slots'\n\n/** Registered Factory name — the `renderFactorySlot`/`registerFactory` key. */\nexport const MODEL_PICKER_FACTORY = 'klarkxy.model-picker'\n/** The one caller-selectable local position: the trigger rendered in place. */\nexport const MODEL_PICKER_ANCHOR_SLOT = 'anchor'\n\n/** Extra row the picker renders above the model groups (pure data; no React). */\nexport interface ModelPickerLeadingItem {\n readonly id: string\n readonly label: string\n readonly selected?: boolean\n}\n\n/** Status banner data the picker renders inside the menu header, above the groups. */\nexport interface ModelPickerStatus {\n /** Whole-request failure text; renders with a retry action. */\n readonly error?: string | null\n /** Advisory row (e.g. the saved route left the catalog); rendered warn-toned, no retry. */\n readonly warning?: string\n /** Whether the owner is loading or selecting (dims the banner). */\n readonly busy?: boolean\n /** Provider-local failures; still usable groups stay selectable. */\n readonly failures?: readonly ModelCatalogFailure[]\n /** Reload action the banner's retry buttons call. */\n readonly retry?: () => void\n}\n\n/**\n * Occurrence input (`renderFactorySlot` `props`). Everything here is data or\n * callbacks — React content travels through the `anchor` local slot instead.\n */\nexport interface ModelPickerProps {\n /** Active UI language; `'zh*'` selects the built-in Chinese copy. */\n readonly locale?: string\n /** Flat catalog choices (grouped internally by provider). */\n readonly choices: readonly ModelMenuChoice[]\n /** Current selection highlight. */\n readonly selected?: { readonly provider: string; readonly model: string }\n /** Model pick; the picker closes after the callback runs. */\n readonly onPick: (route: { provider: string; model: string }) => void\n /** Extra rows above the model groups (e.g. a \"follow default\" row). */\n readonly leading?: readonly ModelPickerLeadingItem[]\n /** Leading-row pick; `undefined` keeps the menu open. */\n readonly onPickLeading?: (id: string) => void\n /** Declared reasoning-effort rows; the slider is hidden while empty. */\n readonly efforts?: ReadonlyArray<{ id: string; name: string }>\n /** Current effort id; `''`/undefined marks the provider-default row. */\n readonly selectedEffort?: string\n /** Effort pick; the menu stays open. `undefined` = provider default. */\n readonly onPickEffort?: (effort: string | undefined) => void\n /** Disables the trigger and every menu action. */\n readonly disabled?: boolean\n /** Trigger caption; the default anchor falls back to localized \"Select model\". */\n readonly triggerLabel?: string\n /** Current effort caption shown after the trigger label (\"model · high\"). */\n readonly triggerEffortLabel?: string\n /** Extra class on the default trigger button. */\n readonly triggerClassName?: string\n /** Show a spinner instead of the chevron while a selection settles. */\n readonly busy?: boolean\n /** Extra class on the portaled menu card. */\n readonly listClassName?: string\n /** Menu opens on the searchable model pane ('model') or the root cells. */\n readonly initialPane?: 'root' | 'model'\n /** Show the search row even for a small catalog. */\n readonly alwaysShowSearch?: boolean\n /** Show the reasoning-effort slider under the model list (default true here). */\n readonly reasoningSlider?: boolean\n /** Status banner rendered inside the menu header (load failures, retry). */\n readonly status?: ModelPickerStatus\n /** Menu open-state changes; the owner may react (e.g. refresh the catalog). */\n readonly onOpenChange?: (open: boolean) => void\n /** Copy overrides; every key is optional. */\n readonly modelLabel?: string\n readonly modelValue?: string\n readonly effortLabel?: string\n readonly defaultEffortLabel?: string\n readonly searchPlaceholder?: string\n readonly emptyLabel?: string\n readonly clearSearchLabel?: string\n readonly retryLabel?: string\n}\n\n/** Props one `anchor` local component receives (plus the framework kit). */\nexport interface ModelPickerAnchorProps {\n /** Mirror of `aria-expanded`; true while the menu is open. */\n readonly open: boolean\n /** Disabled state passed down by the owner. */\n readonly disabled: boolean\n /** Whether a selection is settling; the default anchor shows a spinner. */\n readonly busy: boolean\n /** Resolved trigger caption. */\n readonly label: string\n /** Resolved effort caption appended to the caption, if any. */\n readonly effortLabel?: string\n /** Extra class on the trigger element. */\n readonly className?: string\n /** Anchored-popup marker the picker stamps on the trigger (always 'menu'). */\n readonly 'aria-haspopup'?: 'menu'\n /** Mirror of `open`, for ARIA-compliant custom anchors. */\n readonly 'aria-expanded'?: boolean\n /** Menu element id while the menu is mounted. */\n readonly 'aria-controls'?: string\n /** Resolved accessible name for the trigger. */\n readonly 'aria-label'?: string\n /** Set when the picker is disabled; custom anchors may read it instead of `disabled`. */\n readonly 'aria-disabled'?: boolean\n}\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface SlotFactoryMap {\n /**\n * Reusable model picker: one searchable provider-grouped model list plus an\n * optional reasoning-effort slider. Consumers call `renderFactorySlot` with\n * `ModelPickerProps`; `options.slots.anchor` may supply a custom trigger\n * component typed `ModelPickerAnchorProps`, and `options.fallback` is the\n * menu rendered while no `klarkxy.model-picker` definition is registered.\n */\n 'klarkxy.model-picker': {\n scope: 'root'\n props: ModelPickerProps\n /** Occurrence inject face: the active-locale observable bound as a hook. */\n inject: { hooks: { activeLocale: HostObservable<{ active: string }> } }\n slots: {\n anchor: {\n scope: 'root'\n props: ModelPickerAnchorProps\n }\n }\n locale: 'model-picker'\n }\n }\n interface LocaleNamespaceMap {\n /** Copy owned by @klarkxy/dsh-model-picker. */\n 'model-picker':\n | 'trigger.fallback' | 'trigger.aria' | 'trigger.ariaEffort'\n | 'menu.model' | 'menu.effort' | 'effort.providerDefault'\n | 'search.placeholder' | 'search.clear' | 'search.empty' | 'empty.models'\n | 'status.loading' | 'error.action' | 'action.retry' | 'warning.unroutable'\n }\n}\n","/**\n * Effort preference — a small client-side memory for explicit reasoning-effort\n * picks, keyed by provider+model route.\n *\n * Why it exists: the Host already persists the complete default selection —\n * `sessionController.selectModel` records the Session selection and calls\n * `ctx.agentDefaultModel.saveSelection(selected)` in the background, and the\n * `agentDefaultModel` Config carries `provider`, `model` and an optional\n * `reasoningEffort` field. A Session with no recorded selection follows that\n * saved default through live `AgentOptions` accessors\n * (`dsh-api-session-controller/agent.js` `agentOptions()`), so a new Session\n * inherits the effort only while the default keeps it.\n *\n * The gap is a model switch: the picker's pick submits provider+model only\n * (native semantics — the adapter resolves its own default effort), which\n * makes `saveSelection` write a config WITHOUT `reasoningEffort`; the default\n * effort is erased and the next new Session loses it. Remembering the last\n * successful explicit effort per route and re-attaching it to later model\n * picks restores \"new Session inherits the last human setting\" without\n * touching Host code, Host events, or existing Sessions — the memory only\n * shapes what THIS surface submits.\n *\n * Rules (matching the Host contract):\n * - Only successful explicit picks are remembered. A failed `select` must\n * never update memory — nothing was recorded or saved.\n * - Choosing \"Default\" (effort `undefined`) clears the route's entry; the\n * model then follows the adapter default, never a forced prior pick.\n * - A remembered effort is re-applied only when the catalog declares it for\n * that exact route: a model that advertises no `efforts` never receives an\n * explicit effort, so \"不支援 High 的模型不會收到 High\".\n * - No persistence to disk and no Host calls: the memory lasts for the page\n * lifetime; across reloads the Host's own saved default already carries\n * the effort forward.\n * - Reads never mutate; this module never triggers an LLM call and never\n * touches subagent model choices.\n */\n\n/** One selectable route. */\nexport interface EffortRoute {\n provider: string\n model: string\n}\n\n/** A selection request: the same shape `directory.select` accepts. */\nexport interface EffortSelection extends EffortRoute {\n reasoningEffort?: string\n}\n\n/** The subset of catalog metadata the memory validates against. */\nexport interface RouteReasoning {\n /** Effort ids the model declares (`model.reasoning.efforts[].id`). */\n efforts?: readonly string[]\n}\n\n/** Normalized select result: `{ ok: true }` or `{ ok: false }`. */\nexport type SelectResult = { ok: boolean; error?: unknown } | undefined\n\ntype SelectFn = (selection: EffortSelection) => Promise<SelectResult> | SelectResult\n\nconst keyOf = (route: EffortRoute): string => JSON.stringify([route.provider, route.model])\n\n/**\n * In-memory per-route effort memory. One instance is shared by the composer\n * seat and any face that submits through `submit`, so a slider pick made in\n * one surface is what the next model pick re-attaches.\n */\nexport class EffortPreference {\n /** route key → remembered explicit effort (a cleared route has no entry). */\n private readonly efforts = new Map<string, string>()\n\n /** The remembered explicit effort for one route, or undefined. */\n effortFor(route: EffortRoute): string | undefined {\n return this.efforts.get(keyOf(route))\n }\n\n /**\n * Record one confirmed pick. `undefined` clears the route's entry —\n * \"Default\" is an explicit choice too, and must not be overridden later.\n * Callers invoke this only after the Host accepted the selection.\n */\n remember(route: EffortRoute, effort: string | undefined): void {\n const key = keyOf(route)\n if (effort === undefined) this.efforts.delete(key)\n else this.efforts.set(key, effort)\n }\n\n /**\n * Effort to attach to a fresh pick of `route`: the remembered value when\n * the catalog still declares it for that route, else undefined (the pick\n * then follows the adapter default). Validation is per-route — a model\n * without declared efforts can never inherit an effort remembered for it.\n */\n resolve(route: EffortRoute, reasoning: RouteReasoning | undefined): string | undefined {\n const effort = this.efforts.get(keyOf(route))\n if (effort === undefined) return undefined\n return reasoning?.efforts?.includes(effort) ? effort : undefined\n }\n\n /**\n * Submit helper for a MODEL pick: merge the remembered effort into\n * `selection` when no effort is already present and the target route still\n * supports it, call `select`, and remember the resolved effort only on\n * success. On failure memory is untouched and the result is returned\n * verbatim.\n *\n * This is NOT the right verb for the slider's \"Default\" row: a caller\n * clearing an effort must submit through `select` directly and call\n * `remember(route, undefined)` only after success — routing the clear\n * through `submit` would just re-attach the remembered effort.\n */\n async submit(\n selection: EffortSelection,\n reasoning: RouteReasoning | undefined,\n select: SelectFn,\n ): Promise<SelectResult> {\n const effort = selection.reasoningEffort ?? this.resolve(selection, reasoning)\n const intent: EffortSelection = effort === undefined ? { provider: selection.provider, model: selection.model } : { ...selection, reasoningEffort: effort }\n const result = await select(intent)\n /* Only a confirmed `ok: true` updates memory. `undefined` is NOT success:\n * the seat's fallback select resolves undefined for an unavailable\n * directory, and recording a pick the Host never saw would invent a\n * preference. */\n if (result?.ok !== true) return result\n this.remember(intent, intent.reasoningEffort)\n return result\n }\n}\n","export type PluginLogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fault'\n\nexport const PLUGIN_LOG_LEVELS: readonly PluginLogLevel[] = ['debug', 'info', 'warn', 'error', 'fault']\nexport const DEFAULT_PLUGIN_LOG_LEVEL: PluginLogLevel = 'info'\nexport const PLUGIN_LOG_MAX_MESSAGE_CHARS = 16_000\nexport const PLUGIN_LOG_MAX_CONTEXT_CHARS = 8_000\n\nexport type PluginLogScalar = string | number | boolean | null\nexport type PluginLogContext = Record<string, PluginLogScalar | undefined>\n\nexport interface PluginLogInput {\n level: PluginLogLevel\n event: string\n message: string\n context?: PluginLogContext\n error?: unknown\n}\n\nexport interface PluginLogError {\n name: string\n message: string\n stack?: string\n code?: string\n}\n\nexport interface PluginLogEntry {\n version: 1\n at: string\n level: PluginLogLevel\n source: string\n surface: 'host' | 'client'\n profile?: string\n event: string\n message: string\n pid?: number\n context?: Record<string, PluginLogScalar>\n error?: PluginLogError\n}\n\nexport interface PluginLogger {\n readonly source: string\n readonly file: string | null\n readonly lastWriteError: string | null\n debug(event: string, message: string, context?: PluginLogContext): boolean\n info(event: string, message: string, context?: PluginLogContext): boolean\n warn(event: string, message: string, error?: unknown, context?: PluginLogContext): boolean\n error(event: string, message: string, error?: unknown, context?: PluginLogContext): boolean\n fault(event: string, message: string, error?: unknown, context?: PluginLogContext): boolean\n write(input: PluginLogInput): boolean\n child(context: PluginLogContext): PluginLogger\n}\n\nconst SOURCE_RE = /^[a-z][a-z0-9-]{0,63}$/\nconst EVENT_RE = /^[a-z][a-z0-9._-]{0,127}$/\nconst CONTEXT_KEY_RE = /^[a-zA-Z][a-zA-Z0-9._-]{0,63}$/\nconst SECRET_KEY_RE = /(?:api[_-]?key|access[_-]?token|refresh[_-]?token|bearer|authorization|cookie|set[_-]?cookie|nonce|credential|private[_-]?key|password|secret|app[_-]?secret|client[_-]?secret|z_c0|d_c0)$/i\n\nconst CHAT_PAYLOAD_RE =\n /\"role\"\\s*:\\s*\"(?:system|user|assistant|tool)\"|\"(?:messages|content|prompt|input_text|input_image|image_url)\"\\s*:\\s*[\\[{\"']/i\nconst CREDENTIAL_BODY_RE =\n /-----BEGIN (?:RSA |EC |OPENSSH |PRIVATE )?PRIVATE KEY-----|\"type\"\\s*:\\s*\"service_account\"|credentials\\.json|\\.dsh[/\\\\](?:credentials|auth)/i\nconst AUTH_HEADER_RE = /\\b(Authorization|Proxy-Authorization|Cookie|Set-Cookie)\\s*:\\s*[^\\r\\n]*/gi\nconst BEARER_RE = /\\bBearer\\s+[A-Za-z0-9._\\-+=/]{8,}/g\nconst SECRET_FIELD_RE =\n /([\"']?(?:api[_-]?key|access[_-]?token|refresh[_-]?token|token|bearer|authorization|cookie|set-cookie|nonce|credential|private[_-]?key|password|secret|app[_-]?secret|client[_-]?secret|password|z_c0|d_c0)[\"']?\\s*[:=]\\s*)(?:\"(?:\\\\.|[^\"\\\\])*\"|'(?:\\\\.|[^'\\\\])*'|[^\\s,&;}]+)/gi\nconst SECRET_QUERY_RE =\n /([?&](?:token|api[_-]?key|key|secret|password|bootstrap|code|sig|signature|credential|password)=)[^\\s&#\"']+/gi\nconst URL_CREDENTIAL_RE = /\\b(https?:\\/\\/)[^\\s/:@]+:[^\\s/@]+@/gi\nconst BOOTSTRAP_RE = /\\/bootstrap\\/[^\\s\"'?&#]+/gi\nconst KNOWN_TOKEN_RE = /\\b(?:sk-[A-Za-z0-9_-]{10,}|gh[pousr]_[A-Za-z0-9_]{16,}|github_pat_[A-Za-z0-9_]{20,}|tvly-[A-Za-z0-9_-]{10,}|AKIA[0-9A-Z]{16})\\b/g\nconst PATH_RE = /(?:[A-Za-z]:\\\\|\\\\\\\\)[^\\s\"'`<>|]+|(?:\\/(?:home|Users|tmp|var|root)\\/|~\\/)[^\\s\"'`<>|]+/g\n\nexport function isPluginLogLevel(value: unknown): value is PluginLogLevel {\n return typeof value === 'string' && (PLUGIN_LOG_LEVELS as readonly string[]).includes(value)\n}\n\nexport function pluginLogLevelEnabled(level: PluginLogLevel, minimum: PluginLogLevel): boolean {\n return PLUGIN_LOG_LEVELS.indexOf(level) >= PLUGIN_LOG_LEVELS.indexOf(minimum)\n}\n\nexport function normalizePluginLogSource(raw: string): string {\n const stripped = String(raw || '').trim().replace(/^@[^/]+\\//, '').toLowerCase()\n .replace(/[^a-z0-9-]+/g, '-').replace(/^-+|-+$/g, '')\n const prefixed = /^[a-z]/.test(stripped) ? stripped : `p-${stripped}`\n const bounded = prefixed.slice(0, 64).replace(/-+$/g, '')\n return SOURCE_RE.test(bounded) ? bounded : 'dsh-plugin'\n}\n\nexport function normalizePluginLogEvent(raw: string): string {\n const cleaned = String(raw || '').trim().toLowerCase()\n .replace(/[^a-z0-9._-]+/g, '-').replace(/^[^a-z]+/, '').slice(0, 128)\n return EVENT_RE.test(cleaned) ? cleaned : 'plugin.event'\n}\n\n/**\n * Parse a level specification like `debug` or `dsh-zhihu=debug,dsh-dot:warn,info`.\n * Source-specific rules win over a bare fallback level.\n */\nexport function parsePluginLogLevel(\n spec: string | undefined | null,\n source?: string,\n fallback: PluginLogLevel = DEFAULT_PLUGIN_LOG_LEVEL,\n): PluginLogLevel {\n if (!spec || typeof spec !== 'string') return fallback\n const normalizedSource = source ? normalizePluginLogSource(source) : undefined\n let wildcard: PluginLogLevel | undefined\n for (const token of spec.split(',').map(part => part.trim()).filter(Boolean)) {\n const lowered = token.toLowerCase()\n if (isPluginLogLevel(lowered)) {\n wildcard = lowered\n continue\n }\n const match = /^([^=:]+)[=:]([a-z]+)$/i.exec(token)\n if (!match) continue\n const target = match[1]!.trim()\n const candidate = match[2]!.trim().toLowerCase()\n if (!isPluginLogLevel(candidate)) continue\n if (target === '*') {\n wildcard = candidate\n continue\n }\n if (normalizedSource && normalizePluginLogSource(target) === normalizedSource) {\n return candidate\n }\n }\n return wildcard ?? fallback\n}\n\nexport function sanitizePluginLogText(text: string, maxChars = PLUGIN_LOG_MAX_MESSAGE_CHARS): string {\n if (!text) return ''\n if (CREDENTIAL_BODY_RE.test(text)) return '[omitted credential material]'\n if (CHAT_PAYLOAD_RE.test(text)) return '[omitted chat payload]'\n const redacted = text\n .replace(AUTH_HEADER_RE, '$1: [redacted]')\n .replace(BEARER_RE, 'Bearer [redacted]')\n .replace(SECRET_FIELD_RE, (full, prefix: string) => {\n const value = full.slice(prefix.length)\n if (value.startsWith('\"')) return `${prefix}\"[redacted]\"`\n if (value.startsWith(\"'\")) return `${prefix}'[redacted]'`\n return `${prefix}[redacted]`\n })\n .replace(SECRET_QUERY_RE, '$1[redacted]')\n .replace(URL_CREDENTIAL_RE, '$1[redacted]@')\n .replace(BOOTSTRAP_RE, '/bootstrap/[redacted]')\n .replace(KNOWN_TOKEN_RE, '[redacted]')\n .replace(PATH_RE, '[path]')\n return truncateLogText(redacted, maxChars)\n}\n\nexport function sanitizePluginLogContext(\n input: PluginLogContext | undefined,\n): Record<string, PluginLogScalar> | undefined {\n if (!input) return undefined\n const output: Record<string, PluginLogScalar> = {}\n for (const [key, value] of Object.entries(input).slice(0, 32)) {\n if (value === undefined || !CONTEXT_KEY_RE.test(key)) continue\n if (typeof value === 'number' && !Number.isFinite(value)) continue\n if (SECRET_KEY_RE.test(key)) {\n output[key] = '[redacted]'\n continue\n }\n output[key] = typeof value === 'string' ? sanitizePluginLogText(value, 1_000) : value\n }\n if (!Object.keys(output).length) return undefined\n const encoded = JSON.stringify(output)\n if (encoded.length <= PLUGIN_LOG_MAX_CONTEXT_CHARS) return output\n return { omitted: true, reason: 'Diagnostic context exceeded its size limit.' }\n}\n\nexport function sanitizePluginLogError(error: unknown): PluginLogError | undefined {\n if (error === undefined) return undefined\n const row = error && typeof error === 'object'\n ? error as { name?: unknown; message?: unknown; stack?: unknown; code?: unknown }\n : {}\n const rawMessage = typeof row.message === 'string' ? row.message : String(error)\n const result: PluginLogError = {\n name: typeof row.name === 'string' && row.name.trim() ? sanitizePluginLogText(row.name.trim(), 100) : 'Error',\n message: sanitizePluginLogText(rawMessage) || 'Unknown error',\n }\n if (typeof row.stack === 'string' && row.stack.trim()) {\n result.stack = sanitizePluginLogText(row.stack, 24_000)\n }\n if (typeof row.code === 'string' && /^[A-Za-z0-9_./:-]{1,100}$/.test(row.code)) {\n result.code = sanitizePluginLogText(row.code, 100)\n } else if (typeof row.code === 'number' && Number.isFinite(row.code)) {\n result.code = String(row.code)\n }\n return result\n}\n\nexport function mergePluginLogContext(\n base: PluginLogContext | undefined,\n extra: PluginLogContext | undefined,\n): PluginLogContext | undefined {\n if (!base) return extra\n if (!extra) return base\n return { ...base, ...extra }\n}\n\nexport function buildPluginLogEntry(\n input: PluginLogInput,\n meta: {\n at: Date\n source: string\n surface: 'host' | 'client'\n profile?: string\n pid?: number\n correlation?: PluginLogContext\n },\n): PluginLogEntry {\n const entry: PluginLogEntry = {\n version: 1,\n at: meta.at.toISOString(),\n level: isPluginLogLevel(input.level) ? input.level : 'info',\n source: normalizePluginLogSource(meta.source),\n surface: meta.surface,\n ...(meta.profile ? { profile: meta.profile } : {}),\n event: normalizePluginLogEvent(input.event),\n message: sanitizePluginLogText(input.message || 'No diagnostic message was provided.', PLUGIN_LOG_MAX_MESSAGE_CHARS),\n ...(meta.pid !== undefined ? { pid: meta.pid } : {}),\n }\n const context = sanitizePluginLogContext(mergePluginLogContext(meta.correlation, input.context))\n if (context) entry.context = context\n const error = sanitizePluginLogError(input.error)\n if (error) entry.error = error\n return entry\n}\n\nexport function createChildPluginLogger(parent: PluginLogger, bound: PluginLogContext): PluginLogger {\n return {\n get source() { return parent.source },\n get file() { return parent.file },\n get lastWriteError() { return parent.lastWriteError },\n debug: (event, message, context) => parent.debug(event, message, mergePluginLogContext(bound, context)),\n info: (event, message, context) => parent.info(event, message, mergePluginLogContext(bound, context)),\n warn: (event, message, error, context) => parent.warn(event, message, error, mergePluginLogContext(bound, context)),\n error: (event, message, error, context) => parent.error(event, message, error, mergePluginLogContext(bound, context)),\n fault: (event, message, error, context) => parent.fault(event, message, error, mergePluginLogContext(bound, context)),\n write: input => parent.write({ ...input, context: mergePluginLogContext(bound, input.context) }),\n child: next => createChildPluginLogger(parent, mergePluginLogContext(bound, next) ?? {}),\n }\n}\n\nexport function truncateLogText(text: string, maxChars: number): string {\n if (text.length <= maxChars) return text\n const marker = '[truncated]\\n'\n if (maxChars <= marker.length) return text.slice(0, Math.max(0, maxChars))\n return `${marker}${text.slice(-(maxChars - marker.length))}`\n}\n","import {\n DEFAULT_PLUGIN_LOG_LEVEL, buildPluginLogEntry, createChildPluginLogger,\n normalizePluginLogSource, parsePluginLogLevel, pluginLogLevelEnabled,\n sanitizePluginLogText,\n type PluginLogContext, type PluginLogEntry, type PluginLogInput,\n type PluginLogLevel, type PluginLogger,\n} from './log-shared.ts'\n\nexport * from './log-shared.ts'\n\nexport const CLIENT_PLUGIN_LOG_GLOBAL = '__KLARKXY_PLUGIN_LOGS__'\nexport const CLIENT_PLUGIN_LOG_LIMIT = 500\n\nexport interface ClientPluginLoggerOptions {\n minimumLevel?: PluginLogLevel\n now?: () => Date\n bufferLimit?: number\n forwardToHostLogger?: boolean\n loadedContext?: PluginLogContext\n}\n\ntype BrowserContextLike = {\n effect?: (callback: () => () => void, label?: string) => unknown\n logger?: {\n warn?: (...args: unknown[]) => void\n error?: (...args: unknown[]) => void\n }\n}\n\ntype GlobalLogCarrier = {\n [CLIENT_PLUGIN_LOG_GLOBAL]?: PluginLogEntry[]\n window?: { localStorage?: { getItem?: (key: string) => string | null } }\n console?: {\n debug?: (...args: unknown[]) => void\n info?: (...args: unknown[]) => void\n warn?: (...args: unknown[]) => void\n error?: (...args: unknown[]) => void\n }\n}\n\nfunction readStorageFlag(key: string): string | undefined {\n try {\n const win = (globalThis as unknown as GlobalLogCarrier).window\n const storage = win?.localStorage\n const value = storage?.getItem?.(key)\n return typeof value === 'string' && value.trim() ? value.trim() : undefined\n } catch {\n return undefined\n }\n}\n\nfunction sharedClientBuffer(limit: number): PluginLogEntry[] {\n const carrier = globalThis as unknown as GlobalLogCarrier\n if (!Array.isArray(carrier[CLIENT_PLUGIN_LOG_GLOBAL])) {\n try {\n carrier[CLIENT_PLUGIN_LOG_GLOBAL] = []\n } catch {\n return []\n }\n }\n const list = carrier[CLIENT_PLUGIN_LOG_GLOBAL]!\n const overflow = list.length - limit\n if (overflow > 0) list.splice(0, overflow)\n return list\n}\n\nexport function readClientPluginLogs(source?: string): PluginLogEntry[] {\n const carrier = globalThis as unknown as GlobalLogCarrier\n const list = Array.isArray(carrier[CLIENT_PLUGIN_LOG_GLOBAL]) ? carrier[CLIENT_PLUGIN_LOG_GLOBAL]! : []\n if (!source) return list.slice()\n const normalized = normalizePluginLogSource(source)\n return list.filter(entry => entry.source === normalized)\n}\n\nexport function clearClientPluginLogs(): void {\n const carrier = globalThis as unknown as GlobalLogCarrier\n if (Array.isArray(carrier[CLIENT_PLUGIN_LOG_GLOBAL])) {\n carrier[CLIENT_PLUGIN_LOG_GLOBAL]!.length = 0\n }\n}\n\nexport function createClientPluginLogger(\n source: string,\n ctx?: unknown,\n options: ClientPluginLoggerOptions = {},\n): PluginLogger {\n const normalized = normalizePluginLogSource(source)\n const now = options.now ?? (() => new Date())\n const limit = Math.max(10, options.bufferLimit ?? CLIENT_PLUGIN_LOG_LIMIT)\n const browserCtx = ctx && typeof ctx === 'object' ? ctx as BrowserContextLike : undefined\n\n const resolveMinimum = (): PluginLogLevel => {\n if (options.minimumLevel) return options.minimumLevel\n return parsePluginLogLevel(readStorageFlag('dsh-plugin-log-level'), normalized, DEFAULT_PLUGIN_LOG_LEVEL)\n }\n\n const logger: PluginLogger = {\n source: normalized,\n file: null,\n lastWriteError: null,\n debug: (event, message, context) => logger.write({ level: 'debug', event, message, ...(context ? { context } : {}) }),\n info: (event, message, context) => logger.write({ level: 'info', event, message, ...(context ? { context } : {}) }),\n warn: (event, message, error, context) => logger.write({\n level: 'warn', event, message,\n ...(error !== undefined ? { error } : {}),\n ...(context ? { context } : {}),\n }),\n error: (event, message, error, context) => logger.write({\n level: 'error', event, message,\n ...(error !== undefined ? { error } : {}),\n ...(context ? { context } : {}),\n }),\n fault: (event, message, error, context) => logger.write({\n level: 'fault', event, message,\n ...(error !== undefined ? { error } : {}),\n ...(context ? { context } : {}),\n }),\n child: context => createChildPluginLogger(logger, context),\n write(input: PluginLogInput): boolean {\n try {\n if (!pluginLogLevelEnabled(input.level, resolveMinimum())) return false\n const entry = buildPluginLogEntry(input, {\n at: now(),\n source: normalized,\n surface: 'client',\n })\n const buffer = sharedClientBuffer(limit)\n buffer.push(entry)\n const overflow = buffer.length - limit\n if (overflow > 0) buffer.splice(0, overflow)\n\n if (options.forwardToHostLogger !== false && browserCtx?.logger) {\n const summary = sanitizePluginLogText(`${normalized} [${entry.event}]: ${entry.message}`, 500)\n if (entry.level === 'warn' && typeof browserCtx.logger.warn === 'function') {\n browserCtx.logger.warn(summary)\n } else if ((entry.level === 'error' || entry.level === 'fault') && typeof browserCtx.logger.error === 'function') {\n browserCtx.logger.error(summary)\n }\n }\n if (readStorageFlag('dsh-plugin-log-console') === '1') {\n const con = (globalThis as unknown as GlobalLogCarrier).console\n const fn = entry.level === 'debug' ? con?.debug\n : entry.level === 'info' ? con?.info\n : entry.level === 'warn' ? con?.warn\n : con?.error\n fn?.call(con, `[${normalized}] ${entry.event}: ${entry.message}`, entry)\n }\n return true\n } catch {\n return false\n }\n },\n }\n return logger\n}\n\nexport function installClientPluginLogger(\n ctx: unknown,\n source: string,\n options: ClientPluginLoggerOptions = {},\n): PluginLogger {\n const logger = createClientPluginLogger(source, ctx, options)\n logger.info('client.loaded', 'Client plugin initialized.', options.loadedContext)\n const browserCtx = ctx && typeof ctx === 'object' ? ctx as BrowserContextLike : undefined\n if (typeof browserCtx?.effect === 'function') {\n try {\n browserCtx.effect(() => () => {\n logger.debug('client.disposed', 'Client plugin disposed.')\n }, `${logger.source}.client-logger`)\n } catch {\n // Non-Cordis mock context.\n }\n }\n return logger\n}\n\nexport async function clientLogStep<T>(\n logger: PluginLogger,\n step: string,\n context: PluginLogContext | undefined,\n action: () => Promise<T>,\n completedLevel: PluginLogLevel = 'debug',\n): Promise<T> {\n const started = Date.now()\n const base = { ...context, step }\n logger.debug('step.started', 'Client step started.', base)\n try {\n const result = await action()\n logger.write({\n level: completedLevel,\n event: 'step.completed',\n message: 'Client step completed.',\n context: { ...base, durationMs: Date.now() - started },\n })\n return result\n } catch (error) {\n logger.error('step.failed', 'Client step failed.', error, {\n ...base,\n durationMs: Date.now() - started,\n })\n throw error\n }\n}\n","/**\n * Model picker, browser half.\n *\n * Two surfaces ride one component:\n *\n * - `klarkxy.model-picker` (root Factory): the searchable model picker with a\n * reasoning-effort slider that feature plugins mount through\n * `renderFactorySlot`. Its props are pure data and callbacks so consumers\n * never take a runtime dependency on this package — while the definition is\n * absent the renderer resolves the caller's `options.fallback`.\n * - `conversation.input.model` (single/session, priority -2): the composer\n * model seat, shadowing the shipped entry (priority 0) and a reasoning-slider\n * entry (priority -1). The ledger keeps every occupant, so unmounting this\n * entry restores the previous winner — the native or reference seat returns\n * automatically on disable/uninstall. The label child slot stays declared by\n * the shadowed native entry, which means only it may render it; like\n * reasoning-slider this seat renders the model name verbatim.\n *\n * The seat drives the same per-session ModelDirectory the native seat and the\n * /model popup share (catalog load, selection submission, pending/error\n * projection), so selection semantics stay host-owned.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore, type CSSProperties, type ReactNode } from 'react'\nimport type { Context } from '@deepseek-ai/cordis'\nimport type { FactoryComponentPropsOf, FactoryLocalComponent } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { ModelDirectoryState, ModelSelectInjected } from '@deepseek-ai/dsh-client-ui-model-selection/client'\n/* Type-only merges: client Context services and the composer slot contract. */\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-api-session-controller/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport { IconChevronDownOutlineRegular, IconDataOutlineRegular, IconWarningOutlineRegular, StateDot, Toast } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { modelMenuEffortLabel, type ModelMenuChoice } from '@klarkxy/dsh-model-route'\nimport { ModelMenu, modelMenuCss } from '@klarkxy/dsh-model-route/ui'\nimport {\n MODEL_PICKER_ANCHOR_SLOT, MODEL_PICKER_FACTORY,\n type ModelPickerAnchorProps, type ModelPickerProps,\n} from '@klarkxy/dsh-model-route/model-picker'\nimport { EffortPreference } from './effort-preference.ts'\nimport { installClientPluginLogger, type PluginLogger } from '@klarkxy/dsh-plugin-kit/client-logger'\n\nexport const name = 'dsh-model-picker-client'\nexport const inject = ['slots', 'locale', 'sessions'] as const\n\n/* The seat's cell: the native entry holds priority 0, reasoning-slider -1.\n * -2 makes this seat the winner while both are registered. */\nconst MODEL_SEAT_PRIORITY = -2\n\n/* --------------------------------------------------------------------------\n * Locale\n * ------------------------------------------------------------------------ */\n\nconst NS = 'model-picker'\nexport const dictZh = {\n 'trigger.fallback': '请选择模型',\n 'trigger.aria': '选择模型,当前 {model}',\n 'trigger.ariaEffort': '选择模型,当前 {model},推理等级 {effort}',\n 'menu.model': '模型',\n 'menu.effort': '推理等级',\n 'effort.providerDefault': '跟随模型默认',\n 'search.placeholder': '搜索模型…',\n 'search.clear': '清除搜索',\n 'search.empty': '没有匹配的模型。',\n 'empty.models': '暂无可用模型',\n 'status.loading': '正在刷新模型列表…',\n 'error.action': '模型操作失败:{message}',\n 'action.retry': '重试',\n 'warning.unroutable': '当前模型不在可用目录中',\n}\nexport const dictEn = {\n 'trigger.fallback': 'Select model',\n 'trigger.aria': 'Select model, current {model}',\n 'trigger.ariaEffort': 'Select model, current {model}, reasoning effort {effort}',\n 'menu.model': 'Model',\n 'menu.effort': 'Effort',\n 'effort.providerDefault': 'Default',\n 'search.placeholder': 'Search models…',\n 'search.clear': 'Clear search',\n 'search.empty': 'No matching models.',\n 'empty.models': 'No models available.',\n 'status.loading': 'Refreshing model list…',\n 'error.action': 'Model operation failed: {message}',\n 'action.retry': 'Retry',\n 'warning.unroutable': 'The selected model is not in the available catalog',\n}\ntype PickerKey = keyof typeof dictZh\ntype Translate = (key: PickerKey, params?: Record<string, unknown>) => string\n\nfunction template(text: string, params?: Record<string, unknown>): string {\n return params ? text.replace(/\\{(\\w+)\\}/g, (_, k: string) => String(params[k] ?? `{${k}}`)) : text\n}\n\n/** Copy resolver for tests and for faces that never got a framework `t`. */\nexport function pickerCopy(locale: string | undefined): Translate {\n const dict = locale?.toLowerCase().startsWith('zh') ? dictZh : dictEn\n return (key, params) => template(dict[key], params)\n}\n\n/* --------------------------------------------------------------------------\n * Styles — token whitelist only, scoped under .dsh-model-picker\n * ------------------------------------------------------------------------ */\n\nexport const modelPickerCss = `${modelMenuCss}\n.dsh-model-picker-status {\n display: flex; flex-direction: column; gap: 4px; flex: none;\n}\n.dsh-model-picker-statusRow {\n display: flex; align-items: center; justify-content: space-between; gap: 8px;\n border-radius: var(--dsw-radius-md); padding: 5px 7px;\n color: var(--dsw-alias-state-error-primary);\n background: var(--dsw-alias-interactive-bg-hover-danger);\n font-size: 12px; line-height: 18px;\n}\n.dsh-model-picker-statusRow[data-tone=\"warn\"] {\n color: var(--dsw-alias-label-secondary);\n background: var(--dsw-alias-interactive-bg-hover);\n}\n.dsh-model-picker-statusText { min-width: 0; flex: 1; overflow-wrap: anywhere; }\n.dsh-model-picker-retry {\n color: inherit; font: inherit; font-weight: 600; cursor: pointer;\n background: none; border: none; padding: 0 2px; flex: none;\n}\n.dsh-model-picker-retry:hover:not(:disabled) { text-decoration: underline; }\n.dsh-model-picker-retry:disabled { opacity: 0.6; cursor: default; }\n.dsh-model-picker-triggerIcon { display: var(--dsh-composer-model-icon-display, none); flex: none; }\n`\n\n/* --------------------------------------------------------------------------\n * Catalog shape adapters\n * ------------------------------------------------------------------------ */\n\n/** Directory provider groups → flat ModelMenu choices. */\nexport function directoryChoices(groups: ModelDirectoryState['groups'], bound?: { provider: string; model: string }): ModelMenuChoice[] {\n const choices: ModelMenuChoice[] = []\n for (const group of groups) {\n const providerName = group.name || group.id\n for (const model of group.models) {\n choices.push({\n provider: group.id,\n model: model.id,\n label: `${providerName} / ${model.name || model.id}`,\n providerLabel: providerName,\n efforts: (model.reasoning?.efforts ?? []).map(effort => ({ id: effort.id, name: effort.name || effort.id })),\n })\n }\n }\n if (bound?.provider && bound.model && !choices.some(item => item.provider === bound.provider && item.model === bound.model)) {\n choices.push({ provider: bound.provider, model: bound.model, label: `${bound.provider} / ${bound.model}`, efforts: [] })\n }\n return choices\n}\n\nfunction reasoningOf(groups: ModelDirectoryState['groups'], provider: string, model: string) {\n return groups.find(group => group.id === provider)?.models.find(entry => entry.id === model)?.reasoning\n}\n\n/** Route key only when the saved model is absent from the catalog. Effort-only\n * snapshot updates must not change this — a new `current` object is not a new list. */\nfunction outsideCatalogKey(groups: ModelDirectoryState['groups'], current: { provider: string; model: string } | null): string {\n if (!current) return ''\n for (const group of groups) {\n if (group.id !== current.provider) continue\n if (group.models.some(model => model.id === current.model)) return ''\n }\n return `${current.provider}\\0${current.model}`\n}\n\n/* Model picks submit provider+model verbatim: the adapter resolves its own\n * default effort — see the native ModelSelect.choose path. */\n\n/* --------------------------------------------------------------------------\n * Default anchor (the trigger rendered in place of the caller's row)\n * ------------------------------------------------------------------------ */\n\nexport type AnchorComponent = (props: ModelPickerAnchorProps & Record<string, unknown>) => ReactNode\n\n/**\n * DOM attributes the anchor forwards: framework-stamped ARIA, identity and\n * style fields, and event handlers. Everything else in the local props —\n * injected kit members and hook objects — never reaches the DOM.\n */\nconst TRIGGER_FORWARD = /^(aria-|data-|id$|className$|style$|title$|role$|tabIndex$|on[A-Z])/\n\n/**\n * The trigger every occurrence gets unless the caller selects its own\n * `anchor` local component. It mirrors the composer's model pill: icon +\n * label + effort caption + chevron (spinner while busy).\n */\nfunction DefaultTrigger(props: ModelPickerAnchorProps & Record<string, unknown>): ReactNode {\n const { open, disabled, busy, label, effortLabel, className, ...rest } = props as ModelPickerAnchorProps & Record<string, unknown>\n const forward: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(rest)) if (TRIGGER_FORWARD.test(key)) forward[key] = value\n return <button\n type=\"button\"\n {...forward}\n className={`dsh-model-menu-trigger${className ? ` ${className}` : ''}`}\n disabled={disabled || undefined}\n title={effortLabel ? `${label} · ${effortLabel}` : label}\n >\n <IconDataOutlineRegular className=\"dsh-model-picker-triggerIcon\" size={16} />\n <span className=\"dsh-model-menu-triggerLabel\">{label}</span>\n {effortLabel !== undefined\n ? <span className=\"dsh-model-menu-triggerEffort\">{effortLabel}</span>\n : null}\n {busy\n ? <StateDot state=\"ongoing\" />\n : <IconChevronDownOutlineRegular className={`dsh-model-menu-chevron${open ? ' dsh-model-menu-chevronOpen' : ''}`} />}\n </button>\n}\n\n/* --------------------------------------------------------------------------\n * Factory definition component\n * ------------------------------------------------------------------------ */\n\ntype ModelPickerComponentProps = FactoryComponentPropsOf<'klarkxy.model-picker'>\n\n/**\n * One picker occurrence. `props` is the consumer's ModelPickerProps plus the\n * framework seats (`t`, `useFactorySlot`, injected hooks). Open state is per\n * occurrence; a `disabled` rise closes the menu and every pick is gated so a\n * busy or disabled picker can never select.\n */\nexport function ModelPicker(props: ModelPickerComponentProps): ReactNode {\n const { t, useFactorySlot, useActiveLocale, ...input } = props as ModelPickerComponentProps & ModelPickerProps\n const activeLocale = useActiveLocale ? String(useActiveLocale(snapshot => snapshot.active)) : 'en'\n const [open, setOpen] = useState(false)\n /* `disabled` locks the trigger and every menu action but must not close an\n * already-open card: consumers pulse it with their save state, and the\n * picker's contract keeps the menu mounted so a selection never loses the\n * search, scroll, or the open slider. `busy` (selecting/loading) is softer —\n * the menu stays open so a failure can surface; only actions are gated. */\n const disabled = input.disabled === true\n /* input.busy = an owner's in-flight submission (rows gated, menu stays).\n * status.busy = data loading — it renders a banner row, never a gate. */\n const busy = input.busy === true\n const gatedRef = useRef(disabled || busy)\n gatedRef.current = disabled || busy\n const setMenuOpenRef = useRef((next: boolean): void => {})\n setMenuOpenRef.current = (next: boolean): void => {\n if (disabled && next) return\n setOpen(next)\n input.onOpenChange?.(next)\n }\n const setMenuOpen = (next: boolean): void => setMenuOpenRef.current(next)\n\n const language = input.locale ?? activeLocale\n const selected = input.selected\n const selectedChoice = useMemo(\n () => input.choices.find(choice => choice.provider === selected?.provider && choice.model === selected.model),\n [input.choices, selected?.provider, selected?.model])\n const triggerLabel = input.triggerLabel ?? selectedChoice?.label ?? (selected ? `${selected.provider} / ${selected.model}` : t('trigger.fallback'))\n const effortRows = input.efforts ?? []\n const selectedEffort = input.selectedEffort ?? ''\n /* An unset effort shows the provider-default caption, matching the slider's\n * default row — never the resolved default's own name. */\n const triggerEffortLabel = input.triggerEffortLabel\n ?? (selectedEffort\n ? modelMenuEffortLabel(effortRows.find(row => row.id === selectedEffort) ?? { id: selectedEffort, name: selectedEffort }, language)\n : effortRows.length > 0 ? input.defaultEffortLabel ?? t('effort.providerDefault') : undefined)\n\n /* The status banner occupies the menu's own header seat: a retry row for the\n * whole-request error and one warn row per provider-local failure. The\n * loading row only renders while there is nothing to pick — a refresh of an\n * already-populated catalog stays silent so a background reload (e.g. the\n * settings/document-updated fan-out after every saved selection) never\n * re-lays out the menu or steals the slider's DOM. */\n const status = input.status\n const loading = status?.busy === true && input.choices.length === 0\n const menuHeader = status && (loading || status.error || status.warning || (status.failures?.length ?? 0) > 0)\n ? <div className=\"dsh-model-picker-status\" role={status.error ? 'alert' : 'status'}>\n {loading\n ? <div className=\"dsh-model-picker-statusRow\" data-tone=\"info\">\n <span className=\"dsh-model-picker-statusText\">{t('status.loading')}</span>\n </div>\n : null}\n {status.warning\n ? <div className=\"dsh-model-picker-statusRow\" data-tone=\"warn\">\n <span className=\"dsh-model-picker-statusText\">{status.warning}</span>\n </div>\n : null}\n {status.error\n ? <div className=\"dsh-model-picker-statusRow\">\n <span className=\"dsh-model-picker-statusText\">{t('error.action', { message: status.error })}</span>\n {status.retry ? <button type=\"button\" className=\"dsh-model-picker-retry\" disabled={disabled} onClick={() => status.retry?.()}>{input.retryLabel ?? t('action.retry')}</button> : null}\n </div>\n : null}\n {(status.failures ?? []).map(failure => <div key={failure.id} className=\"dsh-model-picker-statusRow\" data-tone=\"warn\">\n <span className=\"dsh-model-picker-statusText\">{failure.name || failure.id}: {failure.message}</span>\n {status.retry ? <button type=\"button\" className=\"dsh-model-picker-retry\" disabled={disabled} onClick={() => status.retry?.()}>{input.retryLabel ?? t('action.retry')}</button> : null}\n </div>)}\n </div>\n : undefined\n\n const gate = <A extends unknown[]>(fn: ((...args: A) => void) | undefined): ((...args: A) => void) =>\n (...args) => { if (!gatedRef.current) fn?.(...args) }\n\n const Anchor = useFactorySlot(MODEL_PICKER_ANCHOR_SLOT, DefaultTrigger as FactoryLocalComponent<'klarkxy.model-picker', 'anchor'>)\n const anchor = <Anchor\n open={open}\n disabled={disabled}\n busy={busy}\n label={triggerLabel}\n effortLabel={triggerEffortLabel}\n className={input.triggerClassName}\n aria-label={triggerEffortLabel\n ? t('trigger.ariaEffort', { model: triggerLabel, effort: triggerEffortLabel })\n : t('trigger.aria', { model: triggerLabel })}\n />\n\n return <>\n <style>{modelPickerCss}</style>\n <ModelMenu\n locale={language}\n open={open}\n onOpenChange={setMenuOpen}\n anchor={anchor}\n choices={input.choices}\n selected={input.selected}\n onPick={gate(input.onPick)}\n leading={input.leading ?? []}\n onPickLeading={gate(input.onPickLeading)}\n menuHeader={menuHeader}\n disabled={disabled}\n busy={busy}\n efforts={effortRows}\n selectedEffort={selectedEffort}\n onPickEffort={gate(input.onPickEffort)}\n modelLabel={input.modelLabel ?? t('menu.model')}\n modelValue={input.modelValue ?? triggerLabel}\n effortLabel={input.effortLabel ?? t('menu.effort')}\n defaultEffortLabel={input.defaultEffortLabel ?? t('effort.providerDefault')}\n searchPlaceholder={input.searchPlaceholder ?? t('search.placeholder')}\n emptyLabel={input.emptyLabel ?? (input.choices.length === 0 ? t('empty.models') : t('search.empty'))}\n clearSearchLabel={input.clearSearchLabel ?? t('search.clear')}\n initialPane={input.initialPane ?? 'model'}\n alwaysShowSearch={input.alwaysShowSearch ?? true}\n reasoningSlider={input.reasoningSlider ?? true}\n closeOnPick={false}\n closeOnDisable={false}\n listClassName={`dsh-model-picker${input.listClassName ? ` ${input.listClassName}` : ''}`}\n className=\"dsh-model-picker\"\n />\n </>\n}\n\n/* --------------------------------------------------------------------------\n * Composer seat\n * ------------------------------------------------------------------------ */\n\ninterface SeatProps {\n sessionId: string\n locked: boolean\n t: Translate\n}\n\n/** The seat's injected face equals the native ModelSelectInjected. */\ntype InjectedSeatProps = SeatProps & ModelSelectInjected & {\n renderFactorySlot?: (name: string, props: unknown, options?: { fallback?: ReactNode }) => ReactNode\n}\n\n/**\n * The composer model seat: the same injected face the native entry exposes,\n * rendered through the shared factory so the composer and every consumer\n * share one picker implementation. The bare ModelMenu below is the last-ditch\n * path for a missing factory — the seat never loses its control.\n */\nexport function ComposerModelSeat(props: InjectedSeatProps): ReactNode {\n const { t } = props\n const directory = props.directory\n /* Subscribe by directory identity. A fresh closure every render makes\n * useSyncExternalStore resubscribe on each pass; the snapshot itself stays\n * the store's cached value, so this is not what jumps the menu, but the\n * resubscribe is needless churn on the selection that already re-renders. */\n const subscribeDirectory = useCallback((onStoreChange: () => void) => directory.subscribe(onStoreChange), [directory])\n const snapshotDirectory = useCallback(() => directory.getSnapshot(), [directory])\n const state = useSyncExternalStore(subscribeDirectory, snapshotDirectory, snapshotDirectory)\n const [toast, setToast] = useState<{ seq: number; text: string } | null>(null)\n const toastSeq = useRef(0)\n const rootRef = useRef<HTMLSpanElement | null>(null)\n\n const groups = state.groups\n const current = state.current\n const outsideKey = outsideCatalogKey(groups, current)\n const choices = useMemo(() => directoryChoices(\n groups,\n outsideKey === '' ? undefined : { provider: outsideKey.slice(0, outsideKey.indexOf('\\0')), model: outsideKey.slice(outsideKey.indexOf('\\0') + 1) },\n ), [groups, outsideKey])\n const selectedChoice = choices.find(choice => choice.provider === current?.provider && choice.model === current.model)\n const reasoning = current ? reasoningOf(groups, current.provider, current.model) : undefined\n /* The slider offers only efforts the catalog actually advertises — a saved\n * effort the model no longer declares is displayed, never listed. */\n const efforts = useMemo(() => [...(selectedChoice?.efforts ?? [])], [selectedChoice])\n const busy = state.status === 'selecting' || state.pending !== null\n\n /* Mount and every open refresh the shared directory, mirroring the native\n * seat — without this the catalog may sit idle forever. */\n useEffect(() => { props.load() }, [props.load])\n const onMenuOpenChange = (next: boolean): void => { if (next) props.load() }\n\n const report = (error: { code: string; message: string }): void => {\n toastSeq.current += 1\n setToast({ seq: toastSeq.current, text: t('error.action', { message: `${error.code}: ${error.message}` }) })\n }\n const submit = (selection: { provider: string; model: string; reasoningEffort?: string }): void => {\n void props.select(selection).then(result => {\n if (result !== undefined && !result.ok) report(result.error)\n }).catch(error => report({ code: 'model-picker/error', message: error instanceof Error ? error.message : String(error) }))\n }\n /* A saved route that left the catalog stays displayable but is not\n * routable: the synthetic row is disabled so the user cannot \"select\" a\n * model the host cannot dispatch to — matching the native seat's posture. */\n const unroutable = state.routable === false && current !== null\n const pickModel = (route: { provider: string; model: string }): void => {\n if (current?.provider === route.provider && current.model === route.model) return\n if (unroutable && route.provider === current.provider && route.model === current.model) return\n /* Native semantics: switching models submits provider+model only and lets\n * the adapter apply its own default effort. */\n submit({ provider: route.provider, model: route.model })\n }\n const pickEffort = (effort: string | undefined): void => {\n if (!current) return\n if ((current.reasoningEffort ?? undefined) === effort) return\n submit({ provider: current.provider, model: current.model, ...(effort === undefined ? {} : { reasoningEffort: effort }) })\n }\n\n const modelName = selectedChoice\n ? (selectedChoice.label.split(' / ').slice(1).join(' / ') || selectedChoice.model)\n : current?.model ?? t('trigger.fallback')\n /* Trigger caption: a saved effort shows its label; nothing saved shows the\n * provider-default caption when the model declares efforts (matching the\n * slider's default row) or the retained caption when the model is gone. */\n const effortLabel = reasoning === undefined\n ? state.retainedEffort\n : current?.reasoningEffort !== undefined\n ? modelMenuEffortLabel(reasoning.efforts.find(row => row.id === current?.reasoningEffort) ?? { id: current?.reasoningEffort ?? '', name: current?.reasoningEffort ?? '' }, undefined)\n : reasoning.efforts.length > 0 || reasoning.defaultEffort !== undefined\n ? t('effort.providerDefault')\n : undefined\n\n if (!props.available) return null\n\n const fallback = <ModelMenuFallback\n t={t}\n state={state}\n choices={choices}\n efforts={efforts}\n savedEffort={current?.reasoningEffort}\n effortLabel={effortLabel}\n modelName={modelName}\n locked={props.locked}\n busy={busy}\n onPick={pickModel}\n onPickEffort={pickEffort}\n onOpen={onMenuOpenChange}\n onRetry={() => props.load()}\n />\n\n const pickerProps: ModelPickerProps = {\n choices,\n selected: current ? { provider: current.provider, model: current.model } : undefined,\n onPick: pickModel,\n efforts,\n selectedEffort: current?.reasoningEffort ?? '',\n onPickEffort: pickEffort,\n disabled: props.locked,\n busy,\n triggerLabel: modelName,\n triggerEffortLabel: effortLabel,\n onOpenChange: onMenuOpenChange,\n status: {\n error: state.error,\n busy: state.status === 'loading',\n warning: unroutable ? t('warning.unroutable') : undefined,\n failures: state.failures,\n retry: () => props.load(),\n },\n }\n\n return <span ref={rootRef} className=\"dsh-model-picker\">\n {props.renderFactorySlot ? props.renderFactorySlot(MODEL_PICKER_FACTORY, pickerProps, { fallback }) : fallback}\n {toast !== null && <Toast\n // Toast already renders through its own body portal; keying by seq\n // restarts the banner for a fresh error.\n key={toast.seq}\n text={toast.text}\n icon={<IconWarningOutlineRegular />}\n anchor={rootRef.current?.closest('[data-composer-card]') ?? rootRef.current}\n onDone={() => setToast(null)}\n />}\n </span>\n}\n\n/** Bare-menu fallback used only if the factory never registered. */\nfunction ModelMenuFallback(props: {\n t: Translate\n state: ModelDirectoryState\n choices: ModelMenuChoice[]\n efforts: { id: string; name: string }[]\n savedEffort: string | undefined\n effortLabel: string | undefined\n modelName: string\n locked: boolean\n busy: boolean\n onPick(route: { provider: string; model: string }): void\n onPickEffort(effort: string | undefined): void\n onOpen(next: boolean): void\n onRetry(): void\n}): ReactNode {\n const { t, state } = props\n const [open, setOpen] = useState(false)\n useEffect(() => { if (props.locked) setOpen(false) }, [props.locked])\n const gated = props.locked || props.busy\n const unroutable = state.routable === false && state.current !== null\n /* Same quiet-refresh rule as the factory face: the loading banner exists\n * for the initial (empty) load only. */\n const loading = state.status === 'loading' && props.choices.length === 0\n const menuHeader = (loading || state.error || unroutable || state.failures.length > 0)\n ? <div className=\"dsh-model-picker-status\" role={state.error ? 'alert' : 'status'}>\n {loading\n ? <div className=\"dsh-model-picker-statusRow\" data-tone=\"info\">\n <span className=\"dsh-model-picker-statusText\">{t('status.loading')}</span>\n </div>\n : null}\n {unroutable\n ? <div className=\"dsh-model-picker-statusRow\" data-tone=\"warn\">\n <span className=\"dsh-model-picker-statusText\">{t('warning.unroutable')}</span>\n </div>\n : null}\n {state.error\n ? <div className=\"dsh-model-picker-statusRow\">\n <span className=\"dsh-model-picker-statusText\">{t('error.action', { message: state.error })}</span>\n <button type=\"button\" className=\"dsh-model-picker-retry\" disabled={gated} onClick={props.onRetry}>{t('action.retry')}</button>\n </div>\n : null}\n {state.failures.map(failure => <div key={failure.id} className=\"dsh-model-picker-statusRow\" data-tone=\"warn\">\n <span className=\"dsh-model-picker-statusText\">{failure.name || failure.id}: {failure.message}</span>\n <button type=\"button\" className=\"dsh-model-picker-retry\" disabled={gated} onClick={props.onRetry}>{t('action.retry')}</button>\n </div>)}\n </div>\n : undefined\n return <>\n <style>{modelPickerCss}</style>\n <ModelMenu\n locale=\"en\"\n open={open && !props.locked}\n onOpenChange={next => {\n if (props.locked) return\n setOpen(next)\n if (next) props.onOpen(next)\n }}\n anchor={<DefaultTrigger open={open} disabled={gated} busy={props.busy} label={props.modelName} effortLabel={props.effortLabel} aria-label={props.effortLabel ? t('trigger.ariaEffort', { model: props.modelName, effort: props.effortLabel }) : t('trigger.aria', { model: props.modelName })} />}\n choices={props.choices}\n selected={state.current ? { provider: state.current.provider, model: state.current.model } : undefined}\n onPick={route => { if (!gated) props.onPick(route) }}\n menuHeader={menuHeader}\n disabled={props.locked}\n busy={props.busy}\n efforts={props.efforts}\n selectedEffort={props.savedEffort ?? ''}\n onPickEffort={effort => { if (!gated) props.onPickEffort(effort) }}\n modelLabel={t('menu.model')}\n modelValue={props.modelName}\n effortLabel={t('menu.effort')}\n defaultEffortLabel={t('effort.providerDefault')}\n searchPlaceholder={t('search.placeholder')}\n emptyLabel={t('empty.models')}\n clearSearchLabel={t('search.clear')}\n initialPane=\"model\"\n alwaysShowSearch\n reasoningSlider\n closeOnPick={false}\n listClassName=\"dsh-model-picker\"\n className=\"dsh-model-picker\"\n />\n </>\n}\n\n/* --------------------------------------------------------------------------\n * Plugin apply\n * ------------------------------------------------------------------------ */\n\n/**\n * Wrap one per-session `ModelDirectory.select` with the page-lifetime effort\n * memory: a cross-route pick with no explicit effort re-attaches the route's\n * last successful human pick (only while the catalog still declares it), and\n * every confirmed selection records its effort so the Host default save —\n * `sessionController.selectModel` persists the complete selection through\n * `agentDefaultModel.saveSelection` — keeps the effort for new Sessions that\n * follow the default. Memory updates strictly on `result.ok === true`; a\n * failure leaves the remembered route untouched. Exported for the wiring spec.\n */\nexport function createPreferredSelect(\n directory: { store: ModelSelectInjected['directory']; select: ModelSelectInjected['select'] },\n preference: EffortPreference,\n logger?: PluginLogger,\n): ModelSelectInjected['select'] {\n return async selection => {\n const state = directory.store.getSnapshot()\n const current = state.current\n const sameRoute = current !== null && current.provider === selection.provider && current.model === selection.model\n let final = selection\n if (!sameRoute && selection.reasoningEffort === undefined) {\n const reasoning = state.groups\n .find(group => group.id === selection.provider)?.models\n .find(model => model.id === selection.model)?.reasoning\n const effort = preference.resolve(selection, reasoning === undefined ? undefined : { efforts: reasoning.efforts.map(row => row.id) })\n if (effort !== undefined) final = { ...selection, reasoningEffort: effort }\n }\n const result = await directory.select(final)\n if (result?.ok === true) {\n preference.remember(final, final.reasoningEffort)\n logger?.debug('model.selected', 'Applied model selection.', {\n provider: final.provider,\n model: final.model,\n effort: final.reasoningEffort ?? null,\n })\n } else if (result && result.ok === false) {\n logger?.warn('model.select-rejected', 'Model selection failed.', undefined, {\n provider: final.provider,\n model: final.model,\n })\n }\n return result\n }\n}\n\nexport function apply(ctx: Context): void {\n const logger = installClientPluginLogger(ctx, '@klarkxy/dsh-model-picker')\n /* Page-lifetime memory of the last successful explicit effort per route.\n * Scoped to this apply: multiple client contexts (HMR, parallel roots)\n * each own their own. */\n const preference = new EffortPreference()\n\n ctx.effect(() => {\n /* The untyped single-locale form: the typed register demands every\n * installed language dictionary, while the plugin ships zh + en. */\n const zh = ctx.locale?.register(NS, 'zh', dictZh)\n const en = ctx.locale?.register(NS, 'en', dictEn)\n return () => { zh?.(); en?.() }\n })\n\n ctx.slots.registerFactory({\n name: MODEL_PICKER_FACTORY,\n scope: 'root',\n locale: NS,\n inject: () => ({ hooks: { activeLocale: ctx.locale } }),\n slots: { [MODEL_PICKER_ANCHOR_SLOT]: { scope: 'root' } },\n }, ModelPicker as never)\n\n /* The seat waits on the model-selection service instead of probing it once:\n * if the resolver plugin mounts later, this fiber re-runs and registers;\n * if it unloads, the seat entry is disposed and the native occupant shows. */\n ctx.inject(['modelDirectories'], scope => {\n const directories = scope.modelDirectories\n scope.slots.inject('conversation.input.model', () => scope.slots.register({\n name: 'conversation.input.model',\n priority: MODEL_SEAT_PRIORITY,\n locale: NS,\n inject: (sessionId): ModelSelectInjected => {\n const unavailable: ModelSelectInjected = {\n available: false,\n directory: {\n getSnapshot: () => EMPTY_STATE,\n subscribe: () => () => {},\n update: () => {},\n set: () => {},\n },\n load: () => {},\n resolveText: text => ctx.locale?.resolveText(text) ?? String(text),\n select: async () => undefined,\n }\n if (scope.sessions?.subagentAddress?.(sessionId) !== undefined) return unavailable\n try {\n const directory = directories.directoryFor(sessionId)\n return {\n available: true,\n directory: directory.store,\n load: () => {\n void directory.load().catch(error => {\n logger.warn('directory.load-failed', 'Model directory load failed.', error, { sessionId })\n })\n },\n resolveText: text => ctx.locale?.resolveText(text) ?? String(text),\n select: createPreferredSelect(directory, preference, logger),\n }\n } catch (error) {\n logger.warn('directory.unavailable', 'Could not resolve model directory for session.', error, { sessionId })\n return unavailable\n }\n },\n }, ComposerModelSeat as never))\n })\n}\n\nconst EMPTY_STATE: ModelDirectoryState = { current: null, routable: null, groups: [], failures: [], status: 'idle', pending: null, error: null }\n"],"mappings":";;;;;;;AAQA,SAAgB,qBAAqB,QAAsC,QAAyB;CAClG,IAAI,OAAO,SAAS,OAAO,IAAI,OAAO,OAAO;CAM7C,OAAO;EAJL,KAAK,CAAC,MAAM,KAAK;EAAG,MAAM,CAAC,KAAK,MAAM;EAAG,SAAS,CAAC,MAAM,SAAS;EAAG,KAAK,CAAC,KAAK,KAAK;EACrF,QAAQ,CAAC,KAAK,QAAQ;EAAG,MAAM,CAAC,KAAK,MAAM;EAAG,OAAO,CAAC,MAAM,YAAY;EACxE,KAAK,CAAC,MAAM,SAAS;EAAG,OAAO,CAAC,MAAM,OAAO;CAEnC,EAAE,OAAO,GAAG,GAAG,QAAQ,YAAY,CAAC,CAAC,WAAW,IAAI,IAAI,IAAI,MAAM,OAAO;AACvF;;AAWA,SAAgB,mBAAmB,QAAiC;CAClE,MAAM,MAAM,OAAO,MAAM,QAAQ,KAAK;CACtC,OAAO,MAAM,IAAI,OAAO,MAAM,MAAM,MAAM,CAAC,IAAI,OAAO;AACxD;;AAGA,SAAgB,sBAAsB,SAAqC,OAAiC;CAC1G,MAAM,SAAS,MAAM,KAAK,CAAC,CAAC,YAAY;CACxC,MAAM,UAAU,SACZ,QAAQ,QAAO,WAAU,OAAO,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,KAChE,OAAO,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,KAC1C,OAAO,SAAS,YAAY,CAAC,CAAC,SAAS,MAAM,MAG5C,OAAO,eAAe,YAAY,CAAC,CAAC,SAAS,MAAM,KAAK,MAAM,IAClE;CACJ,MAAM,SAA8E,CAAC;CACrF,KAAK,MAAM,UAAU,SAAS;EAC5B,MAAM,MAAM,OAAO,MAAM,QAAQ,KAAK;EACtC,MAAM,OAAO,OAAO,kBAAkB,MAAM,IAAI,OAAO,MAAM,MAAM,GAAG,GAAG,IAAI,OAAO;EACpF,MAAM,OAAO,OAAO,GAAG,EAAE;EACzB,IAAI,QAAQ,KAAK,aAAa,OAAO,UAAU,KAAK,MAAM,KAAK,MAAM;OAChE,OAAO,KAAK;GAAE,UAAU,OAAO;GAAU;GAAM,OAAO,CAAC,MAAM;EAAE,CAAC;CACvE;CACA,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;ACwDA,MAAM,gBAA+B;CAAE,YAAY;CAAU,MAAM;CAAG,KAAK;AAAE;AAE7E,SAAgB,UAAU,OAAuB;CAC/C,MAAM,WAAW,MAAM,QAAQ,YAAY,CAAC,CAAC,WAAW,IAAI,IAAI,OAAO;CACvE,MAAM,OAAO,aAAa,OACtB;EAAE,OAAO;EAAM,QAAQ;EAAQ,SAAS;EAAM,QAAQ;EAAS,OAAO;EAAW,OAAO;CAAO,IAC/F;EAAE,OAAO;EAAS,QAAQ;EAAa,SAAS;EAAW,QAAQ;EAAkB,OAAO;EAAsB,OAAO;CAAe;CAC5I,MAAM,EACJ,MAAM,cAAc,QAAQ,SAAS,UAAU,QAC/C,UAAU,CAAC,GAAG,eAAe,UAAU,CAAC,GAAG,gBAAgB,cAC3D,aAAa,KAAK,OAAO,aAAa,KAAK,cAAc,KAAK,QAAQ,aAAa,qBAAqB,KAAK,SAC7G,oBAAoB,KAAK,QAAQ,aAAa,KAAK,OAAO,mBAAmB,KAAK,OAClF,cAAc,QAAQ,mBAAmB,OAAO,kBAAkB,OAClE,YAAY,WAAW,OAAO,OAAO,OAAO,cAAc,MAAM,iBAAiB,MACjF,WAAW,kBACT;CACJ,MAAM,WAAA,GAAUA,MAAAA,OAAAA,CAA+B,IAAI;CACnD,MAAM,WAAA,GAAUA,MAAAA,OAAAA,CAAO,IAAI;CAC3B,QAAQ,UAAU;CAClB,MAAM,kBAAA,GAAiBA,MAAAA,OAAAA,CAAO,KAAK;CACnC,MAAM,uBAAA,GAAsBA,MAAAA,OAAAA,CAAO,KAAK;CACxC,MAAM,CAAC,eAAe,qBAAA,GAAoBC,MAAAA,SAAAA,CAAS,KAAK;CACxD,MAAM,WAAA,GAAUD,MAAAA,OAAAA,CAA8B,IAAI;CAClD,MAAM,aAAA,GAAYA,MAAAA,OAAAA,CAA8B,IAAI;CACpD,MAAM,aAAA,GAAYA,MAAAA,OAAAA,CAAgC,IAAI;CACtD,MAAM,YAAA,GAAWA,MAAAA,OAAAA,CAAwC,CAAC,CAAC;CAC3D,MAAM,aAAA,GAAYA,MAAAA,OAAAA,CAA8B,IAAI;CACpD,MAAM,CAAC,MAAM,YAAA,GAAWC,MAAAA,SAAAA,CAAe,MAAM;CAC7C,MAAM,CAAC,OAAO,aAAA,GAAYA,MAAAA,SAAAA,CAAS,EAAE;CACrC,MAAM,CAAC,kBAAkB,wBAAA,GAAuBA,MAAAA,SAAAA,CAAwB,IAAI;CAE5E,MAAM,CAAC,QAAQ,cAAA,GAAaA,MAAAA,SAAAA,CAAS,CAAC;CACtC,MAAM,CAAC,SAAS,eAAA,GAAcA,MAAAA,SAAAA,CAA+B,IAAI;CACjE,MAAM,MAAA,GAAKC,MAAAA,MAAAA,CAAM;CACjB,MAAM,aAAa,oBAAoB,QAAQ,SAAS;CACxD,MAAM,cAAA,GAAaC,MAAAA,QAAAA,OAAc,CAAC;EAAE,IAAI;EAAI,MAAM;CAAmB,GAAG,GAAG,QAAQ,KAAI,YAAW;EAAE,GAAG;EAAQ,MAAM,qBAAqB,QAAQ,QAAQ;CAAE,EAAE,CAAC,GAAG;EAAC;EAAoB;EAAS;CAAQ,CAAC;CAIzM,MAAM,kBAAA,GAAiBA,MAAAA,QAAAA,OAAc,sBAAsB,SAAS,EAAE,CAAC,CAAC,KAAI,WAAU;EACpF,GAAG;EACH,QAAA,GAAOC,sCAAAA,WAAAA,CAAW,MAAM,MAAM,KAAI,YAAW;GAC3C;GACA,MAAM,mBAAmB,MAAM;GAK/B,OAAO;IAAC,OAAO;IAAU,OAAO;IAAe,OAAO;IAAO,OAAO;GAAK,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;EACrG,EAAE,GAAG,aAAa,MAAM,KAAK,IAAI,EAAE;CACrC,EAAE,CAAC,CAAC,QAAO,UAAS,MAAM,MAAM,SAAS,CAAC,GAAG;EAAC;EAAS;EAAO;CAAU,CAAC;CACzE,MAAM,iBAAA,GAAgBD,MAAAA,QAAAA,OAAc,eAAe,SAAQ,UAAS,MAAM,MAAM,KAAI,SAAQ,KAAK,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC;CAC3H,MAAM,sBAAsB,cAAc,WAAU,WAAU,OAAO,aAAa,UAAU,YAAY,OAAO,UAAU,SAAS,KAAK;CACvI,MAAM,mBAAmB,KAAK,IAAI,oBAAoB,KAAK,IAAI,GAAG,mBAAmB,GAAG,cAAc,SAAS,CAAC;CAChH,MAAM,cAAc,SAAwB;EAC1C,IAAI,QAAQ,YAAY,MAAM;EAC9B,QAAQ,UAAU;EAClB,aAAa,IAAI;CACnB;CACA,MAAM,oBAA0B;EAC9B,IAAI,QAAQ,eAAe,SAAS;EACpC,eAAe,UAAU;EACzB,oBAAoB,UAAU;EAC9B,iBAAiB,IAAI;CACvB;CACA,MAAM,SAAS,eAAe,UAAgB;EAC5C,MAAM,SAAS,SAAS;EACxB,oBAAoB,UAAU,iBAAiB,WAAW,SAAS,QAC9D,QAAQ,SAAS,SAAS,MAAM,MAAM,QAAQ,QAAQ,SAAS,SAAS,MAAM,MAAM;EACzF,WAAW,KAAK;CAClB;CACA,MAAM,SAAS,SAAqB;EAClC,SAAS,EAAE;EACX,oBAAoB,IAAI;EACxB,UAAU,UAAU;EACpB,QAAQ,IAAI;CACd;;;;CAIA,MAAM,QAAQ,SAAqB;EACjC,UAAU,UAAU,gBAAgB,SAAS,OAAO;EACpD,QAAQ,WAAW;CACrB;CACA,MAAM,aAAa,WAAyB;EAC1C,MAAM,QAAQ,SAAS,QAAQ,QAAQ,SAAoC,SAAS,QAAQ,CAAC,KAAK,QAAQ;EAC1G,IAAI,CAAC,MAAM,QAAQ;EACnB,MAAM,SAAS,MAAM,WAAU,SAAQ,SAAS,SAAS,aAAa;EACtE,MAAM,WAAW,KAAM,SAAS,IAAI,IAAI,MAAM,SAAS,KAAM,SAAS,SAAS,MAAM,UAAU,MAAM,OAAO,EAAE,MAAM;CACtH;CAIA,CAAA,GAAA,MAAA,gBAAA,OAAsB;EACpB,IAAI,QAAQ,CAAC,oBAAoB,SAAS;EAC1C,MAAM,SAAS,SAAS;EACxB,IAAI,WAAW,SAAS,QAAQ,CAAC,QAAQ,SAAS,SAAS,MAAM,GAAG;GAClE,oBAAoB,UAAU;GAC9B;EACF;EACA,MAAM,UAAU,QAAQ,SAAS,cAAc,QAAQ;EACvD,IAAI,CAAC,WAAW,QAAQ,UAAU;EAClC,QAAQ,MAAM;EACd,IAAI,SAAS,kBAAkB,SAAS,oBAAoB,UAAU;CACxE,CAAC;CACD,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,QAAQ,CAAC,oBAAoB,SAAS;EAC1C,MAAM,iBAAiB,UAAuB;GAC5C,IAAI,MAAM,kBAAkB,QAAQ,CAAC,QAAQ,SAAS,SAAS,MAAM,MAAM,GAAG,oBAAoB,UAAU;EAC9G;EACA,SAAS,iBAAiB,WAAW,aAAa;EAClD,SAAS,iBAAiB,eAAe,aAAa;EACtD,aAAa;GACX,SAAS,oBAAoB,WAAW,aAAa;GACrD,SAAS,oBAAoB,eAAe,aAAa;EAC3D;CACF,CAAC;CAED,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,CAAC,eAAe;EACpB,eAAe,UAAU;EACzB,iBAAiB,KAAK;EAGtB,IAAI,CAAC,MAAM,WAAW,IAAI;CAC5B,GAAG,CAAC,eAAe,IAAI,CAAC;CAExB,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,CAAC,MAAM;EAIX,QAAQ,WAAW;EACnB,IAAI,gBAAgB,SAAS,UAAU,UAAU;EACjD,SAAS,EAAE;EACX,oBAAoB,IAAI;CAC1B,GAAG,CAAC,MAAM,WAAW,CAAC;CAKtB,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,YAAY,QAAQ,gBAAgB,WAAW,KAAK;CAC1D,GAAG;EAAC;EAAU;EAAM;CAAc,CAAC;CACnC,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,CAAC,MAAM;EACX,MAAM,gBAAgB,UAA4B;GAChD,MAAM,SAAS,MAAM;GACrB,IAAI,QAAQ,SAAS,SAAS,MAAM,KAAK,QAAQ,SAAS,SAAS,MAAM,GAAG;GAC5E,WAAW,KAAK;EAClB;EAOA,MAAM,iBAAiB,UAA+B;GACpD,IAAI,MAAM,QAAQ,YAAY,MAAM,oBAAoB,MAAM,aAAa;GAC3E,IAAI,CAAC,QAAQ,SAAS;GACtB,MAAM,eAAe;GACrB,IAAI,SAAS,aAAa,KAAK,IAAI;QAC9B,MAAM,IAAI;EACjB;EACA,SAAS,iBAAiB,aAAa,YAAY;EACnD,SAAS,iBAAiB,WAAW,aAAa;EAClD,aAAa;GACX,SAAS,oBAAoB,aAAa,YAAY;GACtD,SAAS,oBAAoB,WAAW,aAAa;EACvD;CACF,GAAG;EAAC;EAAM;EAAc;EAAM;CAAW,CAAC;CAI1C,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,MAAM,SAAS,UAAU;EAGzB,IAAI,CAAC,QAAQ,YAAY,QAAQ,WAAW,MAAM;EAGlD,IAAI,WAAW,WAAW,SAAS,QAAQ;EAC3C,UAAU,UAAU;EACpB,IAAI,WAAW,SAAS;GACtB,IAAI,SAAS,WAAW,YAAY;IAAE,UAAU,SAAS,MAAM;IAAG;GAAO;GACzE,CAAC,QAAQ,SAAS,cAAiC,iEAA6D,KAC3G,SAAS,QAAQ,MAAK,SAAQ,SAAS,QAAQ,CAAC,KAAK,QAAQ,EAAA,EAAI,MAAM;GAC5E;EACF;EACA,SAAS,QAAQ,WAAW,WAAW,IAAI,EAAE,EAAE,MAAM;CACvD,GAAG;EAAC;EAAM;EAAM;EAAY;CAAO,CAAC;CACpC,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,MAAM,WAAW,UAAU;EAC3B,IAAI,aAAa,MAAM;EACvB,QAAA,GAAOE,sCAAAA,wBAAAA,CAAwB,QAAQ;CACzC,GAAG;EAAC;EAAM;EAAM;CAAc,CAAC;CAM/B,MAAM,gBAAgB,QAAQ,SAAS;CACvC,MAAM,eAAe,CAAC,gBAAgB,WAAW,WAAW,IAAI,SAAS,OAAO;CAChF,MAAM,mBAAA,GAAkBL,MAAAA,OAAAA,CAAsB,IAAI;CAClD,CAAA,GAAA,MAAA,gBAAA,OAAsB;EACpB,IAAI,CAAC,iBAAiB,mBAAmB,GAAG;GAC1C,IAAI,CAAC,eAAe,gBAAgB,UAAU;GAC9C;EACF;EACA,IAAI,gBAAgB,YAAY,cAAc;EAC9C,gBAAgB,UAAU;EAC1B,SAAS,QAAQ,QAAQ,SAAS,iBAAiB,EAAE,eAAe,EAAE,OAAO,UAAU,CAAC;CAC1F,GAAG;EAAC;EAAe;EAAc;EAAkB,QAAQ;CAAM,CAAC;CAGlE,CAAA,GAAA,MAAA,gBAAA,OAAsB;EACpB,IAAI,CAAC,MAAM;GAAE,WAAW,IAAI;GAAG;EAAO;EACtC,MAAM,cAAoB;GACxB,MAAM,OAAO,QAAQ,SAAS,sBAAsB;GACpD,IAAI,CAAC,MAAM;GACX,MAAM,SAAS,IAAI,KAAK,QAAQ,SAAS,eAAe,GAAG,KAAK,QAAQ,SAAS,gBAAgB;GACjG,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,MAAM,IAAI;GAC5C,IAAI,KAAK,GAAG,IAAI,KAAK,IAAI,KAAK,IAAI,GAAG,MAAM,GAAG,OAAO,aAAa,KAAK,MAAM;GAC7E,IAAI,KAAK,GAAG,IAAI,KAAK,IAAI,KAAK,IAAI,GAAG,MAAM,GAAG,OAAO,cAAc,KAAK,MAAM;GAC9E,YAAW,SAAS,QAAQ,KAAK,SAAS,KAAK,KAAK,QAAQ,IAAI,OAAO;IAAE,MAAM;IAAG,KAAK;GAAE,CAAE;EAC7F;EACA,MAAM;EACN,OAAO,iBAAiB,UAAU,OAAO,IAAI;EAC7C,OAAO,iBAAiB,UAAU,KAAK;EACvC,aAAa;GACX,OAAO,oBAAoB,UAAU,OAAO,IAAI;GAChD,OAAO,oBAAoB,UAAU,KAAK;EAC5C;CACF,GAAG;EAAC;EAAM;EAAM;EAAS;CAAK,CAAC;CAE/B,SAAS,UAAU,OAAkC;EACnD,IAAI,MAAM,oBAAoB,MAAM,YAAY,aAAa;EAI7D,IAAI,MAAM,QAAQ,YAAY,MAAM;GAClC,MAAM,eAAe;GACrB,IAAI,SAAS,aAAa,KAAK,IAAI;QAC9B,MAAM,IAAI;GACf;EACF;EACA,IAAI,UAAU;EACd,IAAI,CAAC,QAAQ;GAAC;GAAS;GAAK;GAAa;EAAS,CAAC,CAAC,SAAS,MAAM,GAAG,GAAG;GACvE,MAAM,SAAS,MAAM,kBAAkB,UAAU,MAAM,OAAO,QAAQ,QAAQ,IAAI;GAClF,IAAI,EAAE,kBAAkB,sBAAsB,OAAO,YAAY,CAAC,QAAQ,SAAS,SAAS,MAAM,GAAG;GAErG,MAAM,eAAe;GACrB,UAAU,UAAU;GACpB,YAAY;GACZ;EACF;EACA,IAAI,CAAC,MAAM;EACX,IAAI,SAAS,WAAW,eAAe,MAAM,QAAQ,eAAe,MAAM,QAAQ,YAAY;GAC5F,MAAM,eAAe;GACrB,IAAI,cAAc,SAAS,GAAG;IAC5B,qBAAqB,oBAAoB,MAAM,QAAQ,cAAc,IAAI,MAAM,cAAc,UAAU,cAAc,MAAM;IAC3H,WAAU,MAAK,IAAI,CAAC;IACpB,UAAU,SAAS,MAAM;GAC3B;GACA;EACF;EACA,IAAI,SAAS,WAAW,cAAc,MAAM,kBAAkB,qBAAqB,MAAM,QAAQ,WAAY,MAAM,QAAQ,SAAS,CAAC,MAAM,WAAY;GACrJ,IAAI,MAAM,QAAQ,SAAS,cAAc,WAAW,GAAG;GACvD,MAAM,eAAe;GACrB,MAAM,cAAc,cAAc;GAElC,IAAI,eAAe,CAAC,MAAM;IAAE,OAAO;KAAE,UAAU,YAAY;KAAU,OAAO,YAAY;IAAM,CAAC;IAAG,IAAI,aAAa,MAAM,IAAI;GAAE;GAC/H;EACF;EACA,IAAI,MAAM,QAAQ,OAAO;GACvB,IAAI,MAAM,UAAU;IAClB,MAAM,eAAe;IACrB,IAAI,SAAS,aAAa,KAAK,IAAI;SAC9B,MAAM,IAAI;IACf;GACF;GACA,MAAM,UAAU,SAAS;GACzB,MAAM,OAAO,SAAS,QAAQ,QAAQ,SAAoC,SAAS,IAAI;GACvF,IAAI,mBAAmB,qBAAqB,KAAK,SAAS,OAAO,GAAG;IAClE,MAAM,eAAe;IACrB,QAAQ,MAAM;IACd;GACF;GACA,IAAI,SAAS,WAAW,YAAY;IAClC,MAAM,eAAe;IACrB,oBAAoB,IAAI;IACxB,UAAU,SAAS,MAAM;GAC3B;GACA;EACF;EACA,IAAI,MAAM,QAAQ,eAAe,MAAM,QAAQ,WAAW;GACxD,MAAM,eAAe;GACrB,UAAU,MAAM,QAAQ,cAAc,IAAI,EAAE;EAC9C;CACF;CAEA,SAAS,OAAO,OAA+B;EAC7C,MAAM,UAAU,MAAM;EAGtB,IAAI,mBAAmB,SACjB,QAAQ,SAAS,SAAS,OAAO,KAAK,QAAQ,SAAS,SAAS,OAAO,KACtE,CAAC,QAAQ,cAAc;EAK9B,IAAI,CAAC,eAAe,EAAE,mBAAmB,OAAO;EAGhD,IAAI,QAAQ,WAAW,MAAM;EAC7B,IAAI,MAAM,WAAW,KAAK;CAC5B;CAEA,SAAS,UAAU,CAAC;CACpB,IAAI,YAAY;CAChB,IAAI,aAAa;CACjB,MAAM,gBAAgB;EACpB,MAAM,KAAK;EACX,QAAQ,SAAyC;GAAE,SAAS,QAAQ,MAAM;EAAK;CACjF;CAEA,MAAM,OAAO,QAAQ,OAAO,aAAa,eAAA,GACrCM,UAAAA,aAAAA,CACA,iBAAA,GAAA,kBAAA,KAAA,CAACC,sCAAAA,aAAD;EACE,KAAK;EACL,IAAI,GAAG,GAAG;EACV,WAAW,sBAAsB,gBAAgB,IAAI,kBAAkB;EACvE,OAAO,WAAW;EAClB,MAAM,SAAS,UAAU,UAAU;EACnC,cAAY;EACZ,MAAM;EAPR,UAAA;GASG,aAAa,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,WAAU;IAAyB,UAAA;GAAgB,CAAA,IAAI;GACzE,SAAS,SAAS,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA,CACjB,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;IAAQ,KAAK,QAAQ;IAAG,MAAK;IAAS,MAAK;IAAW,WAAU;IAAgC;IAAU,eAAe,MAAM,OAAO;IAAtI,UAAA;KACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAU;MAA4B,UAAA;KAAiB,CAAA;KAC7D,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAU;MAA4B,UAAA;KAAiB,CAAA;KAC7D,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,gCAAD,EAAgC,WAAU,6BAA8B,CAAA;IAClE;GACP,CAAA,GAAA,QAAQ,SAAS,KAAK,CAAC,kBAAkB,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;IAAQ,KAAK,QAAQ;IAAG,MAAK;IAAS,MAAK;IAAW,WAAU;IAAgC;IAAU,eAAe,MAAM,QAAQ;IAAvI,UAAA;KACxC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAU;MAA4B,UAAA;KAAkB,CAAA;KAC9D,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAU;MAA4B,UAAA,eAAe,WAAW,MAAK,QAAO,IAAI,QAAQ,kBAAkB,GAAG,CAAC,EAAE,QAAQ;KAAyB,CAAA;KACvJ,iBAAA,GAAA,kBAAA,IAAA,CAACA,sCAAAA,gCAAD,EAAgC,WAAU,6BAA8B,CAAA;IAClE;GAAI,CAAA,IAAA,IACZ,EAAA,CAAA,IAAI;GACL,SAAS,UAAU,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA;IACjB,aAAa,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACZ,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,OAAD;MACE,KAAK;MACK;MACV,WAAW,wBAAwB,UAAU,KAAK,oCAAoC;MACtF,MAAK;MACL,MAAK;MACL,cAAY;MACZ,iBAAe,GAAG,GAAG;MACrB,yBAAuB,mBAAmB,IAAI,KAAA,IAAY,GAAG,GAAG,SAAS;MACzE,aAAa;MACb,OAAO;MACP,WAAU,UAAS;OAAE,SAAS,MAAM,OAAO,KAAK;OAAG,oBAAoB,CAAC;MAAE;KAC3E,CAAA,GACA,UAAU,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;MAAQ,MAAK;MAAS,WAAU;MAA6B,cAAY;MAA4B;MACnH,eAAe;OAAE,SAAS,EAAE;OAAG,oBAAoB,IAAI;OAAG,UAAU,SAAS,MAAM;MAAE;MACrF,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,sBAAD,CAAuB,CAAA;KACjB,CAAA,IAAI,IACT;IAAI,CAAA,IAAA;IACT,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,KAAK;KAAW,IAAI,GAAG,GAAG;KAAU,WAAU;KAAmC,MAAK;KAAO,cAAY;KAC5G,QAAQ,eAAe,WAAW;KADpC,UAAA,CAEG,QAAQ,SAAS,IAAI,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,WAAU;MAClC,UAAA,QAAQ,KAAI,SACX,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;OAAsB,KAAK,QAAQ;OAAG,MAAK;OAAS,MAAK;OAAgB,gBAAc,KAAK,aAAa;OAAM,UAAU,YAAY;OACnI,WAAW,wBAAwB,KAAK,aAAa,OAAO,6BAA6B;OACzF,eAAe;QAAE,IAAI,YAAY,MAAM;QAAQ,gBAAgB,KAAK,EAAE;QAAG,IAAI,aAAa,MAAM,IAAI;OAAE;OAFxG,UAAA,CAGE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;QAAM,WAAU;QAA4B,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;SAAM,WAAU;SAA4B,UAAA,KAAK;QAAY,CAAA;OAAO,CAAA,GAChH,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;QAAM,WAAU;QAAwB,UAAA,KAAK,aAAa,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,yBAAD,CAA0B,CAAA,IAAI;OAAW,CAAA,CACpG;MALK,GAAA,KAAK,EAKV,CACT;KACE,CAAA,IAAI,MACR,eAAe,KAAI,UAClB,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,WAAD;MAAgC,OAAO,MAAM;MAC1C,UAAA,MAAM,MAAM,KAAI,SAAQ;OACvB,MAAM,QAAQ;OACd,MAAM,SAAS,KAAK;OACpB,MAAM,UAAU,UAAU,aAAa,OAAO,YAAY,SAAS,UAAU,OAAO;OACpF,OAAO,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;QAEL,KAAK,QAAQ;QACb,MAAK;QACL,MAAK;QACL,gBAAc;QACd,IAAI,GAAG,GAAG,SAAS;QACnB,UAAU,aAAa,KAAK;QAC5B,UAAU,YAAY;QACtB,eAAe,oBAAoB,KAAK;QACxC,oBAAkB,UAAU,mBAAmB,KAAK,KAAA;QACpD,WAAW,mDAAmD,UAAU,6BAA6B,KAAK,UAAU,mBAAmB,iCAAiC;QACxK,aAAa,UAAU,mBAAmB,KAAA,UAAkB;SAC1D,IAAI,YAAY,oBAAoB,KAAK;cACpC,SAAS,QAAQ,QAAQ,SAAS,MAAM,EAAE,MAAM;QACvD;QACA,OAAO,OAAO;QACd,eAAe;SAAE,IAAI,YAAY,MAAM;SAAQ,OAAO;UAAE,UAAU,OAAO;UAAU,OAAO,OAAO;SAAM,CAAC;SAAG,IAAI,aAAa,MAAM,IAAI;QAAE;QAjBnI,UAAA,CAmBL,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;SAAM,WAAU;SAA4B,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;UAAM,WAAU;UAA4B,UAAA,mBAAmB,MAAM;SAAQ,CAAA;QAAO,CAAA,GAChI,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;SAAM,WAAU;SAAwB,UAAA,UAAU,iBAAA,GAAA,kBAAA,IAAA,CAACD,sCAAAA,yBAAD,CAA0B,CAAA,IAAI;QAAW,CAAA,CACrF;OApBD,GAAA,GAAG,OAAO,SAAS,GAAG,OAAO,OAoB5B;MACV,CAAC;KACQ,GA5BK,MAAM,QA4BX,CACZ,CACE;;IACJ,mBAAmB,QAAQ,SAAS,KAAK,eAAe,SAAS,IAC9D,iBAAA,GAAA,kBAAA,IAAA,CAAC,cAAD;KAAc,OAAO;KAAa,MAAM;KAAY,UAAU,kBAAkB;KAAc;KAAgB;KAC5G,SAAQ,UAAS,eAAe,KAAK;IAAI,CAAA,IAC3C;IACH,eAAe,WAAW,IAAI,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;KAAK,WAAU;KAAuB,MAAK;KAAU,UAAA;IAAgB,CAAA,IAAI;GACxG,EAAA,CAAA,IAAI;GACL,SAAS,WAAW,iBAAA,GAAA,kBAAA,IAAA,CAAA,kBAAA,UAAA,EAAA,UAClB,WAAW,KAAI,QAAO;IACrB,MAAM,WAAW,kBAAkB,QAAQ,IAAI;IAC/C,OAAO,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;KAAoC,KAAK,QAAQ;KAAG,MAAK;KAAS,MAAK;KAAgB,gBAAc;KAAS,UAAU,YAAY;KACzI,WAAW,wBAAwB,UAAU,6BAA6B;KAC1E,eAAe;MAAE,IAAI,YAAY,MAAM;MAAQ,eAAe,IAAI,MAAM,KAAA,CAAS;MAAG,IAAI,aAAa,MAAM,IAAI;KAAE;KAF5G,UAAA,CAGL,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAU;MAA4B,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAM,WAAU;OAA4B,UAAA,IAAI;MAAW,CAAA;KAAO,CAAA,GAC9G,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAU;MAAwB,UAAA,UAAU,iBAAA,GAAA,kBAAA,IAAA,CAACA,sCAAAA,yBAAD,CAA0B,CAAA,IAAI;KAAW,CAAA,CACrF;IALY,GAAA,IAAI,MAAM,WAKtB;GACV,CAAC,EACD,CAAA,IAAI;EACK;CACb,CAAA,GAAA,SAAS,IACX,IACE;CACJ,MAAM,WAAA,GAAUE,MAAAA,eAAAA,CAAwC,MAAM,KAAA,GAC1DC,MAAAA,aAAAA,CAAa,QAAQ;EAAE,iBAAiB;EAAQ,iBAAiB;EAAM,iBAAiB,OAAO,GAAG,GAAG,SAAS,KAAA;EAAW,iBAAiB,YAAY,KAAA;CAAU,CAAC,IACjK;CACJ,OAAO,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;EAAM,KAAK;EAAS,WAAW,sBAAsB,YAAY,IAAI,cAAc;EAAiB;EAAmB;EAC5H,UAAS,UAAS;GAChB,IAAI,YAAY,MAAM,kBAAkB;GACxC,MAAM,SAAS,MAAM,kBAAkB,UAAU,MAAM,OAAO,QAAQ,QAAQ,IAAI;GAClF,IAAI,EAAE,kBAAkB,sBAAsB,OAAO,YAAY,CAAC,QAAQ,SAAS,SAAS,MAAM,GAAG;GACrG,YAAY;EACd;EACA,cAAa,UAAS;GAAE,IAAI,MAAM,kBAAkB,WAAW,QAAQ,SAAS,SAAS,MAAM,MAAM,KAAK,MAAM,OAAO,QAAQ,QAAQ,MAAM,MAAM,MAAM,eAAe;EAAE;EAPrK,UAAA,CAQJ,SAAS,IACN;;AACR;;;;;;;;;;;;;;;;;;AAmBA,SAAS,aAAa,OAOnB;CACD,MAAM,EAAE,OAAO,MAAM,UAAU,WAAW,OAAO,OAAO,OAAO,WAAW;CAC1E,MAAM,SAAS,KAAK,IAAI,GAAG,KAAK,WAAU,QAAO,IAAI,OAAO,QAAQ,CAAC;CACrE,MAAM,CAAC,UAAU,gBAAA,GAAeb,MAAAA,SAAAA,CAAS,MAAM;CAC/C,MAAM,eAAA,GAAcD,MAAAA,OAAAA,CAAO,QAAQ;CAEnC,CAAA,GAAA,MAAA,UAAA,OAAgB;EAAE,YAAY,UAAU;EAAQ,YAAY,MAAM;CAAE,GAAG,CAAC,MAAM,CAAC;CAC/E,MAAM,WAAW,SAAuB;EACtC,YAAY,UAAU;EACtB,YAAY,IAAI;CAClB;CAGA,MAAM,eAAqB;EACzB,IAAI,YAAY,MAAM;EACtB,MAAM,MAAM,KAAK,YAAY;EAC7B,IAAI,QAAQ,KAAA,GAAW,OAAO,IAAI,OAAO,KAAK,KAAA,IAAY,IAAI,EAAE;CAClE;CACA,MAAM,MAAM,KAAK,IAAI,GAAG,KAAK,SAAS,CAAC;CACvC,MAAM,UAAU,MAAM,IAAI,KAAK,MAAO,WAAW,MAAO,GAAG,IAAI;CAC/D,OAAO,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;EAAK,WAAU;EAA6B,MAAK;EAAQ,cAAY;EAArE,UAAA,CACL,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;IAAM,WAAU;IAA8B,UAAA;GAAY,CAAA,GAC1D,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;IAAM,WAAU;IAA8B,UAAA,KAAK,SAAS,EAAE;GAAW,CAAA,CACtE;EACL,CAAA,GAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAK,WAAU;GAA4B,OAAO,EAAE,QAAQ,QAAQ;GAApE,UAAA;IACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;KACE,MAAK;KACL,WAAU;KACV,KAAK;KACA;KACL,MAAM;KACN,OAAO;KACG;KACV,cAAY;KACZ,iBAAe,YAAY,QAAQ,KAAA;KACnC,kBAAgB,KAAK,SAAS,EAAE;KAChC,WAAU,UAAS;MAIjB,MAAM,QAAQ,OAAQ,MAAM,OAA4B,KAAK;MAC7D,IAAI,OAAO,SAAS,KAAK,GAAG,QAAQ,KAAK;KAC3C;KACA,aAAa;KACb,SAAS;KACT,QAAQ;IACT,CAAA;IACD,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;KAAM,WAAU;KAA6B,eAAY;KAAzD,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAU;MAA4B,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,WAAU,+BAAgC,CAAA;KAAO,CAAA,GACnG,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAU;MACb,UAAA,KAAK,KAAK,KAAK,UACd,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAkC,gBAAc,SAAS,WAAW,KAAK,KAAA;OACvE,WAAU;OAA4B,OAAO,EAAE,QAAQ,MAAM,IAAI,KAAK,MAAO,QAAQ,MAAO,GAAG,IAAI,EAAE;MAAqB,GADjH,IAAI,MAAM,WACuG,CAC7H;KACG,CAAA,CACF;;IACN,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;KAAM,WAAU;KAA6B,eAAY;IAAQ,CAAA;GAC9D;EACF,CAAA,CAAA;;AACP;;;;;;;;;;;;AAaA,MAAa,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC3nB5B,MAAa,uBAAuB;;AAEpC,MAAa,2BAA2B;;;ACoCxC,MAAM,SAAS,UAA+B,KAAK,UAAU,CAAC,MAAM,UAAU,MAAM,KAAK,CAAC;;;;;;AAO1F,IAAa,mBAAb,MAA8B;;CAE5B,0BAA2B,IAAI,IAAoB;;CAGnD,UAAU,OAAwC;EAChD,OAAO,KAAK,QAAQ,IAAI,MAAM,KAAK,CAAC;CACtC;;;;;;CAOA,SAAS,OAAoB,QAAkC;EAC7D,MAAM,MAAM,MAAM,KAAK;EACvB,IAAI,WAAW,KAAA,GAAW,KAAK,QAAQ,OAAO,GAAG;OAC5C,KAAK,QAAQ,IAAI,KAAK,MAAM;CACnC;;;;;;;CAQA,QAAQ,OAAoB,WAA2D;EACrF,MAAM,SAAS,KAAK,QAAQ,IAAI,MAAM,KAAK,CAAC;EAC5C,IAAI,WAAW,KAAA,GAAW,OAAO,KAAA;EACjC,OAAO,WAAW,SAAS,SAAS,MAAM,IAAI,SAAS,KAAA;CACzD;;;;;;;;;;;;;CAcA,MAAM,OACJ,WACA,WACA,QACuB;EACvB,MAAM,SAAS,UAAU,mBAAmB,KAAK,QAAQ,WAAW,SAAS;EAC7E,MAAM,SAA0B,WAAW,KAAA,IAAY;GAAE,UAAU,UAAU;GAAU,OAAO,UAAU;EAAM,IAAI;GAAE,GAAG;GAAW,iBAAiB;EAAO;EAC1J,MAAM,SAAS,MAAM,OAAO,MAAM;EAKlC,IAAI,QAAQ,OAAO,MAAM,OAAO;EAChC,KAAK,SAAS,QAAQ,OAAO,eAAe;EAC5C,OAAO;CACT;AACF;;;AC5HA,MAAa,oBAA+C;CAAC;CAAS;CAAQ;CAAQ;CAAS;AAAO;AACtG,MAAa,2BAA2C;AACxD,MAAa,+BAA+B;AAgD5C,MAAM,YAAY;AAClB,MAAM,WAAW;AACjB,MAAM,iBAAiB;AACvB,MAAM,gBAAgB;AAEtB,MAAM,kBACJ;AACF,MAAM,qBACJ;AACF,MAAM,iBAAiB;AACvB,MAAM,YAAY;AAClB,MAAM,kBACJ;AACF,MAAM,kBACJ;AACF,MAAM,oBAAoB;AAC1B,MAAM,eAAe;AACrB,MAAM,iBAAiB;AACvB,MAAM,UAAU;AAEhB,SAAgB,iBAAiB,OAAyC;CACxE,OAAO,OAAO,UAAU,YAAa,kBAAwC,SAAS,KAAK;AAC7F;AAEA,SAAgB,sBAAsB,OAAuB,SAAkC;CAC7F,OAAO,kBAAkB,QAAQ,KAAK,KAAK,kBAAkB,QAAQ,OAAO;AAC9E;AAEA,SAAgB,yBAAyB,KAAqB;CAC5D,MAAM,WAAW,OAAO,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,aAAa,EAAE,CAAC,CAAC,YAAY,CAAC,CAC7E,QAAQ,gBAAgB,GAAG,CAAC,CAAC,QAAQ,YAAY,EAAE;CAEtD,MAAM,WADW,SAAS,KAAK,QAAQ,IAAI,WAAW,KAAK,WAAA,CAClC,MAAM,GAAG,EAAE,CAAC,CAAC,QAAQ,QAAQ,EAAE;CACxD,OAAO,UAAU,KAAK,OAAO,IAAI,UAAU;AAC7C;AAEA,SAAgB,wBAAwB,KAAqB;CAC3D,MAAM,UAAU,OAAO,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CACnD,QAAQ,kBAAkB,GAAG,CAAC,CAAC,QAAQ,YAAY,EAAE,CAAC,CAAC,MAAM,GAAG,GAAG;CACtE,OAAO,SAAS,KAAK,OAAO,IAAI,UAAU;AAC5C;;;;;AAMA,SAAgB,oBACd,MACA,QACA,WAA2B,0BACX;CAChB,IAAI,CAAC,QAAQ,OAAO,SAAS,UAAU,OAAO;CAC9C,MAAM,mBAAmB,SAAS,yBAAyB,MAAM,IAAI,KAAA;CACrE,IAAI;CACJ,KAAK,MAAM,SAAS,KAAK,MAAM,GAAG,CAAC,CAAC,KAAI,SAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,OAAO,GAAG;EAC5E,MAAM,UAAU,MAAM,YAAY;EAClC,IAAI,iBAAiB,OAAO,GAAG;GAC7B,WAAW;GACX;EACF;EACA,MAAM,QAAQ,0BAA0B,KAAK,KAAK;EAClD,IAAI,CAAC,OAAO;EACZ,MAAM,SAAS,MAAM,EAAE,CAAE,KAAK;EAC9B,MAAM,YAAY,MAAM,EAAE,CAAE,KAAK,CAAC,CAAC,YAAY;EAC/C,IAAI,CAAC,iBAAiB,SAAS,GAAG;EAClC,IAAI,WAAW,KAAK;GAClB,WAAW;GACX;EACF;EACA,IAAI,oBAAoB,yBAAyB,MAAM,MAAM,kBAC3D,OAAO;CAEX;CACA,OAAO,YAAY;AACrB;AAEA,SAAgB,sBAAsB,MAAc,WAAW,8BAAsC;CACnG,IAAI,CAAC,MAAM,OAAO;CAClB,IAAI,mBAAmB,KAAK,IAAI,GAAG,OAAO;CAC1C,IAAI,gBAAgB,KAAK,IAAI,GAAG,OAAO;CAevC,OAAO,gBAdU,KACd,QAAQ,gBAAgB,gBAAgB,CAAC,CACzC,QAAQ,WAAW,mBAAmB,CAAC,CACvC,QAAQ,kBAAkB,MAAM,WAAmB;EAClD,MAAM,QAAQ,KAAK,MAAM,OAAO,MAAM;EACtC,IAAI,MAAM,WAAW,IAAG,GAAG,OAAO,GAAG,OAAO;EAC5C,IAAI,MAAM,WAAW,GAAG,GAAG,OAAO,GAAG,OAAO;EAC5C,OAAO,GAAG,OAAO;CACnB,CAAC,CAAC,CACD,QAAQ,iBAAiB,cAAc,CAAC,CACxC,QAAQ,mBAAmB,eAAe,CAAC,CAC3C,QAAQ,cAAc,uBAAuB,CAAC,CAC9C,QAAQ,gBAAgB,YAAY,CAAC,CACrC,QAAQ,SAAS,QACU,GAAG,QAAQ;AAC3C;AAEA,SAAgB,yBACd,OAC6C;CAC7C,IAAI,CAAC,OAAO,OAAO,KAAA;CACnB,MAAM,SAA0C,CAAC;CACjD,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,CAAC,CAAC,MAAM,GAAG,EAAE,GAAG;EAC7D,IAAI,UAAU,KAAA,KAAa,CAAC,eAAe,KAAK,GAAG,GAAG;EACtD,IAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK,GAAG;EAC1D,IAAI,cAAc,KAAK,GAAG,GAAG;GAC3B,OAAO,OAAO;GACd;EACF;EACA,OAAO,OAAO,OAAO,UAAU,WAAW,sBAAsB,OAAO,GAAK,IAAI;CAClF;CACA,IAAI,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,QAAQ,OAAO,KAAA;CAExC,IADgB,KAAK,UAAU,MACrB,CAAC,CAAC,UAAA,KAAwC,OAAO;CAC3D,OAAO;EAAE,SAAS;EAAM,QAAQ;CAA8C;AAChF;AAEA,SAAgB,uBAAuB,OAA4C;CACjF,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAChC,MAAM,MAAM,SAAS,OAAO,UAAU,WAClC,QACA,CAAC;CACL,MAAM,aAAa,OAAO,IAAI,YAAY,WAAW,IAAI,UAAU,OAAO,KAAK;CAC/E,MAAM,SAAyB;EAC7B,MAAM,OAAO,IAAI,SAAS,YAAY,IAAI,KAAK,KAAK,IAAI,sBAAsB,IAAI,KAAK,KAAK,GAAG,GAAG,IAAI;EACtG,SAAS,sBAAsB,UAAU,KAAK;CAChD;CACA,IAAI,OAAO,IAAI,UAAU,YAAY,IAAI,MAAM,KAAK,GAClD,OAAO,QAAQ,sBAAsB,IAAI,OAAO,IAAM;CAExD,IAAI,OAAO,IAAI,SAAS,YAAY,4BAA4B,KAAK,IAAI,IAAI,GAC3E,OAAO,OAAO,sBAAsB,IAAI,MAAM,GAAG;MAC5C,IAAI,OAAO,IAAI,SAAS,YAAY,OAAO,SAAS,IAAI,IAAI,GACjE,OAAO,OAAO,OAAO,IAAI,IAAI;CAE/B,OAAO;AACT;AAEA,SAAgB,sBACd,MACA,OAC8B;CAC9B,IAAI,CAAC,MAAM,OAAO;CAClB,IAAI,CAAC,OAAO,OAAO;CACnB,OAAO;EAAE,GAAG;EAAM,GAAG;CAAM;AAC7B;AAEA,SAAgB,oBACd,OACA,MAQgB;CAChB,MAAM,QAAwB;EAC5B,SAAS;EACT,IAAI,KAAK,GAAG,YAAY;EACxB,OAAO,iBAAiB,MAAM,KAAK,IAAI,MAAM,QAAQ;EACrD,QAAQ,yBAAyB,KAAK,MAAM;EAC5C,SAAS,KAAK;EACd,GAAI,KAAK,UAAU,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;EAChD,OAAO,wBAAwB,MAAM,KAAK;EAC1C,SAAS,sBAAsB,MAAM,WAAW,uCAAuC,4BAA4B;EACnH,GAAI,KAAK,QAAQ,KAAA,IAAY,EAAE,KAAK,KAAK,IAAI,IAAI,CAAC;CACpD;CACA,MAAM,UAAU,yBAAyB,sBAAsB,KAAK,aAAa,MAAM,OAAO,CAAC;CAC/F,IAAI,SAAS,MAAM,UAAU;CAC7B,MAAM,QAAQ,uBAAuB,MAAM,KAAK;CAChD,IAAI,OAAO,MAAM,QAAQ;CACzB,OAAO;AACT;AAEA,SAAgB,wBAAwB,QAAsB,OAAuC;CACnG,OAAO;EACL,IAAI,SAAS;GAAE,OAAO,OAAO;EAAO;EACpC,IAAI,OAAO;GAAE,OAAO,OAAO;EAAK;EAChC,IAAI,iBAAiB;GAAE,OAAO,OAAO;EAAe;EACpD,QAAQ,OAAO,SAAS,YAAY,OAAO,MAAM,OAAO,SAAS,sBAAsB,OAAO,OAAO,CAAC;EACtG,OAAO,OAAO,SAAS,YAAY,OAAO,KAAK,OAAO,SAAS,sBAAsB,OAAO,OAAO,CAAC;EACpG,OAAO,OAAO,SAAS,OAAO,YAAY,OAAO,KAAK,OAAO,SAAS,OAAO,sBAAsB,OAAO,OAAO,CAAC;EAClH,QAAQ,OAAO,SAAS,OAAO,YAAY,OAAO,MAAM,OAAO,SAAS,OAAO,sBAAsB,OAAO,OAAO,CAAC;EACpH,QAAQ,OAAO,SAAS,OAAO,YAAY,OAAO,MAAM,OAAO,SAAS,OAAO,sBAAsB,OAAO,OAAO,CAAC;EACpH,QAAO,UAAS,OAAO,MAAM;GAAE,GAAG;GAAO,SAAS,sBAAsB,OAAO,MAAM,OAAO;EAAE,CAAC;EAC/F,QAAO,SAAQ,wBAAwB,QAAQ,sBAAsB,OAAO,IAAI,KAAK,CAAC,CAAC;CACzF;AACF;AAEA,SAAgB,gBAAgB,MAAc,UAA0B;CACtE,IAAI,KAAK,UAAU,UAAU,OAAO;CACpC,MAAM,SAAS;CACf,IAAI,YAAY,IAAe,OAAO,KAAK,MAAM,GAAG,KAAK,IAAI,GAAG,QAAQ,CAAC;CACzE,OAAO,GAAG,SAAS,KAAK,MAAM,EAAE,WAAW,GAAc;AAC3D;;;AC9OA,MAAa,2BAA2B;AA8BxC,SAAS,gBAAgB,KAAiC;CACxD,IAAI;EAGF,MAAM,SAFO,WAA2C,QACnC,aAAA,EACE,UAAU,GAAG;EACpC,OAAO,OAAO,UAAU,YAAY,MAAM,KAAK,IAAI,MAAM,KAAK,IAAI,KAAA;CACpE,QAAQ;EACN;CACF;AACF;AAEA,SAAS,mBAAmB,OAAiC;CAC3D,MAAM,UAAU;CAChB,IAAI,CAAC,MAAM,QAAQ,QAAA,0BAAiC,GAClD,IAAI;EACF,QAAQ,4BAA4B,CAAC;CACvC,QAAQ;EACN,OAAO,CAAC;CACV;CAEF,MAAM,OAAO,QAAQ;CACrB,MAAM,WAAW,KAAK,SAAS;CAC/B,IAAI,WAAW,GAAG,KAAK,OAAO,GAAG,QAAQ;CACzC,OAAO;AACT;AAiBA,SAAgB,yBACd,QACA,KACA,UAAqC,CAAC,GACxB;CACd,MAAM,aAAa,yBAAyB,MAAM;CAClD,MAAM,MAAM,QAAQ,8BAAc,IAAI,KAAK;CAC3C,MAAM,QAAQ,KAAK,IAAI,IAAI,QAAQ,eAAA,GAAsC;CACzE,MAAM,aAAa,OAAO,OAAO,QAAQ,WAAW,MAA4B,KAAA;CAEhF,MAAM,uBAAuC;EAC3C,IAAI,QAAQ,cAAc,OAAO,QAAQ;EACzC,OAAO,oBAAoB,gBAAgB,sBAAsB,GAAG,YAAY,wBAAwB;CAC1G;CAEA,MAAM,SAAuB;EAC3B,QAAQ;EACR,MAAM;EACN,gBAAgB;EAChB,QAAQ,OAAO,SAAS,YAAY,OAAO,MAAM;GAAE,OAAO;GAAS;GAAO;GAAS,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;EAAG,CAAC;EACpH,OAAO,OAAO,SAAS,YAAY,OAAO,MAAM;GAAE,OAAO;GAAQ;GAAO;GAAS,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;EAAG,CAAC;EAClH,OAAO,OAAO,SAAS,OAAO,YAAY,OAAO,MAAM;GACrD,OAAO;GAAQ;GAAO;GACtB,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;GACvC,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;EAC/B,CAAC;EACD,QAAQ,OAAO,SAAS,OAAO,YAAY,OAAO,MAAM;GACtD,OAAO;GAAS;GAAO;GACvB,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;GACvC,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;EAC/B,CAAC;EACD,QAAQ,OAAO,SAAS,OAAO,YAAY,OAAO,MAAM;GACtD,OAAO;GAAS;GAAO;GACvB,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;GACvC,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;EAC/B,CAAC;EACD,QAAO,YAAW,wBAAwB,QAAQ,OAAO;EACzD,MAAM,OAAgC;GACpC,IAAI;IACF,IAAI,CAAC,sBAAsB,MAAM,OAAO,eAAe,CAAC,GAAG,OAAO;IAClE,MAAM,QAAQ,oBAAoB,OAAO;KACvC,IAAI,IAAI;KACR,QAAQ;KACR,SAAS;IACX,CAAC;IACD,MAAM,SAAS,mBAAmB,KAAK;IACvC,OAAO,KAAK,KAAK;IACjB,MAAM,WAAW,OAAO,SAAS;IACjC,IAAI,WAAW,GAAG,OAAO,OAAO,GAAG,QAAQ;IAE3C,IAAI,QAAQ,wBAAwB,SAAS,YAAY,QAAQ;KAC/D,MAAM,UAAU,sBAAsB,GAAG,WAAW,IAAI,MAAM,MAAM,KAAK,MAAM,WAAW,GAAG;KAC7F,IAAI,MAAM,UAAU,UAAU,OAAO,WAAW,OAAO,SAAS,YAC9D,WAAW,OAAO,KAAK,OAAO;UACzB,KAAK,MAAM,UAAU,WAAW,MAAM,UAAU,YAAY,OAAO,WAAW,OAAO,UAAU,YACpG,WAAW,OAAO,MAAM,OAAO;IAEnC;IACA,IAAI,gBAAgB,wBAAwB,MAAM,KAAK;KACrD,MAAM,MAAO,WAA2C;KAKxD,CAJW,MAAM,UAAU,UAAU,KAAK,QACtC,MAAM,UAAU,SAAS,KAAK,OAC5B,MAAM,UAAU,SAAS,KAAK,OAC5B,KAAK,MAAA,EACT,KAAK,KAAK,IAAI,WAAW,IAAI,MAAM,MAAM,IAAI,MAAM,WAAW,KAAK;IACzE;IACA,OAAO;GACT,QAAQ;IACN,OAAO;GACT;EACF;CACF;CACA,OAAO;AACT;AAEA,SAAgB,0BACd,KACA,QACA,UAAqC,CAAC,GACxB;CACd,MAAM,SAAS,yBAAyB,QAAQ,KAAK,OAAO;CAC5D,OAAO,KAAK,iBAAiB,8BAA8B,QAAQ,aAAa;CAChF,MAAM,aAAa,OAAO,OAAO,QAAQ,WAAW,MAA4B,KAAA;CAChF,IAAI,OAAO,YAAY,WAAW,YAChC,IAAI;EACF,WAAW,mBAAmB;GAC5B,OAAO,MAAM,mBAAmB,yBAAyB;EAC3D,GAAG,GAAG,OAAO,OAAO,eAAe;CACrC,QAAQ,CAER;CAEF,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;ACrIA,MAAa,OAAO;AACpB,MAAa,SAAS;CAAC;CAAS;CAAU;AAAU;AAIpD,MAAM,sBAAsB;AAM5B,MAAM,KAAK;AACX,MAAa,SAAS;CACpB,oBAAoB;CACpB,gBAAgB;CAChB,sBAAsB;CACtB,cAAc;CACd,eAAe;CACf,0BAA0B;CAC1B,sBAAsB;CACtB,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAChB,kBAAkB;CAClB,gBAAgB;CAChB,gBAAgB;CAChB,sBAAsB;AACxB;AACA,MAAa,SAAS;CACpB,oBAAoB;CACpB,gBAAgB;CAChB,sBAAsB;CACtB,cAAc;CACd,eAAe;CACf,0BAA0B;CAC1B,sBAAsB;CACtB,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAChB,kBAAkB;CAClB,gBAAgB;CAChB,gBAAgB;CAChB,sBAAsB;AACxB;AAIA,SAAS,SAAS,MAAc,QAA0C;CACxE,OAAO,SAAS,KAAK,QAAQ,eAAe,GAAG,MAAc,OAAO,OAAO,MAAM,IAAI,EAAE,EAAE,CAAC,IAAI;AAChG;;AAGA,SAAgB,WAAW,QAAuC;CAChE,MAAM,OAAO,QAAQ,YAAY,CAAC,CAAC,WAAW,IAAI,IAAI,SAAS;CAC/D,QAAQ,KAAK,WAAW,SAAS,KAAK,MAAM,MAAM;AACpD;AAMA,MAAa,iBAAiB,GAAG,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;AA8B9C,SAAgB,iBAAiB,QAAuC,OAAgE;CACtI,MAAM,UAA6B,CAAC;CACpC,KAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,eAAe,MAAM,QAAQ,MAAM;EACzC,KAAK,MAAM,SAAS,MAAM,QACxB,QAAQ,KAAK;GACX,UAAU,MAAM;GAChB,OAAO,MAAM;GACb,OAAO,GAAG,aAAa,KAAK,MAAM,QAAQ,MAAM;GAChD,eAAe;GACf,UAAU,MAAM,WAAW,WAAW,CAAC,EAAA,CAAG,KAAI,YAAW;IAAE,IAAI,OAAO;IAAI,MAAM,OAAO,QAAQ,OAAO;GAAG,EAAE;EAC7G,CAAC;CAEL;CACA,IAAI,OAAO,YAAY,MAAM,SAAS,CAAC,QAAQ,MAAK,SAAQ,KAAK,aAAa,MAAM,YAAY,KAAK,UAAU,MAAM,KAAK,GACxH,QAAQ,KAAK;EAAE,UAAU,MAAM;EAAU,OAAO,MAAM;EAAO,OAAO,GAAG,MAAM,SAAS,KAAK,MAAM;EAAS,SAAS,CAAC;CAAE,CAAC;CAEzH,OAAO;AACT;AAEA,SAAS,YAAY,QAAuC,UAAkB,OAAe;CAC3F,OAAO,OAAO,MAAK,UAAS,MAAM,OAAO,QAAQ,CAAC,EAAE,OAAO,MAAK,UAAS,MAAM,OAAO,KAAK,CAAC,EAAE;AAChG;;;AAIA,SAAS,kBAAkB,QAAuC,SAA6D;CAC7H,IAAI,CAAC,SAAS,OAAO;CACrB,KAAK,MAAM,SAAS,QAAQ;EAC1B,IAAI,MAAM,OAAO,QAAQ,UAAU;EACnC,IAAI,MAAM,OAAO,MAAK,UAAS,MAAM,OAAO,QAAQ,KAAK,GAAG,OAAO;CACrE;CACA,OAAO,GAAG,QAAQ,SAAS,IAAI,QAAQ;AACzC;;;;;;AAgBA,MAAM,kBAAkB;;;;;;AAOxB,SAAS,eAAe,OAAoE;CAC1F,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,aAAa,WAAW,GAAG,SAAS;CACzE,MAAM,UAAmC,CAAC;CAC1C,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,GAAG,IAAI,gBAAgB,KAAK,GAAG,GAAG,QAAQ,OAAO;CAC/F,OAAO,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;EACL,MAAK;EACL,GAAI;EACJ,WAAW,yBAAyB,YAAY,IAAI,cAAc;EAClE,UAAU,YAAY,KAAA;EACtB,OAAO,cAAc,GAAG,MAAM,KAAK,gBAAgB;EAL9C,UAAA;GAOL,iBAAA,GAAA,kBAAA,IAAA,CAACe,sCAAAA,wBAAD;IAAwB,WAAU;IAA+B,MAAM;GAAK,CAAA;GAC5E,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;IAAM,WAAU;IAA+B,UAAA;GAAY,CAAA;GAC1D,gBAAgB,KAAA,IACb,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;IAAM,WAAU;IAAgC,UAAA;GAAkB,CAAA,IAClE;GACH,OACG,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,UAAD,EAAU,OAAM,UAAW,CAAA,IAC3B,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,+BAAD,EAA+B,WAAW,yBAAyB,OAAO,gCAAgC,KAAO,CAAA;EAC/G;;AACV;;;;;;;AAcA,SAAgB,YAAY,OAA6C;CACvE,MAAM,EAAE,GAAG,gBAAgB,iBAAiB,GAAG,UAAU;CACzD,MAAM,eAAe,kBAAkB,OAAO,iBAAgB,aAAY,SAAS,MAAM,CAAC,IAAI;CAC9F,MAAM,CAAC,MAAM,YAAA,GAAWC,MAAAA,SAAAA,CAAS,KAAK;CAMtC,MAAM,WAAW,MAAM,aAAa;CAGpC,MAAM,OAAO,MAAM,SAAS;CAC5B,MAAM,YAAA,GAAWC,MAAAA,OAAAA,CAAO,YAAY,IAAI;CACxC,SAAS,UAAU,YAAY;CAC/B,MAAM,kBAAA,GAAiBA,MAAAA,OAAAA,EAAQ,SAAwB,CAAC,CAAC;CACzD,eAAe,WAAW,SAAwB;EAChD,IAAI,YAAY,MAAM;EACtB,QAAQ,IAAI;EACZ,MAAM,eAAe,IAAI;CAC3B;CACA,MAAM,eAAe,SAAwB,eAAe,QAAQ,IAAI;CAExE,MAAM,WAAW,MAAM,UAAU;CACjC,MAAM,WAAW,MAAM;CACvB,MAAM,kBAAA,GAAiBC,MAAAA,QAAAA,OACf,MAAM,QAAQ,MAAK,WAAU,OAAO,aAAa,UAAU,YAAY,OAAO,UAAU,SAAS,KAAK,GAC5G;EAAC,MAAM;EAAS,UAAU;EAAU,UAAU;CAAK,CAAC;CACtD,MAAM,eAAe,MAAM,gBAAgB,gBAAgB,UAAU,WAAW,GAAG,SAAS,SAAS,KAAK,SAAS,UAAU,EAAE,kBAAkB;CACjJ,MAAM,aAAa,MAAM,WAAW,CAAC;CACrC,MAAM,iBAAiB,MAAM,kBAAkB;CAG/C,MAAM,qBAAqB,MAAM,uBAC3B,iBACA,qBAAqB,WAAW,MAAK,QAAO,IAAI,OAAO,cAAc,KAAK;EAAE,IAAI;EAAgB,MAAM;CAAe,GAAG,QAAQ,IAChI,WAAW,SAAS,IAAI,MAAM,sBAAsB,EAAE,wBAAwB,IAAI,KAAA;CAQxF,MAAM,SAAS,MAAM;CACrB,MAAM,UAAU,QAAQ,SAAS,QAAQ,MAAM,QAAQ,WAAW;CAClE,MAAM,aAAa,WAAW,WAAW,OAAO,SAAS,OAAO,YAAY,OAAO,UAAU,UAAU,KAAK,KACxG,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;EAAK,WAAU;EAA0B,MAAM,OAAO,QAAQ,UAAU;EAAxE,UAAA;GACG,UACG,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,WAAU;IAA6B,aAAU;IACpD,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;KAAM,WAAU;KAA+B,UAAA,EAAE,gBAAgB;IAAQ,CAAA;GACtE,CAAA,IACL;GACH,OAAO,UACJ,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,WAAU;IAA6B,aAAU;IACpD,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;KAAM,WAAU;KAA+B,UAAA,OAAO;IAAc,CAAA;GACjE,CAAA,IACL;GACH,OAAO,QACJ,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;KAAM,WAAU;KAA+B,UAAA,EAAE,gBAAgB,EAAE,SAAS,OAAO,MAAM,CAAC;IAAQ,CAAA,GACjG,OAAO,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;KAAQ,MAAK;KAAS,WAAU;KAAmC;KAAU,eAAe,OAAO,QAAQ;KAAI,UAAA,MAAM,cAAc,EAAE,cAAc;IAAU,CAAA,IAAI,IAC9K;GACL,CAAA,IAAA;IACF,OAAO,YAAY,CAAC,EAAA,CAAG,KAAI,YAAW,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAsB,WAAU;IAA6B,aAAU;IAAvE,UAAA,CACtC,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;KAAM,WAAU;KAAhB,UAAA;MAA+C,QAAQ,QAAQ,QAAQ;MAAG;MAAG,QAAQ;KAAc;IAClG,CAAA,GAAA,OAAO,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;KAAQ,MAAK;KAAS,WAAU;KAAmC;KAAU,eAAe,OAAO,QAAQ;KAAI,UAAA,MAAM,cAAc,EAAE,cAAc;IAAU,CAAA,IAAI,IAC9K;GAH6C,GAAA,QAAQ,EAGrD,CAAC;EACH;CACL,CAAA,IAAA,KAAA;CAEJ,MAAM,QAA6B,QAChC,GAAG,SAAS;EAAE,IAAI,CAAC,SAAS,SAAS,KAAK,GAAG,IAAI;CAAE;CAEtD,MAAM,SAAS,eAAe,0BAA0B,cAAyE;CACjI,MAAM,SAAS,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;EACP;EACI;EACJ;EACN,OAAO;EACP,aAAa;EACb,WAAW,MAAM;EACjB,cAAY,qBACR,EAAE,sBAAsB;GAAE,OAAO;GAAc,QAAQ;EAAmB,CAAC,IAC3E,EAAE,gBAAgB,EAAE,OAAO,aAAa,CAAC;CAC9C,CAAA;CAED,OAAO,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA,CACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD,EAAA,UAAQ,eAAsB,CAAA,GAC9B,iBAAA,GAAA,kBAAA,IAAA,CAAC,WAAD;EACE,QAAQ;EACF;EACN,cAAc;EACN;EACR,SAAS,MAAM;EACf,UAAU,MAAM;EAChB,QAAQ,KAAK,MAAM,MAAM;EACzB,SAAS,MAAM,WAAW,CAAC;EAC3B,eAAe,KAAK,MAAM,aAAa;EAC3B;EACF;EACJ;EACN,SAAS;EACO;EAChB,cAAc,KAAK,MAAM,YAAY;EACrC,YAAY,MAAM,cAAc,EAAE,YAAY;EAC9C,YAAY,MAAM,cAAc;EAChC,aAAa,MAAM,eAAe,EAAE,aAAa;EACjD,oBAAoB,MAAM,sBAAsB,EAAE,wBAAwB;EAC1E,mBAAmB,MAAM,qBAAqB,EAAE,oBAAoB;EACpE,YAAY,MAAM,eAAe,MAAM,QAAQ,WAAW,IAAI,EAAE,cAAc,IAAI,EAAE,cAAc;EAClG,kBAAkB,MAAM,oBAAoB,EAAE,cAAc;EAC5D,aAAa,MAAM,eAAe;EAClC,kBAAkB,MAAM,oBAAoB;EAC5C,iBAAiB,MAAM,mBAAmB;EAC1C,aAAa;EACb,gBAAgB;EAChB,eAAe,mBAAmB,MAAM,gBAAgB,IAAI,MAAM,kBAAkB;EACpF,WAAU;CACX,CAAA,CACD,EAAA,CAAA;AACJ;;;;;;;AAuBA,SAAgB,kBAAkB,OAAqC;CACrE,MAAM,EAAE,MAAM;CACd,MAAM,YAAY,MAAM;CAKxB,MAAM,sBAAA,GAAqBC,MAAAA,YAAAA,EAAa,kBAA8B,UAAU,UAAU,aAAa,GAAG,CAAC,SAAS,CAAC;CACrH,MAAM,qBAAA,GAAoBA,MAAAA,YAAAA,OAAkB,UAAU,YAAY,GAAG,CAAC,SAAS,CAAC;CAChF,MAAM,SAAA,GAAQC,MAAAA,qBAAAA,CAAqB,oBAAoB,mBAAmB,iBAAiB;CAC3F,MAAM,CAAC,OAAO,aAAA,GAAYJ,MAAAA,SAAAA,CAA+C,IAAI;CAC7E,MAAM,YAAA,GAAWC,MAAAA,OAAAA,CAAO,CAAC;CACzB,MAAM,WAAA,GAAUA,MAAAA,OAAAA,CAA+B,IAAI;CAEnD,MAAM,SAAS,MAAM;CACrB,MAAM,UAAU,MAAM;CACtB,MAAM,aAAa,kBAAkB,QAAQ,OAAO;CACpD,MAAM,WAAA,GAAUC,MAAAA,QAAAA,OAAc,iBAC5B,QACA,eAAe,KAAK,KAAA,IAAY;EAAE,UAAU,WAAW,MAAM,GAAG,WAAW,QAAQ,IAAI,CAAC;EAAG,OAAO,WAAW,MAAM,WAAW,QAAQ,IAAI,IAAI,CAAC;CAAE,CACnJ,GAAG,CAAC,QAAQ,UAAU,CAAC;CACvB,MAAM,iBAAiB,QAAQ,MAAK,WAAU,OAAO,aAAa,SAAS,YAAY,OAAO,UAAU,QAAQ,KAAK;CACrH,MAAM,YAAY,UAAU,YAAY,QAAQ,QAAQ,UAAU,QAAQ,KAAK,IAAI,KAAA;CAGnF,MAAM,WAAA,GAAUA,MAAAA,QAAAA,OAAc,CAAC,GAAI,gBAAgB,WAAW,CAAC,CAAE,GAAG,CAAC,cAAc,CAAC;CACpF,MAAM,OAAO,MAAM,WAAW,eAAe,MAAM,YAAY;CAI/D,CAAA,GAAA,MAAA,UAAA,OAAgB;EAAE,MAAM,KAAK;CAAE,GAAG,CAAC,MAAM,IAAI,CAAC;CAC9C,MAAM,oBAAoB,SAAwB;EAAE,IAAI,MAAM,MAAM,KAAK;CAAE;CAE3E,MAAM,UAAU,UAAmD;EACjE,SAAS,WAAW;EACpB,SAAS;GAAE,KAAK,SAAS;GAAS,MAAM,EAAE,gBAAgB,EAAE,SAAS,GAAG,MAAM,KAAK,IAAI,MAAM,UAAU,CAAC;EAAE,CAAC;CAC7G;CACA,MAAM,UAAU,cAAmF;EACjG,MAAW,OAAO,SAAS,CAAC,CAAC,MAAK,WAAU;GAC1C,IAAI,WAAW,KAAA,KAAa,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK;EAC7D,CAAC,CAAC,CAAC,OAAM,UAAS,OAAO;GAAE,MAAM;GAAsB,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EAAE,CAAC,CAAC;CAC3H;CAIA,MAAM,aAAa,MAAM,aAAa,SAAS,YAAY;CAC3D,MAAM,aAAa,UAAqD;EACtE,IAAI,SAAS,aAAa,MAAM,YAAY,QAAQ,UAAU,MAAM,OAAO;EAC3E,IAAI,cAAc,MAAM,aAAa,QAAQ,YAAY,MAAM,UAAU,QAAQ,OAAO;EAGxF,OAAO;GAAE,UAAU,MAAM;GAAU,OAAO,MAAM;EAAM,CAAC;CACzD;CACA,MAAM,cAAc,WAAqC;EACvD,IAAI,CAAC,SAAS;EACd,KAAK,QAAQ,mBAAmB,KAAA,OAAe,QAAQ;EACvD,OAAO;GAAE,UAAU,QAAQ;GAAU,OAAO,QAAQ;GAAO,GAAI,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,iBAAiB,OAAO;EAAG,CAAC;CAC3H;CAEA,MAAM,YAAY,iBACb,eAAe,MAAM,MAAM,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,eAAe,QAC1E,SAAS,SAAS,EAAE,kBAAkB;CAI1C,MAAM,cAAc,cAAc,KAAA,IAC9B,MAAM,iBACN,SAAS,oBAAoB,KAAA,IAC3B,qBAAqB,UAAU,QAAQ,MAAK,QAAO,IAAI,OAAO,SAAS,eAAe,KAAK;EAAE,IAAI,SAAS,mBAAmB;EAAI,MAAM,SAAS,mBAAmB;CAAG,GAAG,KAAA,CAAS,IAClL,UAAU,QAAQ,SAAS,KAAK,UAAU,kBAAkB,KAAA,IAC1D,EAAE,wBAAwB,IAC1B,KAAA;CAER,IAAI,CAAC,MAAM,WAAW,OAAO;CAE7B,MAAM,WAAW,iBAAA,GAAA,kBAAA,IAAA,CAAC,mBAAD;EACZ;EACI;EACE;EACA;EACT,aAAa,SAAS;EACT;EACF;EACX,QAAQ,MAAM;EACR;EACN,QAAQ;EACR,cAAc;EACd,QAAQ;EACR,eAAe,MAAM,KAAK;CAC3B,CAAA;CAED,MAAM,cAAgC;EACpC;EACA,UAAU,UAAU;GAAE,UAAU,QAAQ;GAAU,OAAO,QAAQ;EAAM,IAAI,KAAA;EAC3E,QAAQ;EACR;EACA,gBAAgB,SAAS,mBAAmB;EAC5C,cAAc;EACd,UAAU,MAAM;EAChB;EACA,cAAc;EACd,oBAAoB;EACpB,cAAc;EACd,QAAQ;GACN,OAAO,MAAM;GACb,MAAM,MAAM,WAAW;GACvB,SAAS,aAAa,EAAE,oBAAoB,IAAI,KAAA;GAChD,UAAU,MAAM;GAChB,aAAa,MAAM,KAAK;EAC1B;CACF;CAEA,OAAO,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;EAAM,KAAK;EAAS,WAAU;EAA9B,UAAA,CACJ,MAAM,oBAAoB,MAAM,kBAAkB,sBAAsB,aAAa,EAAE,SAAS,CAAC,IAAI,UACrG,UAAU,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAACG,sCAAAA,OAAD;GAIjB,MAAM,MAAM;GACZ,MAAM,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,2BAAD,CAA4B,CAAA;GAClC,QAAQ,QAAQ,SAAS,QAAQ,sBAAsB,KAAK,QAAQ;GACpE,cAAc,SAAS,IAAI;EAC5B,GALM,MAAM,GAKZ,CACG;;AACR;;AAGA,SAAS,kBAAkB,OAcb;CACZ,MAAM,EAAE,GAAG,UAAU;CACrB,MAAM,CAAC,MAAM,YAAA,GAAWN,MAAAA,SAAAA,CAAS,KAAK;CACtC,CAAA,GAAA,MAAA,UAAA,OAAgB;EAAE,IAAI,MAAM,QAAQ,QAAQ,KAAK;CAAE,GAAG,CAAC,MAAM,MAAM,CAAC;CACpE,MAAM,QAAQ,MAAM,UAAU,MAAM;CACpC,MAAM,aAAa,MAAM,aAAa,SAAS,MAAM,YAAY;CAGjE,MAAM,UAAU,MAAM,WAAW,aAAa,MAAM,QAAQ,WAAW;CACvE,MAAM,aAAc,WAAW,MAAM,SAAS,cAAc,MAAM,SAAS,SAAS,IAChF,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;EAAK,WAAU;EAA0B,MAAM,MAAM,QAAQ,UAAU;EAAvE,UAAA;GACG,UACG,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,WAAU;IAA6B,aAAU;IACpD,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;KAAM,WAAU;KAA+B,UAAA,EAAE,gBAAgB;IAAQ,CAAA;GACtE,CAAA,IACL;GACH,aACG,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,WAAU;IAA6B,aAAU;IACpD,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;KAAM,WAAU;KAA+B,UAAA,EAAE,oBAAoB;IAAQ,CAAA;GAC1E,CAAA,IACL;GACH,MAAM,QACH,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;KAAM,WAAU;KAA+B,UAAA,EAAE,gBAAgB,EAAE,SAAS,MAAM,MAAM,CAAC;IAAQ,CAAA,GACjG,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;KAAQ,MAAK;KAAS,WAAU;KAAyB,UAAU;KAAO,SAAS,MAAM;KAAU,UAAA,EAAE,cAAc;IAAU,CAAA,CAC1H;GACL,CAAA,IAAA;GACH,MAAM,SAAS,KAAI,YAAW,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAsB,WAAU;IAA6B,aAAU;IAAvE,UAAA,CAC7B,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;KAAM,WAAU;KAAhB,UAAA;MAA+C,QAAQ,QAAQ,QAAQ;MAAG;MAAG,QAAQ;KAAc;IACnG,CAAA,GAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;KAAQ,MAAK;KAAS,WAAU;KAAyB,UAAU;KAAO,SAAS,MAAM;KAAU,UAAA,EAAE,cAAc;IAAU,CAAA,CAC1H;GAHoC,GAAA,QAAQ,EAG5C,CAAC;EACH;CACL,CAAA,IAAA,KAAA;CACJ,OAAO,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA,CACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD,EAAA,UAAQ,eAAsB,CAAA,GAC9B,iBAAA,GAAA,kBAAA,IAAA,CAAC,WAAD;EACE,QAAO;EACP,MAAM,QAAQ,CAAC,MAAM;EACrB,eAAc,SAAQ;GACpB,IAAI,MAAM,QAAQ;GAClB,QAAQ,IAAI;GACZ,IAAI,MAAM,MAAM,OAAO,IAAI;EAC7B;EACA,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAAC,gBAAD;GAAsB;GAAM,UAAU;GAAO,MAAM,MAAM;GAAM,OAAO,MAAM;GAAW,aAAa,MAAM;GAAa,cAAY,MAAM,cAAc,EAAE,sBAAsB;IAAE,OAAO,MAAM;IAAW,QAAQ,MAAM;GAAY,CAAC,IAAI,EAAE,gBAAgB,EAAE,OAAO,MAAM,UAAU,CAAC;EAAI,CAAA;EAChS,SAAS,MAAM;EACf,UAAU,MAAM,UAAU;GAAE,UAAU,MAAM,QAAQ;GAAU,OAAO,MAAM,QAAQ;EAAM,IAAI,KAAA;EAC7F,SAAQ,UAAS;GAAE,IAAI,CAAC,OAAO,MAAM,OAAO,KAAK;EAAE;EACvC;EACZ,UAAU,MAAM;EAChB,MAAM,MAAM;EACZ,SAAS,MAAM;EACf,gBAAgB,MAAM,eAAe;EACrC,eAAc,WAAU;GAAE,IAAI,CAAC,OAAO,MAAM,aAAa,MAAM;EAAE;EACjE,YAAY,EAAE,YAAY;EAC1B,YAAY,MAAM;EAClB,aAAa,EAAE,aAAa;EAC5B,oBAAoB,EAAE,wBAAwB;EAC9C,mBAAmB,EAAE,oBAAoB;EACzC,YAAY,EAAE,cAAc;EAC5B,kBAAkB,EAAE,cAAc;EAClC,aAAY;EACZ,kBAAA;EACA,iBAAA;EACA,aAAa;EACb,eAAc;EACd,WAAU;CACX,CAAA,CACD,EAAA,CAAA;AACJ;;;;;;;;;;;AAgBA,SAAgB,sBACd,WACA,YACA,QAC+B;CAC/B,OAAO,OAAM,cAAa;EACxB,MAAM,QAAQ,UAAU,MAAM,YAAY;EAC1C,MAAM,UAAU,MAAM;EACtB,MAAM,YAAY,YAAY,QAAQ,QAAQ,aAAa,UAAU,YAAY,QAAQ,UAAU,UAAU;EAC7G,IAAI,QAAQ;EACZ,IAAI,CAAC,aAAa,UAAU,oBAAoB,KAAA,GAAW;GACzD,MAAM,YAAY,MAAM,OACrB,MAAK,UAAS,MAAM,OAAO,UAAU,QAAQ,CAAC,EAAE,OAChD,MAAK,UAAS,MAAM,OAAO,UAAU,KAAK,CAAC,EAAE;GAChD,MAAM,SAAS,WAAW,QAAQ,WAAW,cAAc,KAAA,IAAY,KAAA,IAAY,EAAE,SAAS,UAAU,QAAQ,KAAI,QAAO,IAAI,EAAE,EAAE,CAAC;GACpI,IAAI,WAAW,KAAA,GAAW,QAAQ;IAAE,GAAG;IAAW,iBAAiB;GAAO;EAC5E;EACA,MAAM,SAAS,MAAM,UAAU,OAAO,KAAK;EAC3C,IAAI,QAAQ,OAAO,MAAM;GACvB,WAAW,SAAS,OAAO,MAAM,eAAe;GAChD,QAAQ,MAAM,kBAAkB,4BAA4B;IAC1D,UAAU,MAAM;IAChB,OAAO,MAAM;IACb,QAAQ,MAAM,mBAAmB;GACnC,CAAC;EACH,OAAO,IAAI,UAAU,OAAO,OAAO,OACjC,QAAQ,KAAK,yBAAyB,2BAA2B,KAAA,GAAW;GAC1E,UAAU,MAAM;GAChB,OAAO,MAAM;EACf,CAAC;EAEH,OAAO;CACT;AACF;AAEA,SAAgB,MAAM,KAAoB;CACxC,MAAM,SAAS,0BAA0B,KAAK,2BAA2B;CAIzE,MAAM,aAAa,IAAI,iBAAiB;CAExC,IAAI,aAAa;EAGf,MAAM,KAAK,IAAI,QAAQ,SAAS,IAAI,MAAM,MAAM;EAChD,MAAM,KAAK,IAAI,QAAQ,SAAS,IAAI,MAAM,MAAM;EAChD,aAAa;GAAE,KAAK;GAAG,KAAK;EAAE;CAChC,CAAC;CAED,IAAI,MAAM,gBAAgB;EACxB,MAAM;EACN,OAAO;EACP,QAAQ;EACR,eAAe,EAAE,OAAO,EAAE,cAAc,IAAI,OAAO,EAAE;EACrD,OAAO,GAAG,2BAA2B,EAAE,OAAO,OAAO,EAAE;CACzD,GAAG,WAAoB;CAKvB,IAAI,OAAO,CAAC,kBAAkB,IAAG,UAAS;EACxC,MAAM,cAAc,MAAM;EAC1B,MAAM,MAAM,OAAO,kCAAkC,MAAM,MAAM,SAAS;GACxE,MAAM;GACN,UAAU;GACV,QAAQ;GACR,SAAS,cAAmC;IAC1C,MAAM,cAAmC;KACvC,WAAW;KACX,WAAW;MACT,mBAAmB;MACnB,uBAAuB,CAAC;MACxB,cAAc,CAAC;MACf,WAAW,CAAC;KACd;KACA,YAAY,CAAC;KACb,cAAa,SAAQ,IAAI,QAAQ,YAAY,IAAI,KAAK,OAAO,IAAI;KACjE,QAAQ,YAAY,KAAA;IACtB;IACA,IAAI,MAAM,UAAU,kBAAkB,SAAS,MAAM,KAAA,GAAW,OAAO;IACvE,IAAI;KACF,MAAM,YAAY,YAAY,aAAa,SAAS;KACpD,OAAO;MACL,WAAW;MACX,WAAW,UAAU;MACrB,YAAY;OACV,UAAe,KAAK,CAAC,CAAC,OAAM,UAAS;QACnC,OAAO,KAAK,yBAAyB,gCAAgC,OAAO,EAAE,UAAU,CAAC;OAC3F,CAAC;MACH;MACA,cAAa,SAAQ,IAAI,QAAQ,YAAY,IAAI,KAAK,OAAO,IAAI;MACjE,QAAQ,sBAAsB,WAAW,YAAY,MAAM;KAC7D;IACF,SAAS,OAAO;KACd,OAAO,KAAK,yBAAyB,kDAAkD,OAAO,EAAE,UAAU,CAAC;KAC3G,OAAO;IACT;GACF;EACF,GAAG,iBAA0B,CAAC;CAChC,CAAC;AACH;AAEA,MAAM,cAAmC;CAAE,SAAS;CAAM,UAAU;CAAM,QAAQ,CAAC;CAAG,UAAU,CAAC;CAAG,QAAQ;CAAQ,SAAS;CAAM,OAAO;AAAK"}