@klarkxy/dsh-git-commit 0.2.5 → 0.3.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","useCallback","useMemo","Button","useRef","useState","useId","useMemo","rankByName","observeStickyMenuGroups","createPortal","MenuSurface","IconChevronRightOutlineRegular","Input","IconCloseFillRegular","IconCheckOutlineRegular","MenuGroup","isValidElement","cloneElement","useState","useRef","useAnchoredPosition","useCallback","Tooltip","Button","createPortal","IconRefreshOutlineRegular","Tag","useSyncExternalStore","IconChevronDownOutlineRegular","Switch"],"sources":["../../dsh-model-route/src/catalog.ts","../../dsh-model-route/src/menu.ts","../../dsh-model-route/src/catalog-ui.tsx","../../dsh-model-route/src/ui.tsx","../../dsh-plugin-kit/src/official-ui.ts","../../dsh-plugin-kit/src/contracts.ts","../../dsh-plugin-kit/src/model-settings-client.ts","../src/contracts.ts","../src/client.tsx"],"sourcesContent":["/**\n * Host model-catalog parsing shared by plugin settings UIs and model hubs.\n * Pure and browser-safe: no React, no host imports. The catalog envelope is\n * structural so hosts may add fields without breaking consumers.\n */\nimport { modelRouteKey, type ModelRoute } from './route.ts'\n\n/** One selectable model. `efforts` are the advertised reasoning efforts. */\nexport interface ModelMenuChoice {\n readonly provider: string\n readonly model: string\n readonly label: string\n readonly efforts: ReadonlyArray<{ id: string; name: string }>\n}\n\n/** Both services are required: Cordis checks the nested namespace separately. */\nexport const MODEL_CATALOG_INJECT = ['remote', 'remote.session'] as const\n\nexport interface ModelCatalogFailure {\n readonly id: string\n readonly name: string\n readonly message: string\n}\n\n/** The catalog face this helper needs; stays structural so hosts may add more. */\nexport interface ModelCatalogClient {\n readonly remote?: {\n readonly session?: { readonly modelCatalog?: () => Promise<unknown> }\n }\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : undefined\n}\n\nfunction asText(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() ? value.trim() : undefined\n}\n\n/** A useful diagnostic even when a transport rejects with a plain object. */\nexport function modelCatalogErrorMessage(value: unknown): string {\n if (value instanceof Error && value.message) return value.message\n const row = asRecord(value)\n return asText(row?.message) ?? asText(value) ?? 'Unable to load the model catalog.'\n}\n\n/**\n * Validate and unwrap a successful catalog without discarding provider failures\n * or newer host metadata. Names and metadata remain optional for older hosts.\n * A broken response is never presented as a successfully loaded empty menu.\n */\nexport function checkedModelCatalog(value: unknown): unknown {\n const envelope = asRecord(value)\n if (envelope?.ok === false) throw new Error(modelCatalogErrorMessage(envelope.error ?? envelope))\n const root = envelope?.ok === true ? asRecord(envelope.value) : envelope\n const malformed = (field: string): never => { throw new Error(`Invalid model catalog: ${field}.`) }\n if (!root || !Array.isArray(root.groups)) return malformed('groups must be an array')\n for (const value of root.groups) {\n const group = asRecord(value)\n if (!group || !asText(group.id) || !Array.isArray(group.models)) return malformed('each group needs an id and models array')\n for (const value of group.models) {\n const model = asRecord(value)\n if (!model || !asText(model.id)) return malformed('each model needs an id')\n if (model.reasoning !== undefined) {\n const reasoning = asRecord(model.reasoning)\n if (!reasoning || !Array.isArray(reasoning.efforts) || reasoning.efforts.some(value => !parseEffort(value))) {\n return malformed('reasoning efforts must be an array of identified efforts')\n }\n }\n }\n }\n if (root.failures !== undefined && (!Array.isArray(root.failures) || root.failures.some(value => {\n const failure = asRecord(value)\n return !failure || !asText(failure.id) || typeof failure.name !== 'string' || typeof failure.message !== 'string'\n }))) return malformed('failures must be an array of provider failures')\n return root\n}\n\n/** Read through the injected session namespace; absence and rejection are errors. */\nexport async function readModelCatalog(client: ModelCatalogClient): Promise<unknown> {\n const session = client.remote?.session\n if (typeof session?.modelCatalog !== 'function') {\n throw new Error('Model catalog unavailable: inject both remote and remote.session.')\n }\n return checkedModelCatalog(await session.modelCatalog())\n}\n\n/** Provider failures are partial results, not a transport failure. */\nexport function modelCatalogFailures(value: unknown): readonly ModelCatalogFailure[] {\n // Rendering can precede the checked load boundary (for example hub owner\n // snapshots). Invalid or absent data must not crash the whole settings page.\n try {\n const root = checkedModelCatalog(value) as { failures?: readonly ModelCatalogFailure[] }\n return root.failures ?? []\n } catch { return [] }\n}\n\n/** Text adapter for existing model-hub status messages. */\nexport function catalogFailures(value: unknown): string[] {\n return modelCatalogFailures(value).map(failure => `${failure.name || failure.id}: ${failure.message}`)\n}\n\nfunction parseEffort(value: unknown): { id: string; name: string } | undefined {\n const row = asRecord(value)\n const id = row ? asText(row.id) : undefined\n if (!id) return undefined\n return { id, name: row ? asText(row.name) ?? id : id }\n}\n\n/** Parse the host session catalog into flat choices, keeping a saved route selectable. */\nexport function parseModelMenuChoices(value: unknown, bound?: ModelRoute): ModelMenuChoice[] {\n const envelope = asRecord(value)\n // Host remote calls resolve to a result envelope ({ ok, value }); older hosts\n // and unit tests hand over the bare catalog. Accept both.\n const root = (envelope && envelope.ok === true ? asRecord(envelope.value) : undefined) ?? envelope ?? {}\n const groups = Array.isArray(root.groups) ? root.groups : []\n const choices: ModelMenuChoice[] = []\n for (const group of groups) {\n const groupRow = asRecord(group)\n const provider = groupRow ? asText(groupRow.id) : undefined\n if (!provider || !groupRow || !Array.isArray(groupRow.models)) continue\n const providerName = asText(groupRow.name) ?? provider\n for (const entry of groupRow.models) {\n const modelRow = asRecord(entry)\n const model = modelRow ? asText(modelRow.id) : undefined\n if (!model || !modelRow) continue\n const name = asText(modelRow.name) ?? model\n const reasoning = asRecord(modelRow.reasoning)\n const efforts = reasoning && Array.isArray(reasoning.efforts)\n ? reasoning.efforts.flatMap(effort => { const parsed = parseEffort(effort); return parsed ? [parsed] : [] })\n : []\n choices.push({ provider, model, label: `${providerName} / ${name}`, efforts })\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\n/** Reasoning-effort options for one choice; the saved value stays selectable. */\nexport function modelMenuEffortOptions(\n choice: ModelMenuChoice | undefined,\n current?: string,\n): Array<{ id: string; name: string }> {\n const listed = (choice?.efforts ?? []).map(item => ({ ...item }))\n if (current && !listed.some(item => item.id === current)) listed.push({ id: current, name: current })\n return listed\n}\n\n/** Flat set of known routes for DetectModelFieldsOptions.knownModel. */\nexport function knownModelFromChoices(choices: readonly ModelMenuChoice[]): (route: ModelRoute) => boolean {\n const known = new Set(choices.map(choice => modelRouteKey(choice.provider, choice.model)))\n return route => known.has(modelRouteKey(route.provider, route.model))\n}\n","/**\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, split from the catalog \"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 : 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 = 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","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { Button } from '@deepseek-ai/dsh-client-ui-primitives'\nimport {\n checkedModelCatalog, modelCatalogErrorMessage, modelCatalogFailures, parseModelMenuChoices,\n type ModelCatalogFailure, type ModelMenuChoice,\n} from './catalog.ts'\n\nexport interface UseModelCatalogOptions {\n /** Used only on mount; subsequent changes come from load(). */\n readonly initialCatalog?: unknown\n /** Disables initial, focus, subscription, and manual refreshes. */\n readonly enabled?: boolean\n readonly subscribe?: (onChange: () => void) => (() => void) | undefined\n}\n\nexport interface ModelCatalogState {\n readonly catalog: unknown\n readonly choices: ModelMenuChoice[]\n readonly loading: boolean\n readonly error: string\n readonly failures: readonly ModelCatalogFailure[]\n readonly refresh: () => Promise<void>\n}\n\ntype Snapshot = Pick<ModelCatalogState, 'catalog' | 'loading' | 'error'>\n\n/**\n * Latest refresh wins, including retries while a previous request is pending.\n * Keep load stable (for example with useCallback); changing it invalidates the\n * previous source and fetches again, so switching clients cannot publish stale data.\n */\nexport function useModelCatalog(load: () => Promise<unknown>, options: UseModelCatalogOptions = {}): ModelCatalogState {\n const enabled = options.enabled !== false\n const enabledRef = useRef(enabled)\n enabledRef.current = enabled\n const live = useRef(false)\n const source = useRef(load)\n const revision = useRef(0)\n const [state, setState] = useState<Snapshot>(() => {\n try {\n return { catalog: options.initialCatalog === undefined ? undefined : checkedModelCatalog(options.initialCatalog), loading: enabled, error: '' }\n } catch (error) {\n return { catalog: undefined, loading: enabled, error: modelCatalogErrorMessage(error) }\n }\n })\n const refresh = useCallback(async (): Promise<void> => {\n if (!live.current || !enabledRef.current) return\n const request = ++revision.current\n setState(previous => ({ ...previous, loading: true, error: '' }))\n try {\n const catalog = checkedModelCatalog(await load())\n if (live.current && request === revision.current) setState({ catalog, loading: false, error: '' })\n } catch (error) {\n if (live.current && request === revision.current) {\n setState(previous => ({ ...previous, loading: false, error: modelCatalogErrorMessage(error) }))\n }\n }\n }, [load, enabled])\n\n useEffect(() => {\n live.current = true\n if (source.current !== load) {\n source.current = load\n // Last-good retention belongs to one source; a new client must not\n // inherit another client's models if its initial request fails.\n setState({ catalog: undefined, loading: enabled, error: '' })\n }\n if (enabled) void refresh()\n else setState(previous => ({ ...previous, loading: false }))\n return () => { live.current = false; ++revision.current }\n }, [enabled, refresh])\n\n useEffect(() => {\n if (!enabled) return\n const reload = (): void => { void refresh() }\n // No polling: the host owns catalog production, and focus is a cheap\n // recovery path for missed ordinary notifications or changed credentials.\n if (typeof window !== 'undefined') window.addEventListener('focus', reload)\n let unsubscribe: (() => void) | undefined\n try { unsubscribe = options.subscribe?.(reload) } catch (error) {\n setState(previous => ({ ...previous, error: modelCatalogErrorMessage(error) }))\n }\n return () => {\n if (typeof window !== 'undefined') window.removeEventListener('focus', reload)\n unsubscribe?.()\n }\n }, [enabled, refresh, options.subscribe])\n\n const choices = useMemo(() => parseModelMenuChoices(state.catalog), [state.catalog])\n const failures = useMemo(() => state.catalog === undefined ? [] : modelCatalogFailures(state.catalog), [state.catalog])\n return { ...state, choices, failures, refresh }\n}\n\nexport interface ModelCatalogStatusProps {\n readonly state: Pick<ModelCatalogState, 'loading' | 'error' | 'failures' | 'refresh'>\n readonly locale?: string\n}\n\n/** Also accepts a mapped state from a caller that owns broader async orchestration. */\nexport function ModelCatalogStatus({ state, locale }: ModelCatalogStatusProps) {\n const zh = locale?.toLowerCase().startsWith('zh') === true\n const copy = zh\n ? { loading: '正在加载模型…', error: '模型列表加载失败', partial: '部分提供商的模型未能加载', retry: '重试' }\n : { loading: 'Loading models…', error: 'Unable to load models', partial: 'Some providers could not load their models', retry: 'Retry' }\n if (!state.loading && !state.error && state.failures.length === 0) return null\n return <div className=\"dsh-model-catalog-status\" lang={zh ? 'zh' : 'en'}>\n {state.loading ? <p role=\"status\">{copy.loading}</p> : null}\n {state.error ? <p role=\"alert\">{copy.error}: {state.error}</p> : null}\n {state.failures.length > 0 ? <div role=\"status\">\n <p>{copy.partial}</p>\n <ul>{state.failures.map((failure, index) => <li key={`${failure.id}:${index}`}>{failure.name || failure.id}: {failure.message}</li>)}</ul>\n </div> : null}\n {state.error || state.failures.length > 0\n ? <Button type=\"button\" size=\"sm\" disabled={state.loading} onClick={() => { void state.refresh() }}>{copy.retry}</Button>\n : null}\n </div>\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 --dsw-* theme 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 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 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 const [menuPos, setMenuPos] = useState<CSSProperties | null>(null)\n const id = useId()\n const showSearch = 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 => ({ choice, name: modelMenuShortName(choice), label: choice.model })), 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 root one, handing the keyboard back to its cell. */\n const back = (from: Pane): void => {\n paneFocus.current = from\n setPane('root')\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 setPane('root')\n setQuery('')\n setHighlightedIndex(null)\n }, [open])\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 document.addEventListener('mousedown', closeOutside)\n return () => document.removeEventListener('mousedown', closeOutside)\n }, [open, onOpenChange])\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 useLayoutEffect(() => {\n if (open && pane === 'model' && activeModelIndex >= 0) itemRefs.current[leading.length + activeModelIndex]?.scrollIntoView({ block: 'nearest' })\n }, [open, pane, activeModelIndex, visibleModels, 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({ 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 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 (event.key === 'Escape' && open) {\n event.preventDefault()\n if (pane !== 'root') back(pane)\n else close(true)\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 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 if (highlighted) { onPick({ provider: highlighted.provider, model: highlighted.model }); close(true) }\n return\n }\n if (event.key === 'Tab') {\n if (event.shiftKey) {\n event.preventDefault()\n if (pane !== 'root') 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 if (event.relatedTarget instanceof Node && (rootRef.current?.contains(event.relatedTarget) || menuRef.current?.contains(event.relatedTarget))) 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 {pane === 'root' ? <>\n <button ref={itemRef()} type=\"button\" role=\"menuitem\" className=\"dsh-model-menu-cell\" 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 ? <button ref={itemRef()} type=\"button\" role=\"menuitem\" className=\"dsh-model-menu-cell\" 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 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}\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}\n className={`dsh-model-menu-option${item.selected === true ? ' dsh-model-menu-selected' : ''}`}\n onClick={() => { onPickLeading?.(item.id); 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 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={() => { onPick({ provider: choice.provider, model: choice.model }); 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 {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}\n className={`dsh-model-menu-option${checked ? ' dsh-model-menu-selected' : ''}`}\n onClick={() => { onPickEffort?.(row.id || undefined); 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 })\n : anchor\n return <span ref={rootRef} className={`dsh-model-menu-root${className ? ` ${className}` : ''}`} onKeyDown={onKeyDown} onBlur={onBlur}\n onClick={event => {\n if (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 * 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 --dsw-* theme tokens may appear here — a literal 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 2px 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 0.12s; }\n.dsh-model-menu-chevronOpen { transform: rotate(180deg); }\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-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.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`\n","/**\n * Shared contract that keeps every plugin's browser-side UI on the official\n * DeepSeek Harness Web design language.\n *\n * Two rules produce that language, and both are load-bearing here:\n *\n * 1. Colour, radius, elevation and focus come from the host theme's real\n * `--dsw-*` tokens, written under their own names. Plugins never invent a\n * token, never alias the official ones behind a private palette (a private\n * alias is just a second, diverging theme), and never carries a literal\n * fallback — the host publishes light and dark, and a literal would pin one\n * of them. The only non-colour custom properties used are the host's own\n * content-font axis and frame clearance.\n *\n * 2. Anything the host already ships is used, not reimplemented. Controls come\n * from `@deepseek-ai/dsh-client-ui-primitives` (`Button`, `Input`,\n * `Checkbox`, `Switch`, `Tag`, `Pill`, `SegmentedControl`, `Menu`, `Modal`,\n * `Tooltip`, `Toast`, `DisclosureRow`, `StateDot`, `PathLabel`, the settings\n * form suite). This module only styles what primitives do not cover: page\n * scaffolding, field layout, banners, empty states and scroll regions.\n *\n * The metrics below are transcribed from the primitives' own CSS modules so a\n * feature panel lines up pixel-for-pixel with a native one: the 14/22 body and\n * 13/20 compact type tiers, the 0.5px hairline scale, and the elevation family\n * that draws a surface's edge in its shadow (`border: 0`) instead of a border.\n */\n\n/**\n * Every `--dsw-*` token this repo is allowed to reference, grouped by role.\n *\n * Plugins may only colour through this list. It is exported so the guard test\n * can fail a build when a stylesheet reaches for anything else — the failure\n * mode this prevents is silent: an unknown token resolves to nothing, so a\n * border disappears or a label inherits the wrong colour with no error anywhere.\n */\nexport const OFFICIAL_THEME_TOKENS = {\n /** Surfaces, from the page up to the topmost nested card. */\n surface: [\n '--dsw-alias-bg-base',\n '--dsw-alias-bg-layer-1',\n '--dsw-alias-bg-layer-2',\n '--dsw-alias-bg-layer-3',\n '--dsw-alias-bg-layer-4',\n '--dsw-alias-bg-module-platform',\n '--dsw-alias-bg-overlay',\n ],\n /** Hairlines. l1 is near-invisible on a menu surface, so menus use l2+. */\n border: ['--dsw-alias-border-l1', '--dsw-alias-border-l2', '--dsw-alias-border-l3', '--dsw-alias-border-l4'],\n /** Text. `caption` is menu shortcut text, `dimmed` is placeholder text. */\n label: [\n '--dsw-alias-label-primary',\n '--dsw-alias-label-secondary',\n '--dsw-alias-label-tertiary',\n '--dsw-alias-label-caption',\n '--dsw-alias-label-dimmed',\n '--dsw-alias-label-error',\n '--dsw-alias-label-primary-foreground',\n ],\n /** Interactive fills. The `-danger` hover belongs to destructive rows. */\n interactive: [\n '--dsw-alias-interactive-bg-hover',\n '--dsw-alias-interactive-bg-active',\n '--dsw-alias-interactive-bg-hover-danger',\n ],\n /** Accent and status. `business` is the focus ring's default colour. */\n accent: [\n '--dsw-alias-brand-primary',\n '--dsw-alias-button-primary-fill',\n '--dsw-alias-button-primary-hover',\n '--dsw-alias-button-tool-bar-fill',\n '--dsw-alias-button-tool-bar-hover',\n '--dsw-alias-button-ghost-active-fill',\n '--dsw-alias-button-ghost-active-border',\n ],\n state: [\n '--dsw-alias-state-business-primary',\n '--dsw-alias-state-success-primary',\n '--dsw-alias-state-warn-primary',\n '--dsw-alias-state-error-primary',\n '--dsw-alias-state-idle-primary',\n ],\n /** Corner scale: sm 8, md 12, lg the large card, panel the modal. */\n radius: ['--dsw-radius-sm', '--dsw-radius-md', '--dsw-radius-lg', '--dsw-radius-panel'],\n /** An elevated surface draws its edge in the shadow, so it keeps border: 0. */\n elevation: [\n '--dsw-elevation-soft',\n '--dsw-elevation-stroke',\n '--dsw-elevation-stroke-color',\n '--dsw-elevation-panel',\n '--dsw-elevation-prominent',\n ],\n /** Floats, masks and scrollbars. */\n overlay: [\n '--dsw-menu-surface-fill',\n '--dsw-menu-backdrop-filter',\n '--dsw-mask-blur',\n '--dsw-alias-bg-mask-1',\n '--dsw-alias-menu-icon',\n '--dsw-alias-scrollbar-bg-l2',\n '--dsw-alias-scrollbar-hover-l2',\n '--dsw-shadow-lv3',\n ],\n /** Motion, focus and type axis, published by the host rather than by a component. */\n system: [\n '--dsw-focus-ring-width',\n '--dsw-focus-ring-color',\n '--dsw-font-markdown-code-font-family',\n '--ds-transition-duration',\n '--ds-ease-in-out',\n '--ds-font-family-code',\n '--dsh-scrollbar-thumb',\n '--dsh-scrollbar-thumb-hover',\n '--dsh-content-font-size-secondary',\n '--dsh-content-font-delta',\n '--dsh-frame-top-clearance',\n ],\n} as const\n\n/** Every official token name, flat. Used by the token guard test. */\nexport const OFFICIAL_THEME_TOKEN_NAMES: readonly string[] = Object.values(OFFICIAL_THEME_TOKENS).flat()\n\n/** The elevation steps a surface can be raised by, softest first. */\nexport type OfficialElevation = 'soft' | 'stroke' | 'panel' | 'prominent'\n\n/**\n * The host's focus ring shorthand, verbatim. Writing this per control is how\n * rings drift apart; a stylesheet that draws its own focus style should use\n * {@link officialFocus} instead. The colour fallback is the host's own default.\n */\nexport const OFFICIAL_FOCUS_RING =\n 'var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary))'\n\n/**\n * A complete `outline` declaration at the official geometry. `offset` defaults\n * to the 2px the native controls use; the host's inline field rules sit at 1px\n * and a segmented tab pulls the ring inside itself at -2px.\n */\nexport function officialFocus(offset = '2px'): string {\n return `outline: ${OFFICIAL_FOCUS_RING}; outline-offset: ${offset}`\n}\n\n/**\n * An elevated surface. The host draws a raised surface's edge inside its\n * shadow rather than as a border, so a card sets `border: 0` and takes the edge\n * from the elevation — which is also why its border stays off the alias-border\n * set that a flat, non-elevated rule would use.\n */\nexport function officialElevation(level: OfficialElevation): string {\n return `border: 0; box-shadow: var(--dsw-elevation-${level})`\n}\n\n/**\n * An elevated surface whose edge should read as a specific hairline. Rebinding\n * the stroke colour is how a menu card picks l1 while a panel picks l3, without\n * the two growing apart by hand.\n */\nexport function officialStrokedElevation(level: OfficialElevation, color: string): string {\n return `--dsw-elevation-stroke-color: ${color}; ${officialElevation(level)}`\n}\n\n/**\n * The shared stylesheet for a plugin UI, scoped under that plugin's root class.\n *\n * Scoping is what keeps this safe to always-bundle into every client: the rules\n * can only match inside the plugin's own subtree, so two plugins can both mount\n * `dsh-ui-card` without either styling the other's markup.\n *\n * Each recipe matches the root element *and* its descendants, because the\n * commonest arrangement is one element that is both — a surface that carries\n * the root class and `dsh-ui-card`, or a portaled dialog that is the root and\n * the `dsh-ui-surface`. A descendant-only scope would silently leave those\n * unstyled, with no error anywhere.\n *\n * A caveat worth knowing: `Modal` and `Menu` portal to `document.body`, so their\n * content leaves the plugin's subtree entirely. A portaled surface therefore\n * needs its own root class on an element inside the portal.\n *\n * Only patterns that primitives do not provide live here. If a control appears\n * below that `Button`/`Input`/`Switch`/`Tag`/`Menu` already covers, that is a\n * bug in this file: use the primitive and delete the recipe.\n */\nexport function officialUiCss(roots: string | readonly string[]): string {\n // One plugin often mounts several unrelated surfaces (a settings seat, a chat\n // card, a header menu), so the caller names every root. The rules below are\n // nested under a single selector list and use `&`, which the browser expands\n // per root — so one stylesheet covers all of them without duplicating itself.\n const scope = (typeof roots === 'string' ? [roots] : roots).map(root => `.${root}`).join(', ')\n const sheet = `\n/* Official DSH Web UI contract. Generated by @klarkxy/dsh-plugin-kit/official-ui.\n * Do not hand-edit the copy inside a plugin: change this module so every plugin\n * moves together. Scope: ${scope} */\n/* The scope rule below stays open for the whole sheet: every rule after it\n * nests with the parent selector, so one stylesheet can cover several unrelated\n * roots without leaking into a neighbouring plugin. Its closing brace is last. */\n${scope} {\n color: var(--dsw-alias-label-primary);\n font-family: inherit;\n font-size: 14px;\n line-height: 22px;\n min-width: 0;\n\n& *, & *::before, & *::after { box-sizing: border-box; }\n& h1, & h2, & h3, & h4, & p, & figure { margin: 0; }\n/* Keyboard focus only: pointer input keeps the native resting appearance. The\n * ring needs no radius of its own — the outline already follows the control's\n * own border-radius, and overriding it here would flatten every control. */\n& :focus-visible { ${officialFocus()}; }\n& [hidden] { display: none !important; }\n\n/* --- Type tiers. The same 14/22 and 13/20 steps the primitives use. --- */\n& .dsh-ui-title { font-size: 16px; line-height: 24px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n& .dsh-ui-heading { font-size: 14px; line-height: 22px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n& .dsh-ui-compact { font-size: 13px; line-height: 20px; color: var(--dsw-alias-label-primary); }\n& .dsh-ui-meta { font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-secondary); }\n& .dsh-ui-hint { font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n& .dsh-ui-error { font-size: 12px; line-height: 18px; color: var(--dsw-alias-state-error-primary); }\n& .dsh-ui-warn { color: var(--dsw-alias-state-warn-primary); }\n& .dsh-ui-success { color: var(--dsw-alias-state-success-primary); }\n& .dsh-ui-muted { color: var(--dsw-alias-label-tertiary); }\n& .dsh-ui-truncate { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n& .dsh-ui-wrap { min-width: 0; overflow-wrap: anywhere; }\n\n/* --- Layout scaffolding. --- */\n& .dsh-ui-stack { display: flex; flex-direction: column; gap: 12px; }\n& .dsh-ui-stack-lg { display: flex; flex-direction: column; gap: 20px; }\n& .dsh-ui-row { display: flex; align-items: center; gap: 8px; min-width: 0; }\n& .dsh-ui-row-wrap { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }\n& .dsh-ui-spacer { flex: 1; min-width: 0; }\n/* A 0.5px l2 rule is the host's section divider; reserve the same rhythm. */\n& .dsh-ui-divider { height: 0.5px; background: var(--dsw-alias-border-l2); }\n& .dsh-ui-section { display: flex; flex-direction: column; gap: 12px; padding-top: 16px; border-top: 0.5px solid var(--dsw-alias-border-l2); }\n\n/* --- Card: a raised surface whose edge lives in the shadow. --- */\n& .dsh-ui-card {\n ${officialElevation('stroke')}\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 16px;\n border-radius: var(--dsw-radius-lg);\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n min-width: 0;\n}\n& .dsh-ui-card--flat { border: 0.5px solid var(--dsw-alias-border-l3); box-shadow: none; }\n& .dsh-ui-card--nested { background: var(--dsw-alias-bg-layer-2); }\n& .dsh-ui-card--plain { background: none; }\n\n/* --- Field: label, control, help, error. The control itself is an\n * official primitive, so this only owns the vertical rhythm. --- */\n& .dsh-ui-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }\n& .dsh-ui-field + .dsh-ui-field { border-top: 0.5px solid var(--dsw-alias-border-l2); padding-top: 12px; }\n& .dsh-ui-label { display: flex; align-items: center; gap: 6px; font-size: 13px; line-height: 20px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n& .dsh-ui-label-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }\n& .dsh-ui-help { font-size: 12px; line-height: 1.6; color: var(--dsw-alias-label-secondary); }\n& .dsh-ui-help p { margin: 0; }\n& .dsh-ui-help p + p { margin-top: 8px; }\n& .dsh-ui-required { color: var(--dsw-alias-state-error-primary); }\n& .dsh-ui-control { width: 100%; min-width: 0; }\n/* An invalid control is marked on the control, not only in the message. */\n& .dsh-ui-control[aria-invalid='true'] { border-color: var(--dsw-alias-state-error-primary); }\n& .dsh-ui-readonly { display: flex; flex-direction: column; gap: 4px; min-width: 0; }\n& .dsh-ui-readonly > dt { font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n& .dsh-ui-readonly > dd { margin: 0; font-size: 13px; line-height: 20px; overflow-wrap: anywhere; }\n\n/* --- Buttons row. A no-op container: it exists so actions line up on the\n * trailing edge the way every native panel does. --- */\n& .dsh-ui-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding-top: 4px; }\n& .dsh-ui-actions-end { justify-content: flex-end; }\n\n/* --- Banners. A banner is a left-rail notice, the shape used for warnings,\n * deprecations and blocking instructions. --- */\n& .dsh-ui-banner {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 10px 14px;\n border: 0.5px solid var(--dsw-alias-border-l3);\n border-left: 3px solid var(--dsw-alias-state-warn-primary);\n border-radius: var(--dsw-radius-md);\n background: var(--dsw-alias-bg-layer-1);\n font-size: 13px;\n line-height: 20px;\n color: var(--dsw-alias-label-secondary);\n}\n& .dsh-ui-banner-title { font-weight: 500; color: var(--dsw-alias-state-warn-primary); }\n& .dsh-ui-banner--info { border-left-color: var(--dsw-alias-state-business-primary); }\n& .dsh-ui-banner--danger { border-left-color: var(--dsw-alias-state-error-primary); }\n& .dsh-ui-banner--success { border-left-color: var(--dsw-alias-state-success-primary); }\n& .dsh-ui-banner p { margin: 0; }\n\n/* --- Inline notice: a transient confirmation with no chrome of its own. --- */\n& .dsh-ui-notice { display: flex; align-items: center; gap: 6px; font-size: 12px; line-height: 18px; color: var(--dsw-alias-state-success-primary); }\n& .dsh-ui-notice--error { color: var(--dsw-alias-state-error-primary); }\n\n/* --- Empty and loading states. Both sit in a dashed well so an empty panel\n * reads as \"nothing here yet\" rather than as a broken layout. --- */\n& .dsh-ui-empty {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 6px;\n padding: 20px 16px;\n border: 0.5px dashed var(--dsw-alias-border-l3);\n border-radius: var(--dsw-radius-md);\n font-size: 13px;\n line-height: 20px;\n color: var(--dsw-alias-label-secondary);\n}\n& .dsh-ui-loading { display: flex; align-items: center; gap: 8px; padding: 20px 0; font-size: 13px; line-height: 20px; color: var(--dsw-alias-label-secondary); }\n\n/* --- Selectable list. A row is a button-sized target with a hover fill and\n * a selected fill; the name carries the weight, the description does not. --- */\n& .dsh-ui-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; min-width: 0; }\n& .dsh-ui-list-scroll { max-height: min(66vh, 760px); overflow-y: auto; overflow-x: hidden; }\n& .dsh-ui-list-row { border-radius: var(--dsw-radius-md); }\n& .dsh-ui-list-row:hover { background: var(--dsw-alias-interactive-bg-hover); }\n& .dsh-ui-list-row[aria-selected='true'], & .dsh-ui-list-row[data-selected] { background: var(--dsw-alias-interactive-bg-active); }\n& .dsh-ui-list-item {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n width: 100%;\n min-width: 0;\n padding: 10px 12px;\n border: 0;\n border-radius: var(--dsw-radius-md);\n background: none;\n font: inherit;\n color: inherit;\n text-align: start;\n cursor: pointer;\n}\n& .dsh-ui-list-item:disabled { cursor: default; }\n& .dsh-ui-list-item:disabled:hover { background: none; }\n& .dsh-ui-list-name { font-size: 14px; line-height: 22px; font-weight: 500; color: var(--dsw-alias-label-primary); overflow-wrap: anywhere; }\n& .dsh-ui-list-desc { font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n\n/* --- Code and structured output. Wraps rather than scrolls, because a\n * feature panel is read rather than scanned. --- */\n& .dsh-ui-code {\n padding: 10px 12px;\n border: 0.5px solid var(--dsw-alias-border-l3);\n border-radius: var(--dsw-radius-md);\n background: var(--dsw-alias-bg-layer-1);\n font-family: var(--ds-font-family-code);\n font-size: 12px;\n line-height: 20px;\n color: var(--dsw-alias-label-secondary);\n overflow-wrap: anywhere;\n white-space: pre-wrap;\n}\n& .dsh-ui-scroll { max-height: 60vh; overflow: auto; overscroll-behavior: contain; }\n\n/* --- A toggle row: label on the left, switch on the trailing edge. This is\n * layout only; the switch itself is the official primitive. --- */\n& .dsh-ui-toggle-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; min-width: 0; padding: 12px 0; }\n& .dsh-ui-toggle-row + .dsh-ui-toggle-row { border-top: 0.5px solid var(--dsw-alias-border-l2); }\n& .dsh-ui-toggle-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }\n& .dsh-ui-toggle-label { font-size: 14px; line-height: 22px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n\n/* --- Floating surface: a panel anchored to a trigger. This is the material\n * a menu card is made of — the translucent fill plus its backdrop blur, with\n * the edge riding inside the prominent elevation. A plugin that hand-rolls this\n * is how tokens like --dsw-specific-menu get invented; use this instead. --- */\n& .dsh-ui-surface {\n --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);\n --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);\n --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);\n position: relative;\n display: flex;\n flex-direction: column;\n border: 0;\n border-radius: var(--dsw-radius-lg);\n background: var(--dsw-menu-surface-fill);\n backdrop-filter: var(--dsw-menu-backdrop-filter);\n box-shadow: var(--dsw-elevation-prominent);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n line-height: 20px;\n min-width: 0;\n}\n& .dsh-ui-surface-body { display: flex; flex-direction: column; gap: 8px; padding: 12px 14px 14px; overflow-y: auto; }\n& .dsh-ui-surface-head { display: flex; align-items: center; gap: 8px; min-width: 0; }\n& .dsh-ui-surface-title { font-size: 14px; line-height: 22px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n\n/* --- Native select. The primitives ship no select, so a plugin that offers a\n * closed list of choices keeps the platform control and matches the official\n * settings field geometry exactly (34px, 0.5px l4, radius-md, layer-3). A\n * SegmentedControl is the primitive to reach for when the choices are few\n * enough to show at once. --- */\n& .dsh-ui-select {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n height: 34px;\n padding: 0 12px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: var(--dsw-radius-md);\n background: var(--dsw-alias-bg-layer-3);\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n}\n& .dsh-ui-select:focus-visible { outline: none; border-color: var(--dsw-alias-state-business-primary); }\n& .dsh-ui-select:disabled { color: var(--dsw-alias-label-tertiary); cursor: default; }\n& .dsh-ui-select[aria-invalid='true'] { border-color: var(--dsw-alias-state-error-primary); }\n\n/* --- Native textarea. The primitives ship no textarea either, so a settings\n * prompt keeps the platform element and the same field shell as the select:\n * 0.5px l4, radius-md, layer-3, 13/1.5 type. It grows vertically instead of\n * locking to the select's 34px row. --- */\n& .dsh-ui-textarea {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n resize: vertical;\n padding: 8px 12px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: var(--dsw-radius-md);\n background: var(--dsw-alias-bg-layer-3);\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n& .dsh-ui-textarea:focus-visible { outline: none; border-color: var(--dsw-alias-state-business-primary); }\n& .dsh-ui-textarea:disabled { color: var(--dsw-alias-label-tertiary); cursor: default; }\n& .dsh-ui-textarea::placeholder { color: var(--dsw-alias-label-dimmed); }\n& .dsh-ui-textarea[aria-invalid='true'] { border-color: var(--dsw-alias-state-error-primary); }\n\n/* Long panels scroll inside themselves instead of growing the host page. */\n& .dsh-ui-panel { display: flex; flex-direction: column; gap: 16px; min-width: 0; }\n& .dsh-ui-panel-wide { max-width: 100%; }\n\n@media (prefers-reduced-motion: reduce) {\n & *, & *::before, & *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }\n}\n}\n`\n // Widen every recipe from \"a descendant of the root\" to \"the root, or one of\n // its descendants\". Written as a transform rather than by hand so no recipe\n // can be added later with only the descendant form. The pattern is narrow on\n // purpose: a leading `&` followed by one recipe class and no combinator, so\n // sibling and child rules such as `.dsh-ui-field + .dsh-ui-field` keep their\n // own meaning and are left alone.\n return sheet.replace(/^& (\\.dsh-ui-[a-z0-9-]+)(?![+>~])/gm, (_match, className: string) =>\n `&${className}, & ${className}`)\n}\n","import type { ContextFormed } from '@deepseek-ai/dsh-llm'\nimport type { ModelRoute } from '@klarkxy/dsh-model-route'\n\n/**\n * The canonical home is @klarkxy/dsh-model-route; re-exported here so existing\n * plugin-kit consumers keep compiling.\n */\nexport type { ModelRoute }\n\n/** Public, browser-safe contracts. Host implementations stay in their owning packages. */\nexport type ProducerSourceKind = `plugin:${string}`\nexport type ProducerMessageSource = { kind: ProducerSourceKind; plugin: string } & ContextFormed\n\n/**\n * V4 sessions persist the producing extension in `kind`; the retired generic\n * `plugin` wrapper is not admitted. Each feature plugin declares its own kind.\n */\ndeclare module '@deepseek-ai/dsh-llm' {\n interface MessageSourceMap {\n [kind: ProducerSourceKind]: ProducerMessageSource\n }\n}\n\nexport function producerMessageSource(plugin: string): ProducerMessageSource {\n return { kind: `plugin:${plugin}`, plugin }\n}\n\nexport type RpcResult<T = unknown> = { ok: true; value: T } | { ok: false; error: { code: string; message: string } }\nexport const CHAT_EVENTS_SLOT = 'dsh-editor.chat.events'\nexport interface EvidenceRef { sessionId: string; seq: number; kind: 'user' | 'tool' | 'turn' | 'manual'; excerpt?: string }\nexport interface TaskContract {\n id: string\n sessionId: string\n sourceVersion: string\n revision: number\n goal: string\n deliverables: string[]\n inScope: string[]\n outOfScope: string[]\n constraints: string[]\n acceptance: string[]\n assumptions: string[]\n questions: string[]\n evidence: EvidenceRef[]\n readiness: 'pending' | 'clear-request' | 'user-confirmed' | 'disclosed-assumptions' | 'cancelled' | 'stale'\n updatedAt: number\n}\nexport interface TaskCheckpoint {\n id: string\n sessionId: string\n sourceVersion: string\n contractVersion?: number\n fromSeq: number\n toSeq: number\n revision: number\n status: 'running' | 'completed' | 'failed' | 'cancelled'\n items: Array<{ label: string; state: 'pending' | 'verified' | 'failed'; evidence: EvidenceRef[] }>\n constraints: string[]\n nextAction: string\n createdAt: number\n}\nexport type KnowledgeScope = { kind: 'global' } | { kind: 'project'; projectId: string }\nexport type KnowledgeKind = 'preference' | 'project-fact' | 'decision' | 'vocabulary' | 'activity' | 'lesson'\n/** Descriptive context, never an executable instruction or authorization. */\nexport interface ContextKnowledge {\n subject: string\n domain: string\n key: string\n aliases: string[]\n observedAt: number\n /** The user's own time expression, not an inferred completion date. */\n eventTime?: string\n activityStatus?: 'planned' | 'in-progress' | 'blocked' | 'paused' | 'completed' | 'cancelled' | 'unknown'\n}\n/** A scoped method. Observations remain candidates until explicitly accepted. */\nexport interface ProcedureKnowledge {\n origin: 'instruction' | 'observation'\n goal: string\n when: string[]\n steps: string[]\n avoid: string[]\n verify: string[]\n}\nexport interface MemoryRecord {\n id: string\n revision: number\n scope: KnowledgeScope\n kind: KnowledgeKind\n status: 'candidate' | 'active' | 'rejected' | 'superseded' | 'revoked' | 'deleted'\n title: string\n content: string\n tags: string[]\n evidence: EvidenceRef[]\n exceptions: string[]\n source: 'user' | 'memory' | 'dream' | 'self-improvement'\n context?: ContextKnowledge\n procedure?: ProcedureKnowledge\n createdAt: number\n updatedAt: number\n expiresAt?: number\n supersedes?: string[]\n /** Exact record revisions behind a derived candidate; revalidated on adoption. */\n basis?: Array<{ id: string; revision: number }>\n}\nexport type NewMemoryRecord = Omit<MemoryRecord, 'id' | 'revision' | 'createdAt' | 'updatedAt'>\nexport interface MemoryQuery { scope: KnowledgeScope; query?: string; kinds?: KnowledgeKind[]; statuses?: MemoryRecord['status'][]; limit?: number }\nexport interface MemoryMutationOptions { signal?: AbortSignal; isCurrent?: () => boolean }\nexport interface MemoryService {\n list(query: MemoryQuery): Promise<MemoryRecord[]>\n create(record: NewMemoryRecord, options?: MemoryMutationOptions): Promise<MemoryRecord>\n update(id: string, patch: Partial<Pick<MemoryRecord, 'title' | 'content' | 'tags' | 'exceptions' | 'status' | 'expiresAt'>>, expectedRevision: number, options?: MemoryMutationOptions): Promise<MemoryRecord>\n /** Explicit user promotion, persisted atomically on the same record; preserves expiry and evidence. */\n promoteToGlobal(id: string, expectedRevision: number, options?: MemoryMutationOptions): Promise<MemoryRecord>\n remove(id: string, expectedRevision: number, options?: MemoryMutationOptions): Promise<void>\n recall(query: MemoryQuery): Promise<MemoryRecord[]>\n}\n\n/**\n * The session creation metadata the host snapshots when it creates a delegated child\n * thread. Mirrors `CreateAgentOptions.meta` in `@deepseek-ai/dsh-agent`; it is durable\n * session data, so it survives a restart and needs no ancestry walk.\n */\nexport interface SubagentSessionLike {\n readonly header?: {\n readonly parentSession?: unknown\n readonly origin?: unknown\n readonly delegationDepth?: unknown\n readonly isSeeded?: unknown\n readonly classification?: unknown\n }\n}\n\n/**\n * True when `session` is a delegated child thread rather than a human-driven top-level\n * conversation.\n *\n * A message's `source.kind === 'user'` cannot answer this: a lead agent's dispatch prompt\n * is delivered as the child's own user message, so delegated work is indistinguishable\n * from a person typing once you only look at the message. Plugins use this to keep\n * automatic writes and derived model calls on top-level sessions.\n */\nexport function isSubagentSession(session: unknown): boolean {\n const header = (session as SubagentSessionLike | null | undefined)?.header\n if (!header || typeof header !== 'object') return false\n if (header.origin === 'subagent' || Number(header.delegationDepth ?? 0) > 0) return true\n // Native human forks also persist parentSession for history lineage. A fork's\n // seeded header distinguishes it from legacy children whose parent is the\n // only marker. Native rc.2 forks omit depth; patched hosts may persist zero.\n // Explicit delegation and unknown metadata still keep the child guard.\n const humanFork = header.isSeeded === true\n && (header.delegationDepth === undefined || header.delegationDepth === 0)\n && header.origin === undefined\n && (header.classification === undefined || header.classification === 'ordinary' || header.classification === 'free')\n return Boolean(header.parentSession) && !humanFork\n}\n\n/** Project keys come only from the host-validated session directory, never client input. */\nexport function projectIdFromCwd(cwd: string | undefined): string | undefined {\n if (typeof cwd !== 'string') return undefined\n const normalized = cwd.trim().replaceAll('\\\\', '/')\n if (!normalized) return undefined\n return normalized === '/' || /^[A-Za-z]:\\/$/.test(normalized) ? normalized : normalized.replace(/\\/+$/, '')\n}\n\n/**\n * Remote contribution for model-settings change notifications.\n * Provided by `@klarkxy/dsh-model-hub` (`ModelSettingsChangesController`);\n * subscribers degrade silently when that package is not installed.\n * The stream carries invalidations only — `ready` is never a settings snapshot.\n */\nexport const MODEL_SETTINGS_CHANGES_REMOTE = {\n package: '@klarkxy/dsh-model-hub',\n descriptors: [{\n id: 'modelSettingsChanges/watch',\n service: 'modelSettingsChangesController',\n namespace: 'modelSettingsChanges',\n method: 'watch',\n mode: 'stream' as const,\n invocation: { kind: 'direct' as const },\n parameters: [] as const,\n cancellation: { parameter: 'signal' as const },\n }],\n}\n\n/**\n * Repository extension: a native web provider announces that its local\n * availability changed. Kind is `search` or `fetch`; id is the provider id.\n * Listeners refresh management state and must not treat this as a network probe.\n */\nexport const WEB_PROVIDER_AVAILABILITY_EVENT = 'web/provider-availability-updated' as const\n\n/**\n * Optional display metadata a provider may attach when it registers directly\n * with `ctx.web`. Execution and credentials stay with the provider; this object\n * is display-only and must never carry secret values.\n */\nexport interface DshWebManagementDescriptor {\n readonly id: string\n readonly label: string\n readonly description: string\n readonly defaultBaseURL?: string\n readonly credentialRef?: string\n /** True when the key is shared with another surface. The page must not delete it. */\n readonly credentialShared?: boolean\n /** Optional notice naming the settings surface that owns a shared credential. */\n readonly credentialHint?: string\n readonly billing: 'request' | 'model-and-tools' | 'none' | 'unknown'\n /** Optional provider-supplied billing summary. */\n readonly pricing?: string\n /** Public HTTPS page explaining provider charges. */\n readonly pricingUrl?: string\n /** Public HTTPS page where the user can create an API key. */\n readonly signupUrl?: string\n /** Plugin that owns configuration. Native providers keep their settings there. */\n readonly configurationOwner?: string\n /** Explicit settings link supplied by the provider, never inferred from its id. */\n readonly configurationUrl?: string\n /** Fixed legacy route migrated by a bundle-owned adapter; not used by native plugins. */\n readonly legacyId?: string\n}\n\n/**\n * Host Creator agent-preset id (`agentPresets.composedPreset`).\n * Plugins that gate Creator-only tools or prompt sections compare against this.\n */\nexport const CREATOR_PRESET_ID = 'cordis'\n","import type { TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol'\nimport { MODEL_SETTINGS_CHANGES_REMOTE } from './contracts.ts'\n\nexport type ModelSettingsChangeFrame = { kind: 'ready' } | { kind: 'changed'; ns: string; revision: number }\n\n/** This stream carries invalidations only; ready is never a settings snapshot. */\nexport function parseModelSettingsChangeFrame(value: unknown): ModelSettingsChangeFrame {\n if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('Invalid model settings change frame')\n const frame = value as Record<string, unknown>\n if (frame.kind === 'ready' && Object.keys(frame).length === 1) return { kind: 'ready' }\n if (frame.kind === 'changed' && Object.keys(frame).length === 3 && typeof frame.ns === 'string' && frame.ns.length > 0\n && typeof frame.revision === 'number' && Number.isSafeInteger(frame.revision) && frame.revision >= 0) {\n return { kind: 'changed', ns: frame.ns, revision: frame.revision }\n }\n throw new Error('Invalid model settings change frame')\n}\n\n/** One contribution mounted by Model Hub; consumers only inject its service. */\nexport const modelSettingsChangesRemote: TypertRemoteContribution = {\n package: MODEL_SETTINGS_CHANGES_REMOTE.package,\n descriptors: MODEL_SETTINGS_CHANGES_REMOTE.descriptors.map(descriptor => ({\n ...descriptor,\n result: { mode: 'strict' as const, typeSymbol: 'ModelSettings.ChangeFrame', create: () => ({ parse: parseModelSettingsChangeFrame }) },\n })),\n}\n\ninterface StreamItem {\n generation: number\n value: unknown\n signal: AbortSignal\n accept(): void\n}\ninterface ChangeStream extends AsyncIterable<StreamItem> { dispose(): Promise<void> }\nexport interface ModelSettingsSubscriberScope {\n remote: {\n modelSettingsChanges: { watch(signal: AbortSignal): AsyncIterable<unknown> }\n $stream(options: {\n name: string\n open(signal: AbortSignal): AsyncIterable<unknown>\n ended(accepted: boolean): Error\n }): ChangeStream\n }\n effect(callback: () => () => void | Promise<void>): unknown\n}\nexport interface ModelSettingsSubscriberContext {\n inject(dependencies: string[], callback: (scope: unknown) => void): unknown\n}\nexport interface ModelSettingsSubscriber {\n subscribe(onChange: () => void, onError?: (message: string) => void): () => void\n}\n\n/** Native RemoteStream owns carrier reconnects; no timers or browser transport.\n * A factory shares one logical stream while at least one subscriber remains. */\nexport function createModelSettingsSubscriber(ctx: ModelSettingsSubscriberContext, namespace: string): ModelSettingsSubscriber {\n const listeners = new Set<{ change: () => void; error?: (message: string) => void }>()\n let injection: { dispose(): void | Promise<void> } | undefined\n let current: { stream: ChangeStream; active: boolean } | undefined\n let lifecycle = 0\n let failureMessage: string | undefined\n const report = (message: string) => {\n failureMessage = message\n for (const listener of [...listeners]) {\n try { listener.error?.(message) } catch { /* Isolate page callbacks. */ }\n }\n }\n const invalidate = () => {\n for (const listener of [...listeners]) {\n if (!listeners.has(listener)) continue\n try { listener.change() } catch (error) {\n try { listener.error?.(error instanceof Error ? error.message : String(error)) } catch { /* Isolate callbacks. */ }\n }\n }\n }\n const start = () => {\n const life = ++lifecycle\n injection = ctx.inject(['remote', 'remote.modelSettingsChanges'], injected => {\n if (life !== lifecycle || !listeners.size) return\n const scope = injected as ModelSettingsSubscriberScope\n const stream = scope.remote.$stream({\n name: 'Model settings sync',\n open: signal => scope.remote.modelSettingsChanges.watch(signal),\n ended: accepted => new Error(`Model settings sync stream ended ${accepted ? 'after' : 'before'} ready; refresh or reopen the page`),\n })\n const session = { stream, active: true }\n current = session\n scope.effect(() => () => {\n session.active = false\n if (current === session) {\n current = undefined\n if (life === lifecycle && listeners.size) report('Model settings sync service unavailable')\n }\n return stream.dispose()\n })\n void (async () => {\n let generation: number | undefined\n let ready = false\n try {\n for await (const item of stream) {\n if (!session.active || life !== lifecycle || !listeners.size) break\n if (item.signal.aborted) continue\n if (generation !== item.generation) { generation = item.generation; ready = false }\n const frame = parseModelSettingsChangeFrame(item.value)\n if (frame.kind === 'ready') {\n ready = true\n failureMessage = undefined\n // Accept the validated invalidation baseline, not fetched data.\n // Every current listener queues its own latest settings read.\n item.accept()\n invalidate()\n } else {\n if (!ready) throw new Error('Model settings sync change arrived before ready')\n if (namespace === '*' || frame.ns === namespace) invalidate()\n }\n }\n } catch (error) {\n if (session.active && life === lifecycle) report(error instanceof Error ? error.message : String(error))\n } finally {\n if (current === session) current = undefined\n session.active = false\n await stream.dispose().catch(() => {})\n }\n })()\n }) as { dispose(): void | Promise<void> }\n queueMicrotask(() => {\n if (life === lifecycle && listeners.size && !current) report('Model settings sync service unavailable')\n })\n }\n return Object.freeze({ subscribe(onChange: () => void, onError?: (message: string) => void) {\n const listener = { change: onChange, error: onError }\n listeners.add(listener)\n if (!injection) start()\n else if (failureMessage) queueMicrotask(() => {\n if (listeners.has(listener) && failureMessage) {\n try { listener.error?.(failureMessage) } catch { /* Isolate callbacks. */ }\n }\n })\n return () => {\n if (!listeners.delete(listener) || listeners.size) return\n lifecycle++\n if (current) { current.active = false; void current.stream.dispose().catch(() => {}) }\n current = undefined\n failureMessage = undefined\n const previous = injection\n injection = undefined\n try { void Promise.resolve(previous?.dispose()).catch(() => {}) } catch { /* Already unloaded. */ }\n }\n } })\n}\n","import { defaultModelRoute, normalizeModelRoute, type ModelRoute } from '@klarkxy/dsh-model-route'\nexport { defaultModelRoute, normalizeModelRoute }\n\n/** Browser-safe contracts. Shared RPC/result types stay on @klarkxy/dsh-plugin-kit. */\nimport type { RpcResult as SharedRpcResult } from '@klarkxy/dsh-plugin-kit/contracts'\nexport type RpcResult<T = unknown> = Extract<SharedRpcResult<T>, { ok: true }> | {\n ok: false\n error: { code: string; message: string; partial?: PartialCommitResult }\n}\n\nexport const PLUGIN_NAME = '@klarkxy/dsh-git-commit'\nexport const FEATURE_ID = 'git-commit'\nexport const PURPOSE_ID = 'git-commit.plan'\nexport const RPC_CHANNEL = '/dsh-git-commit'\nexport const GIT_COMMIT_CLIENT_SERVICE = 'dshGitCommitClient'\nexport const PROMPT_VERSION = 'git-commit.v1'\nexport const SCHEMA_VERSION = 'commit-plan-json.v1'\nexport const CONTRACT_VERSION = 1\n\nexport const DEFAULT_MAX_OUTPUT_TOKENS = 2048\n/** Total character budget for the change manifest sent to the model. */\nexport const MAX_MANIFEST_CHARS = 48_000\n/** Per-file preview cap for untracked files. */\nexport const MAX_UNTRACKED_PREVIEW_CHARS = 2_000\n/** Recent commit subjects supplied as style reference. */\nexport const RECENT_LOG_COUNT = 10\n/** Hard cap for one generated commit message line. */\nexport const MAX_MESSAGE_CHARS = 120\n/** git subprocess timeout. */\nexport const GIT_TIMEOUT_MS = 30_000\nexport const SETTINGS_KEY = 'current'\n\n/**\n * Plugin-page model selection. Empty provider/model means \"follow the default\".\n * The value shape, empty default, and 250/80 normalizer live in\n * @klarkxy/dsh-model-route; this alias keeps the commit-specific name.\n */\nexport type CommitModelRoute = ModelRoute\n\nexport interface GitCommitSettings {\n readonly revision: number\n readonly model: CommitModelRoute\n /**\n * Opt-in single commit when the model produced no usable plan. Off by\n * default: an unplanned commit is one the user never reviewed, so a failed\n * or unusable model call rejects the run instead of writing to the index.\n */\n readonly allowFallback: boolean\n}\n\nexport const defaultSettings = (): GitCommitSettings => ({\n revision: 0, model: defaultModelRoute(), allowFallback: false,\n})\n\n/** Untrusted stored flags stay opt-in: anything but a literal true is false. */\nexport function normalizeFallback(value: unknown): boolean {\n return value === true\n}\n\nexport interface CommitModelInfo {\n readonly provider: string\n readonly model: string\n /** 'page' is the plugin-page selection; 'default' follows the session or host chat model. */\n readonly source: 'page' | 'default'\n}\n\nexport interface GitCommitStatus {\n readonly available: boolean\n /** Machine-readable reason when unavailable: 'no-session' | 'no-cwd' | 'not-a-repo' | 'no-git'. */\n readonly reason?: string\n readonly detail?: string\n readonly root?: string\n readonly branch?: string\n readonly workspace: { readonly files: number }\n readonly model?: CommitModelInfo\n}\n\nexport interface CommitGroupResult {\n /** Empty only when a created commit's hash could not be read. */\n readonly hash: string\n readonly message: string\n readonly files: readonly string[]\n}\n\nexport interface CommitRunResult {\n readonly branch: string\n readonly commits: readonly CommitGroupResult[]\n /** True when the model plan was unavailable and a single fallback commit was used. */\n readonly fallback: boolean\n readonly model?: CommitModelInfo\n}\n\n/**\n * Commits that already exist when a later group fails or the run is cancelled.\n * `commits` is the durable outcome; `failure` is why the rest did not run.\n * A recorded commit is never rolled back and never retried by this plugin.\n */\nexport interface PartialCommitResult {\n readonly branch: string\n readonly commits: readonly CommitGroupResult[]\n readonly fallback: boolean\n readonly model?: CommitModelInfo\n readonly failure: { readonly code: string; readonly message: string }\n readonly remaining: readonly { readonly message: string; readonly files: readonly string[] }[]\n /** After a rejected commit command, unchanged HEAD could not be proved; completion and ownership are unconfirmed. */\n readonly uncertain?: readonly { readonly message: string; readonly files: readonly string[] }[]\n}\n","import type { Context } from '@deepseek-ai/cordis'\nimport {\n MODEL_CATALOG_INJECT, readModelCatalog, modelMenuEffortLabel, modelMenuEffortOptions, parseModelMenuChoices,\n} from '@klarkxy/dsh-model-route'\nimport { ModelCatalogStatus, ModelMenu, modelMenuCss, useModelCatalog } from '@klarkxy/dsh-model-route/ui'\nimport { useCallback, useEffect, useRef, useState, useSyncExternalStore } from 'react'\nimport { createPortal } from 'react-dom'\nimport {\n Button, IconChevronDownOutlineRegular, IconRefreshOutlineRegular, Switch, Tag, Tooltip, useAnchoredPosition, useDismissOnOutsidePointer,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport { officialUiCss } from '@klarkxy/dsh-plugin-kit/official-ui'\nimport { createModelSettingsSubscriber } from '@klarkxy/dsh-plugin-kit/model-settings-client'\nimport {\n GIT_COMMIT_CLIENT_SERVICE, PLUGIN_NAME, RPC_CHANNEL, type CommitModelRoute, type CommitRunResult,\n type GitCommitSettings, type GitCommitStatus, type PartialCommitResult, type RpcResult,\n} from './contracts.ts'\n\nexport const name = 'dsh-git-commit-client'\nexport const inject = ['slots', 'connection', ...MODEL_CATALOG_INJECT, 'locale'] as const\n\nconst NS = 'dsh-git-commit.action'\n\nconst zh = {\n action: '提交',\n title: '提交到 Git',\n commitAction: '分次提交全部工作区修改',\n files: '个文件',\n model: '模型',\n modelDefault: '默认模型',\n modelCustom: '插件设置',\n filesCount: '({n} 个文件)',\n confirmPrompt: '将把 {n} 个文件的全部修改分次提交到当前分支。',\n confirm: '确认提交',\n cancel: '取消',\n loading: '正在读取仓库状态…',\n running: '正在整理修改并分次提交…',\n done: '已创建提交',\n partial: '本次提交未全部完成;以下提交已保留',\n stopped: '本次操作未确认完成',\n uncertain: '以下提交组的结果不确定。请检查 Git 日志和状态,确认后再操作。',\n hashUnavailable: '提交已创建,哈希未读取',\n remaining: '尚未提交:{n} 组',\n cancelled: '提交操作已取消',\n fallback: '模型不可用,已合并为单个提交',\n noWorkspace: '工作区没有修改',\n unavailable: '不可用',\n reasonNoRepo: '当前目录不在 Git 仓库中',\n reasonNoGit: '未找到 git 命令',\n reasonNoCwd: '会话没有工作目录',\n reasonNoSession: '会话不在线',\n sessionRunning: '会话正在运行,提交已暂停',\n refresh: '刷新',\n failed: '操作失败',\n disabled: '插件已停用',\n busy: '已有提交操作正在进行',\n stale: '设置已更新,请刷新后重试',\n workspaceChanged: '工作区或分支已变更,请刷新后重试提交',\n settingsUnavailable: '无法读取提交设置,请重新加载插件后重试',\n invalidRequest: '提交请求无效,请刷新后重试',\n planUnavailable: '模型没有给出可用的提交方案,已取消本次提交,工作区没有被改动。换一个模型重试,或在插件设置里开启兜底提交。',\n close: '关闭',\n}\n\nconst en: Record<keyof typeof zh, string> = {\n action: 'Commit',\n title: 'Commit to Git',\n commitAction: 'Commit all workspace changes',\n files: 'files',\n model: 'Model',\n modelDefault: 'default model',\n modelCustom: 'Plugin settings',\n filesCount: ' ({n} files)',\n confirmPrompt: 'All changes in {n} files will be committed to the current branch in one or more commits.',\n confirm: 'Commit now',\n cancel: 'Cancel',\n loading: 'Reading repository status…',\n running: 'Organizing changes into commits…',\n done: 'Commits created',\n partial: 'This run stopped before completion; these commits were kept',\n stopped: 'This run did not finish with a confirmed result',\n uncertain: 'The outcome of these groups is uncertain. Check Git log and status before taking further action.',\n hashUnavailable: 'Commit created; hash unavailable',\n remaining: 'Groups not committed: {n}',\n cancelled: 'Commit run cancelled',\n fallback: 'Model unavailable; used a single commit',\n noWorkspace: 'No workspace changes',\n unavailable: 'Unavailable',\n reasonNoRepo: 'Current directory is not inside a Git repository',\n reasonNoGit: 'git executable not found',\n reasonNoCwd: 'Session has no working directory',\n reasonNoSession: 'Session is not live',\n sessionRunning: 'Session is running; commits paused',\n refresh: 'Refresh',\n failed: 'Operation failed',\n disabled: 'Plugin disabled',\n busy: 'A commit run is already in progress',\n stale: 'Settings changed; refresh and retry',\n workspaceChanged: 'The workspace or branch changed; refresh and retry the commit',\n settingsUnavailable: 'Could not read commit settings; reload the plugin and retry',\n invalidRequest: 'Invalid commit request; refresh and retry',\n planUnavailable: 'The model returned no usable commit plan, so the run was cancelled and your workspace is untouched. Try another model, or turn on the fallback in plugin settings.',\n close: 'Close',\n}\n\ntype Key = keyof typeof zh\ntype Translate = (key: Key) => string\n\ninterface ConnectionLike {\n generation?: { subscribe(listener: () => void): () => void }\n rpc: { call(channel: string, endpoint: string, payload: unknown): Promise<unknown> }\n}\n\ninterface SessionSnapshotLike {\n running?: boolean\n}\n\ninterface UseSessionLike {\n <T>(selector: (snapshot: SessionSnapshotLike) => T): T\n}\n\n/** A failed RPC keeps its code so the panel can explain a rejection in its own words. */\nclass RpcError extends Error {\n readonly code: string\n readonly partial?: PartialCommitResult\n constructor(code: string, message: string, partial?: PartialCommitResult) {\n super(message)\n this.name = 'RpcError'\n this.code = code\n this.partial = partial\n }\n}\n\nexport interface GitCommitActionProps {\n sessionId: string\n useSession: UseSessionLike\n call: (endpoint: string, payload: unknown) => Promise<unknown>\n t: Translate\n}\n\nasync function rpc<T>(\n call: GitCommitActionProps['call'], endpoint: string, payload: unknown = {}, fallback = '',\n): Promise<T> {\n const result = await call(endpoint, payload) as RpcResult<T> | undefined\n if (!result || result.ok !== true) {\n const failed = result && 'error' in result ? result.error : undefined\n throw new RpcError(failed?.code ?? 'unknown', failed?.message ? failed.message : fallback,\n failed && 'partial' in failed ? failed.partial : undefined)\n }\n return result.value\n}\n\nfunction reasonText(t: Translate, status: GitCommitStatus): string {\n switch (status.reason) {\n case 'not-a-repo': return t('reasonNoRepo')\n case 'no-git': return t('reasonNoGit')\n case 'no-cwd': return t('reasonNoCwd')\n case 'no-session': return t('reasonNoSession')\n default: return t('unavailable')\n }\n}\n\n/** A refusal the plugin can name gets its own sentence; the rest stay verbatim. */\nfunction errorText(t: Translate, error: { code: string; message: string }): string {\n const keys: Record<string, Key> = {\n 'plan-unavailable': 'planUnavailable', 'no-session': 'reasonNoSession', 'no-cwd': 'reasonNoCwd',\n 'no-git': 'reasonNoGit', 'not-a-repo': 'reasonNoRepo', 'no-changes': 'noWorkspace',\n 'session-running': 'sessionRunning', 'session-changed': 'workspaceChanged', 'workspace-changed': 'workspaceChanged',\n busy: 'busy', stale: 'stale', disposed: 'disabled', cancelled: 'cancelled',\n 'settings-unavailable': 'settingsUnavailable', 'bad-request': 'invalidRequest', 'not-found': 'invalidRequest',\n }\n const key = keys[error.code]\n return key ? t(key) : error.message || t('failed')\n}\n\nfunction panelError(reason: unknown): { code: string; message: string } {\n return reason instanceof RpcError\n ? { code: reason.code, message: reason.message }\n : { code: 'unknown', message: reason instanceof Error ? reason.message : String(reason) }\n}\n\nfunction GitBranchIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <circle cx=\"4.5\" cy=\"3.5\" r=\"1.6\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <circle cx=\"4.5\" cy=\"12.5\" r=\"1.6\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <circle cx=\"11.5\" cy=\"6.5\" r=\"1.6\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <path d=\"M4.5 5.1v5.8\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <path d=\"M11.5 8.1c0 2-1.6 2.9-3.4 3\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n </svg>\n )\n}\n\nexport function GitCommitAction({ sessionId, useSession, call, t }: GitCommitActionProps) {\n const [open, setOpen] = useState(false)\n const [status, setStatus] = useState<GitCommitStatus>()\n const [loading, setLoading] = useState(false)\n const [running, setRunning] = useState(false)\n const [result, setResult] = useState<CommitRunResult | PartialCommitResult | null>(null)\n const [error, setError] = useState<{ code: string; message: string } | null>(null)\n const [confirming, setConfirming] = useState(false)\n const rootRef = useRef<HTMLDivElement>(null)\n const triggerRef = useRef<HTMLButtonElement>(null)\n const panelRef = useRef<HTMLDivElement>(null)\n const generationRef = useRef(0)\n const position = useAnchoredPosition({ open, anchorRef: triggerRef, panelRef, gap: 5, margin: 16 })\n const sessionRunning = useSession(snapshot => snapshot.running === true)\n\n const changeOpen = useCallback((next: boolean) => {\n setOpen(next)\n setConfirming(false)\n if (next) {\n setResult(null)\n setError(null)\n }\n }, [])\n\n // Move focus into the dialog once it is positioned, so keyboard users land inside it.\n const positioned = Boolean(position)\n useEffect(() => {\n if (open && positioned) panelRef.current?.focus()\n }, [open, positioned])\n\n useDismissOnOutsidePointer(rootRef, open, changeOpen, panelRef)\n\n useEffect(() => {\n generationRef.current += 1\n setOpen(false)\n setStatus(undefined)\n setResult(null)\n setError(null)\n setRunning(false)\n }, [sessionId])\n\n const loadStatus = useCallback(async () => {\n const generation = generationRef.current\n setLoading(true)\n setError(null)\n try {\n const next = await rpc<GitCommitStatus>(call, 'status', { sessionId })\n if (generationRef.current !== generation) return\n setStatus(next)\n } catch (reason) {\n if (generationRef.current !== generation) return\n setStatus(undefined)\n setError(panelError(reason))\n } finally {\n if (generationRef.current === generation) setLoading(false)\n }\n }, [call, sessionId])\n\n useEffect(() => {\n if (!open) return\n void loadStatus()\n }, [open, loadStatus])\n\n useEffect(() => {\n if (!open) return\n const dismiss = (event: KeyboardEvent) => {\n if (event.key !== 'Escape') return\n event.preventDefault()\n changeOpen(false)\n triggerRef.current?.focus()\n }\n document.addEventListener('keydown', dismiss)\n return () => document.removeEventListener('keydown', dismiss)\n }, [open, changeOpen])\n\n const runCommit = useCallback(async () => {\n const generation = generationRef.current\n setConfirming(false)\n setRunning(true)\n setResult(null)\n setError(null)\n try {\n const value = await rpc<CommitRunResult>(call, 'commit', { sessionId })\n if (generationRef.current !== generation) return\n setResult(value)\n } catch (reason) {\n if (generationRef.current !== generation) return\n if (reason instanceof RpcError && reason.partial) setResult(reason.partial)\n setError(panelError(reason))\n } finally {\n if (generationRef.current === generation) {\n // Even a rejected run may have durable commits or changed the index.\n const next = await rpc<GitCommitStatus>(call, 'status', { sessionId }).catch(() => undefined)\n if (generationRef.current === generation) {\n setStatus(next)\n setRunning(false)\n }\n }\n }\n }, [call, sessionId])\n\n const available = status?.available === true\n const workspaceCount = status?.workspace.files ?? 0\n const canCommit = available && !running && !sessionRunning && workspaceCount > 0\n\n return (\n <div ref={rootRef} className=\"gcm-root\">\n <Tooltip label={t('title')} side=\"bottom\" gap={4}>\n <Button\n ref={triggerRef}\n variant=\"ghost\"\n size=\"sm\"\n icon={<GitBranchIcon />}\n aria-label={t('title')}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n onClick={() => changeOpen(!open)}\n >\n {t('action')}\n </Button>\n </Tooltip>\n {open && createPortal(\n <div\n ref={panelRef}\n className=\"gcm-root dsh-ui-surface gcm-panel\"\n style={position ?? { visibility: 'hidden', left: 0, top: 0 }}\n role=\"dialog\"\n tabIndex={-1}\n aria-label={t('title')}\n >\n <div className=\"dsh-ui-surface-body\">\n <div className=\"dsh-ui-surface-head\">\n <span className=\"dsh-ui-surface-title\">{t('title')}</span>\n {status?.branch ? <span className=\"dsh-ui-hint dsh-ui-truncate\">{status.branch}</span> : null}\n <span className=\"dsh-ui-spacer\" />\n <Tooltip label={t('refresh')} side=\"bottom\" gap={4}>\n <Button variant=\"ghost\" size=\"sm\" aria-label={t('refresh')} icon={<IconRefreshOutlineRegular size={14} />}\n disabled={loading || running} onClick={() => void loadStatus()} />\n </Tooltip>\n </div>\n {loading && !status && <p className=\"dsh-ui-hint\" role=\"status\">{t('loading')}</p>}\n {error !== null && <p className=\"dsh-ui-error\" role=\"alert\">{errorText(t, error)}</p>}\n {status && !available && <p className=\"dsh-ui-meta\" role=\"status\">{reasonText(t, status)}</p>}\n {available && (\n <>\n {status?.model ? (\n <p className=\"gcm-model\">\n <span className=\"dsh-ui-hint\">{t('model')}</span>\n <span className=\"dsh-ui-truncate\">{status.model.provider}/{status.model.model}</span>\n <Tag tone={status.model.source === 'page' ? 'info' : 'neutral'}>\n {status.model.source === 'page' ? t('modelCustom') : t('modelDefault')}\n </Tag>\n </p>\n ) : null}\n {confirming && canCommit ? (\n <div className=\"dsh-ui-stack\" role=\"group\" aria-label={t('commitAction')}>\n <p className=\"dsh-ui-hint dsh-ui-wrap\">{t('confirmPrompt').replace('{n}', String(workspaceCount))}</p>\n <div className=\"dsh-ui-actions\">\n <Button variant=\"ghost\" size=\"md\" onClick={() => setConfirming(false)}>{t('cancel')}</Button>\n <Button variant=\"primary\" size=\"md\" onClick={() => void runCommit()}>{t('confirm')}</Button>\n </div>\n </div>\n ) : (\n <Button variant=\"primary\" size=\"md\"\n disabled={!canCommit}\n onClick={() => setConfirming(true)}>\n {t('commitAction')}{t('filesCount').replace('{n}', String(workspaceCount))}\n </Button>\n )}\n {workspaceCount === 0 && <p className=\"dsh-ui-hint\">{t('noWorkspace')}</p>}\n {sessionRunning && <p className=\"dsh-ui-hint\">{t('sessionRunning')}</p>}\n </>\n )}\n {running && <p className=\"dsh-ui-hint\" role=\"status\">{t('running')}</p>}\n {result && (\n <div className=\"dsh-ui-stack\">\n <p className=\"dsh-ui-hint dsh-ui-wrap\">{t('failure' in result ? result.commits.length ? 'partial' : 'stopped' : 'done')} · {result.branch}</p>\n <ul className=\"gcm-commits\">\n {result.commits.map((commit, index) => (\n <li key={`${index}:${commit.hash}`}>\n <code>{commit.hash || t('hashUnavailable')}</code> {commit.message}\n <div className=\"dsh-ui-hint\">{commit.files.join(', ')}</div>\n </li>\n ))}\n </ul>\n {result.fallback && <p className=\"dsh-ui-hint\">{t('fallback')}</p>}\n {'uncertain' in result && result.uncertain?.length ? <>\n <p className=\"dsh-ui-hint\" role=\"status\">{t('uncertain')}</p>\n <ul className=\"gcm-commits\">\n {result.uncertain.map((group, index) => <li key={index}>{group.message}\n <div className=\"dsh-ui-hint\">{group.files.join(', ')}</div>\n </li>)}\n </ul>\n </> : null}\n {'remaining' in result && <>\n <p className=\"dsh-ui-hint\">{t('remaining').replace('{n}', String(result.remaining.length))}</p>\n <ul className=\"gcm-commits\">\n {result.remaining.map((group, index) => <li key={index}>{group.message}\n <div className=\"dsh-ui-hint\">{group.files.join(', ')}</div>\n </li>)}\n </ul>\n </>}\n </div>\n )}\n </div>\n </div>,\n document.body,\n )}\n </div>\n )\n}\n\nexport const clientCss = `${officialUiCss('gcm-root')}${modelMenuCss}\n/* Only the floating panel's geometry is this plugin's own: the material, the\n * rounded edge and the scrollbar tokens all come from the shared contract.\n *\n * The root class is spelled out because the panel is portaled and *is* the\n * root: the dsh-ui-surface recipe therefore reaches it as a compound\n * .gcm-root.dsh-ui-surface selector and declares position:relative at the\n * weight a bare .gcm-panel rule also carries. Left unqualified that recipe\n * wins, and the anchored left/top degrade into offsets from the panel's static\n * spot at the end of body — the popover then renders under the page instead\n * of at the trigger. Naming both classes puts this rule at the same weight,\n * later in the sheet, so it wins. */\n.gcm-root.gcm-panel { position: fixed; width: min(360px, calc(100vw - 32px)); max-height: min(560px, calc(100vh - 32px)); overflow: auto; }\n.gcm-model { display: flex; align-items: center; gap: 6px; min-width: 0; margin: 0; font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-primary); }\n.gcm-commits { margin: 0; padding-inline-start: 18px; display: grid; gap: 2px; font-size: 12px; line-height: 18px; overflow-wrap: anywhere; }\n.gcm-commits code { font-size: 12px; background: var(--dsw-alias-bg-layer-2); padding: 0 4px; border-radius: var(--dsw-radius-sm); }\n.gcm-settings { display: flex; flex-direction: column; gap: 12px; min-width: 0; }\n.gcm-settings-status { display: flex; flex-direction: column; gap: 4px; }\n`\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context { dshGitCommitClient: { active: boolean } }\n}\n\ntype Client = Context & {\n connection: ConnectionLike\n remote?: { session?: { modelCatalog?: () => Promise<unknown> } }\n slots: {\n inject(key: string, callback: () => unknown): () => void\n register(spec: { name: string; id: string; order: number; locale: string; inject: () => unknown } | { name: string; key: string }, render: unknown): () => void\n }\n locale: {\n register(ns: string, locales: { zh: Record<string, string>; en: Record<string, string> }): () => void\n getSnapshot?(): { active: string }\n subscribe?(listener: () => void): () => void\n }\n}\n\n/** Host UI language, following live switches with the host's English fallback. */\nfunction useHostLocale(client: Client): string {\n const subscribe = useCallback(\n (listener: () => void) => client.locale.subscribe?.(listener) ?? (() => {}),\n [client],\n )\n const snapshot = useCallback(() => client.locale.getSnapshot?.().active ?? 'en', [client])\n return useSyncExternalStore(subscribe, snapshot, snapshot)\n}\n\nconst settingsZh = {\n pageTitle: 'Git 提交',\n model: '提交规划模型',\n modelDefault: '默认模型',\n modelHint: '留空则使用当前会话模型,再回落到宿主默认对话模型。',\n fallback: '模型不可用时仍然提交',\n fallbackHint: '默认关闭:模型规划失败会取消本次提交,工作区不变。开启后全部改动会合并成一个提交,由插件代写提交信息。',\n loading: '正在读取设置…',\n saved: '已保存。',\n stale: '设置已更新,请刷新后重试。',\n failed: '无法读取提交设置。',\n retry: '重试',\n refresh: '刷新设置',\n syncUnavailable: '自动刷新不可用,请手动刷新设置。',\n}\n\nconst settingsEn: Record<keyof typeof settingsZh, string> = {\n pageTitle: 'Git Commit',\n model: 'Commit planning model',\n modelDefault: 'Default model',\n modelHint: 'Leave empty to use the current session model, then the host default chat model.',\n fallback: 'Commit even without a model plan',\n fallbackHint: 'Off by default: a failed plan cancels the run and leaves the workspace untouched. When on, every change lands in one commit with a plugin-written message.',\n loading: 'Loading settings…',\n saved: 'Saved.',\n stale: 'Settings changed; refresh and retry.',\n failed: 'Could not load commit settings.',\n retry: 'Retry',\n refresh: 'Refresh settings',\n syncUnavailable: 'Automatic refresh unavailable; refresh settings manually.',\n}\n\nfunction settingsCopy(locale: string): Record<keyof typeof settingsZh, string> {\n return String(locale).startsWith('zh') ? settingsZh : settingsEn\n}\n\n/** Plugin-page settings row: pick the model this plugin's planning call uses. */\nexport function GitCommitSettingsPanel(props: { client: Client; locale?: string; subscribeSettings?: (change: () => void, error?: (message: string) => void) => () => void }) {\n const hostLocale = useHostLocale(props.client)\n const text = settingsCopy(props.locale ?? hostLocale)\n const language = String(props.locale ?? hostLocale).toLowerCase().startsWith('zh') ? 'zh' : 'en'\n const [settings, setSettings] = useState<GitCommitSettings | undefined>(undefined)\n const loadCatalog = useCallback(() => readModelCatalog(props.client), [props.client])\n const subscribeCatalog = useCallback((change: () => void) => props.client.connection.generation?.subscribe(change), [props.client])\n const catalogState = useModelCatalog(loadCatalog, { subscribe: subscribeCatalog })\n const { refresh: refreshCatalog } = catalogState\n const choices = parseModelMenuChoices(catalogState.catalog, settings?.model)\n const [menuOpen, setMenuOpen] = useState(false)\n const [error, setError] = useState<'' | 'failed' | 'stale'>('')\n const [note, setNote] = useState(false)\n const [busy, setBusy] = useState(false)\n const [syncError, setSyncError] = useState('')\n const operation = useRef({ epoch: 0, active: false, reading: false, writing: false, pending: false })\n const refreshRef = useRef<() => void>(() => {})\n\n const call = useCallback(\n (endpoint: string, payload: unknown = {}) => props.client.connection.rpc.call(RPC_CHANNEL, endpoint, payload),\n [props.client],\n )\n\n const refresh = () => {\n const state = operation.current\n if (!state.active) return\n if (state.reading || state.writing) { state.pending = true; return }\n state.pending = false; state.reading = true; setBusy(true)\n const epoch = state.epoch\n void rpc<GitCommitSettings>(call, 'settings', {}, text.failed).then(next => {\n if (state.active && state.epoch === epoch && !state.pending) { setSettings(next); setError('') }\n }).catch(() => {\n if (state.active && state.epoch === epoch && !state.pending) setError('failed')\n }).finally(() => {\n if (!state.active || state.epoch !== epoch) return\n state.reading = false; setBusy(false)\n if (state.pending) refreshRef.current()\n })\n }\n refreshRef.current = refresh\n useEffect(() => {\n const state = operation.current\n state.epoch++; state.active = true; state.reading = false; state.writing = false; state.pending = false\n setBusy(false); setSettings(undefined); setError(''); setNote(false)\n refreshRef.current()\n return () => { state.active = false; state.epoch++ }\n }, [call])\n useEffect(() => {\n setSyncError('')\n let live = true\n const stop = props.subscribeSettings?.(() => { if (live) { setSyncError(''); refreshCatalog(); refreshRef.current() } }, message => { if (live) setSyncError(message) })\n return () => { live = false; stop?.() }\n }, [props.subscribeSettings, props.client, refreshCatalog])\n\n // One patch shape for both rows: the service replaces the whole row, so an\n // update to the toggle must carry the model it is not changing.\n const save = useCallback((patch: { model?: CommitModelRoute; allowFallback?: boolean }) => {\n const state = operation.current\n if (!settings || !state.active || state.writing || state.reading) return\n state.writing = true\n const epoch = state.epoch\n setBusy(true); setNote(false); setError('')\n void rpc<GitCommitSettings>(call, 'settings.update', {\n settings: {\n model: patch.model ?? settings.model,\n allowFallback: patch.allowFallback ?? settings.allowFallback,\n },\n expectedRevision: settings.revision,\n }, text.stale).then(next => {\n if (state.active && state.epoch === epoch) { setSettings(next); setNote(true) }\n }).catch(() => {\n if (state.active && state.epoch === epoch) setError('stale')\n }).finally(() => {\n if (!state.active || state.epoch !== epoch) return\n state.writing = false; setBusy(false)\n if (state.pending) refreshRef.current()\n })\n }, [call, settings, text.saved, text.stale])\n\n if (!settings) {\n return (\n <section className=\"gcm-root gcm-settings\">\n {error\n ? <p role=\"alert\" className=\"dsh-ui-error\">{text[error]}</p>\n : <p role=\"status\" className=\"dsh-ui-hint\">{text.loading}</p>}\n {syncError && <p role=\"status\" className=\"dsh-ui-hint\">{text.syncUnavailable}</p>}\n <Button variant=\"ghost\" size=\"sm\" disabled={busy} onClick={() => refreshRef.current()}>{text.retry}</Button>\n </section>\n )\n }\n\n const current = settings.model\n const follow = !current.provider || !current.model\n const selected = follow ? undefined : choices.find(item => item.provider === current.provider && item.model === current.model)\n const efforts = follow ? [] : modelMenuEffortOptions(selected, current.reasoningEffort)\n const currentLabel = follow ? text.modelDefault : selected?.label ?? `${current.provider} / ${current.model}`\n const selectedEffort = efforts.find(item => item.id === (current.reasoningEffort || ''))\n const effortName = selectedEffort ? modelMenuEffortLabel(selectedEffort, language) : undefined\n\n return (\n <section className=\"gcm-root gcm-settings\" data-testid=\"git-commit-settings\">\n <div className=\"gcm-settings-status\">\n {syncError && <p role=\"status\" className=\"dsh-ui-hint\">{text.syncUnavailable}</p>}\n <Button variant=\"ghost\" size=\"sm\" disabled={busy} onClick={() => refreshRef.current()}>{text.refresh}</Button>\n {error && <p role=\"alert\" className=\"dsh-ui-error\">{text[error]}</p>}\n {note && <p role=\"status\" className=\"dsh-ui-notice\">{text.saved}</p>}\n </div>\n <div className=\"dsh-ui-field\">\n <span className=\"dsh-ui-label\">{text.model}</span>\n <ModelCatalogStatus state={catalogState} locale={language} />\n <ModelMenu\n locale={language}\n open={menuOpen && !busy}\n onOpenChange={next => setMenuOpen(next && !busy)}\n listClassName=\"gcm-root\"\n anchor={<button type=\"button\" className=\"dsh-model-menu-trigger\" disabled={busy} aria-label={`${text.model}: ${currentLabel}`}>\n <span className=\"dsh-model-menu-triggerLabel\">{currentLabel}</span>\n {!follow && efforts.length ? <span className=\"dsh-model-menu-triggerEffort\">{effortName ?? text.modelDefault}</span> : null}\n <IconChevronDownOutlineRegular className={`dsh-model-menu-chevron${menuOpen && !busy ? ' dsh-model-menu-chevronOpen' : ''}`} />\n </button>}\n choices={choices}\n selected={follow ? undefined : { provider: current.provider, model: current.model }}\n onPick={picked => save({ model: { provider: picked.provider, model: picked.model } })}\n leading={[{ id: 'default', label: text.modelDefault, selected: follow }]}\n onPickLeading={() => save({ model: { provider: '', model: '' } })}\n efforts={efforts}\n selectedEffort={current.reasoningEffort || ''}\n onPickEffort={effort => save({ model: follow\n ? { provider: '', model: '' }\n : { provider: current.provider, model: current.model, ...(effort ? { reasoningEffort: effort } : {}) } })}\n modelLabel={text.model}\n modelValue={currentLabel}\n defaultEffortLabel={text.modelDefault}\n />\n </div>\n <p className=\"dsh-ui-meta\">{text.modelHint}</p>\n <article className=\"gcm-root dsh-ui-card\">\n <header className=\"dsh-ui-toggle-row\">\n <div className=\"dsh-ui-toggle-text\">\n <h3 className=\"dsh-ui-toggle-label\">{text.fallback}</h3>\n <p className=\"dsh-ui-hint\">{text.fallbackHint}</p>\n </div>\n <Switch\n checked={settings.allowFallback}\n label={text.fallback}\n disabled={busy}\n onChange={next => save({ allowFallback: next })}\n />\n </header>\n </article>\n </section>\n )\n}\n\nexport function apply(ctx: Context): void {\n const client = ctx as unknown as Client\n const settingsSubscriber = createModelSettingsSubscriber(ctx, PLUGIN_NAME)\n const subscribeSettings = (change: () => void, error?: (message: string) => void) => settingsSubscriber.subscribe(change, error)\n ctx.provide(GIT_COMMIT_CLIENT_SERVICE, { active: true })\n ctx.effect(() => client.locale.register(NS, { zh: { ...zh }, en: { ...en } }), 'git-commit.locale')\n // One stylesheet for both the header popover and the plugin-page settings,\n // so the settings page is styled even when no session header is mounted.\n ctx.effect(() => {\n if (typeof document === 'undefined') return () => {}\n const style = document.createElement('style')\n style.setAttribute('data-plugin', name)\n style.textContent = clientCss\n document.head.appendChild(style)\n return () => style.remove()\n }, 'git-commit.styles')\n ctx.effect(() => client.slots.inject('plugins.bundle.config', () => client.slots.register(\n { name: 'plugins.bundle.config', key: PLUGIN_NAME },\n () => <GitCommitSettingsPanel client={client} subscribeSettings={subscribeSettings} />,\n )), 'git-commit.settings')\n ctx.effect(() => client.slots.inject('conversation.session.header.actions', () => client.slots.register(\n {\n name: 'conversation.session.header.actions',\n id: 'git-commit',\n order: 10,\n locale: NS,\n inject: () => ({\n call: (endpoint: string, payload: unknown) => client.connection.rpc.call(RPC_CHANNEL, endpoint, payload),\n }),\n },\n GitCommitAction,\n )), 'git-commit.slot')\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.inner.cjs","names":["useRef","useState","useCallback","useMemo","Button","useRef","useState","useId","useMemo","rankByName","observeStickyMenuGroups","createPortal","MenuSurface","IconChevronRightOutlineRegular","Input","IconCloseFillRegular","IconCheckOutlineRegular","MenuGroup","isValidElement","cloneElement","useState","useRef","useAnchoredPosition","useCallback","Tooltip","Button","createPortal","IconRefreshOutlineRegular","Tag","useSyncExternalStore","IconChevronDownOutlineRegular","Switch"],"sources":["../../dsh-model-route/src/catalog.ts","../../dsh-model-route/src/menu.ts","../../dsh-model-route/src/catalog-ui.tsx","../../dsh-model-route/src/ui.tsx","../../dsh-plugin-kit/src/official-ui.ts","../../dsh-plugin-kit/src/contracts.ts","../../dsh-plugin-kit/src/model-settings-client.ts","../src/contracts.ts","../src/client.tsx"],"sourcesContent":["/**\n * Host model-catalog parsing shared by plugin settings UIs and model hubs.\n * Pure and browser-safe: no React, no host imports. The catalog envelope is\n * structural so hosts may add fields without breaking consumers.\n */\nimport { modelRouteKey, type ModelRoute } from './route.ts'\n\n/** One selectable model. `efforts` are the advertised reasoning efforts. */\nexport interface ModelMenuChoice {\n readonly provider: string\n readonly model: string\n readonly label: string\n readonly efforts: ReadonlyArray<{ id: string; name: string }>\n}\n\n/** Both services are required: Cordis checks the nested namespace separately. */\nexport const MODEL_CATALOG_INJECT = ['remote', 'remote.session'] as const\n\nexport interface ModelCatalogFailure {\n readonly id: string\n readonly name: string\n readonly message: string\n}\n\n/** The catalog face this helper needs; stays structural so hosts may add more. */\nexport interface ModelCatalogClient {\n readonly remote?: {\n readonly session?: { readonly modelCatalog?: () => Promise<unknown> }\n }\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : undefined\n}\n\nfunction asText(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() ? value.trim() : undefined\n}\n\n/** A useful diagnostic even when a transport rejects with a plain object. */\nexport function modelCatalogErrorMessage(value: unknown): string {\n if (value instanceof Error && value.message) return value.message\n const row = asRecord(value)\n return asText(row?.message) ?? asText(value) ?? 'Unable to load the model catalog.'\n}\n\n/**\n * Validate and unwrap a successful catalog without discarding provider failures\n * or newer host metadata. Names and metadata remain optional for older hosts.\n * A broken response is never presented as a successfully loaded empty menu.\n */\nexport function checkedModelCatalog(value: unknown): unknown {\n const envelope = asRecord(value)\n if (envelope?.ok === false) throw new Error(modelCatalogErrorMessage(envelope.error ?? envelope))\n const root = envelope?.ok === true ? asRecord(envelope.value) : envelope\n const malformed = (field: string): never => { throw new Error(`Invalid model catalog: ${field}.`) }\n if (!root || !Array.isArray(root.groups)) return malformed('groups must be an array')\n for (const value of root.groups) {\n const group = asRecord(value)\n if (!group || !asText(group.id) || !Array.isArray(group.models)) return malformed('each group needs an id and models array')\n for (const value of group.models) {\n const model = asRecord(value)\n if (!model || !asText(model.id)) return malformed('each model needs an id')\n if (model.reasoning !== undefined) {\n const reasoning = asRecord(model.reasoning)\n if (!reasoning || !Array.isArray(reasoning.efforts) || reasoning.efforts.some(value => !parseEffort(value))) {\n return malformed('reasoning efforts must be an array of identified efforts')\n }\n }\n }\n }\n if (root.failures !== undefined && (!Array.isArray(root.failures) || root.failures.some(value => {\n const failure = asRecord(value)\n return !failure || !asText(failure.id) || typeof failure.name !== 'string' || typeof failure.message !== 'string'\n }))) return malformed('failures must be an array of provider failures')\n return root\n}\n\n/** Read through the injected session namespace; absence and rejection are errors. */\nexport async function readModelCatalog(client: ModelCatalogClient): Promise<unknown> {\n const session = client.remote?.session\n if (typeof session?.modelCatalog !== 'function') {\n throw new Error('Model catalog unavailable: inject both remote and remote.session.')\n }\n return checkedModelCatalog(await session.modelCatalog())\n}\n\n/** Provider failures are partial results, not a transport failure. */\nexport function modelCatalogFailures(value: unknown): readonly ModelCatalogFailure[] {\n // Rendering can precede the checked load boundary (for example hub owner\n // snapshots). Invalid or absent data must not crash the whole settings page.\n try {\n const root = checkedModelCatalog(value) as { failures?: readonly ModelCatalogFailure[] }\n return root.failures ?? []\n } catch { return [] }\n}\n\n/** Text adapter for existing model-hub status messages. */\nexport function catalogFailures(value: unknown): string[] {\n return modelCatalogFailures(value).map(failure => `${failure.name || failure.id}: ${failure.message}`)\n}\n\nfunction parseEffort(value: unknown): { id: string; name: string } | undefined {\n const row = asRecord(value)\n const id = row ? asText(row.id) : undefined\n if (!id) return undefined\n return { id, name: row ? asText(row.name) ?? id : id }\n}\n\n/** Parse the host session catalog into flat choices, keeping a saved route selectable. */\nexport function parseModelMenuChoices(value: unknown, bound?: ModelRoute): ModelMenuChoice[] {\n const envelope = asRecord(value)\n // Host remote calls resolve to a result envelope ({ ok, value }); older hosts\n // and unit tests hand over the bare catalog. Accept both.\n const root = (envelope && envelope.ok === true ? asRecord(envelope.value) : undefined) ?? envelope ?? {}\n const groups = Array.isArray(root.groups) ? root.groups : []\n const choices: ModelMenuChoice[] = []\n for (const group of groups) {\n const groupRow = asRecord(group)\n const provider = groupRow ? asText(groupRow.id) : undefined\n if (!provider || !groupRow || !Array.isArray(groupRow.models)) continue\n const providerName = asText(groupRow.name) ?? provider\n for (const entry of groupRow.models) {\n const modelRow = asRecord(entry)\n const model = modelRow ? asText(modelRow.id) : undefined\n if (!model || !modelRow) continue\n const name = asText(modelRow.name) ?? model\n const reasoning = asRecord(modelRow.reasoning)\n const efforts = reasoning && Array.isArray(reasoning.efforts)\n ? reasoning.efforts.flatMap(effort => { const parsed = parseEffort(effort); return parsed ? [parsed] : [] })\n : []\n choices.push({ provider, model, label: `${providerName} / ${name}`, efforts })\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\n/** Reasoning-effort options for one choice; the saved value stays selectable. */\nexport function modelMenuEffortOptions(\n choice: ModelMenuChoice | undefined,\n current?: string,\n): Array<{ id: string; name: string }> {\n const listed = (choice?.efforts ?? []).map(item => ({ ...item }))\n if (current && !listed.some(item => item.id === current)) listed.push({ id: current, name: current })\n return listed\n}\n\n/** Flat set of known routes for DetectModelFieldsOptions.knownModel. */\nexport function knownModelFromChoices(choices: readonly ModelMenuChoice[]): (route: ModelRoute) => boolean {\n const known = new Set(choices.map(choice => modelRouteKey(choice.provider, choice.model)))\n return route => known.has(modelRouteKey(route.provider, route.model))\n}\n","/**\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, split from the catalog \"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 : 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 = 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","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { Button } from '@deepseek-ai/dsh-client-ui-primitives'\nimport {\n checkedModelCatalog, modelCatalogErrorMessage, modelCatalogFailures, parseModelMenuChoices,\n type ModelCatalogFailure, type ModelMenuChoice,\n} from './catalog.ts'\n\nexport interface UseModelCatalogOptions {\n /** Used only on mount; subsequent changes come from load(). */\n readonly initialCatalog?: unknown\n /** Disables initial, focus, subscription, and manual refreshes. */\n readonly enabled?: boolean\n readonly subscribe?: (onChange: () => void) => (() => void) | undefined\n}\n\nexport interface ModelCatalogState {\n readonly catalog: unknown\n readonly choices: ModelMenuChoice[]\n readonly loading: boolean\n readonly error: string\n readonly failures: readonly ModelCatalogFailure[]\n readonly refresh: () => Promise<void>\n}\n\ntype Snapshot = Pick<ModelCatalogState, 'catalog' | 'loading' | 'error'>\n\n/**\n * Latest refresh wins, including retries while a previous request is pending.\n * Keep load stable (for example with useCallback); changing it invalidates the\n * previous source and fetches again, so switching clients cannot publish stale data.\n */\nexport function useModelCatalog(load: () => Promise<unknown>, options: UseModelCatalogOptions = {}): ModelCatalogState {\n const enabled = options.enabled !== false\n const enabledRef = useRef(enabled)\n enabledRef.current = enabled\n const live = useRef(false)\n const source = useRef(load)\n const revision = useRef(0)\n const [state, setState] = useState<Snapshot>(() => {\n try {\n return { catalog: options.initialCatalog === undefined ? undefined : checkedModelCatalog(options.initialCatalog), loading: enabled, error: '' }\n } catch (error) {\n return { catalog: undefined, loading: enabled, error: modelCatalogErrorMessage(error) }\n }\n })\n const refresh = useCallback(async (): Promise<void> => {\n if (!live.current || !enabledRef.current) return\n const request = ++revision.current\n setState(previous => ({ ...previous, loading: true, error: '' }))\n try {\n const catalog = checkedModelCatalog(await load())\n if (live.current && request === revision.current) setState({ catalog, loading: false, error: '' })\n } catch (error) {\n if (live.current && request === revision.current) {\n setState(previous => ({ ...previous, loading: false, error: modelCatalogErrorMessage(error) }))\n }\n }\n }, [load, enabled])\n\n useEffect(() => {\n live.current = true\n if (source.current !== load) {\n source.current = load\n // Last-good retention belongs to one source; a new client must not\n // inherit another client's models if its initial request fails.\n setState({ catalog: undefined, loading: enabled, error: '' })\n }\n if (enabled) void refresh()\n else setState(previous => ({ ...previous, loading: false }))\n return () => { live.current = false; ++revision.current }\n }, [enabled, refresh])\n\n useEffect(() => {\n if (!enabled) return\n const reload = (): void => { void refresh() }\n // No polling: the host owns catalog production, and focus is a cheap\n // recovery path for missed ordinary notifications or changed credentials.\n if (typeof window !== 'undefined') window.addEventListener('focus', reload)\n let unsubscribe: (() => void) | undefined\n try { unsubscribe = options.subscribe?.(reload) } catch (error) {\n setState(previous => ({ ...previous, error: modelCatalogErrorMessage(error) }))\n }\n return () => {\n if (typeof window !== 'undefined') window.removeEventListener('focus', reload)\n unsubscribe?.()\n }\n }, [enabled, refresh, options.subscribe])\n\n const choices = useMemo(() => parseModelMenuChoices(state.catalog), [state.catalog])\n const failures = useMemo(() => state.catalog === undefined ? [] : modelCatalogFailures(state.catalog), [state.catalog])\n return { ...state, choices, failures, refresh }\n}\n\nexport interface ModelCatalogStatusProps {\n readonly state: Pick<ModelCatalogState, 'loading' | 'error' | 'failures' | 'refresh'>\n readonly locale?: string\n}\n\n/**\n * Also accepts a mapped state from a caller that owns broader async orchestration.\n *\n * The dsh-ui-* classes carry the styling and resolve through the consuming\n * plugin's own officialUiCss scope (every consumer mounts its root class, so\n * e.g. `.dsh-model-hub .dsh-ui-loading` paints this); dsh-model-catalog-status\n * stays as a structural hook for tests and layout, never a colour source.\n */\nexport function ModelCatalogStatus({ state, locale }: ModelCatalogStatusProps) {\n const zh = locale?.toLowerCase().startsWith('zh') === true\n const copy = zh\n ? { loading: '正在加载模型…', error: '模型列表加载失败', partial: '部分提供商的模型未能加载', retry: '重试' }\n : { loading: 'Loading models…', error: 'Unable to load models', partial: 'Some providers could not load their models', retry: 'Retry' }\n if (!state.loading && !state.error && state.failures.length === 0) return null\n return <div className=\"dsh-model-catalog-status dsh-ui-stack\" lang={zh ? 'zh' : 'en'}>\n {state.loading ? <p role=\"status\" className=\"dsh-ui-loading\">{copy.loading}</p> : null}\n {state.error ? <p role=\"alert\" className=\"dsh-ui-error dsh-ui-wrap\">{copy.error}: {state.error}</p> : null}\n {state.failures.length > 0 ? <div role=\"status\" className=\"dsh-ui-meta\">\n <p>{copy.partial}</p>\n <ul className=\"dsh-ui-list\">{state.failures.map((failure, index) => <li key={`${failure.id}:${index}`}>{failure.name || failure.id}: {failure.message}</li>)}</ul>\n </div> : null}\n {state.error || state.failures.length > 0\n ? <div className=\"dsh-ui-actions\"><Button type=\"button\" size=\"sm\" disabled={state.loading} onClick={() => { void state.refresh() }}>{copy.retry}</Button></div>\n : null}\n </div>\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 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 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 const [menuPos, setMenuPos] = useState<CSSProperties | null>(null)\n const id = useId()\n const showSearch = 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 => ({ choice, name: modelMenuShortName(choice), label: choice.model })), 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 root one, handing the keyboard back to its cell. */\n const back = (from: Pane): void => {\n paneFocus.current = from\n setPane('root')\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 setPane('root')\n setQuery('')\n setHighlightedIndex(null)\n }, [open])\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 document.addEventListener('mousedown', closeOutside)\n return () => document.removeEventListener('mousedown', closeOutside)\n }, [open, onOpenChange])\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 useLayoutEffect(() => {\n if (open && pane === 'model' && activeModelIndex >= 0) itemRefs.current[leading.length + activeModelIndex]?.scrollIntoView({ block: 'nearest' })\n }, [open, pane, activeModelIndex, visibleModels, 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({ 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 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 (event.key === 'Escape' && open) {\n event.preventDefault()\n if (pane !== 'root') back(pane)\n else close(true)\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 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 if (highlighted) { onPick({ provider: highlighted.provider, model: highlighted.model }); close(true) }\n return\n }\n if (event.key === 'Tab') {\n if (event.shiftKey) {\n event.preventDefault()\n if (pane !== 'root') 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 if (event.relatedTarget instanceof Node && (rootRef.current?.contains(event.relatedTarget) || menuRef.current?.contains(event.relatedTarget))) 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 {pane === 'root' ? <>\n <button ref={itemRef()} type=\"button\" role=\"menuitem\" className=\"dsh-model-menu-cell\" 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 ? <button ref={itemRef()} type=\"button\" role=\"menuitem\" className=\"dsh-model-menu-cell\" 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 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}\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}\n className={`dsh-model-menu-option${item.selected === true ? ' dsh-model-menu-selected' : ''}`}\n onClick={() => { onPickLeading?.(item.id); 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 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={() => { onPick({ provider: choice.provider, model: choice.model }); 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 {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}\n className={`dsh-model-menu-option${checked ? ' dsh-model-menu-selected' : ''}`}\n onClick={() => { onPickEffort?.(row.id || undefined); 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 })\n : anchor\n return <span ref={rootRef} className={`dsh-model-menu-root${className ? ` ${className}` : ''}`} onKeyDown={onKeyDown} onBlur={onBlur}\n onClick={event => {\n if (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 * 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-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`\n","/**\n * Shared contract that keeps every plugin's browser-side UI on the official\n * DeepSeek Harness Web design language.\n *\n * Two rules produce that language, and both are load-bearing here:\n *\n * 1. Colour, radius, elevation and focus come from the host theme's real\n * `--dsw-*` tokens, written under their own names. Plugins never invent a\n * token, never alias the official ones behind a private palette (a private\n * alias is just a second, diverging theme), and never carries a literal\n * fallback — the host publishes light and dark, and a literal would pin one\n * of them. The only non-colour custom properties used are the host's own\n * content-font axis and frame clearance.\n *\n * 2. Anything the host already ships is used, not reimplemented. Controls come\n * from `@deepseek-ai/dsh-client-ui-primitives` (`Button`, `Input`,\n * `Checkbox`, `Switch`, `Tag`, `Pill`, `SegmentedControl`, `Menu`, `Modal`,\n * `Tooltip`, `Toast`, `DisclosureRow`, `StateDot`, `PathLabel`, the settings\n * form suite). This module only styles what primitives do not cover: page\n * scaffolding, field layout, banners, empty states and scroll regions.\n *\n * The metrics below are transcribed from the primitives' own CSS modules so a\n * feature panel lines up pixel-for-pixel with a native one: the 14/22 body and\n * 13/20 compact type tiers, the 0.5px hairline scale, and the elevation family\n * that draws a surface's edge in its shadow (`border: 0`) instead of a border.\n */\n\n/**\n * Every `--dsw-*` token this repo is allowed to reference, grouped by role.\n *\n * Plugins may only colour through this list. It is exported so the guard test\n * can fail a build when a stylesheet reaches for anything else — the failure\n * mode this prevents is silent: an unknown token resolves to nothing, so a\n * border disappears or a label inherits the wrong colour with no error anywhere.\n */\nexport const OFFICIAL_THEME_TOKENS = {\n /** Surfaces, from the page up to the topmost nested card. */\n surface: [\n '--dsw-alias-bg-base',\n '--dsw-alias-bg-layer-1',\n '--dsw-alias-bg-layer-2',\n '--dsw-alias-bg-layer-3',\n '--dsw-alias-bg-layer-4',\n '--dsw-alias-bg-module-platform',\n '--dsw-alias-bg-overlay',\n ],\n /** Hairlines. l1 is near-invisible on a menu surface, so menus use l2+. */\n border: ['--dsw-alias-border-l1', '--dsw-alias-border-l2', '--dsw-alias-border-l3', '--dsw-alias-border-l4'],\n /** Text. `caption` is menu shortcut text, `dimmed` is placeholder text. */\n label: [\n '--dsw-alias-label-primary',\n '--dsw-alias-label-secondary',\n '--dsw-alias-label-tertiary',\n '--dsw-alias-label-caption',\n '--dsw-alias-label-dimmed',\n '--dsw-alias-label-error',\n '--dsw-alias-label-primary-foreground',\n ],\n /** Interactive fills. The `-danger` hover belongs to destructive rows. */\n interactive: [\n '--dsw-alias-interactive-bg-hover',\n '--dsw-alias-interactive-bg-active',\n '--dsw-alias-interactive-bg-hover-danger',\n ],\n /** Accent and status. `business` is the focus ring's default colour. */\n accent: [\n '--dsw-alias-brand-primary',\n '--dsw-alias-button-primary-fill',\n '--dsw-alias-button-primary-hover',\n '--dsw-alias-button-tool-bar-fill',\n '--dsw-alias-button-tool-bar-hover',\n '--dsw-alias-button-ghost-active-fill',\n '--dsw-alias-button-ghost-active-border',\n ],\n state: [\n '--dsw-alias-state-business-primary',\n '--dsw-alias-state-success-primary',\n '--dsw-alias-state-warn-primary',\n '--dsw-alias-state-error-primary',\n '--dsw-alias-state-idle-primary',\n ],\n /** Corner scale: sm 8, md 12, lg the large card, panel the modal. */\n radius: ['--dsw-radius-sm', '--dsw-radius-md', '--dsw-radius-lg', '--dsw-radius-panel'],\n /** An elevated surface draws its edge in the shadow, so it keeps border: 0. */\n elevation: [\n '--dsw-elevation-soft',\n '--dsw-elevation-stroke',\n '--dsw-elevation-stroke-color',\n '--dsw-elevation-panel',\n '--dsw-elevation-prominent',\n ],\n /** Floats, masks and scrollbars. */\n overlay: [\n '--dsw-menu-surface-fill',\n '--dsw-menu-backdrop-filter',\n '--dsw-mask-blur',\n '--dsw-alias-bg-mask-1',\n '--dsw-alias-menu-icon',\n '--dsw-alias-scrollbar-bg-l2',\n '--dsw-alias-scrollbar-hover-l2',\n '--dsw-shadow-lv3',\n ],\n /** Motion, focus and type axis, published by the host rather than by a component. */\n system: [\n '--dsw-focus-ring-width',\n '--dsw-focus-ring-color',\n '--dsw-font-markdown-code-font-family',\n '--ds-transition-duration',\n '--ds-ease-in-out',\n '--ds-font-family-code',\n '--dsh-scrollbar-thumb',\n '--dsh-scrollbar-thumb-hover',\n '--dsh-content-font-size-secondary',\n '--dsh-content-font-delta',\n '--dsh-frame-top-clearance',\n ],\n} as const\n\n/** Every official token name, flat. Used by the token guard test. */\nexport const OFFICIAL_THEME_TOKEN_NAMES: readonly string[] = Object.values(OFFICIAL_THEME_TOKENS).flat()\n\n/** The elevation steps a surface can be raised by, softest first. */\nexport type OfficialElevation = 'soft' | 'stroke' | 'panel' | 'prominent'\n\n/**\n * The host's focus ring shorthand, verbatim. Writing this per control is how\n * rings drift apart; a stylesheet that draws its own focus style should use\n * {@link officialFocus} instead. The colour fallback is the host's own default.\n */\nexport const OFFICIAL_FOCUS_RING =\n 'var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary))'\n\n/**\n * A complete `outline` declaration at the official geometry. `offset` defaults\n * to the 2px the native controls use; the host's inline field rules sit at 1px\n * and a segmented tab pulls the ring inside itself at -2px.\n */\nexport function officialFocus(offset = '2px'): string {\n return `outline: ${OFFICIAL_FOCUS_RING}; outline-offset: ${offset}`\n}\n\n/**\n * An elevated surface. The host draws a raised surface's edge inside its\n * shadow rather than as a border, so a card sets `border: 0` and takes the edge\n * from the elevation — which is also why its border stays off the alias-border\n * set that a flat, non-elevated rule would use.\n */\nexport function officialElevation(level: OfficialElevation): string {\n return `border: 0; box-shadow: var(--dsw-elevation-${level})`\n}\n\n/**\n * An elevated surface whose edge should read as a specific hairline. Rebinding\n * the stroke colour is how a menu card picks l1 while a panel picks l3, without\n * the two growing apart by hand.\n */\nexport function officialStrokedElevation(level: OfficialElevation, color: string): string {\n return `--dsw-elevation-stroke-color: ${color}; ${officialElevation(level)}`\n}\n\n/**\n * The shared stylesheet for a plugin UI, scoped under that plugin's root class.\n *\n * Scoping is what keeps this safe to always-bundle into every client: the rules\n * can only match inside the plugin's own subtree, so two plugins can both mount\n * `dsh-ui-card` without either styling the other's markup.\n *\n * Each recipe matches the root element *and* its descendants, because the\n * commonest arrangement is one element that is both — a surface that carries\n * the root class and `dsh-ui-card`, or a portaled dialog that is the root and\n * the `dsh-ui-surface`. A descendant-only scope would silently leave those\n * unstyled, with no error anywhere.\n *\n * A caveat worth knowing: `Modal` and `Menu` portal to `document.body`, so their\n * content leaves the plugin's subtree entirely. A portaled surface therefore\n * needs its own root class on an element inside the portal.\n *\n * Only patterns that primitives do not provide live here. If a control appears\n * below that `Button`/`Input`/`Switch`/`Tag`/`Menu` already covers, that is a\n * bug in this file: use the primitive and delete the recipe.\n */\nexport function officialUiCss(roots: string | readonly string[]): string {\n // One plugin often mounts several unrelated surfaces (a settings seat, a chat\n // card, a header menu), so the caller names every root. The rules below are\n // nested under a single selector list and use `&`, which the browser expands\n // per root — so one stylesheet covers all of them without duplicating itself.\n const scope = (typeof roots === 'string' ? [roots] : roots).map(root => `.${root}`).join(', ')\n const sheet = `\n/* Official DSH Web UI contract. Generated by @klarkxy/dsh-plugin-kit/official-ui.\n * Do not hand-edit the copy inside a plugin: change this module so every plugin\n * moves together. Scope: ${scope} */\n/* The scope rule below stays open for the whole sheet: every rule after it\n * nests with the parent selector, so one stylesheet can cover several unrelated\n * roots without leaking into a neighbouring plugin. Its closing brace is last. */\n${scope} {\n color: var(--dsw-alias-label-primary);\n font-family: inherit;\n font-size: 14px;\n line-height: 22px;\n min-width: 0;\n\n& *, & *::before, & *::after { box-sizing: border-box; }\n& h1, & h2, & h3, & h4, & p, & figure { margin: 0; }\n/* Keyboard focus only: pointer input keeps the native resting appearance. The\n * ring needs no radius of its own — the outline already follows the control's\n * own border-radius, and overriding it here would flatten every control. */\n& :focus-visible { ${officialFocus()}; }\n& [hidden] { display: none !important; }\n\n/* --- Type tiers. The same 14/22 and 13/20 steps the primitives use. --- */\n& .dsh-ui-title { font-size: 16px; line-height: 24px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n& .dsh-ui-heading { font-size: 14px; line-height: 22px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n& .dsh-ui-compact { font-size: 13px; line-height: 20px; color: var(--dsw-alias-label-primary); }\n& .dsh-ui-meta { font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-secondary); }\n& .dsh-ui-hint { font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n& .dsh-ui-error { font-size: 12px; line-height: 18px; color: var(--dsw-alias-state-error-primary); }\n& .dsh-ui-warn { color: var(--dsw-alias-state-warn-primary); }\n& .dsh-ui-success { color: var(--dsw-alias-state-success-primary); }\n& .dsh-ui-muted { color: var(--dsw-alias-label-tertiary); }\n& .dsh-ui-truncate { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n& .dsh-ui-wrap { min-width: 0; overflow-wrap: anywhere; }\n\n/* --- Layout scaffolding. --- */\n& .dsh-ui-stack { display: flex; flex-direction: column; gap: 12px; }\n& .dsh-ui-stack-lg { display: flex; flex-direction: column; gap: 20px; }\n/* Plugin detail pages share one reading column. These are layout recipes;\n * controls keep their own primitive styles. Form spacing follows the host's\n * settings-form/fields.module.css and SettingsForm.module.css. */\n& .dsh-ui-page { display: flex; flex-direction: column; gap: 16px; width: 100%; max-width: 760px; min-width: 0; }\n& .dsh-ui-form { display: flex; flex-direction: column; gap: 0; min-width: 0; }\n&.dsh-ui-form > .dsh-ui-field, & .dsh-ui-form > .dsh-ui-field { padding: 12px 0; }\n& .dsh-ui-form-footer { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding-top: 16px; min-width: 0; }\n& .dsh-ui-fields-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 20px; min-width: 0; margin: 0; padding: 0; border: 0; }\n@media (max-width: 560px) {\n & .dsh-ui-fields-grid { grid-template-columns: minmax(0, 1fr); }\n}\n& .dsh-ui-row { display: flex; align-items: center; gap: 8px; min-width: 0; }\n& .dsh-ui-row-wrap { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }\n& .dsh-ui-spacer { flex: 1; min-width: 0; }\n/* A 0.5px l2 rule is the host's section divider; reserve the same rhythm. */\n& .dsh-ui-divider { height: 0.5px; background: var(--dsw-alias-border-l2); }\n& .dsh-ui-section { display: flex; flex-direction: column; gap: 12px; padding-top: 16px; border-top: 0.5px solid var(--dsw-alias-border-l2); }\n\n/* --- Card: a raised surface whose edge lives in the shadow. --- */\n& .dsh-ui-card {\n ${officialElevation('stroke')}\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 16px;\n border-radius: var(--dsw-radius-lg);\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n min-width: 0;\n}\n& .dsh-ui-card--flat { border: 0.5px solid var(--dsw-alias-border-l3); box-shadow: none; }\n& .dsh-ui-card--nested { background: var(--dsw-alias-bg-layer-2); }\n& .dsh-ui-card--plain { background: none; }\n\n/* --- Field: label, control, help, error. The control itself is an\n * official primitive, so this only owns the vertical rhythm. --- */\n& .dsh-ui-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }\n& .dsh-ui-field + .dsh-ui-field { border-top: 0.5px solid var(--dsw-alias-border-l2); padding-top: 12px; }\n/* Grid fields share a row, so the stacked-field divider must not win later in\n * the cascade. Reset it here, after the field recipe. */\n& .dsh-ui-fields-grid > .dsh-ui-field { padding: 0; border: 0; }\n& .dsh-ui-label { display: flex; align-items: center; gap: 6px; font-size: 13px; line-height: 20px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n& .dsh-ui-label-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }\n& .dsh-ui-help { font-size: 12px; line-height: 1.6; color: var(--dsw-alias-label-secondary); }\n& .dsh-ui-help p { margin: 0; }\n& .dsh-ui-help p + p { margin-top: 8px; }\n& .dsh-ui-required { color: var(--dsw-alias-state-error-primary); }\n& .dsh-ui-control { width: 100%; min-width: 0; }\n/* An invalid control is marked on the control, not only in the message. */\n& .dsh-ui-control[aria-invalid='true'] { border-color: var(--dsw-alias-state-error-primary); }\n& .dsh-ui-readonly { display: flex; flex-direction: column; gap: 4px; min-width: 0; }\n& .dsh-ui-readonly > dt { font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n& .dsh-ui-readonly > dd { margin: 0; font-size: 13px; line-height: 20px; overflow-wrap: anywhere; }\n\n/* --- Buttons row. A no-op container: it exists so actions line up on the\n * trailing edge the way every native panel does. --- */\n& .dsh-ui-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding-top: 4px; }\n& .dsh-ui-actions-end { justify-content: flex-end; }\n\n/* --- Banners. A banner is a left-rail notice, the shape used for warnings,\n * deprecations and blocking instructions. --- */\n& .dsh-ui-banner {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 10px 14px;\n border: 0.5px solid var(--dsw-alias-border-l3);\n border-left: 3px solid var(--dsw-alias-state-warn-primary);\n border-radius: var(--dsw-radius-md);\n background: var(--dsw-alias-bg-layer-1);\n font-size: 13px;\n line-height: 20px;\n color: var(--dsw-alias-label-secondary);\n}\n& .dsh-ui-banner-title { font-weight: 500; color: var(--dsw-alias-state-warn-primary); }\n& .dsh-ui-banner--info { border-left-color: var(--dsw-alias-state-business-primary); }\n& .dsh-ui-banner--danger { border-left-color: var(--dsw-alias-state-error-primary); }\n& .dsh-ui-banner--success { border-left-color: var(--dsw-alias-state-success-primary); }\n& .dsh-ui-banner p { margin: 0; }\n\n/* --- Inline notice: a transient confirmation with no chrome of its own. --- */\n& .dsh-ui-notice { display: flex; align-items: center; gap: 6px; font-size: 12px; line-height: 18px; color: var(--dsw-alias-state-success-primary); }\n& .dsh-ui-notice--error { color: var(--dsw-alias-state-error-primary); }\n\n/* --- Empty and loading states. Both sit in a dashed well so an empty panel\n * reads as \"nothing here yet\" rather than as a broken layout. --- */\n& .dsh-ui-empty {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 6px;\n padding: 20px 16px;\n border: 0.5px dashed var(--dsw-alias-border-l3);\n border-radius: var(--dsw-radius-md);\n font-size: 13px;\n line-height: 20px;\n color: var(--dsw-alias-label-secondary);\n}\n& .dsh-ui-loading { display: flex; align-items: center; gap: 8px; padding: 20px 0; font-size: 13px; line-height: 20px; color: var(--dsw-alias-label-secondary); }\n\n/* --- Selectable list. A row is a button-sized target with a hover fill and\n * a selected fill; the name carries the weight, the description does not. --- */\n& .dsh-ui-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; min-width: 0; }\n& .dsh-ui-list-scroll { max-height: min(66vh, 760px); overflow-y: auto; overflow-x: hidden; }\n& .dsh-ui-list-row { border-radius: var(--dsw-radius-md); }\n& .dsh-ui-list-row:hover { background: var(--dsw-alias-interactive-bg-hover); }\n& .dsh-ui-list-row[aria-selected='true'], & .dsh-ui-list-row[data-selected] { background: var(--dsw-alias-interactive-bg-active); }\n& .dsh-ui-list-item {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n width: 100%;\n min-width: 0;\n padding: 10px 12px;\n border: 0;\n border-radius: var(--dsw-radius-md);\n background: none;\n font: inherit;\n color: inherit;\n text-align: start;\n cursor: pointer;\n}\n& .dsh-ui-list-item:disabled { cursor: default; }\n& .dsh-ui-list-item:disabled:hover { background: none; }\n& .dsh-ui-list-name { font-size: 14px; line-height: 22px; font-weight: 500; color: var(--dsw-alias-label-primary); overflow-wrap: anywhere; }\n& .dsh-ui-list-desc { font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n\n/* --- Code and structured output. Wraps rather than scrolls, because a\n * feature panel is read rather than scanned. --- */\n& .dsh-ui-code {\n padding: 10px 12px;\n border: 0.5px solid var(--dsw-alias-border-l3);\n border-radius: var(--dsw-radius-md);\n background: var(--dsw-alias-bg-layer-1);\n font-family: var(--ds-font-family-code);\n font-size: 12px;\n line-height: 20px;\n color: var(--dsw-alias-label-secondary);\n overflow-wrap: anywhere;\n white-space: pre-wrap;\n}\n& .dsh-ui-scroll { max-height: 60vh; overflow: auto; overscroll-behavior: contain; }\n\n/* --- A toggle row: label on the left, switch on the trailing edge. This is\n * layout only; the switch itself is the official primitive. --- */\n& .dsh-ui-toggle-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; min-width: 0; padding: 12px 0; }\n& .dsh-ui-toggle-row + .dsh-ui-toggle-row { border-top: 0.5px solid var(--dsw-alias-border-l2); }\n& .dsh-ui-toggle-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }\n& .dsh-ui-toggle-label { font-size: 14px; line-height: 22px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n\n/* --- Floating surface: a panel anchored to a trigger. This is the material\n * a menu card is made of — the translucent fill plus its backdrop blur, with\n * the edge riding inside the prominent elevation. A plugin that hand-rolls this\n * is how tokens like --dsw-specific-menu get invented; use this instead. --- */\n& .dsh-ui-surface {\n --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);\n --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);\n --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);\n position: relative;\n display: flex;\n flex-direction: column;\n border: 0;\n border-radius: var(--dsw-radius-lg);\n background: var(--dsw-menu-surface-fill);\n backdrop-filter: var(--dsw-menu-backdrop-filter);\n box-shadow: var(--dsw-elevation-prominent);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n line-height: 20px;\n min-width: 0;\n}\n& .dsh-ui-surface-body { display: flex; flex-direction: column; gap: 8px; padding: 12px 14px 14px; overflow-y: auto; }\n& .dsh-ui-surface-head { display: flex; align-items: center; gap: 8px; min-width: 0; }\n& .dsh-ui-surface-title { font-size: 14px; line-height: 22px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n\n/* --- Native select. The primitives ship no select, so a plugin that offers a\n * closed list of choices keeps the platform control and matches the official\n * settings field geometry exactly (34px, 0.5px l4, radius-md, layer-3). A\n * SegmentedControl is the primitive to reach for when the choices are few\n * enough to show at once. --- */\n& .dsh-ui-select {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n height: 34px;\n padding: 0 12px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: var(--dsw-radius-md);\n background: var(--dsw-alias-bg-layer-3);\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n}\n& .dsh-ui-select:focus-visible { outline: none; border-color: var(--dsw-alias-state-business-primary); }\n& .dsh-ui-select:disabled { color: var(--dsw-alias-label-tertiary); cursor: default; }\n& .dsh-ui-select[aria-invalid='true'] { border-color: var(--dsw-alias-state-error-primary); }\n\n/* --- Native textarea. The primitives ship no textarea either, so a settings\n * prompt keeps the platform element and the same field shell as the select:\n * 0.5px l4, radius-md, layer-3, 13/1.5 type. It grows vertically instead of\n * locking to the select's 34px row. --- */\n& .dsh-ui-textarea {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n resize: vertical;\n padding: 8px 12px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: var(--dsw-radius-md);\n background: var(--dsw-alias-bg-layer-3);\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n& .dsh-ui-textarea:focus-visible { outline: none; border-color: var(--dsw-alias-state-business-primary); }\n& .dsh-ui-textarea:disabled { color: var(--dsw-alias-label-tertiary); cursor: default; }\n& .dsh-ui-textarea::placeholder { color: var(--dsw-alias-label-dimmed); }\n& .dsh-ui-textarea[aria-invalid='true'] { border-color: var(--dsw-alias-state-error-primary); }\n\n/* Long panels scroll inside themselves instead of growing the host page. */\n& .dsh-ui-panel { display: flex; flex-direction: column; gap: 16px; min-width: 0; }\n& .dsh-ui-panel-wide { max-width: 100%; }\n\n@media (prefers-reduced-motion: reduce) {\n & *, & *::before, & *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }\n}\n}\n`\n // Widen every recipe from \"a descendant of the root\" to \"the root, or one of\n // its descendants\". Written as a transform rather than by hand so no recipe\n // can be added later with only the descendant form. The pattern is narrow on\n // purpose: a leading `&` followed by one recipe class and no combinator, so\n // sibling and child rules such as `.dsh-ui-field + .dsh-ui-field` keep their\n // own meaning and are left alone.\n return sheet.replace(/^& (\\.dsh-ui-[a-z0-9-]+)(?=\\s*\\{)/gm, (_match, className: string) =>\n `&${className}, & ${className}`)\n}\n","import type { ContextFormed } from '@deepseek-ai/dsh-llm'\nimport type { ModelRoute } from '@klarkxy/dsh-model-route'\n\n/**\n * The canonical home is @klarkxy/dsh-model-route; re-exported here so existing\n * plugin-kit consumers keep compiling.\n */\nexport type { ModelRoute }\n\n/** Public, browser-safe contracts. Host implementations stay in their owning packages. */\nexport type ProducerSourceKind = `plugin:${string}`\nexport type ProducerMessageSource = { kind: ProducerSourceKind; plugin: string } & ContextFormed\n\n/**\n * V4 sessions persist the producing extension in `kind`; the retired generic\n * `plugin` wrapper is not admitted. Each feature plugin declares its own kind.\n */\ndeclare module '@deepseek-ai/dsh-llm' {\n interface MessageSourceMap {\n [kind: ProducerSourceKind]: ProducerMessageSource\n }\n}\n\nexport function producerMessageSource(plugin: string): ProducerMessageSource {\n return { kind: `plugin:${plugin}`, plugin }\n}\n\nexport type RpcResult<T = unknown> = { ok: true; value: T } | { ok: false; error: { code: string; message: string } }\nexport const CHAT_EVENTS_SLOT = 'dsh-editor.chat.events'\nexport interface EvidenceRef { sessionId: string; seq: number; kind: 'user' | 'tool' | 'turn' | 'manual'; excerpt?: string }\nexport interface TaskContract {\n id: string\n sessionId: string\n sourceVersion: string\n revision: number\n goal: string\n deliverables: string[]\n inScope: string[]\n outOfScope: string[]\n constraints: string[]\n acceptance: string[]\n assumptions: string[]\n questions: string[]\n evidence: EvidenceRef[]\n readiness: 'pending' | 'clear-request' | 'user-confirmed' | 'disclosed-assumptions' | 'cancelled' | 'stale'\n updatedAt: number\n}\nexport interface TaskCheckpoint {\n id: string\n sessionId: string\n sourceVersion: string\n contractVersion?: number\n fromSeq: number\n toSeq: number\n revision: number\n status: 'running' | 'completed' | 'failed' | 'cancelled'\n items: Array<{ label: string; state: 'pending' | 'verified' | 'failed'; evidence: EvidenceRef[] }>\n constraints: string[]\n nextAction: string\n createdAt: number\n}\nexport type KnowledgeScope = { kind: 'global' } | { kind: 'project'; projectId: string }\nexport type KnowledgeKind = 'preference' | 'project-fact' | 'decision' | 'vocabulary' | 'activity' | 'lesson'\n/** Descriptive context, never an executable instruction or authorization. */\nexport interface ContextKnowledge {\n subject: string\n domain: string\n key: string\n aliases: string[]\n observedAt: number\n /** The user's own time expression, not an inferred completion date. */\n eventTime?: string\n activityStatus?: 'planned' | 'in-progress' | 'blocked' | 'paused' | 'completed' | 'cancelled' | 'unknown'\n}\n/** A scoped method. Observations remain candidates until explicitly accepted. */\nexport interface ProcedureKnowledge {\n origin: 'instruction' | 'observation'\n goal: string\n when: string[]\n steps: string[]\n avoid: string[]\n verify: string[]\n}\nexport interface MemoryRecord {\n id: string\n revision: number\n scope: KnowledgeScope\n kind: KnowledgeKind\n status: 'candidate' | 'active' | 'rejected' | 'superseded' | 'revoked' | 'deleted'\n title: string\n content: string\n tags: string[]\n evidence: EvidenceRef[]\n exceptions: string[]\n source: 'user' | 'memory' | 'dream' | 'self-improvement'\n context?: ContextKnowledge\n procedure?: ProcedureKnowledge\n createdAt: number\n updatedAt: number\n expiresAt?: number\n supersedes?: string[]\n /** Exact record revisions behind a derived candidate; revalidated on adoption. */\n basis?: Array<{ id: string; revision: number }>\n}\nexport type NewMemoryRecord = Omit<MemoryRecord, 'id' | 'revision' | 'createdAt' | 'updatedAt'>\nexport interface MemoryQuery { scope: KnowledgeScope; query?: string; kinds?: KnowledgeKind[]; statuses?: MemoryRecord['status'][]; limit?: number }\nexport interface MemoryMutationOptions { signal?: AbortSignal; isCurrent?: () => boolean }\nexport interface MemoryService {\n list(query: MemoryQuery): Promise<MemoryRecord[]>\n create(record: NewMemoryRecord, options?: MemoryMutationOptions): Promise<MemoryRecord>\n update(id: string, patch: Partial<Pick<MemoryRecord, 'title' | 'content' | 'tags' | 'exceptions' | 'status' | 'expiresAt'>>, expectedRevision: number, options?: MemoryMutationOptions): Promise<MemoryRecord>\n /** Explicit user promotion, persisted atomically on the same record; preserves expiry and evidence. */\n promoteToGlobal(id: string, expectedRevision: number, options?: MemoryMutationOptions): Promise<MemoryRecord>\n remove(id: string, expectedRevision: number, options?: MemoryMutationOptions): Promise<void>\n recall(query: MemoryQuery): Promise<MemoryRecord[]>\n}\n\n/**\n * The session creation metadata the host snapshots when it creates a delegated child\n * thread. Mirrors `CreateAgentOptions.meta` in `@deepseek-ai/dsh-agent`; it is durable\n * session data, so it survives a restart and needs no ancestry walk.\n */\nexport interface SubagentSessionLike {\n readonly header?: {\n readonly parentSession?: unknown\n readonly origin?: unknown\n readonly delegationDepth?: unknown\n readonly isSeeded?: unknown\n readonly classification?: unknown\n }\n}\n\n/**\n * True when `session` is a delegated child thread rather than a human-driven top-level\n * conversation.\n *\n * A message's `source.kind === 'user'` cannot answer this: a lead agent's dispatch prompt\n * is delivered as the child's own user message, so delegated work is indistinguishable\n * from a person typing once you only look at the message. Plugins use this to keep\n * automatic writes and derived model calls on top-level sessions.\n */\nexport function isSubagentSession(session: unknown): boolean {\n const header = (session as SubagentSessionLike | null | undefined)?.header\n if (!header || typeof header !== 'object') return false\n if (header.origin === 'subagent' || Number(header.delegationDepth ?? 0) > 0) return true\n // Native human forks also persist parentSession for history lineage. A fork's\n // seeded header distinguishes it from legacy children whose parent is the\n // only marker. Native rc.2 forks omit depth; patched hosts may persist zero.\n // Explicit delegation and unknown metadata still keep the child guard.\n const humanFork = header.isSeeded === true\n && (header.delegationDepth === undefined || header.delegationDepth === 0)\n && header.origin === undefined\n && (header.classification === undefined || header.classification === 'ordinary' || header.classification === 'free')\n return Boolean(header.parentSession) && !humanFork\n}\n\n/** Project keys come only from the host-validated session directory, never client input. */\nexport function projectIdFromCwd(cwd: string | undefined): string | undefined {\n if (typeof cwd !== 'string') return undefined\n const normalized = cwd.trim().replaceAll('\\\\', '/')\n if (!normalized) return undefined\n return normalized === '/' || /^[A-Za-z]:\\/$/.test(normalized) ? normalized : normalized.replace(/\\/+$/, '')\n}\n\n/**\n * One settings owner's Remote stream. Typert accepts either case in an RPC\n * segment, so the Cordis service key and the wire namespace use the same\n * Pascal segment. The scope's first letter stays uppercase.\n */\nexport interface ModelSettingsChangesIdentity {\n readonly service: string\n readonly namespace: string\n}\n\n/** `@klarkxy/dsh-git-commit` becomes `KlarkxyDshGitCommitModelSettingsChanges`. */\nexport function modelSettingsChangesIdentity(packageName: string): ModelSettingsChangesIdentity {\n const scoped = /^@([^/]+)\\/(.+)$/.exec(packageName)\n const body = scoped ? `${scoped[1]}/${scoped[2]}` : packageName\n const parts = body.split(/[^A-Za-z0-9]+/).filter(Boolean)\n if (!parts.length) throw new Error('Model settings package name has no RPC segment')\n const segment = `${parts.map(part => part.charAt(0).toUpperCase() + part.slice(1)).join('')}ModelSettingsChanges`\n if (!/^[A-Z][A-Za-z0-9]*$/.test(segment)) throw new Error(`Model settings sync name is not an RPC segment: ${segment}`)\n return { service: segment, namespace: segment }\n}\n\n/**\n * Repository extension: a native web provider announces that its local\n * availability changed. Kind is `search` or `fetch`; id is the provider id.\n * Listeners refresh management state and must not treat this as a network probe.\n */\nexport const WEB_PROVIDER_AVAILABILITY_EVENT = 'web/provider-availability-updated' as const\n\n/**\n * Optional display metadata a provider may attach when it registers directly\n * with `ctx.web`. Execution and credentials stay with the provider; this object\n * is display-only and must never carry secret values.\n */\nexport interface DshWebManagementDescriptor {\n readonly id: string\n readonly label: string\n readonly description: string\n readonly defaultBaseURL?: string\n readonly credentialRef?: string\n /** True when the key is shared with another surface. The page must not delete it. */\n readonly credentialShared?: boolean\n /** Optional notice naming the settings surface that owns a shared credential. */\n readonly credentialHint?: string\n readonly billing: 'request' | 'model-and-tools' | 'none' | 'unknown'\n /** Optional provider-supplied billing summary. */\n readonly pricing?: string\n /** Public HTTPS page explaining provider charges. */\n readonly pricingUrl?: string\n /** Public HTTPS page where the user can create an API key. */\n readonly signupUrl?: string\n /** Plugin that owns configuration. Native providers keep their settings there. */\n readonly configurationOwner?: string\n /** Explicit settings link supplied by the provider, never inferred from its id. */\n readonly configurationUrl?: string\n /** Fixed legacy route migrated by a bundle-owned adapter; not used by native plugins. */\n readonly legacyId?: string\n}\n\n/**\n * Host Creator agent-preset id (`agentPresets.composedPreset`).\n * Plugins that gate Creator-only tools or prompt sections compare against this.\n */\nexport const CREATOR_PRESET_ID = 'cordis'\n","import type { TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol'\nimport { modelSettingsChangesIdentity, type ModelSettingsChangesIdentity } from './contracts.ts'\n\nexport type ModelSettingsChangeFrame = { kind: 'ready' } | { kind: 'changed'; ns: string; revision: number }\n\n/** This stream carries invalidations only; ready is never a settings snapshot. */\nexport function parseModelSettingsChangeFrame(value: unknown): ModelSettingsChangeFrame {\n if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('Invalid model settings change frame')\n const frame = value as Record<string, unknown>\n if (frame.kind === 'ready' && Object.keys(frame).length === 1) return { kind: 'ready' }\n if (frame.kind === 'changed' && Object.keys(frame).length === 3 && typeof frame.ns === 'string' && frame.ns.length > 0\n && typeof frame.revision === 'number' && Number.isSafeInteger(frame.revision) && frame.revision >= 0) {\n return { kind: 'changed', ns: frame.ns, revision: frame.revision }\n }\n throw new Error('Invalid model settings change frame')\n}\n\n/** One owner's contribution. Each package mounts only its own endpoint. */\nexport function modelSettingsChangesRemote(packageName: string, identity: ModelSettingsChangesIdentity = modelSettingsChangesIdentity(packageName)): TypertRemoteContribution {\n return {\n package: packageName,\n descriptors: [{\n id: `${identity.namespace}/watch`,\n service: identity.service,\n namespace: identity.namespace,\n method: 'watch',\n mode: 'stream' as const,\n invocation: { kind: 'direct' as const },\n parameters: [],\n cancellation: { parameter: 'signal' as const },\n result: { mode: 'strict' as const, typeSymbol: 'ModelSettings.ChangeFrame', create: () => ({ parse: parseModelSettingsChangeFrame }) },\n }],\n }\n}\n\ninterface RemoteMountScope {\n remote: { $mount(contribution: TypertRemoteContribution): Promise<() => Promise<void>> }\n effect(callback: () => () => void | Promise<void>): unknown\n}\ninterface RemoteMountContext {\n inject(dependencies: string[], callback: (scope: unknown) => void): unknown\n}\n\n/** Mount from a synchronous apply. Disposal waits for an in-flight mount and\n * then withdraws it, so the contribution cannot outlive the plugin. */\nexport function mountModelSettingsChanges(ctx: RemoteMountContext, packageName: string): void {\n const contribution = modelSettingsChangesRemote(packageName)\n ctx.inject(['remote'], injected => {\n const scope = injected as RemoteMountScope\n const mounting = scope.remote.$mount(contribution)\n void mounting.catch(() => {})\n scope.effect(() => async () => {\n const unmount = await mounting.catch(() => undefined)\n await unmount?.()\n })\n })\n}\n\ninterface StreamItem {\n generation: number\n value: unknown\n signal: AbortSignal\n accept(): void\n}\ninterface ChangeStream extends AsyncIterable<StreamItem> { dispose(): Promise<void> }\ntype OpenChangeStream = (options: {\n name: string\n open(signal: AbortSignal): AsyncIterable<unknown>\n ended(accepted: boolean): Error\n}) => ChangeStream\nexport interface ModelSettingsSubscriberScope {\n remote: { $stream: OpenChangeStream } & Record<string, { watch?(signal: AbortSignal): AsyncIterable<unknown> } | OpenChangeStream | undefined>\n effect(callback: () => () => void | Promise<void>): unknown\n}\nexport interface ModelSettingsSubscriberContext {\n inject(dependencies: string[], callback: (scope: unknown) => void): unknown\n}\nexport interface ModelSettingsSubscriber {\n subscribe(onChange: () => void, onError?: (message: string) => void): () => void\n}\n\n/** Native RemoteStream owns carrier reconnects; no timers or browser transport.\n * A factory shares one logical stream while at least one subscriber remains. */\nexport function createModelSettingsSubscriber(\n ctx: ModelSettingsSubscriberContext,\n packageName: string,\n identity: ModelSettingsChangesIdentity = modelSettingsChangesIdentity(packageName),\n accept: (ns: string) => boolean = ns => ns === packageName,\n): ModelSettingsSubscriber {\n const endpoint = identity\n const listeners = new Set<{ change: () => void; error?: (message: string) => void }>()\n let injection: { dispose(): void | Promise<void> } | undefined\n let current: { stream: ChangeStream; active: boolean } | undefined\n let lifecycle = 0\n let failureMessage: string | undefined\n const report = (message: string) => {\n failureMessage = message\n for (const listener of [...listeners]) {\n try { listener.error?.(message) } catch { /* Isolate page callbacks. */ }\n }\n }\n const invalidate = () => {\n for (const listener of [...listeners]) {\n if (!listeners.has(listener)) continue\n try { listener.change() } catch (error) {\n try { listener.error?.(error instanceof Error ? error.message : String(error)) } catch { /* Isolate callbacks. */ }\n }\n }\n }\n const start = () => {\n const life = ++lifecycle\n injection = ctx.inject(['remote', `remote.${endpoint.namespace}`], injected => {\n if (life !== lifecycle || !listeners.size) return\n const scope = injected as ModelSettingsSubscriberScope\n const service = scope.remote[endpoint.namespace]\n if (!service || !('watch' in service) || !service.watch) { report('Model settings sync service unavailable'); return }\n const watch = service.watch\n const stream = scope.remote.$stream({\n name: 'Model settings sync',\n open: signal => watch(signal),\n ended: accepted => new Error(`Model settings sync stream ended ${accepted ? 'after' : 'before'} ready; refresh or reopen the page`),\n })\n const session = { stream, active: true }\n current = session\n scope.effect(() => () => {\n session.active = false\n if (current === session) {\n current = undefined\n if (life === lifecycle && listeners.size) report('Model settings sync service unavailable')\n }\n return stream.dispose()\n })\n void (async () => {\n let generation: number | undefined\n let ready = false\n try {\n for await (const item of stream) {\n if (!session.active || life !== lifecycle || !listeners.size) break\n if (item.signal.aborted) continue\n if (generation !== item.generation) { generation = item.generation; ready = false }\n const frame = parseModelSettingsChangeFrame(item.value)\n if (frame.kind === 'ready') {\n ready = true\n failureMessage = undefined\n // Accept the validated invalidation baseline, not fetched data.\n // Every current listener queues its own latest settings read.\n item.accept()\n invalidate()\n } else {\n if (!ready) throw new Error('Model settings sync change arrived before ready')\n if (accept(frame.ns)) invalidate()\n }\n }\n } catch (error) {\n if (session.active && life === lifecycle) report(error instanceof Error ? error.message : String(error))\n } finally {\n if (current === session) current = undefined\n session.active = false\n await stream.dispose().catch(() => {})\n }\n })()\n }) as { dispose(): void | Promise<void> }\n queueMicrotask(() => {\n if (life === lifecycle && listeners.size && !current) report('Model settings sync service unavailable')\n })\n }\n return Object.freeze({ subscribe(onChange: () => void, onError?: (message: string) => void) {\n const listener = { change: onChange, error: onError }\n listeners.add(listener)\n if (!injection) start()\n else if (failureMessage) queueMicrotask(() => {\n if (listeners.has(listener) && failureMessage) {\n try { listener.error?.(failureMessage) } catch { /* Isolate callbacks. */ }\n }\n })\n return () => {\n if (!listeners.delete(listener) || listeners.size) return\n lifecycle++\n if (current) { current.active = false; void current.stream.dispose().catch(() => {}) }\n current = undefined\n failureMessage = undefined\n const previous = injection\n injection = undefined\n try { void Promise.resolve(previous?.dispose()).catch(() => {}) } catch { /* Already unloaded. */ }\n }\n } })\n}\n","import { defaultModelRoute, normalizeModelRoute, type ModelRoute } from '@klarkxy/dsh-model-route'\nexport { defaultModelRoute, normalizeModelRoute }\n\n/** Browser-safe contracts. Shared RPC/result types stay on @klarkxy/dsh-plugin-kit. */\nimport type { RpcResult as SharedRpcResult } from '@klarkxy/dsh-plugin-kit/contracts'\nexport type RpcResult<T = unknown> = Extract<SharedRpcResult<T>, { ok: true }> | {\n ok: false\n error: { code: string; message: string; partial?: PartialCommitResult }\n}\n\nexport const PLUGIN_NAME = '@klarkxy/dsh-git-commit'\nexport const FEATURE_ID = 'git-commit'\nexport const PURPOSE_ID = 'git-commit.plan'\nexport const RPC_CHANNEL = '/dsh-git-commit'\nexport const GIT_COMMIT_CLIENT_SERVICE = 'dshGitCommitClient'\nexport const PROMPT_VERSION = 'git-commit.v1'\nexport const SCHEMA_VERSION = 'commit-plan-json.v1'\nexport const CONTRACT_VERSION = 1\n\nexport const DEFAULT_MAX_OUTPUT_TOKENS = 2048\n/** Total character budget for the change manifest sent to the model. */\nexport const MAX_MANIFEST_CHARS = 48_000\n/** Per-file preview cap for untracked files. */\nexport const MAX_UNTRACKED_PREVIEW_CHARS = 2_000\n/** Recent commit subjects supplied as style reference. */\nexport const RECENT_LOG_COUNT = 10\n/** Hard cap for one generated commit message line. */\nexport const MAX_MESSAGE_CHARS = 120\n/** git subprocess timeout. */\nexport const GIT_TIMEOUT_MS = 30_000\nexport const SETTINGS_KEY = 'current'\n\n/**\n * Plugin-page model selection. Empty provider/model means \"follow the default\".\n * The value shape, empty default, and 250/80 normalizer live in\n * @klarkxy/dsh-model-route; this alias keeps the commit-specific name.\n */\nexport type CommitModelRoute = ModelRoute\n\nexport interface GitCommitSettings {\n readonly revision: number\n readonly model: CommitModelRoute\n /**\n * Opt-in single commit when the model produced no usable plan. Off by\n * default: an unplanned commit is one the user never reviewed, so a failed\n * or unusable model call rejects the run instead of writing to the index.\n */\n readonly allowFallback: boolean\n}\n\nexport const defaultSettings = (): GitCommitSettings => ({\n revision: 0, model: defaultModelRoute(), allowFallback: false,\n})\n\n/** Untrusted stored flags stay opt-in: anything but a literal true is false. */\nexport function normalizeFallback(value: unknown): boolean {\n return value === true\n}\n\nexport interface CommitModelInfo {\n readonly provider: string\n readonly model: string\n /** 'page' is the plugin-page selection; 'default' follows the session or host chat model. */\n readonly source: 'page' | 'default'\n}\n\nexport interface GitCommitStatus {\n readonly available: boolean\n /** Machine-readable reason when unavailable: 'no-session' | 'no-cwd' | 'not-a-repo' | 'no-git'. */\n readonly reason?: string\n readonly detail?: string\n readonly root?: string\n readonly branch?: string\n readonly workspace: { readonly files: number }\n readonly model?: CommitModelInfo\n}\n\nexport interface CommitGroupResult {\n /** Empty only when a created commit's hash could not be read. */\n readonly hash: string\n readonly message: string\n readonly files: readonly string[]\n}\n\nexport interface CommitRunResult {\n readonly branch: string\n readonly commits: readonly CommitGroupResult[]\n /** True when the model plan was unavailable and a single fallback commit was used. */\n readonly fallback: boolean\n readonly model?: CommitModelInfo\n}\n\n/**\n * Commits that already exist when a later group fails or the run is cancelled.\n * `commits` is the durable outcome; `failure` is why the rest did not run.\n * A recorded commit is never rolled back and never retried by this plugin.\n */\nexport interface PartialCommitResult {\n readonly branch: string\n readonly commits: readonly CommitGroupResult[]\n readonly fallback: boolean\n readonly model?: CommitModelInfo\n readonly failure: { readonly code: string; readonly message: string }\n readonly remaining: readonly { readonly message: string; readonly files: readonly string[] }[]\n /** After a rejected commit command, unchanged HEAD could not be proved; completion and ownership are unconfirmed. */\n readonly uncertain?: readonly { readonly message: string; readonly files: readonly string[] }[]\n}\n","import type { Context } from '@deepseek-ai/cordis'\nimport {\n MODEL_CATALOG_INJECT, readModelCatalog, modelMenuEffortLabel, modelMenuEffortOptions, parseModelMenuChoices,\n} from '@klarkxy/dsh-model-route'\nimport { ModelCatalogStatus, ModelMenu, modelMenuCss, useModelCatalog } from '@klarkxy/dsh-model-route/ui'\nimport { useCallback, useEffect, useRef, useState, useSyncExternalStore } from 'react'\nimport { createPortal } from 'react-dom'\nimport {\n Button, IconChevronDownOutlineRegular, IconRefreshOutlineRegular, Switch, Tag, Tooltip, useAnchoredPosition, useDismissOnOutsidePointer,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport { officialUiCss } from '@klarkxy/dsh-plugin-kit/official-ui'\nimport { createModelSettingsSubscriber, mountModelSettingsChanges } from '@klarkxy/dsh-plugin-kit/model-settings-client'\nimport {\n GIT_COMMIT_CLIENT_SERVICE, PLUGIN_NAME, RPC_CHANNEL, type CommitModelRoute, type CommitRunResult,\n type GitCommitSettings, type GitCommitStatus, type PartialCommitResult, type RpcResult,\n} from './contracts.ts'\n\nexport const name = 'dsh-git-commit-client'\nexport const inject = ['slots', 'connection', ...MODEL_CATALOG_INJECT, 'locale'] as const\n\nconst NS = 'dsh-git-commit.action'\n\nconst zh = {\n action: '提交',\n title: '提交到 Git',\n commitAction: '分次提交全部工作区修改',\n files: '个文件',\n model: '模型',\n modelDefault: '默认模型',\n modelCustom: '插件设置',\n filesCount: '({n} 个文件)',\n confirmPrompt: '将把 {n} 个文件的全部修改分次提交到当前分支。',\n confirm: '确认提交',\n cancel: '取消',\n loading: '正在读取仓库状态…',\n running: '正在整理修改并分次提交…',\n done: '已创建提交',\n partial: '本次提交未全部完成;以下提交已保留',\n stopped: '本次操作未确认完成',\n uncertain: '以下提交组的结果不确定。请检查 Git 日志和状态,确认后再操作。',\n hashUnavailable: '提交已创建,哈希未读取',\n remaining: '尚未提交:{n} 组',\n cancelled: '提交操作已取消',\n fallback: '模型不可用,已合并为单个提交',\n noWorkspace: '工作区没有修改',\n unavailable: '不可用',\n reasonNoRepo: '当前目录不在 Git 仓库中',\n reasonNoGit: '未找到 git 命令',\n reasonNoCwd: '会话没有工作目录',\n reasonNoSession: '会话不在线',\n sessionRunning: '会话正在运行,提交已暂停',\n refresh: '刷新',\n failed: '操作失败',\n disabled: '插件已停用',\n busy: '已有提交操作正在进行',\n stale: '设置已更新,请刷新后重试',\n workspaceChanged: '工作区或分支已变更,请刷新后重试提交',\n settingsUnavailable: '无法读取提交设置,请重新加载插件后重试',\n invalidRequest: '提交请求无效,请刷新后重试',\n planUnavailable: '模型没有给出可用的提交方案,已取消本次提交,工作区没有被改动。换一个模型重试,或在插件设置里开启兜底提交。',\n close: '关闭',\n}\n\nconst en: Record<keyof typeof zh, string> = {\n action: 'Commit',\n title: 'Commit to Git',\n commitAction: 'Commit all workspace changes',\n files: 'files',\n model: 'Model',\n modelDefault: 'default model',\n modelCustom: 'Plugin settings',\n filesCount: ' ({n} files)',\n confirmPrompt: 'All changes in {n} files will be committed to the current branch in one or more commits.',\n confirm: 'Commit now',\n cancel: 'Cancel',\n loading: 'Reading repository status…',\n running: 'Organizing changes into commits…',\n done: 'Commits created',\n partial: 'This run stopped before completion; these commits were kept',\n stopped: 'This run did not finish with a confirmed result',\n uncertain: 'The outcome of these groups is uncertain. Check Git log and status before taking further action.',\n hashUnavailable: 'Commit created; hash unavailable',\n remaining: 'Groups not committed: {n}',\n cancelled: 'Commit run cancelled',\n fallback: 'Model unavailable; used a single commit',\n noWorkspace: 'No workspace changes',\n unavailable: 'Unavailable',\n reasonNoRepo: 'Current directory is not inside a Git repository',\n reasonNoGit: 'git executable not found',\n reasonNoCwd: 'Session has no working directory',\n reasonNoSession: 'Session is not live',\n sessionRunning: 'Session is running; commits paused',\n refresh: 'Refresh',\n failed: 'Operation failed',\n disabled: 'Plugin disabled',\n busy: 'A commit run is already in progress',\n stale: 'Settings changed; refresh and retry',\n workspaceChanged: 'The workspace or branch changed; refresh and retry the commit',\n settingsUnavailable: 'Could not read commit settings; reload the plugin and retry',\n invalidRequest: 'Invalid commit request; refresh and retry',\n planUnavailable: 'The model returned no usable commit plan, so the run was cancelled and your workspace is untouched. Try another model, or turn on the fallback in plugin settings.',\n close: 'Close',\n}\n\ntype Key = keyof typeof zh\ntype Translate = (key: Key) => string\n\ninterface ConnectionLike {\n generation?: { subscribe(listener: () => void): () => void }\n rpc: { call(channel: string, endpoint: string, payload: unknown): Promise<unknown> }\n}\n\ninterface SessionSnapshotLike {\n running?: boolean\n}\n\ninterface UseSessionLike {\n <T>(selector: (snapshot: SessionSnapshotLike) => T): T\n}\n\n/** A failed RPC keeps its code so the panel can explain a rejection in its own words. */\nclass RpcError extends Error {\n readonly code: string\n readonly partial?: PartialCommitResult\n constructor(code: string, message: string, partial?: PartialCommitResult) {\n super(message)\n this.name = 'RpcError'\n this.code = code\n this.partial = partial\n }\n}\n\nexport interface GitCommitActionProps {\n sessionId: string\n useSession: UseSessionLike\n call: (endpoint: string, payload: unknown) => Promise<unknown>\n t: Translate\n}\n\nasync function rpc<T>(\n call: GitCommitActionProps['call'], endpoint: string, payload: unknown = {}, fallback = '',\n): Promise<T> {\n const result = await call(endpoint, payload) as RpcResult<T> | undefined\n if (!result || result.ok !== true) {\n const failed = result && 'error' in result ? result.error : undefined\n throw new RpcError(failed?.code ?? 'unknown', failed?.message ? failed.message : fallback,\n failed && 'partial' in failed ? failed.partial : undefined)\n }\n return result.value\n}\n\nfunction reasonText(t: Translate, status: GitCommitStatus): string {\n switch (status.reason) {\n case 'not-a-repo': return t('reasonNoRepo')\n case 'no-git': return t('reasonNoGit')\n case 'no-cwd': return t('reasonNoCwd')\n case 'no-session': return t('reasonNoSession')\n default: return t('unavailable')\n }\n}\n\n/** A refusal the plugin can name gets its own sentence; the rest stay verbatim. */\nfunction errorText(t: Translate, error: { code: string; message: string }): string {\n const keys: Record<string, Key> = {\n 'plan-unavailable': 'planUnavailable', 'no-session': 'reasonNoSession', 'no-cwd': 'reasonNoCwd',\n 'no-git': 'reasonNoGit', 'not-a-repo': 'reasonNoRepo', 'no-changes': 'noWorkspace',\n 'session-running': 'sessionRunning', 'session-changed': 'workspaceChanged', 'workspace-changed': 'workspaceChanged',\n busy: 'busy', stale: 'stale', disposed: 'disabled', cancelled: 'cancelled',\n 'settings-unavailable': 'settingsUnavailable', 'bad-request': 'invalidRequest', 'not-found': 'invalidRequest',\n }\n const key = keys[error.code]\n return key ? t(key) : error.message || t('failed')\n}\n\nfunction panelError(reason: unknown): { code: string; message: string } {\n return reason instanceof RpcError\n ? { code: reason.code, message: reason.message }\n : { code: 'unknown', message: reason instanceof Error ? reason.message : String(reason) }\n}\n\nfunction GitBranchIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <circle cx=\"4.5\" cy=\"3.5\" r=\"1.6\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <circle cx=\"4.5\" cy=\"12.5\" r=\"1.6\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <circle cx=\"11.5\" cy=\"6.5\" r=\"1.6\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <path d=\"M4.5 5.1v5.8\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n <path d=\"M11.5 8.1c0 2-1.6 2.9-3.4 3\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n </svg>\n )\n}\n\nexport function GitCommitAction({ sessionId, useSession, call, t }: GitCommitActionProps) {\n const [open, setOpen] = useState(false)\n const [status, setStatus] = useState<GitCommitStatus>()\n const [loading, setLoading] = useState(false)\n const [running, setRunning] = useState(false)\n const [result, setResult] = useState<CommitRunResult | PartialCommitResult | null>(null)\n const [error, setError] = useState<{ code: string; message: string } | null>(null)\n const [confirming, setConfirming] = useState(false)\n const rootRef = useRef<HTMLDivElement>(null)\n const triggerRef = useRef<HTMLButtonElement>(null)\n const panelRef = useRef<HTMLDivElement>(null)\n const generationRef = useRef(0)\n const position = useAnchoredPosition({ open, anchorRef: triggerRef, panelRef, gap: 5, margin: 16 })\n const sessionRunning = useSession(snapshot => snapshot.running === true)\n\n const changeOpen = useCallback((next: boolean) => {\n setOpen(next)\n setConfirming(false)\n if (next) {\n setResult(null)\n setError(null)\n }\n }, [])\n\n // Move focus into the dialog once it is positioned, so keyboard users land inside it.\n const positioned = Boolean(position)\n useEffect(() => {\n if (open && positioned) panelRef.current?.focus()\n }, [open, positioned])\n\n useDismissOnOutsidePointer(rootRef, open, changeOpen, panelRef)\n\n useEffect(() => {\n generationRef.current += 1\n setOpen(false)\n setStatus(undefined)\n setResult(null)\n setError(null)\n setRunning(false)\n }, [sessionId])\n\n const loadStatus = useCallback(async () => {\n const generation = generationRef.current\n setLoading(true)\n setError(null)\n try {\n const next = await rpc<GitCommitStatus>(call, 'status', { sessionId })\n if (generationRef.current !== generation) return\n setStatus(next)\n } catch (reason) {\n if (generationRef.current !== generation) return\n setStatus(undefined)\n setError(panelError(reason))\n } finally {\n if (generationRef.current === generation) setLoading(false)\n }\n }, [call, sessionId])\n\n useEffect(() => {\n if (!open) return\n void loadStatus()\n }, [open, loadStatus])\n\n useEffect(() => {\n if (!open) return\n const dismiss = (event: KeyboardEvent) => {\n if (event.key !== 'Escape') return\n event.preventDefault()\n changeOpen(false)\n triggerRef.current?.focus()\n }\n document.addEventListener('keydown', dismiss)\n return () => document.removeEventListener('keydown', dismiss)\n }, [open, changeOpen])\n\n const runCommit = useCallback(async () => {\n const generation = generationRef.current\n setConfirming(false)\n setRunning(true)\n setResult(null)\n setError(null)\n try {\n const value = await rpc<CommitRunResult>(call, 'commit', { sessionId })\n if (generationRef.current !== generation) return\n setResult(value)\n } catch (reason) {\n if (generationRef.current !== generation) return\n if (reason instanceof RpcError && reason.partial) setResult(reason.partial)\n setError(panelError(reason))\n } finally {\n if (generationRef.current === generation) {\n // Even a rejected run may have durable commits or changed the index.\n const next = await rpc<GitCommitStatus>(call, 'status', { sessionId }).catch(() => undefined)\n if (generationRef.current === generation) {\n setStatus(next)\n setRunning(false)\n }\n }\n }\n }, [call, sessionId])\n\n const available = status?.available === true\n const workspaceCount = status?.workspace.files ?? 0\n const canCommit = available && !running && !sessionRunning && workspaceCount > 0\n\n return (\n <div ref={rootRef} className=\"gcm-root\">\n <Tooltip label={t('title')} side=\"bottom\" gap={4}>\n <Button\n ref={triggerRef}\n variant=\"ghost\"\n size=\"sm\"\n icon={<GitBranchIcon />}\n aria-label={t('title')}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n onClick={() => changeOpen(!open)}\n >\n {t('action')}\n </Button>\n </Tooltip>\n {open && createPortal(\n <div\n ref={panelRef}\n className=\"gcm-root dsh-ui-surface gcm-panel\"\n style={position ?? { visibility: 'hidden', left: 0, top: 0 }}\n role=\"dialog\"\n tabIndex={-1}\n aria-label={t('title')}\n >\n <div className=\"dsh-ui-surface-body\">\n <div className=\"dsh-ui-surface-head\">\n <span className=\"dsh-ui-surface-title\">{t('title')}</span>\n {status?.branch ? <span className=\"dsh-ui-hint dsh-ui-truncate\">{status.branch}</span> : null}\n <span className=\"dsh-ui-spacer\" />\n <Tooltip label={t('refresh')} side=\"bottom\" gap={4}>\n <Button variant=\"ghost\" size=\"sm\" aria-label={t('refresh')} icon={<IconRefreshOutlineRegular size={14} />}\n disabled={loading || running} onClick={() => void loadStatus()} />\n </Tooltip>\n </div>\n {loading && !status && <p className=\"dsh-ui-hint\" role=\"status\">{t('loading')}</p>}\n {error !== null && <p className=\"dsh-ui-error\" role=\"alert\">{errorText(t, error)}</p>}\n {status && !available && <p className=\"dsh-ui-meta\" role=\"status\">{reasonText(t, status)}</p>}\n {available && (\n <>\n {status?.model ? (\n <p className=\"gcm-model\">\n <span className=\"dsh-ui-hint\">{t('model')}</span>\n <span className=\"dsh-ui-truncate\">{status.model.provider}/{status.model.model}</span>\n <Tag tone={status.model.source === 'page' ? 'info' : 'neutral'}>\n {status.model.source === 'page' ? t('modelCustom') : t('modelDefault')}\n </Tag>\n </p>\n ) : null}\n {confirming && canCommit ? (\n <div className=\"dsh-ui-stack\" role=\"group\" aria-label={t('commitAction')}>\n <p className=\"dsh-ui-hint dsh-ui-wrap\">{t('confirmPrompt').replace('{n}', String(workspaceCount))}</p>\n <div className=\"dsh-ui-actions\">\n <Button variant=\"ghost\" size=\"md\" onClick={() => setConfirming(false)}>{t('cancel')}</Button>\n <Button variant=\"primary\" size=\"md\" onClick={() => void runCommit()}>{t('confirm')}</Button>\n </div>\n </div>\n ) : (\n <Button variant=\"primary\" size=\"md\"\n disabled={!canCommit}\n onClick={() => setConfirming(true)}>\n {t('commitAction')}{t('filesCount').replace('{n}', String(workspaceCount))}\n </Button>\n )}\n {workspaceCount === 0 && <p className=\"dsh-ui-hint\">{t('noWorkspace')}</p>}\n {sessionRunning && <p className=\"dsh-ui-hint\">{t('sessionRunning')}</p>}\n </>\n )}\n {running && <p className=\"dsh-ui-hint\" role=\"status\">{t('running')}</p>}\n {result && (\n <div className=\"dsh-ui-stack\">\n <p className=\"dsh-ui-hint dsh-ui-wrap\">{t('failure' in result ? result.commits.length ? 'partial' : 'stopped' : 'done')} · {result.branch}</p>\n <ul className=\"gcm-commits\">\n {result.commits.map((commit, index) => (\n <li key={`${index}:${commit.hash}`}>\n <code>{commit.hash || t('hashUnavailable')}</code> {commit.message}\n <div className=\"dsh-ui-hint\">{commit.files.join(', ')}</div>\n </li>\n ))}\n </ul>\n {result.fallback && <p className=\"dsh-ui-hint\">{t('fallback')}</p>}\n {'uncertain' in result && result.uncertain?.length ? <>\n <p className=\"dsh-ui-hint\" role=\"status\">{t('uncertain')}</p>\n <ul className=\"gcm-commits\">\n {result.uncertain.map((group, index) => <li key={index}>{group.message}\n <div className=\"dsh-ui-hint\">{group.files.join(', ')}</div>\n </li>)}\n </ul>\n </> : null}\n {'remaining' in result && <>\n <p className=\"dsh-ui-hint\">{t('remaining').replace('{n}', String(result.remaining.length))}</p>\n <ul className=\"gcm-commits\">\n {result.remaining.map((group, index) => <li key={index}>{group.message}\n <div className=\"dsh-ui-hint\">{group.files.join(', ')}</div>\n </li>)}\n </ul>\n </>}\n </div>\n )}\n </div>\n </div>,\n document.body,\n )}\n </div>\n )\n}\n\nexport const clientCss = `${officialUiCss('gcm-root')}${modelMenuCss}\n/* Only the floating panel's geometry is this plugin's own: the material, the\n * rounded edge and the scrollbar tokens all come from the shared contract.\n *\n * The root class is spelled out because the panel is portaled and *is* the\n * root: the dsh-ui-surface recipe therefore reaches it as a compound\n * .gcm-root.dsh-ui-surface selector and declares position:relative at the\n * weight a bare .gcm-panel rule also carries. Left unqualified that recipe\n * wins, and the anchored left/top degrade into offsets from the panel's static\n * spot at the end of body — the popover then renders under the page instead\n * of at the trigger. Naming both classes puts this rule at the same weight,\n * later in the sheet, so it wins. */\n.gcm-root.gcm-panel { position: fixed; width: min(360px, calc(100vw - 32px)); max-height: min(560px, calc(100vh - 32px)); overflow: auto; }\n.gcm-root .gcm-model { display: flex; align-items: center; gap: 6px; min-width: 0; margin: 0; font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-primary); }\n.gcm-root .gcm-commits { margin: 0; padding-inline-start: 18px; display: grid; gap: 2px; font-size: 12px; line-height: 18px; overflow-wrap: anywhere; }\n.gcm-root .gcm-commits code { font-size: 12px; background: var(--dsw-alias-bg-layer-2); padding: 0 4px; border-radius: var(--dsw-radius-sm); }\n.gcm-root .gcm-settings-status { display: flex; flex-direction: column; gap: 4px; }\n`\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context { dshGitCommitClient: { active: boolean } }\n}\n\ntype Client = Context & {\n connection: ConnectionLike\n remote?: { session?: { modelCatalog?: () => Promise<unknown> } }\n slots: {\n inject(key: string, callback: () => unknown): () => void\n register(spec: { name: string; id: string; order: number; locale: string; inject: () => unknown } | { name: string; key: string }, render: unknown): () => void\n }\n locale: {\n register(ns: string, locales: { zh: Record<string, string>; en: Record<string, string> }): () => void\n getSnapshot?(): { active: string }\n subscribe?(listener: () => void): () => void\n }\n}\n\n/** Host UI language, following live switches with the host's English fallback. */\nfunction useHostLocale(client: Client): string {\n const subscribe = useCallback(\n (listener: () => void) => client.locale.subscribe?.(listener) ?? (() => {}),\n [client],\n )\n const snapshot = useCallback(() => client.locale.getSnapshot?.().active ?? 'en', [client])\n return useSyncExternalStore(subscribe, snapshot, snapshot)\n}\n\nconst settingsZh = {\n pageTitle: 'Git 提交',\n model: '提交规划模型',\n modelDefault: '默认模型',\n modelHint: '留空则使用当前会话模型,再回落到宿主默认对话模型。',\n fallback: '模型不可用时仍然提交',\n fallbackHint: '默认关闭:模型规划失败会取消本次提交,工作区不变。开启后全部改动会合并成一个提交,由插件代写提交信息。',\n loading: '正在读取设置…',\n saved: '已保存。',\n stale: '设置已更新,请刷新后重试。',\n failed: '无法读取提交设置。',\n retry: '重试',\n refresh: '刷新设置',\n syncUnavailable: '自动刷新不可用,请手动刷新设置。',\n}\n\nconst settingsEn: Record<keyof typeof settingsZh, string> = {\n pageTitle: 'Git Commit',\n model: 'Commit planning model',\n modelDefault: 'Default model',\n modelHint: 'Leave empty to use the current session model, then the host default chat model.',\n fallback: 'Commit even without a model plan',\n fallbackHint: 'Off by default: a failed plan cancels the run and leaves the workspace untouched. When on, every change lands in one commit with a plugin-written message.',\n loading: 'Loading settings…',\n saved: 'Saved.',\n stale: 'Settings changed; refresh and retry.',\n failed: 'Could not load commit settings.',\n retry: 'Retry',\n refresh: 'Refresh settings',\n syncUnavailable: 'Automatic refresh unavailable; refresh settings manually.',\n}\n\nfunction settingsCopy(locale: string): Record<keyof typeof settingsZh, string> {\n return String(locale).startsWith('zh') ? settingsZh : settingsEn\n}\n\n/** Plugin-page settings row: pick the model this plugin's planning call uses. */\nexport function GitCommitSettingsPanel(props: { client: Client; locale?: string; subscribeSettings?: (change: () => void, error?: (message: string) => void) => () => void }) {\n const hostLocale = useHostLocale(props.client)\n const text = settingsCopy(props.locale ?? hostLocale)\n const language = String(props.locale ?? hostLocale).toLowerCase().startsWith('zh') ? 'zh' : 'en'\n const [settings, setSettings] = useState<GitCommitSettings | undefined>(undefined)\n const loadCatalog = useCallback(() => readModelCatalog(props.client), [props.client])\n const subscribeCatalog = useCallback((change: () => void) => props.client.connection.generation?.subscribe(change), [props.client])\n const catalogState = useModelCatalog(loadCatalog, { subscribe: subscribeCatalog })\n const { refresh: refreshCatalog } = catalogState\n const choices = parseModelMenuChoices(catalogState.catalog, settings?.model)\n const [menuOpen, setMenuOpen] = useState(false)\n const [error, setError] = useState<'' | 'failed' | 'stale'>('')\n const [note, setNote] = useState(false)\n const [busy, setBusy] = useState(false)\n const [syncError, setSyncError] = useState('')\n const operation = useRef({ epoch: 0, active: false, reading: false, writing: false, pending: false })\n const refreshRef = useRef<() => void>(() => {})\n\n const call = useCallback(\n (endpoint: string, payload: unknown = {}) => props.client.connection.rpc.call(RPC_CHANNEL, endpoint, payload),\n [props.client],\n )\n\n const refresh = () => {\n const state = operation.current\n if (!state.active) return\n if (state.reading || state.writing) { state.pending = true; return }\n state.pending = false; state.reading = true; setBusy(true)\n const epoch = state.epoch\n void rpc<GitCommitSettings>(call, 'settings', {}, text.failed).then(next => {\n if (state.active && state.epoch === epoch && !state.pending) { setSettings(next); setError('') }\n }).catch(() => {\n if (state.active && state.epoch === epoch && !state.pending) setError('failed')\n }).finally(() => {\n if (!state.active || state.epoch !== epoch) return\n state.reading = false; setBusy(false)\n if (state.pending) refreshRef.current()\n })\n }\n refreshRef.current = refresh\n useEffect(() => {\n const state = operation.current\n state.epoch++; state.active = true; state.reading = false; state.writing = false; state.pending = false\n setBusy(false); setSettings(undefined); setError(''); setNote(false)\n refreshRef.current()\n return () => { state.active = false; state.epoch++ }\n }, [call])\n useEffect(() => {\n setSyncError('')\n let live = true\n const stop = props.subscribeSettings?.(() => { if (live) { setSyncError(''); refreshCatalog(); refreshRef.current() } }, message => { if (live) setSyncError(message) })\n return () => { live = false; stop?.() }\n }, [props.subscribeSettings, props.client, refreshCatalog])\n\n // One patch shape for both rows: the service replaces the whole row, so an\n // update to the toggle must carry the model it is not changing.\n const save = useCallback((patch: { model?: CommitModelRoute; allowFallback?: boolean }) => {\n const state = operation.current\n if (!settings || !state.active || state.writing || state.reading) return\n state.writing = true\n const epoch = state.epoch\n setBusy(true); setNote(false); setError('')\n void rpc<GitCommitSettings>(call, 'settings.update', {\n settings: {\n model: patch.model ?? settings.model,\n allowFallback: patch.allowFallback ?? settings.allowFallback,\n },\n expectedRevision: settings.revision,\n }, text.stale).then(next => {\n if (state.active && state.epoch === epoch) { setSettings(next); setNote(true) }\n }).catch(() => {\n if (state.active && state.epoch === epoch) setError('stale')\n }).finally(() => {\n if (!state.active || state.epoch !== epoch) return\n state.writing = false; setBusy(false)\n if (state.pending) refreshRef.current()\n })\n }, [call, settings, text.saved, text.stale])\n\n if (!settings) {\n return (\n <section className=\"gcm-root gcm-settings dsh-ui-page\">\n {error\n ? <p role=\"alert\" className=\"dsh-ui-error\">{text[error]}</p>\n : <p role=\"status\" className=\"dsh-ui-hint\">{text.loading}</p>}\n {syncError && <p role=\"status\" className=\"dsh-ui-hint\">{text.syncUnavailable}</p>}\n <Button variant=\"ghost\" size=\"sm\" disabled={busy} onClick={() => refreshRef.current()}>{text.retry}</Button>\n </section>\n )\n }\n\n const current = settings.model\n const follow = !current.provider || !current.model\n const selected = follow ? undefined : choices.find(item => item.provider === current.provider && item.model === current.model)\n const efforts = follow ? [] : modelMenuEffortOptions(selected, current.reasoningEffort)\n const currentLabel = follow ? text.modelDefault : selected?.label ?? `${current.provider} / ${current.model}`\n const selectedEffort = efforts.find(item => item.id === (current.reasoningEffort || ''))\n const effortName = selectedEffort ? modelMenuEffortLabel(selectedEffort, language) : undefined\n\n return (\n <section className=\"gcm-root gcm-settings dsh-ui-page\" data-testid=\"git-commit-settings\">\n <div className=\"gcm-settings-status\">\n {syncError && <p role=\"status\" className=\"dsh-ui-hint\">{text.syncUnavailable}</p>}\n <Button variant=\"ghost\" size=\"sm\" disabled={busy} onClick={() => refreshRef.current()}>{text.refresh}</Button>\n {error && <p role=\"alert\" className=\"dsh-ui-error\">{text[error]}</p>}\n {note && <p role=\"status\" className=\"dsh-ui-notice\">{text.saved}</p>}\n </div>\n <div className=\"dsh-ui-field\">\n <span className=\"dsh-ui-label\">{text.model}</span>\n <ModelCatalogStatus state={catalogState} locale={language} />\n <ModelMenu\n locale={language}\n open={menuOpen && !busy}\n onOpenChange={next => setMenuOpen(next && !busy)}\n listClassName=\"gcm-root\"\n anchor={<button type=\"button\" className=\"dsh-model-menu-trigger\" disabled={busy} aria-label={`${text.model}: ${currentLabel}`}>\n <span className=\"dsh-model-menu-triggerLabel\">{currentLabel}</span>\n {!follow && efforts.length ? <span className=\"dsh-model-menu-triggerEffort\">{effortName ?? text.modelDefault}</span> : null}\n <IconChevronDownOutlineRegular className={`dsh-model-menu-chevron${menuOpen && !busy ? ' dsh-model-menu-chevronOpen' : ''}`} />\n </button>}\n choices={choices}\n selected={follow ? undefined : { provider: current.provider, model: current.model }}\n onPick={picked => save({ model: { provider: picked.provider, model: picked.model } })}\n leading={[{ id: 'default', label: text.modelDefault, selected: follow }]}\n onPickLeading={() => save({ model: { provider: '', model: '' } })}\n efforts={efforts}\n selectedEffort={current.reasoningEffort || ''}\n onPickEffort={effort => save({ model: follow\n ? { provider: '', model: '' }\n : { provider: current.provider, model: current.model, ...(effort ? { reasoningEffort: effort } : {}) } })}\n modelLabel={text.model}\n modelValue={currentLabel}\n defaultEffortLabel={text.modelDefault}\n />\n </div>\n <p className=\"dsh-ui-meta\">{text.modelHint}</p>\n <article className=\"gcm-root dsh-ui-card\">\n <header className=\"dsh-ui-toggle-row\">\n <div className=\"dsh-ui-toggle-text\">\n <h3 className=\"dsh-ui-toggle-label\">{text.fallback}</h3>\n <p className=\"dsh-ui-hint\">{text.fallbackHint}</p>\n </div>\n <Switch\n checked={settings.allowFallback}\n label={text.fallback}\n disabled={busy}\n onChange={next => save({ allowFallback: next })}\n />\n </header>\n </article>\n </section>\n )\n}\n\nexport function apply(ctx: Context): void {\n const client = ctx as unknown as Client\n mountModelSettingsChanges(ctx, PLUGIN_NAME)\n const settingsSubscriber = createModelSettingsSubscriber(ctx, PLUGIN_NAME)\n const subscribeSettings = (change: () => void, error?: (message: string) => void) => settingsSubscriber.subscribe(change, error)\n ctx.provide(GIT_COMMIT_CLIENT_SERVICE, { active: true })\n ctx.effect(() => client.locale.register(NS, { zh: { ...zh }, en: { ...en } }), 'git-commit.locale')\n // One stylesheet for both the header popover and the plugin-page settings,\n // so the settings page is styled even when no session header is mounted.\n ctx.effect(() => {\n if (typeof document === 'undefined') return () => {}\n const style = document.createElement('style')\n style.setAttribute('data-plugin', name)\n style.textContent = clientCss\n document.head.appendChild(style)\n return () => style.remove()\n }, 'git-commit.styles')\n ctx.effect(() => client.slots.inject('plugins.bundle.config', () => client.slots.register(\n { name: 'plugins.bundle.config', key: PLUGIN_NAME },\n () => <GitCommitSettingsPanel client={client} subscribeSettings={subscribeSettings} />,\n )), 'git-commit.settings')\n ctx.effect(() => client.slots.inject('conversation.session.header.actions', () => client.slots.register(\n {\n name: 'conversation.session.header.actions',\n id: 'git-commit',\n order: 10,\n locale: NS,\n inject: () => ({\n call: (endpoint: string, payload: unknown) => client.connection.rpc.call(RPC_CHANNEL, endpoint, payload),\n }),\n },\n GitCommitAction,\n )), 'git-commit.slot')\n}\n"],"mappings":"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"}