@klarkxy/dsh-model-hub 0.1.8 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -12
- package/docs/README.zh-CN.md +9 -12
- package/lib/client.inner.cjs +2093 -1521
- package/lib/client.inner.cjs.map +1 -1
- package/lib/client.js +2093 -1521
- package/lib/index.d.ts +1 -39
- package/lib/index.js +120 -512
- package/lib/index.js.map +1 -1
- package/locale/en.json +2 -2
- package/locale/zh.json +2 -2
- package/package.json +4 -4
package/lib/client.inner.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.inner.cjs","names":["asText","Button","useRef","useState","useId","useMemo","rankByName","observeStickyMenuGroups","createPortal","MenuSurface","IconChevronRightOutlineRegular","Input","IconCloseFillRegular","IconCheckOutlineRegular","MenuGroup","isValidElement","cloneElement","useState","useMemo","IconChevronDownOutlineRegular","TEXT","useText","useCallback","useSyncExternalStore","useMemo","useState","Input","Button","useRef","checkedCatalog","Switch","useCallback","useSyncExternalStore","useMemo","useState","useRef","checkedCatalog","SegmentedTabs","Input","Button"],"sources":["../../dsh-model-route/src/route.ts","../../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/client-model-menu.tsx","../src/client-copy.ts","../src/client-cast.tsx","../src/client.tsx"],"sourcesContent":["/**\n * Shared model-route value contract.\n *\n * A feature plugin stores its model override as a ModelRoute on its own\n * settings page. Empty provider/model means \"follow the host default model\".\n * Pure and browser-safe: no cordis, no React, no schema library.\n */\n\n/** A concrete provider model a feature call should use. */\nexport interface ModelRoute {\n provider: string\n model: string\n reasoningEffort?: string\n}\n\n/** Empty route: no explicit model, the feature follows the host default. */\nexport function defaultModelRoute(): ModelRoute {\n return { provider: '', model: '' }\n}\n\n/** Structural check: both id fields are strings (either may be empty). */\nexport function isModelRouteValue(value: unknown): value is ModelRoute {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false\n const row = value as Record<string, unknown>\n return typeof row.provider === 'string' && typeof row.model === 'string'\n}\n\nconst MAX_ID_CHARS = 250\nconst MAX_EFFORT_CHARS = 80\n\nfunction asText(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() ? value.trim() : undefined\n}\n\n/**\n * Coerce a stored value into a ModelRoute. Anything malformed collapses to the\n * empty route, matching the per-plugin normalizers this contract replaces.\n */\nexport function normalizeModelRoute(value: unknown): ModelRoute {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return defaultModelRoute()\n const row = value as Record<string, unknown>\n const provider = asText(row.provider) ?? ''\n const model = asText(row.model) ?? ''\n const effort = asText(row.reasoningEffort)\n if (!provider || !model || provider.length > MAX_ID_CHARS || model.length > MAX_ID_CHARS) return defaultModelRoute()\n return effort && effort.length <= MAX_EFFORT_CHARS ? { provider, model, reasoningEffort: effort } : { provider, model }\n}\n\n/** The override to actually call with: undefined when the route is empty. */\nexport function modelRouteOverride(route: ModelRoute | undefined): ModelRoute | undefined {\n const provider = route?.provider?.trim()\n const model = route?.model?.trim()\n if (!provider || !model) return undefined\n const effort = route?.reasoningEffort?.trim()\n return effort ? { provider, model, reasoningEffort: effort } : { provider, model }\n}\n\nconst KEY_SEPARATOR = '\\u001f'\n\n/** Stable key for one route, safe to use as a select-option value. */\nexport function modelRouteKey(provider: string, model: string): string {\n return provider && model ? `${provider}${KEY_SEPARATOR}${model}` : ''\n}\n\n/** Inverse of modelRouteKey; undefined for malformed keys. */\nexport function parseModelRouteKey(value: string): { provider: string; model: string } | undefined {\n const index = value.indexOf(KEY_SEPARATOR)\n if (index <= 0) return undefined\n const provider = value.slice(0, index)\n const model = value.slice(index + KEY_SEPARATOR.length)\n if (!provider || !model) return undefined\n return { provider, model }\n}\n\n/** True when both routes name the same target; two empty routes are equal. */\nexport function sameModelRoute(a: ModelRoute | undefined, b: ModelRoute | undefined): boolean {\n const left = modelRouteOverride(a)\n const right = modelRouteOverride(b)\n if (!left || !right) return !left === !right\n return left.provider === right.provider && left.model === right.model\n && (left.reasoningEffort ?? '') === (right.reasoningEffort ?? '')\n}\n","/**\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 { useEffect, useMemo, useState } from 'react'\nimport { IconChevronDownOutlineRegular } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { modelMenuEffortLabel, modelMenuEffortOptions, normalizeModelRoute, parseModelMenuChoices, type ModelRoute } from '@klarkxy/dsh-model-route'\nimport { ModelMenu } from '@klarkxy/dsh-model-route/ui'\n\n/** The text surface FieldMenu needs; both the fields tab and the cast tab supply it. */\nexport interface FieldMenuText {\n (key: 'follow' | 'effortDefault' | 'model' | 'effort' | 'searchModels' | 'noModels' | 'clearSearch'): string\n language: 'zh' | 'en'\n}\n\n/** One detected field's standard editor: the same ModelMenu every marked field gets. */\nexport function FieldMenu({ t, catalog, current, disabled, label, allowFollow = true, followLabel, reasoningEffort = true, onSet }: {\n t: FieldMenuText\n catalog: unknown\n current: ModelRoute | undefined\n disabled: boolean\n label: string\n allowFollow?: boolean\n followLabel?: string\n reasoningEffort?: boolean\n onSet: (route: ModelRoute) => void\n}) {\n const [open, setOpen] = useState(false)\n useEffect(() => { if (disabled) setOpen(false) }, [disabled])\n const route = normalizeModelRoute(current)\n const follow = !route.provider || !route.model\n const choices = useMemo(() => parseModelMenuChoices(catalog, follow ? undefined : route), [catalog, follow, route.provider, route.model])\n const selected = follow ? undefined : choices.find(choice => choice.provider === route.provider && choice.model === route.model)\n const efforts = follow || !reasoningEffort ? [] : modelMenuEffortOptions(selected, route.reasoningEffort || '')\n const currentLabel = follow ? followLabel || t('follow') : selected?.label ?? `${route.provider} / ${route.model}`\n const selectedEffort = efforts.find(item => item.id === (route.reasoningEffort || ''))\n const effortName = selectedEffort ? modelMenuEffortLabel(selectedEffort, t.language) : undefined\n return <ModelMenu\n locale={t.language}\n open={open && !disabled}\n onOpenChange={next => setOpen(next && !disabled)}\n listClassName=\"dsh-model-hub\"\n anchor={<button type=\"button\" className=\"dsh-model-menu-trigger\" disabled={disabled} aria-label={`${label}: ${currentLabel}`} aria-haspopup=\"menu\" aria-expanded={open && !disabled}>\n <span className=\"dsh-model-menu-triggerLabel\">{currentLabel}</span>\n {!follow && efforts.length ? <span className=\"dsh-model-menu-triggerEffort\">{effortName ?? t('effortDefault')}</span> : null}\n <IconChevronDownOutlineRegular className={`dsh-model-menu-chevron${open ? ' dsh-model-menu-chevronOpen' : ''}`} />\n </button>}\n choices={choices}\n selected={follow ? undefined : { provider: route.provider, model: route.model }}\n onPick={picked => onSet({ provider: picked.provider, model: picked.model })}\n leading={allowFollow ? [{ id: 'follow', label: followLabel || t('follow'), selected: follow }] : []}\n onPickLeading={() => onSet({ provider: '', model: '' })}\n efforts={efforts}\n selectedEffort={route.reasoningEffort || ''}\n onPickEffort={effort => onSet(follow\n ? { provider: '', model: '' }\n : { provider: route.provider, model: route.model, ...(effort ? { reasoningEffort: effort } : {}) })}\n modelLabel={t('model')}\n modelValue={currentLabel}\n effortLabel={t('effort')}\n defaultEffortLabel={t('effortDefault')}\n searchPlaceholder={t('searchModels')}\n emptyLabel={t('noModels')}\n clearSearchLabel={t('clearSearch')}\n />\n}\n\n\nexport function messageOf(error: unknown): string {\n if (error instanceof Error) return error.message\n if (error && typeof error === 'object' && 'message' in error) return String(error.message)\n return String(error)\n}\n\n// Preserve the hub's helper exports while keeping catalog validation and failure\n// decoding in the shared route contract used by both pages.\nexport { checkedModelCatalog as checkedCatalog, catalogFailures } from '@klarkxy/dsh-model-route'\n\n","import type { ModelSettingsText } from '@klarkxy/dsh-plugin-kit/model-settings'\n\nexport function hubText(value: ModelSettingsText | undefined, language: 'zh' | 'en'): string {\n return typeof value === 'string' ? value : value?.[language] ?? ''\n}\n\n/** Local validation defaults, without rewriting provider diagnostics. */\nexport const hubMessages = [\n ['请求失败', 'Request failed'],\n ['字段引用无效', 'Invalid field reference'],\n ['请先刷新,以获取有效的设置版本', 'A valid expected revision is required; refresh and retry'],\n ['模型路由无效', 'Invalid model route'],\n ['模型设置提供方已变化,请刷新后重试', 'Model settings owner changed; refresh and retry'],\n ['设置已变化,请刷新后重试', 'Settings changed; refresh and retry'],\n ['此模型字段不可编辑', 'Not an editable model field'],\n ['此设置需要选择具体模型', 'This model setting requires a concrete model'],\n ['模型设置提供方已卸载,请刷新后重试', 'Model settings owner unloaded; refresh and retry'],\n ['自测字段仅用于诊断', 'Self-test fields are diagnostic only'],\n ['提供方设置版本无效', 'Invalid owner revision'],\n ['未检测到此模型字段', 'Not a detected model field'],\n ['没有可编辑的集合条目', 'No collection item to edit'],\n ['设置版本无效', 'Invalid revision'],\n ['ChatGPT 需要 Codex 模型', 'ChatGPT requires a Codex model'],\n ['Codex 模型目录不可用。', 'Codex model catalog is unavailable.'],\n ['配置已在别处修改,请刷新后重试。', 'Settings changed elsewhere. Refresh and try again.'],\n ['设置已更新,请刷新后重试。', 'Settings changed. Refresh and try again.'],\n ['正在保存配置,请稍后重试。', 'Settings are being saved. Try again shortly.'],\n ['ChatGPT 插件已卸载。', 'The ChatGPT plugin has been unloaded.'],\n ['配置格式无效。', 'Invalid settings format.'],\n ['请等当前调用完成后保存配置。', 'Wait for the current call to finish before saving settings.'],\n ['无法保存标题设置。', 'Could not save title settings.'],\n ['标题设置无效。', 'Invalid title settings.'],\n ['模型设置同步服务不可用', 'Model settings sync service unavailable'],\n ['模型设置变更消息无效', 'Invalid model settings change frame'],\n ['模型设置同步尚未就绪便收到变更消息', 'Model settings sync change arrived before ready'],\n ['模型设置同步在就绪后中断;请刷新或重新打开页面', 'Model settings sync stream ended after ready; refresh or reopen the page'],\n ['模型设置同步在就绪前中断;请刷新或重新打开页面', 'Model settings sync stream ended before ready; refresh or reopen the page'],\n ['Git 提交模型设置字段不存在', 'Unknown Git Commit model setting'],\n ['Git 提交插件已停用', 'dsh-git-commit: plugin disabled'],\n ['Git 提交设置已变化;请重新加载后重试', 'dsh-git-commit: settings changed; reload and retry'],\n ['安全自动模型设置字段不存在', 'Unknown Safe Auto model setting'],\n ['设置已变化;请重新加载后重试', 'Settings changed; reload and retry'],\n ['请求无效', 'Invalid request'],\n ['此处只能编辑审查设置', 'Only reviewer settings may be edited here'],\n ['配置必须是对象', 'config must be an object'],\n ['启用状态必须是布尔值', 'enabled must be a boolean'],\n ['静态只读开关必须是布尔值', 'staticReadonly must be a boolean'],\n ['审查模型供应商或模型标识无效', 'invalid reviewer provider/model identifier'],\n ['供应商和模型必须一起配置', 'provider and model must be configured together'],\n ['设置思考强度需要先选择审查模型', 'reasoningEffort requires a reviewer model'],\n ['所选模型不支持该思考强度', 'The selected model does not support this reasoning effort'],\n ['启用状态无效', 'Invalid enabled state'],\n ['找不到原生子代理模型选择设置', 'native subagent-model-selection-settings not found'],\n ['路由需要非空的供应商和模型标识', 'A route requires non-empty provider and model ids'],\n ['供应商和模型标识最长 250 字符', 'Route provider and model ids are limited to 250 characters'],\n ['路由思考强度必须是非空字符串', 'A route reasoning effort must be a non-empty string'],\n ['路由思考强度最长 250 字符', 'Route reasoning effort is limited to 250 characters'],\n ['无效的路由下标', 'Invalid route index'],\n ['没有 profile 目录,无法保存任务倾向', 'No profile directory; cast tendencies cannot be stored'],\n ['任务倾向需要非空的供应商和模型标识', 'A tendency requires non-empty provider and model ids'],\n ['任务倾向必须是字符串', 'A tendency must be a string'],\n ['任务倾向最长 500 字符', 'A tendency is limited to 500 characters'],\n ['添加模型后才能启用子代理阵容', 'Add a model before enabling subagent cast'],\n ['任务倾向已变化,请刷新后重试', 'Cast tendencies changed; refresh and retry'],\n ['任务倾向版本已达上限', 'Cast tendency revision limit reached'],\n ['无法读取任务倾向文件;请恢复 cast.json 的访问权限后刷新', 'Cast tendency store cannot be read; restore access to cast.json and refresh'],\n ['任务倾向文件损坏;请修复 cast.json 后刷新', 'Cast tendency store is damaged; repair cast.json and refresh'],\n ['任务倾向文件版本不受支持;请使用兼容的插件再保存', 'Cast tendency store version is unsupported; use a compatible plugin before saving'],\n ['任务倾向文件格式无效;请修复 cast.json 后刷新', 'Cast tendency store schema is invalid; repair cast.json and refresh'],\n ...(['provider', 'model', 'reasoningEffort', 'reviewerPrompt'] as const).map(key => [`${key} 必须是字符串`, `${key} must be a string`] as const),\n ...(['timeoutMs', 'maxInputBytes', 'outputTokens', 'maxReviewsPerTask', 'consecutiveDenials', 'humanApprovalTimeoutMs'] as const).map(key => [`${key} 无效`, `invalid ${key}`] as const),\n] as const\n\nexport function hubMessage(message: string, language: 'zh' | 'en'): string {\n const pair = hubMessages.find(pair => (pair as readonly string[]).includes(message))\n return pair?.[language === 'zh' ? 0 : 1] ?? message\n}\n","/**\n * dsh-model-hub — subagent cast tab. Lists the allowlist of models subagents\n * may pick from, each with an optional free-text task tendency the main agent\n * consults when delegating. Every write goes through the hub host's cast RPC\n * with the native settings revision as CAS; `cast.setTendency` uses its own\n * durable file revision. The page owns its own fetch,\n * subscription and write locking, following the HubPage RequestScope pattern.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'\nimport { Button, Input, Switch } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { modelCatalogFailures, normalizeModelRoute, type ModelRoute } from '@klarkxy/dsh-model-route'\nimport { ModelCatalogStatus } from '@klarkxy/dsh-model-route/ui'\nimport { hubMessage } from './client-copy.ts'\nimport { FieldMenu, checkedCatalog, messageOf } from './client-model-menu.tsx'\nimport type { CastCommit } from './cast.ts'\nimport type { RunningSubagentEntry, RunningSubagentsState } from './running.ts'\nexport type { RunningSubagentEntry, RunningSubagentsState } from './running.ts'\n\n/** One cast entry as served by the host: a concrete route plus its tendency. */\nexport interface CastRoute {\n /** Raw index in the native allowedModels array; the write handle. The host\n * skips malformed entries when reading, so a route's position in `routes`\n * can diverge from this index — always address writes by `index`. */\n index?: number\n provider: string\n model: string\n reasoningEffort?: string\n tendency?: string\n}\n/** Write payload for add/set: the tendency is edited by its own endpoint. */\nexport type CastRouteInput = ModelRoute\nexport interface CastState {\n enabled: boolean\n revision: number\n tendencyRevision?: number\n tendencyError?: string\n routes: CastRoute[]\n}\n\n/** The slice of the hub API this tab needs; the full HubApi extends it. */\nexport interface CastApi {\n getCast(): Promise<CastState>\n setCastEnabled(payload: { enabled: boolean; expectedRevision: number }): Promise<CastCommit>\n addCastRoute(payload: { route: CastRouteInput; expectedRevision: number }): Promise<CastCommit>\n setCastRoute(payload: { index: number; route: CastRouteInput; expectedRevision: number }): Promise<CastCommit>\n removeCastRoute(payload: { index: number; expectedRevision: number }): Promise<CastCommit>\n setCastTendency(payload: { provider: string; model: string; tendency: string; expectedRevision: number }): Promise<CastState>\n listRunning(): Promise<RunningSubagentsState>\n modelCatalog(): Promise<unknown>\n subscribeChanges?(onChange: () => void, onError?: (message: string) => void): () => void\n}\n\n/* One language at a time, chosen from the host locale. */\nconst TEXT = {\n zh: {\n title: '子代理阵容',\n enabledLabel: '启用子代理阵容',\n enabledHint: '此名单限制子代理的显式选模;不指定模型时仍可继承父会话。名单修改对新建会话生效,已有会话及其子代理沿用原名单。任务倾向供委派时参考。',\n loading: '正在读取…',\n failed: (message: string) => `读取失败:${message}`,\n syncFailed: (message: string) => `自动同步不可用:${message}`,\n writeFailed: (message: string) => `未保存:${message}。请刷新后重试。`,\n saved: '已保存。名单修改对新建会话生效。',\n savedRefreshFailed: (message: string) => `已保存;阵容刷新失败:${message}。请刷新以读取最新设置。`,\n conflict: '阵容设置已在别处修改,当前输入保留。请刷新核对后重试。',\n tendencyFailed: (message: string) => `任务倾向不可用:${message}。原文件已保留;修复后刷新。`,\n draftChanged: (saved: string) => `此任务倾向已在别处更新。当前已保存:${saved || '(空)'}。输入已保留;刷新核对后再保存。`,\n refresh: '刷新',\n refreshing: '正在刷新…',\n saving: '正在保存…',\n empty: '先添加模型,再启用显式模型选择。移除最后一个模型会关闭开关。',\n addModel: '添加模型…',\n remove: '移除',\n removeRoute: (label: string) => `移除 ${label}`,\n tendencyLabel: (label: string) => `${label} 的任务倾向`,\n tendencyPlaceholder: '例如:代码审查、快速问答…',\n routeExists: (route: string) => `路由 ${route} 已在列表中`,\n follow: '跟随宿主默认',\n model: '模型',\n effort: '思考强度',\n effortDefault: '默认',\n searchModels: '搜索模型…',\n noModels: '没有匹配的模型',\n clearSearch: '清除搜索',\n runningTitle: '运行中的子代理',\n runningEmpty: '当前没有运行中的子代理。',\n runningPending: '尚未发起模型请求',\n runningRemote: '远程子代理,无法读取路由',\n runningFailed: (message: string) => `运行状态读取失败:${message}`,\n effortAdapterDefault: (effort: string) => `${effort}(适配器默认)`,\n },\n en: {\n title: 'Subagent Cast',\n enabledLabel: 'Enable subagent cast',\n enabledHint: 'This list limits explicit subagent model choices; omitting a model can still inherit the parent session. List changes apply to new conversations. Existing conversations and their subagents keep their saved lists. Task tendencies guide delegation.',\n loading: 'Loading…',\n failed: (message: string) => `Load failed: ${message}`,\n syncFailed: (message: string) => `Live sync unavailable: ${message}`,\n writeFailed: (message: string) => `Not saved: ${message}. Refresh, then try again.`,\n saved: 'Saved. List changes apply to new conversations.',\n savedRefreshFailed: (message: string) => `Saved; cast refresh failed: ${message}. Refresh to read the latest settings.`,\n conflict: 'Cast settings changed elsewhere; your draft is preserved. Refresh, review, then try again.',\n tendencyFailed: (message: string) => `Task tendencies unavailable: ${message}. The original file is preserved; repair it, then refresh.`,\n draftChanged: (saved: string) => `This tendency changed elsewhere. Currently saved: ${saved || '(empty)'}. Your draft is preserved; refresh and review before saving.`,\n refresh: 'Refresh',\n refreshing: 'Refreshing…',\n saving: 'Saving…',\n empty: 'Add a model before enabling explicit model selection. Removing the last model turns the switch off.',\n addModel: 'Add model…',\n remove: 'Remove',\n removeRoute: (label: string) => `Remove ${label}`,\n tendencyLabel: (label: string) => `Task tendency for ${label}`,\n tendencyPlaceholder: 'e.g. code review, quick Q&A…',\n routeExists: (route: string) => `Route ${route} is already in the list`,\n follow: 'Follow host default',\n model: 'Model',\n effort: 'Reasoning',\n effortDefault: 'Default',\n searchModels: 'Search models…',\n noModels: 'No matching models',\n clearSearch: 'Clear search',\n runningTitle: 'Running subagents',\n runningEmpty: 'No subagents are running.',\n runningPending: 'No model request yet',\n runningRemote: 'Remote subagent; route unavailable',\n runningFailed: (message: string) => `Running state failed: ${message}`,\n effortAdapterDefault: (effort: string) => `${effort} (adapter default)`,\n },\n}\n/* Exported so the i18n spec can check zh/en key alignment. */\nexport const castCopy = TEXT\ntype TextKey = keyof typeof TEXT.en\n\ntype LocaleLike = string | { getSnapshot?: () => { active?: string }; subscribe?: (fn: () => void) => () => void } | undefined\nfunction useText(locale: LocaleLike) {\n const subscribe = useCallback((notify: () => void) => typeof locale === 'object' ? locale.subscribe?.(notify) ?? (() => {}) : () => {}, [locale])\n const snapshot = useCallback(() => typeof locale === 'string' ? locale : locale?.getSnapshot?.()?.active ?? 'en', [locale])\n const active = useSyncExternalStore(subscribe, snapshot, snapshot)\n const table = String(active || 'en').toLowerCase().startsWith('zh') ? TEXT.zh : TEXT.en\n return useMemo(() => Object.assign((key: TextKey, ...args: string[]) => {\n const value = table[key]\n return typeof value === 'function' ? (value as (...rest: string[]) => string)(...args) : value\n }, { language: table === TEXT.zh ? 'zh' as const : 'en' as const }), [table])\n}\n\nconst castCss = `\n.dsh-model-hub .cast-head{display:flex;gap:12px;align-items:center;justify-content:space-between;flex-wrap:wrap}\n.dsh-model-hub .cast-row{display:grid;grid-template-columns:minmax(180px,1fr) minmax(160px,1fr) auto;gap:12px;align-items:center;padding:8px 0;border-bottom:.5px solid var(--dsw-alias-border-l1)}\n.dsh-model-hub .cast-row-model{min-width:0}\n.dsh-model-hub .cast-row-model .dsh-model-menu-root{max-width:100%}\n.dsh-model-hub .cast-row-model .dsh-model-menu-trigger{max-width:100%}\n.dsh-model-hub .cast-row-tendency{min-width:0}\n.dsh-model-hub .cast-banner{display:flex;gap:12px;align-items:center;justify-content:space-between;flex-wrap:wrap}\n.dsh-model-hub .cast-add{display:flex}\n.dsh-model-hub .cast-add .dsh-model-menu-root{max-width:100%}\n.dsh-model-hub .cast-running{margin-top:16px}\n.dsh-model-hub .cast-running-title{font-size:14px;line-height:22px;font-weight:600;margin:0 0 4px;color:var(--dsw-alias-label-primary)}\n.dsh-model-hub .cast-running-row{display:flex;gap:12px;align-items:baseline;flex-wrap:wrap;padding:6px 0;border-bottom:.5px solid var(--dsw-alias-border-l1)}\n.dsh-model-hub .cast-running-label{font-size:13px;line-height:20px;color:var(--dsw-alias-label-primary);overflow-wrap:anywhere;min-width:0}\n.dsh-model-hub .cast-running-route{font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;min-width:0}\n@media(max-width:520px){.dsh-model-hub .cast-row{grid-template-columns:minmax(0,1fr);gap:8px}}\n`\n\n/** CAS rejections all carry a refresh hint in either language. */\nfunction isConflict(message: string): boolean {\n return /refresh and retry|reload and retry|刷新后重试|重新加载后重试|请先刷新/i.test(message)\n}\n\n/** The host's duplicate-route error interpolates the route; localize it here. */\nfunction localizeCastError(message: string, t: ReturnType<typeof useText>): string {\n const duplicate = /^Route \"(.+)\" already exists$/.exec(message)\n if (duplicate) return t('routeExists', duplicate[1]!)\n return hubMessage(message, t.language)\n}\n\nfunction routeInput(route: ModelRoute): CastRouteInput {\n const normalized = normalizeModelRoute(route)\n return normalized.reasoningEffort\n ? { provider: normalized.provider, model: normalized.model, reasoningEffort: normalized.reasoningEffort }\n : { provider: normalized.provider, model: normalized.model }\n}\n\ninterface RequestScope { api: CastApi; active: boolean; busy: boolean; queued: boolean }\n\n/** One live subagent row: label (or short id) plus its effective route. */\nfunction runningRouteText(entry: RunningSubagentEntry, t: ReturnType<typeof useText>): string {\n if (!entry.local) return t('runningRemote')\n const route = entry.route\n if (!route) return t('runningPending')\n const effort = route.reasoningEffort\n ? entry.effortIsAdapterDefault ? t('effortAdapterDefault', route.reasoningEffort) : route.reasoningEffort\n : ''\n return `${route.provider} / ${route.model}${effort ? ` · ${effort}` : ''}`\n}\n\n/** One cast entry: model picker, tendency input saved on blur, remove button. */\nfunction CastRow({ t, catalog, route, tendencyRevision, draftReview, disabled, tendencyDisabled, menuDisabled, onSetRoute, onSetTendency, onRemove }: {\n t: ReturnType<typeof useText>\n catalog: unknown\n route: CastRoute\n tendencyRevision: number | undefined\n draftReview: number\n disabled: boolean\n tendencyDisabled: boolean\n menuDisabled: boolean\n onSetRoute: (route: ModelRoute) => void\n onSetTendency: (tendency: string, expectedRevision: number) => void\n onRemove: () => void\n}) {\n const label = `${route.provider} / ${route.model}`\n const saved = route.tendency ?? ''\n const [draft, setDraft] = useState({ text: saved, saved, revision: tendencyRevision, review: draftReview })\n useEffect(() => {\n setDraft(current => {\n if (current.text.trim() === current.saved || current.text.trim() === saved) return { text: saved, saved, revision: tendencyRevision, review: draftReview }\n // Only an explicit user refresh rebases an unsaved draft. Automatic\n // notifications keep the version it was based on, so blur cannot clobber.\n return current.review !== draftReview ? { ...current, saved, revision: tendencyRevision, review: draftReview } : current\n })\n }, [saved, tendencyRevision, draftReview])\n return <div className=\"cast-row\">\n <div className=\"cast-row-model\">\n {/* The native AllowedModelRoute schema is {provider, model} only, so the\n * effort picker stays hidden; an effort carried by older data still\n * round-trips through reads but is dropped when the route is re-picked. */}\n <FieldMenu t={t} catalog={catalog} current={route} label={label} allowFollow={false} reasoningEffort={false} disabled={menuDisabled} onSet={onSetRoute} />\n </div>\n <div className=\"cast-row-tendency\">\n <Input type=\"text\" aria-label={t('tendencyLabel', label)} placeholder={t('tendencyPlaceholder')}\n value={draft.text} disabled={tendencyDisabled} maxLength={500}\n onChange={event => setDraft(current => ({ ...current, text: event.target.value }))}\n onBlur={() => { const tendency = draft.text.trim(); if (!tendencyDisabled && draft.revision !== undefined && tendency !== saved) onSetTendency(tendency, draft.revision) }} />\n {draft.text.trim() !== saved && draft.revision !== tendencyRevision ? <p role=\"status\" className=\"dsh-ui-help dsh-ui-wrap\">{t('draftChanged', saved)}</p> : null}\n </div>\n <Button variant=\"outline\" aria-label={t('removeRoute', label)} disabled={disabled} onClick={onRemove}>{t('remove')}</Button>\n </div>\n}\n\nexport function CastPage({ api, locale }: { api: CastApi; locale: LocaleLike }) {\n const t = useText(locale)\n const [cast, setCast] = useState<CastState | null>(null)\n const [catalog, setCatalog] = useState<unknown>(null)\n const [running, setRunning] = useState<RunningSubagentsState | null>(null)\n const [runningError, setRunningError] = useState('')\n const [loadError, setLoadError] = useState('')\n const [catalogError, setCatalogError] = useState('')\n const [syncError, setSyncError] = useState('')\n const [writeError, setWriteError] = useState('')\n const [saved, setSaved] = useState(false)\n const [conflict, setConflict] = useState(false)\n const [saving, setSaving] = useState('')\n const [refreshing, setRefreshing] = useState(false)\n const [draftReview, setDraftReview] = useState(0)\n const scopeRef = useRef<RequestScope | null>(null)\n const refresh = useCallback(async (scope: RequestScope, reviewDrafts = false) => {\n if (!scope.active) return\n if (scope.busy) { scope.queued = true; return }\n scope.queued = false\n scope.busy = true\n setRefreshing(true)\n // These independent reads all run even when one fails. Retain each last\n // successful result, and never replay a rejected write after refreshing.\n const [castResult, models, live] = await Promise.allSettled([\n Promise.resolve().then(() => scope.api.getCast()),\n Promise.resolve().then(() => scope.api.modelCatalog()).then(checkedCatalog),\n Promise.resolve().then(() => scope.api.listRunning()),\n ])\n if (!scope.active) return\n if (castResult.status === 'fulfilled') {\n setCast(castResult.value); setLoadError(''); setWriteError(''); setConflict(false); setSaved(false)\n if (reviewDrafts) setDraftReview(current => current + 1)\n }\n else setLoadError(messageOf(castResult.reason))\n if (models.status === 'fulfilled') { setCatalog(models.value); setCatalogError('') }\n else setCatalogError(messageOf(models.reason))\n if (live.status === 'fulfilled') { setRunning(live.value); setRunningError('') }\n else setRunningError(messageOf(live.reason))\n scope.busy = false\n setRefreshing(false)\n if (scope.queued) void refresh(scope)\n }, [])\n useEffect(() => {\n const scope: RequestScope = { api, active: true, busy: false, queued: false }\n scopeRef.current = scope\n setSaving('')\n setWriteError('')\n setSaved(false)\n setConflict(false)\n setLoadError('')\n setCatalogError('')\n setSyncError('')\n setCast(null)\n setCatalog(null)\n setRunning(null)\n setRunningError('')\n void refresh(scope)\n const unsubscribe = api.subscribeChanges?.(() => {\n if (!scope.active) return\n setSyncError('')\n void refresh(scope)\n }, message => { if (scope.active) setSyncError(message) })\n return () => { scope.active = false; unsubscribe?.(); scopeRef.current = null }\n }, [api, refresh])\n const mutate = (key: string, run: (scope: RequestScope) => Promise<CastState | CastCommit>) => {\n const scope = scopeRef.current\n if (!scope?.active || scope.api !== api || scope.busy || writeError || (saved && loadError)) return\n // Lock before React's next commit so same-tick selections cannot race CAS.\n scope.busy = true\n setSaved(false)\n setSaving(key)\n Promise.resolve().then(() => run(scope))\n .then(value => {\n if (!scope.active) return\n if ('committed' in value) { setSaved(true); scope.queued = true }\n else setCast(value)\n setWriteError(''); setConflict(false)\n },\n error => { if (scope.active) { const message = messageOf(error); setWriteError(message); setConflict(isConflict(message)) } })\n .finally(() => {\n if (scope.active) {\n scope.busy = false\n setSaving('')\n if (scope.queued) void refresh(scope)\n }\n })\n }\n const refreshNow = async () => {\n const scope = scopeRef.current\n if (scope?.api === api && !scope.busy) await refresh(scope, true)\n }\n const disabled = saving !== '' || refreshing || writeError !== '' || (saved && loadError !== '')\n const catalogStatus = {\n loading: refreshing,\n error: catalogError ? hubMessage(catalogError, t.language) : '',\n failures: modelCatalogFailures(catalog),\n refresh: refreshNow,\n }\n /* The root also carries the hub root class so officialUiCss('dsh-model-hub')\n * and castCss (both scoped under .dsh-model-hub) still apply when CastPage\n * renders outside HubPage's own subtree. */\n return <div className=\"cast-root dsh-model-hub dsh-ui-stack\" aria-label={t('title')} aria-busy={saving !== '' || refreshing}>\n <style>{castCss}</style>\n <div className=\"cast-head\">\n <Switch checked={cast?.enabled ?? false} label={t('enabledLabel')} disabled={disabled || cast === null || (!cast.enabled && cast.routes.length === 0)}\n onChange={next => { if (cast) mutate('enabled', scope => scope.api.setCastEnabled({ enabled: next, expectedRevision: cast.revision })) }} />\n <Button variant=\"ghost\" disabled={saving !== '' || refreshing} onClick={refreshNow}>{refreshing ? t('refreshing') : t('refresh')}</Button>\n </div>\n <p className=\"dsh-ui-help\">{t('enabledHint')}</p>\n {loadError ? <p role=\"alert\" className=\"dsh-ui-error dsh-ui-wrap\">{t(saved ? 'savedRefreshFailed' : 'failed', hubMessage(loadError, t.language))}</p> : null}\n {cast?.tendencyError ? <p role=\"alert\" className=\"dsh-ui-error dsh-ui-wrap\">{t('tendencyFailed', hubMessage(cast.tendencyError, t.language))}</p> : null}\n {syncError ? <p role=\"alert\" className=\"dsh-ui-error dsh-ui-wrap\">{t('syncFailed', hubMessage(syncError, t.language))}</p> : null}\n <ModelCatalogStatus state={catalogStatus} locale={t.language} />\n {writeError ? <div className=\"dsh-ui-banner dsh-ui-banner--danger cast-banner\" role=\"alert\">\n <span className=\"dsh-ui-wrap\">{conflict ? t('conflict') : t('writeFailed', localizeCastError(writeError, t))}</span>\n <Button variant=\"outline\" size=\"sm\" disabled={saving !== '' || refreshing} onClick={refreshNow}>{refreshing ? t('refreshing') : t('refresh')}</Button>\n </div> : null}\n {saving ? <p role=\"status\" className=\"dsh-ui-help\">{t('saving')}</p> : null}\n {saved && !loadError ? <p role=\"status\" className=\"dsh-ui-help\">{t('saved')}</p> : null}\n {cast === null && !loadError ? <p className=\"dsh-ui-loading\">{t('loading')}</p> : null}\n {cast !== null && cast.routes.length === 0 ? <p className=\"dsh-ui-help\">{t('empty')}</p> : null}\n {cast?.routes.map((route, position) => {\n /* Writes address the host's raw route index; fall back to the array\n * position only for contract-conforming hosts that omit it. */\n const handle = route.index ?? position\n return <CastRow key={JSON.stringify([route.provider, route.model])}\n t={t} catalog={catalog} route={route}\n tendencyRevision={cast.tendencyRevision} draftReview={draftReview}\n tendencyDisabled={disabled || !!cast.tendencyError || cast.tendencyRevision === undefined}\n disabled={disabled} menuDisabled={disabled || catalog === null}\n onSetRoute={next => mutate(`route:${handle}`, scope => scope.api.setCastRoute({ index: handle, route: routeInput(next), expectedRevision: cast.revision }))}\n onSetTendency={(tendency, expectedRevision) => mutate(`tendency:${handle}`, scope => scope.api.setCastTendency({ provider: route.provider, model: route.model, tendency, expectedRevision }))}\n onRemove={() => mutate(`remove:${handle}`, scope => scope.api.removeCastRoute({ index: handle, expectedRevision: cast.revision }))}\n />\n })}\n {cast !== null ? <div className=\"cast-add\">\n <FieldMenu t={t} catalog={catalog} current={undefined} label={t('addModel')} allowFollow={false} followLabel={t('addModel')}\n reasoningEffort={false} disabled={disabled || catalog === null}\n onSet={picked => mutate('add', scope => scope.api.addCastRoute({ route: routeInput(picked), expectedRevision: cast.revision }))} />\n </div> : null}\n <section className=\"cast-running\" aria-label={t('runningTitle')}>\n <h3 className=\"cast-running-title\">{t('runningTitle')}</h3>\n {runningError ? <p role=\"alert\" className=\"dsh-ui-error dsh-ui-wrap\">{t('runningFailed', hubMessage(runningError, t.language))}</p> : null}\n {running === null && !runningError ? <p className=\"dsh-ui-loading\">{t('loading')}</p> : null}\n {running !== null && running.entries.length === 0 ? <p className=\"dsh-ui-help\">{t('runningEmpty')}</p> : null}\n {running?.entries.map(entry => <div key={entry.id} className=\"cast-running-row\">\n <span className=\"cast-running-label\">{entry.label || entry.id}</span>\n <span className=\"cast-running-route\">{runningRouteText(entry, t)}</span>\n </div>)}\n </section>\n </div>\n}\n","/**\n * dsh-model-hub — browser half. One settings-page section listing every\n * detected model-route field across plugins. Each row is edited with the\n * contract's standard ModelMenu (dsh-model-route/ui) and written back through\n * the hub's host RPC — `settings.mutate` on the host, CAS by descriptor\n * revision. An empty route means \"follow the host default\" and unsets the\n * field.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'\nimport { Button, Input, SegmentedTabs } from '@deepseek-ai/dsh-client-ui-primitives'\nimport {\n MODEL_CATALOG_INJECT, modelCatalogFailures, normalizeModelRoute, parseModelMenuChoices, readModelCatalog, type ModelRoute,\n} from '@klarkxy/dsh-model-route'\nimport { ModelCatalogStatus, modelMenuCss } from '@klarkxy/dsh-model-route/ui'\nimport { officialUiCss } from '@klarkxy/dsh-plugin-kit/official-ui'\nimport { modelSettingsChangesIdentity } from '@klarkxy/dsh-plugin-kit/contracts'\nimport { createModelSettingsSubscriber, mountModelSettingsChanges, type ModelSettingsSubscriberContext } from '@klarkxy/dsh-plugin-kit/model-settings-client'\nimport type { ModelSettingsText } from '@klarkxy/dsh-plugin-kit/model-settings'\nimport { FieldMenu, catalogFailures, checkedCatalog, messageOf } from './client-model-menu.tsx'\nexport { FieldMenu, catalogFailures } from './client-model-menu.tsx'\nimport type { FieldCommit } from './owners.ts'\nimport { hubMessage, hubText } from './client-copy.ts'\nimport { CastPage, type CastApi } from './client-cast.tsx'\n\nexport const name = 'dsh-model-hub-client'\nexport const inject = ['slots', 'connection', ...MODEL_CATALOG_INJECT, 'locale']\nexport const CHANNEL = '/dsh-model-hub'\nexport const BUNDLE = '@klarkxy/dsh-model-hub'\n\n/* One language at a time, chosen from the host locale. */\nconst TEXT = {\n zh: {\n title: '模型枢纽',\n intro: '一页查看并修改各插件的模型路由;改动立即写入对应插件自己的设置。',\n tabsLabel: '模型枢纽分区',\n tabFields: '字段总览',\n tabCast: '子代理阵容',\n loading: '正在读取…',\n empty: '没有检测到模型字段。',\n failed: (message: string) => `读取失败:${message}`,\n syncFailed: (message: string) => `自动同步不可用:${message}`,\n catalogFailed: (message: string) => `模型列表读取失败:${message}`,\n writeFailed: (message: string) => `未保存:${message}。请刷新后重新选择。`,\n saved: '已保存,正在刷新…',\n savedRefreshFailed: (message: string) => `已保存;页面刷新失败:${message}。请刷新以读取最新设置。`,\n refresh: '刷新',\n refreshing: '正在刷新…',\n saving: '正在保存…',\n search: '搜索插件、字段或当前模型…',\n noFields: '没有匹配的模型字段',\n follow: '跟随宿主默认',\n restorePluginDefault: '恢复插件默认',\n model: '模型',\n effort: '思考强度',\n effortDefault: '默认',\n searchModels: '搜索模型…',\n noModels: '没有匹配的模型',\n clearSearch: '清除搜索',\n collectionTemplate: '集合中没有可编辑的条目;请先在所属插件中添加条目。',\n items: '条目',\n },\n en: {\n title: 'Model Hub',\n intro: \"View and edit every plugin's model route on one page; changes write into the owning plugin's own settings at once.\",\n tabsLabel: 'Model Hub sections',\n tabFields: 'Fields',\n tabCast: 'Subagent Cast',\n loading: 'Loading…',\n empty: 'No model fields detected.',\n failed: (message: string) => `Load failed: ${message}`,\n syncFailed: (message: string) => `Live sync unavailable: ${message}`,\n catalogFailed: (message: string) => `Model list failed: ${message}`,\n writeFailed: (message: string) => `Not saved: ${message}. Refresh, then choose again.`,\n saved: 'Saved; refreshing…',\n savedRefreshFailed: (message: string) => `Saved; page refresh failed: ${message}. Refresh to read the latest settings.`,\n refresh: 'Refresh',\n refreshing: 'Refreshing…',\n saving: 'Saving…',\n search: 'Search plugins, fields or current models…',\n noFields: 'No matching model fields',\n follow: 'Follow host default',\n restorePluginDefault: 'Restore plugin default',\n model: 'Model',\n effort: 'Reasoning',\n effortDefault: 'Default',\n searchModels: 'Search models…',\n noModels: 'No matching models',\n clearSearch: 'Clear search',\n collectionTemplate: 'No collection item to edit. Add an item in the owning plugin first.',\n items: 'Items',\n },\n}\ntype TextKey = keyof typeof TEXT.en\n\ntype LocaleLike = string | { getSnapshot?: () => { active?: string }; subscribe?: (fn: () => void) => () => void } | undefined\nfunction useText(locale: LocaleLike) {\n const subscribe = useCallback((notify: () => void) => typeof locale === 'object' ? locale.subscribe?.(notify) ?? (() => {}) : () => {}, [locale])\n const snapshot = useCallback(() => typeof locale === 'string' ? locale : locale?.getSnapshot?.()?.active ?? 'en', [locale])\n const active = useSyncExternalStore(subscribe, snapshot, snapshot)\n const table = String(active || 'en').toLowerCase().startsWith('zh') ? TEXT.zh : TEXT.en\n return useMemo(() => Object.assign((key: TextKey, ...args: string[]) => {\n const value = table[key]\n return typeof value === 'function' ? (value as (...rest: string[]) => string)(...args) : value\n }, { language: table === TEXT.zh ? 'zh' as const : 'en' as const }), [table])\n}\n\nexport interface HubField {\n path: string[]\n via: 'marker' | 'shape' | 'contribution'\n marker?: { purpose?: string; label?: ModelSettingsText; reasoningEffort?: boolean }\n label?: ModelSettingsText\n description?: ModelSettingsText\n allowFollow?: boolean\n followLabel?: string | { zh: string; en: string }\n supportsReasoning?: false\n current?: ModelRoute\n editable?: false\n arrayItem?: true\n}\nexport interface HubEntry {\n ns: string\n title?: ModelSettingsText\n source?: 'owner'\n ownerId?: string\n catalog?: unknown\n error?: ModelSettingsText\n catalogError?: ModelSettingsText\n revision: number\n fields: HubField[]\n}\n\nexport interface HubApi extends CastApi {\n list(): Promise<HubEntry[]>\n setField(payload: { ns: string; path: string[]; route: unknown; expectedRevision: number; ownerId?: string }): Promise<FieldCommit>\n}\n\nconst css = `${officialUiCss('dsh-model-hub')}${modelMenuCss}\n.dsh-model-hub .hub-toolbar{display:flex;gap:12px;align-items:center}\n.dsh-model-hub .hub-search{flex:1;min-width:0}\n.dsh-model-hub .hub-group{min-width:0}\n.dsh-model-hub .hub-group-head{display:flex;gap:8px;align-items:baseline;flex-wrap:wrap;margin:12px 0 4px}\n.dsh-model-hub .hub-group-title{font-size:14px;line-height:22px;font-weight:600;margin:0;color:var(--dsw-alias-label-primary)}\n.dsh-model-hub .hub-namespace{font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere}\n.dsh-model-hub .hub-row{display:grid;grid-template-columns:minmax(140px,1fr) minmax(180px,1fr);gap:16px;align-items:center;padding:8px 0;border-bottom:.5px solid var(--dsw-alias-border-l1)}\n.dsh-model-hub .hub-row-copy{min-width:0}\n.dsh-model-hub .hub-row-label{font-size:13px;line-height:20px;color:var(--dsw-alias-label-primary);overflow-wrap:anywhere}\n.dsh-model-hub .hub-row-description{font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;margin:2px 0 0}\n.dsh-model-hub .hub-editor{min-width:0;display:flex;justify-content:flex-end}\n.dsh-model-hub .hub-editor .dsh-model-menu-root{max-width:100%}\n.dsh-model-hub .hub-editor .dsh-model-menu-trigger{max-width:100%}\n@media(max-width:520px){.dsh-model-hub .hub-toolbar{gap:8px}.dsh-model-hub .hub-row{grid-template-columns:minmax(0,1fr);gap:4px}.dsh-model-hub .hub-editor{justify-content:flex-start}.dsh-model-hub .hub-namespace{width:100%}}\n`\nfunction Style() {\n return <style>{css}</style>\n}\n\n\nfunction humanize(value: string): string {\n const text = value.replace(/([a-z\\d])([A-Z])/g, '$1 $2').replace(/[-_.]+/g, ' ').trim()\n return text.charAt(0).toUpperCase() + text.slice(1)\n}\n\nfunction fieldLabel(field: HubField, t: ReturnType<typeof useText>): string {\n return hubText(field.marker?.label || field.label, t.language) || field.path.map(part => part === '[]' ? t('items') : part === 'model' ? t('model') : /^\\d+$/.test(part) ? `#${Number(part) + 1}` : humanize(part)).join(' / ')\n}\n\nfunction followLabel(field: HubField, t: ReturnType<typeof useText>): string {\n return typeof field.followLabel === 'string' ? field.followLabel : field.followLabel?.[t.language]\n || t(field.via === 'contribution' || field.arrayItem ? 'follow' : 'restorePluginDefault')\n}\n\nfunction pluginTitle(entry: HubEntry, t: ReturnType<typeof useText>): string {\n return hubText(entry.title, t.language) || humanize((entry.ns.split('/').at(-1) || entry.ns).replace(/^dsh-/, ''))\n}\n\n\ninterface RequestScope { api: HubApi; active: boolean; busy: boolean; queued: boolean }\n\nexport function HubPage({ view, api, locale, initialEntries = null, initialCatalog = null }: {\n view?: string\n api: HubApi\n locale: LocaleLike\n initialEntries?: HubEntry[] | null\n initialCatalog?: unknown\n}) {\n const t = useText(locale)\n const [entries, setEntries] = useState<HubEntry[] | null>(initialEntries)\n const [catalog, setCatalog] = useState<unknown>(initialCatalog)\n const [listError, setListError] = useState('')\n const [catalogError, setCatalogError] = useState('')\n const [writeError, setWriteError] = useState('')\n const [saved, setSaved] = useState(false)\n const [syncError, setSyncError] = useState('')\n const [writing, setWriting] = useState('')\n const [refreshing, setRefreshing] = useState(false)\n const [query, setQuery] = useState('')\n const [tab, setTab] = useState<'fields' | 'cast'>('fields')\n const scopeRef = useRef<RequestScope | null>(null)\n const refresh = useCallback(async (scope: RequestScope) => {\n if (!scope.active) return\n if (scope.busy) { scope.queued = true; return }\n scope.queued = false\n scope.busy = true\n setRefreshing(true)\n // These independent reads both run even when one fails. Retain each last\n // successful result, and never replay a rejected write after refreshing.\n const [fields, models] = await Promise.allSettled([\n Promise.resolve().then(() => scope.api.list()),\n Promise.resolve().then(() => scope.api.modelCatalog()).then(checkedCatalog),\n ])\n if (!scope.active) return\n if (fields.status === 'fulfilled') { setEntries(fields.value); setListError(''); setWriteError(''); setSaved(false) }\n else setListError(messageOf(fields.reason))\n if (models.status === 'fulfilled') { setCatalog(models.value); setCatalogError('') }\n else setCatalogError(messageOf(models.reason))\n scope.busy = false\n setRefreshing(false)\n if (scope.queued) void refresh(scope)\n }, [])\n useEffect(() => {\n if (view === 'summary') return\n const scope: RequestScope = { api, active: true, busy: false, queued: false }\n scopeRef.current = scope\n setWriting('')\n setWriteError('')\n setSaved(false)\n setListError('')\n setCatalogError('')\n setSyncError('')\n setEntries(initialEntries)\n setCatalog(initialCatalog)\n void refresh(scope)\n const unsubscribe = api.subscribeChanges?.(() => {\n if (!scope.active) return\n setSyncError('')\n void refresh(scope)\n }, message => { if (scope.active) setSyncError(message) })\n return () => { scope.active = false; unsubscribe?.(); scopeRef.current = null }\n // Initial data seeds a new API lifetime; it is not a subscription.\n }, [api, view, refresh])\n const setRoute = (entry: HubEntry, field: HubField, route: ModelRoute) => {\n const scope = scopeRef.current\n if (!scope?.active || scope.api !== api || scope.busy || writeError) return\n const key = `${entry.ns}:${field.path.join('.')}`\n // Lock before React's next commit so same-tick selections cannot race CAS.\n scope.busy = true\n setSaved(false)\n setWriting(key)\n Promise.resolve().then(() => scope.api.setField({ ns: entry.ns, path: field.path, route, expectedRevision: entry.revision, ...(entry.ownerId ? { ownerId: entry.ownerId } : {}) }))\n .then(() => { if (scope.active) { setSaved(true); setWriteError(''); scope.queued = true } },\n error => { if (scope.active) setWriteError(messageOf(error)) })\n .finally(() => {\n if (scope.active) {\n scope.busy = false\n setWriting('')\n if (scope.queued) void refresh(scope)\n }\n })\n }\n if (view === 'summary') {\n return <div className=\"dsh-model-hub\" lang={t.language}><Style /><p className=\"dsh-ui-compact dsh-ui-wrap\">{t('intro')}</p></div>\n }\n const needle = query.trim().toLocaleLowerCase()\n /* The native subagent cast settings live on their own tab below; the fields\n * matrix must not offer a second editor for the same data. */\n const groups = (entries ?? []).map(entry => ({ ...entry, fields: entry.fields.filter(field =>\n !(entry.ns === BUNDLE && field.path.length === 1 && ['selfTestMeta', 'selfTestRole'].includes(field.path[0] || ''))) }))\n .filter(entry => entry.ns !== 'subagent-model-selection-settings' && (entry.fields.length > 0 || entry.error || entry.catalogError))\n const visible = groups.map(entry => ({ ...entry, fields: entry.fields.filter(field => {\n if (!needle) return true\n const route = normalizeModelRoute(field.current)\n const model = parseModelMenuChoices(entry.catalog !== undefined ? entry.catalog : catalog, route).find(choice => choice.provider === route.provider && choice.model === route.model)?.label || ''\n return [entry.ns, pluginTitle(entry, t), fieldLabel(field, t), hubText(field.description, t.language), field.path.join('.'), route.provider, route.model, model, !route.model ? followLabel(field, t) : '']\n .some(text => text?.toLocaleLowerCase().includes(needle))\n }) })).filter(entry => entry.fields.length > 0 || ((entry.error || entry.catalogError) && (!needle || [entry.ns, pluginTitle(entry, t)].some(text => text.toLocaleLowerCase().includes(needle)))))\n const disabled = writing !== '' || refreshing || writeError !== '' || (saved && listError !== '')\n const refreshNow = async () => {\n const scope = scopeRef.current\n // A status retry uses the same coordinated read and cannot queue behind a\n // write or rebase a descriptor until the current operation has settled.\n if (scope?.api === api && !scope.busy) await refresh(scope)\n }\n const catalogStatus = {\n loading: refreshing,\n error: catalogError ? hubMessage(catalogError, t.language) : '',\n failures: modelCatalogFailures(catalog),\n refresh: refreshNow,\n }\n return <section className=\"dsh-model-hub dsh-ui-page\" lang={t.language} aria-label={t('title')} aria-busy={writing !== '' || refreshing}>\n <Style />\n <SegmentedTabs<'fields' | 'cast'>\n value={tab}\n onChange={setTab}\n label={t('tabsLabel')}\n className=\"hub-tabs\"\n items={[\n { value: 'fields', label: t('tabFields'), id: 'dsh-model-hub-tab-fields', panelId: 'dsh-model-hub-panel-fields' },\n { value: 'cast', label: t('tabCast'), id: 'dsh-model-hub-tab-cast', panelId: 'dsh-model-hub-panel-cast' },\n ]}\n />\n <div role=\"tabpanel\" id=\"dsh-model-hub-panel-fields\" aria-labelledby=\"dsh-model-hub-tab-fields\" hidden={tab !== 'fields'} className=\"dsh-ui-stack\">\n <div className=\"hub-toolbar\">\n <Input className=\"hub-search\" type=\"search\" aria-label={t('search')} placeholder={t('search')} value={query} onChange={event => setQuery(event.target.value)} />\n <Button variant=\"ghost\" disabled={writing !== '' || refreshing} onClick={refreshNow}>{refreshing ? t('refreshing') : t('refresh')}</Button>\n </div>\n {listError ? <p role=\"alert\" className=\"dsh-ui-error dsh-ui-wrap\">{t(saved ? 'savedRefreshFailed' : 'failed', hubMessage(listError, t.language))}</p> : null}\n {syncError ? <p role=\"alert\" className=\"dsh-ui-error dsh-ui-wrap\">{t('syncFailed', hubMessage(syncError, t.language))}</p> : null}\n <ModelCatalogStatus state={catalogStatus} locale={t.language} />\n {writeError ? <p role=\"alert\" className=\"dsh-ui-error dsh-ui-wrap\">{t('writeFailed', hubMessage(writeError, t.language))}</p> : null}\n {writing ? <p role=\"status\" className=\"dsh-ui-help\">{t('saving')}</p> : null}\n {saved && !listError ? <p role=\"status\" className=\"dsh-ui-help\">{t('saved')}</p> : null}\n {entries === null && !listError ? <p className=\"dsh-ui-loading\">{t('loading')}</p> : null}\n {entries !== null && groups.length === 0 ? <p className=\"dsh-ui-help\">{t('empty')}</p> : null}\n {groups.length > 0 && visible.length === 0 ? <p className=\"dsh-ui-help\">{t('noFields')}</p> : null}\n {visible.map(entry => <section key={entry.ns} className=\"hub-group\" aria-label={pluginTitle(entry, t)}>\n <div className=\"hub-group-head\"><h3 className=\"hub-group-title\">{pluginTitle(entry, t)}</h3><span className=\"hub-namespace\">{entry.ns}</span></div>\n {entry.error ? <p role=\"alert\" className=\"dsh-ui-error dsh-ui-wrap\">{t('failed', hubMessage(hubText(entry.error, t.language), t.language))}</p> : null}\n {entry.catalogError ? <p role=\"alert\" className=\"dsh-ui-error dsh-ui-wrap\">{t('catalogFailed', hubMessage(hubText(entry.catalogError, t.language), t.language))}</p> : null}\n {entry.catalog !== undefined ? catalogFailures(entry.catalog).map((failure, index) => <p key={index} role=\"alert\" className=\"dsh-ui-error dsh-ui-wrap\">{t('catalogFailed', hubMessage(failure, t.language))}</p>) : null}\n {entry.fields.map(field => {\n const key = `${entry.ns}:${field.path.join('.')}`\n const label = fieldLabel(field, t)\n return <div key={key} className=\"hub-row\">\n <div className=\"hub-row-copy\"><div className=\"hub-row-label\">{label}</div>\n {field.description ? <p className=\"hub-row-description\">{hubText(field.description, t.language)}</p> : null}</div>\n <div className=\"hub-editor\">{field.editable === false ? field.description ? null : <span className=\"dsh-ui-help\">{t('collectionTemplate')}</span> : <FieldMenu\n t={t}\n catalog={entry.catalog !== undefined ? entry.catalog : catalog}\n current={field.current}\n label={label}\n allowFollow={field.allowFollow}\n followLabel={followLabel(field, t)}\n reasoningEffort={field.supportsReasoning === false ? false : field.marker?.reasoningEffort}\n disabled={disabled || !!entry.error || !!entry.catalogError || (entry.catalog === undefined && catalog === null)}\n onSet={route => setRoute(entry, field, route)}\n />}</div>\n </div>\n })}\n </section>)}\n </div>\n <div role=\"tabpanel\" id=\"dsh-model-hub-panel-cast\" aria-labelledby=\"dsh-model-hub-tab-cast\" hidden={tab !== 'cast'}>\n {tab === 'cast' ? <CastPage api={api} locale={locale} /> : null}\n </div>\n </section>\n}\n\ninterface HubClientContext {\n slots: {\n inject(name: string, callback: () => unknown): unknown\n register(options: unknown, component: unknown): unknown\n }\n connection: { rpc: { call(channel: string, endpoint: string, payload: unknown): Promise<{ ok: boolean; value?: unknown; error?: { message?: string } }> } }\n remote: { session: { modelCatalog(): Promise<unknown> } }\n effect(callback: () => () => void | Promise<void>): unknown\n locale: LocaleLike\n}\n\nexport function apply(ctx: unknown): void {\n const client = ctx as unknown as HubClientContext\n mountModelSettingsChanges(ctx as ModelSettingsSubscriberContext, BUNDLE)\n const changes = createModelSettingsSubscriber(ctx as ModelSettingsSubscriberContext, BUNDLE, modelSettingsChangesIdentity(BUNDLE), () => true)\n const call = async (endpoint: string, payload: unknown): Promise<never> => {\n const result = await client.connection.rpc.call(CHANNEL, endpoint, payload)\n if (!result?.ok) throw new Error(result?.error?.message || 'Request failed')\n return result.value as never\n }\n const api: HubApi = Object.freeze({\n list: () => call('fields.list', {}),\n setField: (payload: { ns: string; path: string[]; route: unknown; expectedRevision: number; ownerId?: string }) => call('fields.set', payload),\n modelCatalog: () => readModelCatalog(client),\n subscribeChanges: changes.subscribe,\n getCast: () => call('cast.get', {}),\n setCastEnabled: (payload: { enabled: boolean; expectedRevision: number }) => call('cast.setEnabled', payload),\n addCastRoute: (payload: { route: unknown; expectedRevision: number }) => call('cast.addRoute', payload),\n setCastRoute: (payload: { index: number; route: unknown; expectedRevision: number }) => call('cast.setRoute', payload),\n removeCastRoute: (payload: { index: number; expectedRevision: number }) => call('cast.removeRoute', payload),\n setCastTendency: (payload: { provider: string; model: string; tendency: string; expectedRevision: number }) => call('cast.setTendency', payload),\n listRunning: () => call('cast.running', {}),\n })\n client.slots.inject('plugins.bundle.config', () => client.slots.register({\n name: 'plugins.bundle.config', key: BUNDLE, inject: () => ({ api, locale: (ctx as { locale?: LocaleLike }).locale }),\n }, HubPage))\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.inner.cjs","names":["asText","createElement","Button","useRef","useState","useId","useMemo","rankByName","observeStickyMenuGroups","createPortal","MenuSurface","IconChevronRightOutlineRegular","Input","IconCloseFillRegular","IconCheckOutlineRegular","MenuGroup","isValidElement","cloneElement","useState","useMemo","IconChevronDownOutlineRegular","TEXT","useText","useCallback","useSyncExternalStore","useMemo","useState","Input","Button","useRef","checkedCatalog","Switch","useCallback","useSyncExternalStore","css","useState","IconRefreshOutlineRegular","IconChevronRightOutlineRegular","StateDot","Tooltip","useMemo","useRef","IconChevronDownOutlineRegular","createPortal"],"sources":["../../dsh-plugin-kit/src/official-ui.ts","../../dsh-model-route/src/route.ts","../../dsh-model-route/src/catalog.ts","../../dsh-model-route/src/menu.ts","../../dsh-plugin-kit/src/contracts.ts","../../dsh-plugin-kit/src/client-utils.ts","../../dsh-plugin-kit/src/model-settings-client.ts","../../dsh-model-route/src/catalog-ui.tsx","../../dsh-model-route/src/ui.tsx","../src/client-copy.ts","../src/client-model-menu.tsx","../src/client-cast.tsx","../src/client-subagent-catalog.tsx","../src/client.tsx"],"sourcesContent":["/**\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","/**\n * Shared model-route value contract.\n *\n * A feature plugin stores its model override as a ModelRoute on its own\n * settings page. Empty provider/model means \"follow the host default model\".\n * Pure and browser-safe: no cordis, no React, no schema library.\n */\n\n/** A concrete provider model a feature call should use. */\nexport interface ModelRoute {\n provider: string\n model: string\n reasoningEffort?: string\n}\n\n/** Empty route: no explicit model, the feature follows the host default. */\nexport function defaultModelRoute(): ModelRoute {\n return { provider: '', model: '' }\n}\n\n/** Structural check: both id fields are strings (either may be empty). */\nexport function isModelRouteValue(value: unknown): value is ModelRoute {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false\n const row = value as Record<string, unknown>\n return typeof row.provider === 'string' && typeof row.model === 'string'\n}\n\nconst MAX_ID_CHARS = 250\nconst MAX_EFFORT_CHARS = 80\n\nfunction asText(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() ? value.trim() : undefined\n}\n\n/**\n * Coerce a stored value into a ModelRoute. Anything malformed collapses to the\n * empty route, matching the per-plugin normalizers this contract replaces.\n */\nexport function normalizeModelRoute(value: unknown): ModelRoute {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return defaultModelRoute()\n const row = value as Record<string, unknown>\n const provider = asText(row.provider) ?? ''\n const model = asText(row.model) ?? ''\n const effort = asText(row.reasoningEffort)\n if (!provider || !model || provider.length > MAX_ID_CHARS || model.length > MAX_ID_CHARS) return defaultModelRoute()\n return effort && effort.length <= MAX_EFFORT_CHARS ? { provider, model, reasoningEffort: effort } : { provider, model }\n}\n\n/** The override to actually call with: undefined when the route is empty. */\nexport function modelRouteOverride(route: ModelRoute | undefined): ModelRoute | undefined {\n const provider = route?.provider?.trim()\n const model = route?.model?.trim()\n if (!provider || !model) return undefined\n const effort = route?.reasoningEffort?.trim()\n return effort ? { provider, model, reasoningEffort: effort } : { provider, model }\n}\n\nconst KEY_SEPARATOR = '\\u001f'\n\n/** Stable key for one route, safe to use as a select-option value. */\nexport function modelRouteKey(provider: string, model: string): string {\n return provider && model ? `${provider}${KEY_SEPARATOR}${model}` : ''\n}\n\n/** Inverse of modelRouteKey; undefined for malformed keys. */\nexport function parseModelRouteKey(value: string): { provider: string; model: string } | undefined {\n const index = value.indexOf(KEY_SEPARATOR)\n if (index <= 0) return undefined\n const provider = value.slice(0, index)\n const model = value.slice(index + KEY_SEPARATOR.length)\n if (!provider || !model) return undefined\n return { provider, model }\n}\n\n/** True when both routes name the same target; two empty routes are equal. */\nexport function sameModelRoute(a: ModelRoute | undefined, b: ModelRoute | undefined): boolean {\n const left = modelRouteOverride(a)\n const right = modelRouteOverride(b)\n if (!left || !right) return !left === !right\n return left.provider === right.provider && left.model === right.model\n && (left.reasoningEffort ?? '') === (right.reasoningEffort ?? '')\n}\n","/**\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 type { ContextFormed } from '@deepseek-ai/dsh-llm'\nimport { modelRouteOverride, 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\n/**\n * Shared \"Session Management\" settings section id. The section is provided by\n * shared infrastructure (see `registerSessionSettingsItem` in `client-utils`),\n * not by any one business plugin: every participant registers only a row into\n * {@link SESSION_SETTINGS_ITEM_SLOT}, so any enabled subset yields the same page.\n */\nexport const SESSION_SETTINGS_SECTION_ID = 'session-manager'\n\n/**\n * Child list slot declared by the shared Session Management page. Neutral\n * naming on purpose: participants never import each other, they only\n * contribute `{id, order}` rows into this slot while the page is alive.\n */\nexport const SESSION_SETTINGS_ITEM_SLOT = 'dsh.session-settings.item'\n\n/**\n * Host-owned nav icon seat: a root-scoped list where each entry's `id` must\n * equal the `settings.section` id it decorates. Owner props are\n * `{size, active}`; icons stay `aria-hidden` so the section label remains the\n * accessible name. Contributors into a shared section may register the same\n * icon `id` with different priorities — the ledger keeps every entry while the\n * host renders one icon per section.\n */\nexport const SETTINGS_SECTION_ICON_SLOT = 'settings.section.icon'\n\n/* Shared auxiliary-model default. Feature plugins may store a global default\n * route that fills the tier between their own saved override and the live\n * session model. The durable state is a root-context singleton (like the\n * shared session-settings page): it exists while any participant retains it\n * and is never owned by a business plugin. See `auxiliary-model.ts`. */\n\n/** Root context service key holding the shared auxiliary-model state. */\nexport const AUXILIARY_MODEL_SERVICE = 'dshAuxiliaryModel'\n\n/** Authenticated host-RPC channel for get/set of the shared default. */\nexport const AUXILIARY_MODEL_CHANNEL = '/dsh-auxiliary-model'\n\n/** Model-settings namespace under which the shared default is published. */\nexport const AUXILIARY_MODEL_NS = '@klarkxy/dsh-plugin-kit/auxiliary-model'\n\n/**\n * Typert identity of the shared change stream. Mounted on the root context\n * with ownerNs filtering, so frames only carry {@link AUXILIARY_MODEL_NS}.\n */\nexport const AUXILIARY_MODEL_CHANGES_IDENTITY = modelSettingsChangesIdentity('@klarkxy/dsh-plugin-kit')\n\n/** The value the shared default persists: `model: null` means follow the live session/host model. */\nexport interface AuxiliaryModelDefaults {\n readonly revision: number\n readonly model: ModelRoute | null\n}\n\n/** Shape of the root singleton; produced and owned by `auxiliary-model.ts`. */\nexport interface AuxiliaryModelShared {\n readonly ready: Promise<void>\n snapshot(): AuxiliaryModelDefaults\n}\n\nfunction sharedAuxiliaryModel(host: unknown): AuxiliaryModelShared | undefined {\n const root = (host as { root?: unknown } | undefined)?.root as { get?(name: string, strict?: boolean): unknown } | undefined\n try {\n const shared = root?.get?.(AUXILIARY_MODEL_SERVICE, false) as AuxiliaryModelShared | undefined\n return shared && typeof shared.snapshot === 'function' ? shared : undefined\n } catch { return undefined }\n}\n\n/**\n * Synchronously read the shared auxiliary default; `undefined` only when no\n * participant retains the singleton or the default is legitimately unset.\n * An initialization or snapshot failure propagates: silently falling back to\n * a different model after a storage error would spend the wrong budget.\n */\nexport function getAuxiliaryModel(host: unknown): ModelRoute | undefined {\n const shared = sharedAuxiliaryModel(host)\n if (!shared) return undefined\n return modelRouteOverride(shared.snapshot().model ?? undefined)\n}\n","import type { Context } from '@deepseek-ai/cordis'\nimport { createElement, useCallback, useEffect, useRef, useSyncExternalStore, type ReactNode } from 'react'\nimport { SESSION_SETTINGS_ITEM_SLOT, SESSION_SETTINGS_SECTION_ID, SETTINGS_SECTION_ICON_SLOT } from './contracts.ts'\n\n/** Fixed pause for failing background reads; manual work is never replayed. */\nexport function createPluginReadGate(now: () => number = Date.now) {\n let pausedUntil = 0\n let epoch = 0\n return {\n canRead: () => now() >= pausedUntil,\n reset: () => { epoch++; pausedUntil = 0 },\n async run<T>(read: () => Promise<T>): Promise<T> {\n const current = epoch\n try {\n const value = await read()\n if (current === epoch) pausedUntil = 0\n return value\n } catch (error) {\n // The native Connection error is an Error with this exact HTTP text.\n // Authentication, application failures, and cancellation stay distinct.\n const message = error instanceof Error ? error.message : ''\n if (current === epoch && (/(?:^|\\s)transport failure for .+: HTTP (?:404|405|503)\\b/.test(message)\n || (error instanceof TypeError && /^(?:Failed to fetch|fetch failed|NetworkError when attempting to fetch resource\\.?)$/i.test(message)))) {\n pausedUntil = now() + 30_000\n }\n throw error\n }\n },\n }\n}\n\nexport interface NativeSurfaceClient {\n sessions: {\n binding?(sessionId: string): { eventSource: { subscribe(listener: () => void): () => void } } | undefined\n }\n uiWorkspace: { current?: { getSnapshot(): { sessionId: string } | undefined; subscribe(listener: () => void): () => void } }\n uiSession: { adapter: { current: { getSnapshot(): { key?: string }; subscribe(listener: () => void): () => void } } }\n locale: { getSnapshot(): { active: string }; subscribe(listener: () => void): () => void }\n connection?: { generation?: { subscribe(listener: () => void): () => void } }\n}\n\n/** The Editor retains its manuscript session separately; native DSH exposes the main-view binding. */\nexport function selectedSessionId(client: Pick<NativeSurfaceClient, 'uiWorkspace' | 'uiSession'>): string {\n const workspace = client.uiWorkspace?.current\n return workspace\n ? workspace.getSnapshot()?.sessionId ?? ''\n : client.uiSession.adapter.current.getSnapshot().key ?? ''\n}\n\n/**\n * Owner props are data the host composed, never a Cordis context: reading an\n * undeclared property off one throws instead of returning undefined, which\n * would crash the slot entry and abdicate its cell for good. Tolerate a\n * throwing read so a mistaken prop degrades to \"not supplied\".\n */\nfunction read(source: unknown, key: string): unknown {\n if (source === null || typeof source !== 'object') return undefined\n try {\n return (source as Record<string, unknown>)[key]\n } catch {\n return undefined\n }\n}\n\nfunction readString(source: unknown, key: string): string | undefined {\n const value = read(source, key)\n return typeof value === 'string' ? value : undefined\n}\n\n/** Owner props win; native settings only supplies close, so resolve its selected session. */\nexport function useNativeSeat(client: NativeSurfaceClient, props?: unknown) {\n const current = useSyncExternalStore(\n useCallback((fn: () => void) => (client.uiWorkspace?.current ?? client.uiSession.adapter.current).subscribe(fn), [client]),\n useCallback(() => selectedSessionId(client), [client]),\n () => '',\n )\n const language = useSyncExternalStore(\n useCallback((fn: () => void) => client.locale.subscribe(fn), [client]),\n useCallback(() => client.locale.getSnapshot().active, [client]),\n () => 'en',\n )\n const sessionId = readString(props, 'sessionId') ?? readString(read(props, 'owner'), 'sessionId') ?? current\n const requestedLocale = read(props, 'locale') ?? read(read(props, 'owner'), 'locale') ?? language\n return { sessionId, locale: (String(requestedLocale).startsWith('zh') ? 'zh' : 'en') as 'zh' | 'en',\n hidden: read(props, 'hidden') === true || read(read(props, 'owner'), 'hidden') === true }\n}\n\n/** Refresh on native log boundaries/reconnect/focus. Read-only settling is bounded to an observed job. */\nexport function useFeatureRefresh(\n client: NativeSurfaceClient, sessionId: string, refresh: () => void,\n working = false, enabled = true,\n): void {\n const refreshRef = useRef(refresh)\n refreshRef.current = refresh\n useEffect(() => {\n if (!enabled) return\n let timer: ReturnType<typeof setTimeout> | undefined\n const queue = () => {\n if (typeof document !== 'undefined' && document.visibilityState === 'hidden') return\n clearTimeout(timer)\n timer = setTimeout(() => refreshRef.current(), 150)\n }\n const source = sessionId ? client.sessions.binding?.(sessionId)?.eventSource : undefined\n const stopEvents = source?.subscribe(queue)\n const stopConnection = client.connection?.generation?.subscribe(queue)\n const visibility = () => { if (document.visibilityState === 'visible') queue() }\n window.addEventListener('focus', queue)\n document.addEventListener('visibilitychange', visibility)\n // Details are collapsed by default; opening an existing panel must get current state.\n document.addEventListener('toggle', queue, true)\n return () => {\n clearTimeout(timer)\n stopEvents?.(); stopConnection?.()\n window.removeEventListener('focus', queue)\n document.removeEventListener('visibilitychange', visibility)\n document.removeEventListener('toggle', queue, true)\n }\n }, [client, sessionId, enabled])\n useEffect(() => {\n if (!enabled || !working) return\n let delay = 250\n const until = Date.now() + 300_000\n let timer: ReturnType<typeof setTimeout>\n const tick = () => {\n if (Date.now() >= until) return\n if (document.visibilityState !== 'hidden') refreshRef.current()\n delay = Math.min(delay * 2, 2000)\n timer = setTimeout(tick, delay)\n }\n timer = setTimeout(tick, delay)\n return () => clearTimeout(timer)\n }, [client, sessionId, working, enabled])\n}\n\n/* Shared \"Session Management\" settings page. The page is root-owned shared\n * infrastructure, not a business plugin: any participant alone yields the same\n * section, and participants never import each other. Synchronization crosses\n * separately bundled copies of this helper through the Cordis root context —\n * `root.get`/`root.provide` is the only rendezvous, so no window global or\n * module singleton is needed and no participant depends on another being enabled.\n */\n\n/** A row contributed into the shared Session Management page. */\nexport interface SessionSettingsItemSpec {\n readonly id: string\n readonly order: number\n}\n\n/* Original line icons for settings-section navigation seats. The official\n * `dsh-client-ui-primitives` icon set covers generic glyphs only; these keep\n * the same conventions (16×16 viewBox, 1px stroke, round caps, currentColor)\n * so the plugin set stays visually consistent with the native nav. Colors\n * never appear here: `currentColor` lets the host style the active state, and\n * `aria-hidden` keeps the section label the single accessible name. */\n\n/** Owner props the host's `settings.section.icon` seat hands to its cell. */\nexport interface SettingsSectionIconProps {\n readonly size?: number\n /** Selection state; the nav styles active icons through color, not geometry. */\n readonly active?: boolean\n}\n\ntype IconChild = readonly [tag: string, attrs: Record<string, string | number>]\n\n/** One `<svg>` with the shared icon chrome; children are plain elements. */\nfunction lineIcon(children: IconChild[]) {\n return function SettingsSectionIcon(props: SettingsSectionIconProps): ReactNode {\n return createElement('svg', {\n 'aria-hidden': 'true',\n width: props.size ?? 16,\n height: props.size ?? 16,\n viewBox: '0 0 16 16',\n fill: 'none',\n stroke: 'currentColor',\n strokeWidth: 1,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n }, ...children.map(([tag, attrs], index) => createElement(tag, { key: index, ...attrs })))\n }\n}\n\n/** Chat bubble for the shared Session Management section. */\nexport const IconSessionSettings = lineIcon([\n ['path', { d: 'M8.5 13a5.5 5.5 0 0 0 5.5-5.5A5.5 5.5 0 0 0 8.5 2 5.5 5.5 0 0 0 3 7.5a5.48 5.48 0 0 0 .9 3L2.8 12.6a.5.5 0 0 0 .62.62l2.9-.98a5.48 5.48 0 0 0 2.18.76Z' }],\n])\n\n/** Serif-flavoured letter A for the Font section. */\nexport const IconFontSettings = lineIcon([\n ['path', { d: 'M3.3 12.6 7.9 3.1a.5.5 0 0 1 .9 0l4.6 9.5' }],\n ['path', { d: 'M5.2 9.4h6.3' }],\n ['path', { d: 'M2.4 12.6h2.4' }],\n ['path', { d: 'M11.9 12.6h2.4' }],\n])\n\n/** Keyboard for the Shortcuts section. */\nexport const IconKeyboardSettings = lineIcon([\n ['rect', { x: 1.75, y: 4.75, width: 12.5, height: 7.5, rx: 1.2 }],\n ['path', { d: 'M4.5 7.25h0' }],\n ['path', { d: 'M8 7.25h0' }],\n ['path', { d: 'M11.5 7.25h0' }],\n ['path', { d: 'M5.25 9.75h5.5' }],\n])\n\n/** Linked model nodes for the Model Management section. */\nexport const IconModelNetworkSettings = lineIcon([\n ['line', { x1: 10.6, y1: 5.3, x2: 8.8, y2: 7.1 }],\n ['line', { x1: 7.2, y1: 8.9, x2: 5.4, y2: 10.7 }],\n ['circle', { cx: 12, cy: 4, r: 1.9 }],\n ['circle', { cx: 4, cy: 12, r: 1.9 }],\n ['circle', { cx: 8, cy: 8, r: 1.5 }],\n])\n\n/**\n * Contribute the nav icon of a `settings.section` entry. The `settings\n * .section.icon` seat is declared by the host independently of the section\n * list, so the wait runs in parallel: the icon appears as soon as both seats\n * exist and unloading removes it again, restoring the host's default glyph.\n * The `id` must equal the section id; `order`/`priority` mirror `order` so the\n * icon cell sorts like its section and, for shared sections, several\n * contributors can register the same icon id under different priorities\n * without duplicating nav entries.\n */\nexport function registerSettingsSectionIcon(\n ctx: Context,\n sectionId: string,\n order: number,\n component: (props: SettingsSectionIconProps) => ReactNode,\n): () => void {\n const slots = (ctx as unknown as { slots: SessionSettingsSlots }).slots\n return slots.inject(SETTINGS_SECTION_ICON_SLOT, () =>\n slots.register({ name: SETTINGS_SECTION_ICON_SLOT, id: sectionId, order, priority: order }, component))\n}\n\ninterface SessionSettingsSlots {\n inject(key: string, callback: () => Iterable<(() => void) | void> | (() => void) | void): () => void\n register(spec: Record<string, unknown>, render: unknown): () => void\n}\n\ninterface SessionSettingsRoot {\n get(name: string, strict?: boolean): unknown\n provide(name: string, value: unknown): () => void\n readonly slots?: SessionSettingsSlots\n}\n\n/** Private Cordis rendezvous; every bundled copy of this helper resolves the same root service. */\nconst SESSION_SETTINGS_PAGE_SERVICE = 'dshSessionSettingsPage'\n\ninterface SessionSettingsPage {\n retain(): void\n release(): void\n}\n\n/** The page component renders only its declared child list: items paint their own titles and styles. */\nfunction SessionSettingsPageView(props: { renderSlot: (key: string, owner: Record<string, never>) => ReactNode }): ReactNode {\n return props.renderSlot(SESSION_SETTINGS_ITEM_SLOT, {})\n}\n\n/**\n * Acquire the root-owned page service, creating and providing it on first use.\n * One counter covers participants, the section wait and the provider: the last\n * release removes the wait and then the provider synchronously (Cordis deletes\n * the impl before its async disposer awaits), so a later acquire sees a clean\n * get() miss and can re-establish the page.\n */\nfunction acquireSessionSettingsPage(root: SessionSettingsRoot): SessionSettingsPage {\n const existing = root.get(SESSION_SETTINGS_PAGE_SERVICE, false) as SessionSettingsPage | undefined\n if (existing) return existing\n const slots = root.slots as SessionSettingsSlots\n let users = 0\n let stopPage: (() => void) | undefined\n let unprovide: (() => void) | undefined\n const page: SessionSettingsPage = {\n retain() {\n // The reservation is counted before the throwing install, so a failure\n // lets the caller's release() undo it fully instead of leaking the service.\n users += 1\n if (!stopPage) {\n stopPage = slots.inject('settings.section', () => slots.register(\n {\n name: 'settings.section',\n id: SESSION_SETTINGS_SECTION_ID,\n order: 30,\n label: () => {\n const locale = root.get('locale', false) as { getSnapshot?(): { active?: unknown } } | undefined\n return String(locale?.getSnapshot?.().active ?? '').startsWith('zh') ? '会话管理' : 'Session Management'\n },\n children: { [SESSION_SETTINGS_ITEM_SLOT]: { kind: 'list', scope: 'root' } },\n },\n SessionSettingsPageView,\n ))\n }\n },\n release() {\n if (users <= 0) return\n users -= 1\n if (users > 0) return\n // The last contributor tears the section down; collapsing its children\n // declaration clears the item slot for every other bundle as well.\n stopPage?.()\n stopPage = undefined\n unprovide?.()\n },\n }\n unprovide = root.provide(SESSION_SETTINGS_PAGE_SERVICE, page)\n return page\n}\n\n/**\n * Contribute one row to the shared Session Management settings page.\n *\n * `ctx` is the plugin's own context: the row's slot wait unloads with the\n * plugin, while the page itself is retained on the shared root context for as\n * long as any contributor lives. There is no fallback seat — when every\n * contributor is gone the section disappears with the page. Returns a disposer.\n * Shared root-owned infrastructure (the auxiliary-model card) calls this on\n * `ctx.root` so its row, icon and page share are owned by the root lifetime\n * and released by the returned disposer, not by any plugin fiber.\n */\nexport function registerSessionSettingsItem(\n ctx: Context,\n item: SessionSettingsItemSpec,\n component: (props: never) => ReactNode,\n): () => void {\n const slots = (ctx as unknown as { slots: SessionSettingsSlots }).slots\n const root = ctx.root as unknown as SessionSettingsRoot\n const page = acquireSessionSettingsPage(root)\n let stopItem: (() => void) | undefined\n let stopIcon: (() => void) | undefined\n try {\n page.retain()\n stopItem = slots.inject(SESSION_SETTINGS_ITEM_SLOT, () => slots.register({ name: SESSION_SETTINGS_ITEM_SLOT, ...item }, component))\n // Every contributor also waits on the nav-icon seat, registering the same\n // section icon id under its own priority (its row order). Same-id entries\n // coexist on the ledger while the host renders one icon, so no contributor\n // owns the icon and none depends on another for it; the wait lives with\n // this ctx, so it fires now on fresh loads and retro-fills on HMR.\n stopIcon = slots.inject(SETTINGS_SECTION_ICON_SLOT, () => slots.register(\n { name: SETTINGS_SECTION_ICON_SLOT, id: SESSION_SETTINGS_SECTION_ID, order: item.order, priority: item.order },\n IconSessionSettings,\n ))\n } catch (error) {\n // A synchronous failure (for example a duplicate row id or a failing page\n // install) must not pin the shared page for a contributor that never joined.\n stopIcon?.()\n stopItem?.()\n page.release()\n throw error\n }\n // The disposer may be invoked by both ctx.effect and an explicit caller;\n // releasing twice would unbalance the shared refcount.\n let disposed = false\n return () => {\n if (disposed) return\n disposed = true\n stopIcon?.()\n stopItem?.()\n page.release()\n }\n}\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 { 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","import type { ModelSettingsText } from '@klarkxy/dsh-plugin-kit/model-settings'\n\nexport function hubText(value: ModelSettingsText | undefined, language: 'zh' | 'en'): string {\n return typeof value === 'string' ? value : value?.[language] ?? ''\n}\n\n/** Local validation defaults, without rewriting provider diagnostics. */\nexport const hubMessages = [\n ['请求失败', 'Request failed'],\n ['字段引用无效', 'Invalid field reference'],\n ['请先刷新,以获取有效的设置版本', 'A valid expected revision is required; refresh and retry'],\n ['模型路由无效', 'Invalid model route'],\n ['模型设置提供方已变化,请刷新后重试', 'Model settings owner changed; refresh and retry'],\n ['设置已变化,请刷新后重试', 'Settings changed; refresh and retry'],\n ['此模型字段不可编辑', 'Not an editable model field'],\n ['此设置需要选择具体模型', 'This model setting requires a concrete model'],\n ['模型设置提供方已卸载,请刷新后重试', 'Model settings owner unloaded; refresh and retry'],\n ['自测字段仅用于诊断', 'Self-test fields are diagnostic only'],\n ['提供方设置版本无效', 'Invalid owner revision'],\n ['未检测到此模型字段', 'Not a detected model field'],\n ['没有可编辑的集合条目', 'No collection item to edit'],\n ['设置版本无效', 'Invalid revision'],\n ['ChatGPT 需要 Codex 模型', 'ChatGPT requires a Codex model'],\n ['Codex 模型目录不可用。', 'Codex model catalog is unavailable.'],\n ['配置已在别处修改,请刷新后重试。', 'Settings changed elsewhere. Refresh and try again.'],\n ['设置已更新,请刷新后重试。', 'Settings changed. Refresh and try again.'],\n ['正在保存配置,请稍后重试。', 'Settings are being saved. Try again shortly.'],\n ['ChatGPT 插件已卸载。', 'The ChatGPT plugin has been unloaded.'],\n ['配置格式无效。', 'Invalid settings format.'],\n ['请等当前调用完成后保存配置。', 'Wait for the current call to finish before saving settings.'],\n ['无法保存标题设置。', 'Could not save title settings.'],\n ['标题设置无效。', 'Invalid title settings.'],\n ['模型设置同步服务不可用', 'Model settings sync service unavailable'],\n ['模型设置变更消息无效', 'Invalid model settings change frame'],\n ['模型设置同步尚未就绪便收到变更消息', 'Model settings sync change arrived before ready'],\n ['模型设置同步在就绪后中断;请刷新或重新打开页面', 'Model settings sync stream ended after ready; refresh or reopen the page'],\n ['模型设置同步在就绪前中断;请刷新或重新打开页面', 'Model settings sync stream ended before ready; refresh or reopen the page'],\n ['Git 提交模型设置字段不存在', 'Unknown Git Commit model setting'],\n ['Git 提交插件已停用', 'dsh-git-commit: plugin disabled'],\n ['Git 提交设置已变化;请重新加载后重试', 'dsh-git-commit: settings changed; reload and retry'],\n ['安全自动模型设置字段不存在', 'Unknown Safe Auto model setting'],\n ['设置已变化;请重新加载后重试', 'Settings changed; reload and retry'],\n ['请求无效', 'Invalid request'],\n ['此处只能编辑审查设置', 'Only reviewer settings may be edited here'],\n ['配置必须是对象', 'config must be an object'],\n ['启用状态必须是布尔值', 'enabled must be a boolean'],\n ['静态只读开关必须是布尔值', 'staticReadonly must be a boolean'],\n ['审查模型供应商或模型标识无效', 'invalid reviewer provider/model identifier'],\n ['供应商和模型必须一起配置', 'provider and model must be configured together'],\n ['设置思考强度需要先选择审查模型', 'reasoningEffort requires a reviewer model'],\n ['所选模型不支持该思考强度', 'The selected model does not support this reasoning effort'],\n ['启用状态无效', 'Invalid enabled state'],\n ['找不到原生子代理模型选择设置', 'native subagent-model-selection-settings not found'],\n ['路由需要非空的供应商和模型标识', 'A route requires non-empty provider and model ids'],\n ['供应商和模型标识最长 250 字符', 'Route provider and model ids are limited to 250 characters'],\n ['路由思考强度必须是非空字符串', 'A route reasoning effort must be a non-empty string'],\n ['路由思考强度最长 250 字符', 'Route reasoning effort is limited to 250 characters'],\n ['无效的路由下标', 'Invalid route index'],\n ['没有 profile 目录,无法保存任务倾向', 'No profile directory; cast tendencies cannot be stored'],\n ['任务倾向需要非空的供应商和模型标识', 'A tendency requires non-empty provider and model ids'],\n ['任务倾向必须是字符串', 'A tendency must be a string'],\n ['任务倾向最长 500 字符', 'A tendency is limited to 500 characters'],\n ['添加模型后才能启用子代理阵容', 'Add a model before enabling subagent cast'],\n ['任务倾向已变化,请刷新后重试', 'Cast tendencies changed; refresh and retry'],\n ['任务倾向版本已达上限', 'Cast tendency revision limit reached'],\n ['无法读取任务倾向文件;请恢复 cast.json 的访问权限后刷新', 'Cast tendency store cannot be read; restore access to cast.json and refresh'],\n ['任务倾向文件损坏;请修复 cast.json 后刷新', 'Cast tendency store is damaged; repair cast.json and refresh'],\n ['任务倾向文件版本不受支持;请使用兼容的插件再保存', 'Cast tendency store version is unsupported; use a compatible plugin before saving'],\n ['任务倾向文件格式无效;请修复 cast.json 后刷新', 'Cast tendency store schema is invalid; repair cast.json and refresh'],\n ...(['provider', 'model', 'reasoningEffort', 'reviewerPrompt'] as const).map(key => [`${key} 必须是字符串`, `${key} must be a string`] as const),\n ...(['timeoutMs', 'maxInputBytes', 'outputTokens', 'maxReviewsPerTask', 'consecutiveDenials', 'humanApprovalTimeoutMs'] as const).map(key => [`${key} 无效`, `invalid ${key}`] as const),\n] as const\n\nexport function hubMessage(message: string, language: 'zh' | 'en'): string {\n const pair = hubMessages.find(pair => (pair as readonly string[]).includes(message))\n return pair?.[language === 'zh' ? 0 : 1] ?? message\n}\n","import { useEffect, useMemo, useState } from 'react'\nimport { IconChevronDownOutlineRegular } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { modelMenuEffortLabel, modelMenuEffortOptions, modelMenuShortName, normalizeModelRoute, parseModelMenuChoices, type ModelRoute } from '@klarkxy/dsh-model-route'\nimport { ModelMenu } from '@klarkxy/dsh-model-route/ui'\n\n/** The text surface FieldMenu needs; both the fields tab and the cast tab supply it. */\nexport interface FieldMenuText {\n (key: 'follow' | 'effortDefault' | 'model' | 'effort' | 'searchModels' | 'noModels' | 'clearSearch'): string\n language: 'zh' | 'en'\n}\n\n/**\n * One detected field's standard editor: the same ModelMenu every marked field gets.\n *\n * `display: 'short'` shows only the model name on the trigger; the accessible\n * name and the title keep the full provider/model route so two providers that\n * ship the same model name stay distinguishable. Picking another model keeps\n * the current reasoning effort when the new model advertises it, so switching a\n * route does not silently reset the user's choice.\n */\nexport function FieldMenu({ t, catalog, current, disabled, label, allowFollow = true, followLabel, reasoningEffort = true, display = 'full', onSet }: {\n t: FieldMenuText\n catalog: unknown\n current: ModelRoute | undefined\n disabled: boolean\n label: string\n allowFollow?: boolean\n followLabel?: string\n reasoningEffort?: boolean\n display?: 'full' | 'short'\n onSet: (route: ModelRoute) => void\n}) {\n const [open, setOpen] = useState(false)\n useEffect(() => { if (disabled) setOpen(false) }, [disabled])\n const route = normalizeModelRoute(current)\n const follow = !route.provider || !route.model\n const choices = useMemo(() => parseModelMenuChoices(catalog, follow ? undefined : route), [catalog, follow, route.provider, route.model])\n const selected = follow ? undefined : choices.find(choice => choice.provider === route.provider && choice.model === route.model)\n const efforts = follow || !reasoningEffort ? [] : modelMenuEffortOptions(selected, route.reasoningEffort || '')\n const menuLabel = follow ? followLabel || t('follow') : selected?.label ?? `${route.provider} / ${route.model}`\n /* The full route stays in the accessible name and the tooltip; the button\n * itself may show only the model name. */\n const routeLabel = follow ? menuLabel : `${route.provider} / ${route.model}`\n const accessible = label === routeLabel ? routeLabel : `${label}: ${routeLabel}`\n const currentLabel = display === 'short' && !follow ? (selected ? modelMenuShortName(selected) : route.model) : menuLabel\n const selectedEffort = efforts.find(item => item.id === (route.reasoningEffort || ''))\n const effortName = selectedEffort ? modelMenuEffortLabel(selectedEffort, t.language) : undefined\n return <ModelMenu\n locale={t.language}\n open={open && !disabled}\n onOpenChange={next => setOpen(next && !disabled)}\n listClassName=\"dsh-model-hub\"\n anchor={<button type=\"button\" className=\"dsh-model-menu-trigger\" disabled={disabled} aria-label={accessible} title={routeLabel} aria-haspopup=\"menu\" aria-expanded={open && !disabled}>\n <span className=\"dsh-model-menu-triggerLabel\">{currentLabel}</span>\n {!follow && efforts.length ? <span className=\"dsh-model-menu-triggerEffort\">{` · ${effortName ?? t('effortDefault')}`}</span> : null}\n <IconChevronDownOutlineRegular className={`dsh-model-menu-chevron${open ? ' dsh-model-menu-chevronOpen' : ''}`} />\n </button>}\n choices={choices}\n selected={follow ? undefined : { provider: route.provider, model: route.model }}\n onPick={picked => {\n /* Keep the current effort when the new model lists it; an effort the new\n * model does not support is dropped rather than carried into a route\n * that cannot honour it. */\n const choice = choices.find(item => item.provider === picked.provider && item.model === picked.model)\n const effort = route.reasoningEffort\n const supported = Boolean(effort) && Boolean(choice?.efforts.some(item => item.id === effort))\n onSet({ provider: picked.provider, model: picked.model, ...(supported ? { reasoningEffort: effort } : {}) })\n }}\n leading={allowFollow ? [{ id: 'follow', label: followLabel || t('follow'), selected: follow }] : []}\n onPickLeading={() => onSet({ provider: '', model: '' })}\n efforts={efforts}\n selectedEffort={route.reasoningEffort || ''}\n onPickEffort={effort => onSet(follow\n ? { provider: '', model: '' }\n : { provider: route.provider, model: route.model, ...(effort ? { reasoningEffort: effort } : {}) })}\n modelLabel={t('model')}\n modelValue={currentLabel}\n effortLabel={t('effort')}\n defaultEffortLabel={t('effortDefault')}\n searchPlaceholder={t('searchModels')}\n emptyLabel={t('noModels')}\n clearSearchLabel={t('clearSearch')}\n />\n}\n\n\nexport function messageOf(error: unknown): string {\n if (error instanceof Error) return error.message\n if (error && typeof error === 'object' && 'message' in error) return String(error.message)\n return String(error)\n}\n\n// Preserve the hub's helper exports while keeping catalog validation and failure\n// decoding in the shared route contract used by both pages.\nexport { checkedModelCatalog as checkedCatalog, catalogFailures } from '@klarkxy/dsh-model-route'\n","/**\n * dsh-model-hub — subagent configuration page.\n *\n * Lists the allowlist of models subagents may pick from. Each row carries the\n * model, its reasoning effort and an optional free-text task tendency the main\n * agent consults when delegating.\n *\n * Writes are split by owner: the native settings CAS owns provider and model\n * (the native schema strips a reasoning effort), while the plugin's own file\n * CAS owns the per-route effort and tendency. A preference write answers with\n * the committed state, so the page never waits for a later refresh that could\n * still carry the previous value.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'\nimport { Button, Input, Switch } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { modelCatalogFailures, normalizeModelRoute, type ModelRoute } from '@klarkxy/dsh-model-route'\nimport { ModelCatalogStatus } from '@klarkxy/dsh-model-route/ui'\nimport { hubMessage } from './client-copy.ts'\nimport { FieldMenu, checkedCatalog, messageOf } from './client-model-menu.tsx'\nimport type { CastCommit } from './cast.ts'\n\n/**\n * Settings namespaces this page watches. The native route list and the\n * plugin-side preference store are its own scope; unrelated model-settings\n * traffic (for example a running subagent's route refresh) must not re-read it.\n * The literals mirror `CAST_NAMESPACE` and `CAST_TENDENCIES_NAMESPACE` in\n * cast.ts, which the browser half cannot import (it is host-only code).\n */\nexport const CAST_WATCH_NAMESPACES = ['subagent-model-selection-settings', '@klarkxy/dsh-model-hub/cast-tendencies'] as const\n\n/** One cast entry as served by the host: a concrete route plus its preferences. */\nexport interface CastRoute {\n /** Raw index in the native allowedModels array; the write handle. The host\n * skips malformed entries when reading, so a route's position in `routes`\n * can diverge from this index — always address writes by `index`. */\n index?: number\n provider: string\n model: string\n /** Plugin-side preference; the native schema never carries it. */\n reasoningEffort?: string\n tendency?: string\n}\n/** Write payload for add/set: the native CAS owns provider and model only. */\nexport interface CastRouteInput { provider: string; model: string }\nexport interface CastState {\n enabled: boolean\n revision: number\n tendencyRevision?: number\n tendencyError?: string\n routes: CastRoute[]\n}\n\n/** The slice of the hub API this page needs; the full HubApi extends it. */\nexport interface CastApi {\n getCast(): Promise<CastState>\n setCastEnabled(payload: { enabled: boolean; expectedRevision: number }): Promise<CastCommit>\n addCastRoute(payload: { route: CastRouteInput; expectedRevision: number }): Promise<CastCommit>\n setCastRoute(payload: { index: number; route: CastRouteInput; expectedRevision: number }): Promise<CastCommit>\n removeCastRoute(payload: { index: number; expectedRevision: number }): Promise<CastCommit>\n setCastTendency(payload: { provider: string; model: string; tendency: string; expectedRevision: number }): Promise<CastState>\n /** Saves the plugin-side preferences of one route and answers with the\n * committed state, so the page shows the saved value at once. */\n setCastRoutePreferences(payload: {\n provider: string\n model: string\n preferences: { tendency?: string; reasoningEffort?: string }\n expectedRevision: number\n }): Promise<CastState>\n modelCatalog(): Promise<unknown>\n subscribeChanges?(onChange: () => void, onError?: (message: string) => void): () => void\n}\n\n/* One language at a time, chosen from the host locale. */\nconst TEXT = {\n zh: {\n title: '子代理配置',\n enabledLabel: '启用子代理选模',\n enabledHint: '配置新建子代理的模型与思考强度。名单修改对新建会话生效,已有会话沿用原名单。',\n loading: '正在读取…',\n failed: (message: string) => `读取失败:${message}`,\n syncFailed: (message: string) => `自动同步不可用:${message}`,\n writeFailed: (message: string) => `未保存:${message}。请刷新后重试。`,\n saved: '已保存。',\n savedRefreshFailed: (message: string) => `已保存;配置刷新失败:${message}。请刷新以读取最新设置。`,\n conflict: '配置已在别处修改,当前输入保留。请刷新核对后重试。',\n tendencyFailed: (message: string) => `任务倾向不可用:${message}。原文件已保留;修复后刷新。`,\n draftChanged: (saved: string) => `此任务倾向已在别处更新。当前已保存:${saved || '(空)'}。输入已保留;刷新核对后再保存。`,\n refresh: '刷新',\n refreshing: '正在刷新…',\n saving: '正在保存…',\n empty: '先添加模型,再启用显式模型选择。移除最后一个模型会关闭开关。',\n addModel: '添加模型…',\n remove: '移除',\n removeRoute: (label: string) => `移除 ${label}`,\n tendencyLabel: (label: string) => `${label} 的任务倾向`,\n tendencyPlaceholder: '例如:代码审查、快速问答…',\n routeExists: (route: string) => `路由 ${route} 已在列表中`,\n follow: '跟随宿主默认',\n model: '模型',\n effort: '思考强度',\n effortDefault: '默认',\n searchModels: '搜索模型…',\n noModels: '没有匹配的模型',\n clearSearch: '清除搜索',\n },\n en: {\n title: 'Subagent configuration',\n enabledLabel: 'Enable subagent model selection',\n enabledHint: 'Configure the model and reasoning effort for new subagents. List changes apply to new conversations; existing conversations keep their saved list.',\n loading: 'Loading…',\n failed: (message: string) => `Load failed: ${message}`,\n syncFailed: (message: string) => `Live sync unavailable: ${message}`,\n writeFailed: (message: string) => `Not saved: ${message}. Refresh, then try again.`,\n saved: 'Saved.',\n savedRefreshFailed: (message: string) => `Saved; configuration refresh failed: ${message}. Refresh to read the latest settings.`,\n conflict: 'Settings changed elsewhere; your draft is preserved. Refresh, review, then try again.',\n tendencyFailed: (message: string) => `Task tendencies unavailable: ${message}. The original file is preserved; repair it, then refresh.`,\n draftChanged: (saved: string) => `This tendency changed elsewhere. Currently saved: ${saved || '(empty)'}. Your draft is preserved; refresh and review before saving.`,\n refresh: 'Refresh',\n refreshing: 'Refreshing…',\n saving: 'Saving…',\n empty: 'Add a model before enabling explicit model selection. Removing the last model turns the switch off.',\n addModel: 'Add model…',\n remove: 'Remove',\n removeRoute: (label: string) => `Remove ${label}`,\n tendencyLabel: (label: string) => `Task tendency for ${label}`,\n tendencyPlaceholder: 'e.g. code review, quick Q&A…',\n routeExists: (route: string) => `Route ${route} is already in the list`,\n follow: 'Follow host default',\n model: 'Model',\n effort: 'Reasoning',\n effortDefault: 'Default',\n searchModels: 'Search models…',\n noModels: 'No matching models',\n clearSearch: 'Clear search',\n },\n}\n/* Exported so the i18n spec can check zh/en key alignment. */\nexport const castCopy = TEXT\ntype TextKey = keyof typeof TEXT.en\n\ntype LocaleLike = string | { getSnapshot?: () => { active?: string }; subscribe?: (fn: () => void) => () => void } | undefined\nfunction useText(locale: LocaleLike) {\n const subscribe = useCallback((notify: () => void) => typeof locale === 'object' ? locale.subscribe?.(notify) ?? (() => {}) : () => {}, [locale])\n const snapshot = useCallback(() => typeof locale === 'string' ? locale : locale?.getSnapshot?.()?.active ?? 'en', [locale])\n const active = useSyncExternalStore(subscribe, snapshot, snapshot)\n const table = String(active || 'en').toLowerCase().startsWith('zh') ? TEXT.zh : TEXT.en\n return useMemo(() => Object.assign((key: TextKey, ...args: string[]) => {\n const value = table[key]\n return typeof value === 'function' ? (value as (...rest: string[]) => string)(...args) : value\n }, { language: table === TEXT.zh ? 'zh' as const : 'en' as const }), [table])\n}\n\nconst castCss = `\n.dsh-model-hub .cast-head{display:flex;gap:12px;align-items:center;justify-content:space-between;flex-wrap:wrap}\n.dsh-model-hub .cast-row{display:grid;grid-template-columns:minmax(180px,1fr) minmax(160px,1fr) auto;gap:12px;align-items:center;padding:8px 0;border-bottom:.5px solid var(--dsw-alias-border-l1)}\n.dsh-model-hub .cast-row-model{min-width:0}\n.dsh-model-hub .cast-row-model .dsh-model-menu-root{max-width:100%}\n.dsh-model-hub .cast-row-model .dsh-model-menu-trigger{max-width:100%}\n.dsh-model-hub .cast-row-tendency{min-width:0}\n.dsh-model-hub .cast-banner{display:flex;gap:12px;align-items:center;justify-content:space-between;flex-wrap:wrap}\n.dsh-model-hub .cast-add{display:flex}\n.dsh-model-hub .cast-add .dsh-model-menu-root{max-width:100%}\n@media(max-width:520px){.dsh-model-hub .cast-row{grid-template-columns:minmax(0,1fr);gap:8px}}\n`\n\n/** CAS rejections all carry a refresh hint in either language. */\nfunction isConflict(message: string): boolean {\n return /refresh and retry|reload and retry|刷新后重试|重新加载后重试|请先刷新/i.test(message)\n}\n\n/** The host's duplicate-route error interpolates the route; localize it here. */\nfunction localizeCastError(message: string, t: ReturnType<typeof useText>): string {\n const duplicate = /^Route \"(.+)\" already exists$/.exec(message)\n if (duplicate) return t('routeExists', duplicate[1]!)\n return hubMessage(message, t.language)\n}\n\n/** The native write carries provider and model only; the effort is separate. */\nfunction routeInput(route: ModelRoute): CastRouteInput {\n const normalized = normalizeModelRoute(route)\n return { provider: normalized.provider, model: normalized.model }\n}\n\ninterface RequestScope { api: CastApi; active: boolean; busy: boolean; queued: boolean }\n\n/** One cast entry: model picker, tendency input saved on blur, remove button. */\nfunction CastRow({ t, catalog, route, tendencyRevision, draftReview, disabled, tendencyDisabled, menuDisabled, onSetRoute, onSetTendency, onRemove }: {\n t: ReturnType<typeof useText>\n catalog: unknown\n route: CastRoute\n tendencyRevision: number | undefined\n draftReview: number\n disabled: boolean\n tendencyDisabled: boolean\n menuDisabled: boolean\n onSetRoute: (route: ModelRoute) => void\n onSetTendency: (tendency: string, expectedRevision: number) => void\n onRemove: () => void\n}) {\n const label = `${route.provider} / ${route.model}`\n const saved = route.tendency ?? ''\n const [draft, setDraft] = useState({ text: saved, saved, revision: tendencyRevision, review: draftReview })\n useEffect(() => {\n setDraft(current => {\n if (current.text.trim() === current.saved || current.text.trim() === saved) return { text: saved, saved, revision: tendencyRevision, review: draftReview }\n // Only an explicit user refresh rebases an unsaved draft. Automatic\n // notifications keep the version it was based on, so blur cannot clobber.\n return current.review !== draftReview ? { ...current, saved, revision: tendencyRevision, review: draftReview } : current\n })\n }, [saved, tendencyRevision, draftReview])\n return <div className=\"cast-row\">\n <div className=\"cast-row-model\">\n {/* The native AllowedModelRoute schema is {provider, model} only, so the\n * effort lives in the plugin's own preference store; the picker still\n * offers it next to the model. */}\n <FieldMenu t={t} catalog={catalog} current={route} label={label} allowFollow={false} reasoningEffort display=\"short\" disabled={menuDisabled} onSet={onSetRoute} />\n </div>\n <div className=\"cast-row-tendency\">\n <Input type=\"text\" aria-label={t('tendencyLabel', label)} placeholder={t('tendencyPlaceholder')}\n value={draft.text} disabled={tendencyDisabled} maxLength={500}\n onChange={event => setDraft(current => ({ ...current, text: event.target.value }))}\n onBlur={() => { const tendency = draft.text.trim(); if (!tendencyDisabled && draft.revision !== undefined && tendency !== saved) onSetTendency(tendency, draft.revision) }} />\n {draft.text.trim() !== saved && draft.revision !== tendencyRevision ? <p role=\"status\" className=\"dsh-ui-help dsh-ui-wrap\">{t('draftChanged', saved)}</p> : null}\n </div>\n <Button variant=\"outline\" aria-label={t('removeRoute', label)} disabled={disabled} onClick={onRemove}>{t('remove')}</Button>\n </div>\n}\n\nexport function CastPage({ api, locale }: { api: CastApi; locale: LocaleLike }) {\n const t = useText(locale)\n const [cast, setCast] = useState<CastState | null>(null)\n const [catalog, setCatalog] = useState<unknown>(null)\n const [loadError, setLoadError] = useState('')\n const [catalogError, setCatalogError] = useState('')\n const [syncError, setSyncError] = useState('')\n const [writeError, setWriteError] = useState('')\n const [saved, setSaved] = useState(false)\n const [conflict, setConflict] = useState(false)\n const [saving, setSaving] = useState('')\n const [refreshing, setRefreshing] = useState(false)\n const [draftReview, setDraftReview] = useState(0)\n /* The model the add control last offered: it keeps the effort pane of that\n * model reachable, so a newly added model can take an effort right away. */\n const [pending, setPending] = useState<ModelRoute | undefined>(undefined)\n const scopeRef = useRef<RequestScope | null>(null)\n const refresh = useCallback(async (scope: RequestScope, reviewDrafts = false) => {\n if (!scope.active) return\n if (scope.busy) { scope.queued = true; return }\n scope.queued = false\n scope.busy = true\n setRefreshing(true)\n // These independent reads both run even when one fails. Retain each last\n // successful result, and never replay a rejected write after refreshing.\n const [castResult, models] = await Promise.allSettled([\n Promise.resolve().then(() => scope.api.getCast()),\n Promise.resolve().then(() => scope.api.modelCatalog()).then(checkedCatalog),\n ])\n if (!scope.active) return\n if (castResult.status === 'fulfilled') {\n setCast(castResult.value); setLoadError(''); setWriteError(''); setConflict(false); setSaved(false)\n if (reviewDrafts) setDraftReview(current => current + 1)\n }\n else setLoadError(messageOf(castResult.reason))\n if (models.status === 'fulfilled') { setCatalog(models.value); setCatalogError('') }\n else setCatalogError(messageOf(models.reason))\n scope.busy = false\n setRefreshing(false)\n if (scope.queued) void refresh(scope)\n }, [])\n useEffect(() => {\n const scope: RequestScope = { api, active: true, busy: false, queued: false }\n scopeRef.current = scope\n setSaving('')\n setWriteError('')\n setSaved(false)\n setConflict(false)\n setLoadError('')\n setCatalogError('')\n setSyncError('')\n setCast(null)\n setCatalog(null)\n setPending(undefined)\n void refresh(scope)\n /* Only this page's own scope may re-read it; other model-settings traffic\n * (a running subagent's route refresh) must not restart the read. */\n const unsubscribe = api.subscribeChanges?.(() => {\n if (!scope.active) return\n setSyncError('')\n void refresh(scope)\n }, message => { if (scope.active) setSyncError(message) })\n return () => { scope.active = false; unsubscribe?.(); scopeRef.current = null }\n }, [api, refresh])\n const mutate = (key: string, run: (scope: RequestScope) => Promise<CastState | CastCommit>) => {\n const scope = scopeRef.current\n if (!scope?.active || scope.api !== api || scope.busy || writeError || (saved && loadError)) return\n // Lock before React's next commit so same-tick selections cannot race CAS.\n scope.busy = true\n setSaved(false)\n setSaving(key)\n Promise.resolve().then(() => run(scope))\n .then(value => {\n if (!scope.active) return\n // A committed state is the final word: no refresh may overwrite it with\n // a value read before the write.\n if ('committed' in value) { setSaved(true); scope.queued = true }\n else { setCast(value); setSaved(true) }\n setWriteError(''); setConflict(false)\n },\n error => { if (scope.active) { const message = messageOf(error); setWriteError(message); setConflict(isConflict(message)) } })\n .finally(() => {\n if (scope.active) {\n scope.busy = false\n setSaving('')\n if (scope.queued) void refresh(scope)\n }\n })\n }\n const refreshNow = async () => {\n const scope = scopeRef.current\n if (scope?.api === api && !scope.busy) await refresh(scope, true)\n }\n // The add picker may retain a newly added route for an effort pick. Once\n // that route is removed (including in another tab), the next pick adds it\n // again instead of treating the selection as a preference-only change.\n const activePending = pending && cast?.routes.some(route => route.provider === pending.provider && route.model === pending.model) ? pending : undefined\n const disabled = saving !== '' || refreshing || writeError !== '' || (saved && loadError !== '')\n const catalogStatus = {\n loading: refreshing,\n error: catalogError ? hubMessage(catalogError, t.language) : '',\n failures: modelCatalogFailures(catalog),\n refresh: refreshNow,\n }\n /* The preference revision is the plugin's own CAS domain; the native route\n * list keeps its own revision. */\n const preferencesRevision = cast?.tendencyRevision ?? 0\n /** Save one route's plugin-side preferences; the answer is the new state. */\n const savePreferences = (provider: string, model: string, preferences: { tendency?: string; reasoningEffort?: string }, key: string) => {\n mutate(key, scope => scope.api.setCastRoutePreferences({ provider, model, preferences, expectedRevision: preferencesRevision }))\n }\n /** Apply one pick of the row's menu: a new model, or only a new effort. */\n const applyRoute = (handle: number, route: CastRoute, next: ModelRoute) => {\n const effort = next.reasoningEffort ?? ''\n if (next.provider === route.provider && next.model === route.model) {\n // The route stays; only the plugin-side effort changes.\n if (effort === (route.reasoningEffort ?? '')) return\n savePreferences(route.provider, route.model, { reasoningEffort: effort }, `effort:${handle}`)\n return\n }\n // The native CAS owns provider and model; a carried-over effort is a\n // separate plugin-side write for the new route.\n mutate(`route:${handle}`, async scope => {\n const commit = await scope.api.setCastRoute({ index: handle, route: routeInput(next), expectedRevision: cast?.revision ?? 0 })\n if (!next.reasoningEffort) return commit\n return scope.api.setCastRoutePreferences({\n provider: next.provider, model: next.model,\n preferences: { reasoningEffort: next.reasoningEffort },\n expectedRevision: preferencesRevision,\n })\n })\n }\n /* The root also carries the hub root class so officialUiCss('dsh-model-hub')\n * and castCss (both scoped under .dsh-model-hub) still apply when CastPage\n * renders outside HubPage's own subtree. */\n return <div className=\"cast-root dsh-model-hub dsh-ui-stack\" aria-label={t('title')} aria-busy={saving !== '' || refreshing}>\n <style>{castCss}</style>\n <div className=\"cast-head\">\n <Switch checked={cast?.enabled ?? false} label={t('enabledLabel')} disabled={disabled || cast === null || (!cast.enabled && cast.routes.length === 0)}\n onChange={next => { if (cast) mutate('enabled', scope => scope.api.setCastEnabled({ enabled: next, expectedRevision: cast.revision })) }} />\n <Button variant=\"ghost\" disabled={saving !== '' || refreshing} onClick={refreshNow}>{refreshing ? t('refreshing') : t('refresh')}</Button>\n </div>\n <p className=\"dsh-ui-help\">{t('enabledHint')}</p>\n {loadError ? <p role=\"alert\" className=\"dsh-ui-error dsh-ui-wrap\">{t(saved ? 'savedRefreshFailed' : 'failed', hubMessage(loadError, t.language))}</p> : null}\n {cast?.tendencyError ? <p role=\"alert\" className=\"dsh-ui-error dsh-ui-wrap\">{t('tendencyFailed', hubMessage(cast.tendencyError, t.language))}</p> : null}\n {syncError ? <p role=\"alert\" className=\"dsh-ui-error dsh-ui-wrap\">{t('syncFailed', hubMessage(syncError, t.language))}</p> : null}\n <ModelCatalogStatus state={catalogStatus} locale={t.language} />\n {writeError ? <div className=\"dsh-ui-banner dsh-ui-banner--danger cast-banner\" role=\"alert\">\n <span className=\"dsh-ui-wrap\">{conflict ? t('conflict') : t('writeFailed', localizeCastError(writeError, t))}</span>\n <Button variant=\"outline\" size=\"sm\" disabled={saving !== '' || refreshing} onClick={refreshNow}>{refreshing ? t('refreshing') : t('refresh')}</Button>\n </div> : null}\n {saving ? <p role=\"status\" className=\"dsh-ui-help\">{t('saving')}</p> : null}\n {saved && !loadError ? <p role=\"status\" className=\"dsh-ui-help\">{t('saved')}</p> : null}\n {cast === null && !loadError ? <p className=\"dsh-ui-loading\">{t('loading')}</p> : null}\n {cast !== null && cast.routes.length === 0 ? <p className=\"dsh-ui-help\">{t('empty')}</p> : null}\n {cast?.routes.map((route, position) => {\n /* Writes address the host's raw route index; fall back to the array\n * position only for contract-conforming hosts that omit it. */\n const handle = route.index ?? position\n return <CastRow key={JSON.stringify([route.provider, route.model])}\n t={t} catalog={catalog} route={route}\n tendencyRevision={cast.tendencyRevision} draftReview={draftReview}\n tendencyDisabled={disabled || !!cast.tendencyError || cast.tendencyRevision === undefined}\n disabled={disabled} menuDisabled={disabled || catalog === null}\n onSetRoute={next => applyRoute(handle, route, next)}\n onSetTendency={(tendency, expectedRevision) => mutate(`tendency:${handle}`, scope => scope.api.setCastTendency({ provider: route.provider, model: route.model, tendency, expectedRevision }))}\n onRemove={() => mutate(`remove:${handle}`, scope => scope.api.removeCastRoute({ index: handle, expectedRevision: cast.revision }))}\n />\n })}\n <div className=\"cast-add\">\n <FieldMenu t={t} catalog={catalog} current={activePending} label={t('addModel')} allowFollow={false} followLabel={t('addModel')}\n reasoningEffort display=\"short\" disabled={disabled || catalog === null}\n onSet={picked => {\n if (!picked.provider || !picked.model) { setPending(undefined); return }\n if (activePending && activePending.provider === picked.provider && activePending.model === picked.model) {\n // The model is already in the list; only its effort changed.\n const effort = picked.reasoningEffort ?? ''\n if (effort === (activePending.reasoningEffort ?? '')) return\n mutate('add-effort', async scope => {\n const state = await scope.api.setCastRoutePreferences({\n provider: picked.provider, model: picked.model,\n preferences: { reasoningEffort: effort },\n expectedRevision: preferencesRevision,\n })\n setPending(undefined)\n return state\n })\n return\n }\n mutate('add', async scope => {\n const commit = await scope.api.addCastRoute({ route: routeInput(picked), expectedRevision: cast?.revision ?? 0 })\n setPending(picked)\n if (!picked.reasoningEffort) return commit\n return scope.api.setCastRoutePreferences({\n provider: picked.provider, model: picked.model,\n preferences: { reasoningEffort: picked.reasoningEffort },\n expectedRevision: preferencesRevision,\n })\n })\n }} />\n </div>\n </div>\n}\n","/**\n * dsh-model-hub — read-only subagent model readout inside the host's own\n * subagent catalog popup.\n *\n * The host owns two session-header cells for the subagent catalog:\n * `conversation.session.header.actions` with id `subagent-catalog` (the\n * descendant count) and `conversation.session.header.lineage` (the breadcrumb\n * switcher plus the descendant count of the current child). This module\n * registers a copy of both cells under the host's own ids with a lower\n * priority, so the plugin's version is the one the header renders while the\n * host's entry stays in the slot ledger and returns when the plugin unloads.\n *\n * The copy keeps the host's tree, navigation, sidebar, hover and keyboard\n * behaviour and adds one read-only line per catalog row: the model and the\n * reasoning effort that child session actually used. Native copy comes from\n * the host's `subagent` locale namespace; only the new route labels are local.\n *\n * The route comes from the session's `modelSelection` projection view, read as\n * `projectionValues.modelSelection.lastUsed`. The host derives that value from\n * the last `request/header` event, so it is the selection a request really\n * used. `next` is the selection intended for the *next* request (a pending\n * choice) and is never shown as an already-used route. A child that never\n * made a model request reports `lastUsed: null`, which is reported as \"no\n * model request yet\" rather than as a route.\n *\n * The catalog rows live in the host's private DOM contract: this module keeps\n * the host's CSS-module class names (pinned per host build) and its tree\n * roles, so the popup keeps the host's own look. When the host renames those\n * classes the popup falls back to this module's own stylesheet.\n */\nimport {\n useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore,\n type CSSProperties, type KeyboardEvent, type MouseEvent,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport {\n IconChevronDownOutlineRegular, IconChevronRightOutlineRegular, IconRefreshOutlineRegular, StateDot, Tooltip,\n} from '@deepseek-ai/dsh-client-ui-primitives'\n\n/* ------------------------------------------------------------------ *\n * Host contract types\n * ------------------------------------------------------------------ */\n\n/** One entry of a session's projected subagent catalog. */\nexport interface SubagentCatalogEntry {\n id: string\n label?: string\n mode?: 'one-shot' | 'continuable' | 'unknown' | 'external'\n}\n\n/** A model selection as the host records it: provider, model and optional effort. */\nexport interface SubagentModelSelection {\n provider: string\n model: string\n reasoningEffort?: string\n}\n\n/**\n * The host's `modelSelection` projection view.\n *\n * `lastUsed` is the selection the last request used and stays null until a\n * request happens. `next` is the pending selection for the next request; it is\n * part of the host's view but is never rendered as an already-used route.\n */\nexport interface SubagentModelSelectionProjection {\n lastUsed: SubagentModelSelection | null\n next?: SubagentModelSelection | null\n}\n\n/** Projection values the catalog rows read. */\nexport interface SubagentProjectionValues {\n title?: string\n modelSelection?: SubagentModelSelectionProjection\n subagentTiming?: {\n active?: { since: number; through: number }\n settledMs: number\n lastTurnCompleted?: boolean\n }\n tokenUsage?: {\n uncachedInputTokens: number\n outputTokens: number\n cacheReadTokens: number\n cacheWriteTokens: number\n }\n}\n\n/** One session row of the host's session list. */\nexport interface SubagentSessionSummary {\n id?: string\n title?: string\n displayTitle?: string\n parentId?: string\n origin?: string\n running?: boolean\n /** Durable format state of the session's stored data. */\n formatStatus?: string\n projectionValues?: SubagentProjectionValues\n}\n\n/** One session's projected values, as the host's session store publishes them. */\nexport interface SubagentProjectionSnapshot {\n state: 'idle' | 'loading' | 'ready' | 'error' | 'migration-required'\n error?: { message?: string } | null\n values: { subagentCatalog?: SubagentCatalogEntry[] }\n}\n\n/** The host's session store, as the catalog reads it. */\nexport interface SubagentSessionsState {\n byId: Record<string, SubagentSessionSummary>\n projectionsBySession: Record<string, SubagentProjectionSnapshot>\n}\n\n/** Durable address of one addressed child session. */\nexport interface SubagentAddress {\n parentSessionId: string\n childSessionId: string\n mode: 'one-shot' | 'continuable' | 'unknown'\n}\n\n/** Standard session props the two host cells hand to their occupant. */\nexport interface SubagentCatalogOwnerProps {\n /** The session the header renders. */\n sessionId: string\n /** Selector over the host's session store. */\n useSessions: <T>(selector: (state: SubagentSessionsState) => T) => T\n /** Selector over the host's session status map. */\n useSessionStatus: <T>(selector: (state: ReadonlyMap<string, { running?: boolean }>) => T) => T\n}\n\n/** Owner props of the breadcrumb lineage cell. */\nexport interface SubagentLineageOwnerProps extends SubagentCatalogOwnerProps {\n /** Session the breadcrumb title represents. */\n lineageSessionId: string\n /** Title shown next to the switcher. */\n displayTitle: string\n /** Navigate to the ancestor title when the combined title is used. */\n openTitle?: () => void\n /** Selector over the current session's snapshot. */\n useSession: <T>(selector: (session: { subagent?: { address?: { childSessionId?: string; parentSessionId?: string } } }) => T) => T\n}\n\n/** Business actions the plugin injects into both cells. */\nexport interface SubagentCatalogInjected {\n /** Open a child session in the main workspace. */\n openChild: (address: SubagentAddress) => void\n /** Open a child session in the right sidebar. */\n openChildAside: (address: SubagentAddress) => void\n /** Ask the host to load a session's projections. */\n refreshProjection: (sessionId: string) => void\n /** Host locale, for live language switching. */\n locale: LocaleLike\n /** Host translator keeps every native catalog language intact. */\n hostT: HostTranslator\n}\n\n/* ------------------------------------------------------------------ *\n * Copy\n * ------------------------------------------------------------------ */\n\n/**\n * Native catalog text is supplied by the host's `subagent` translator.\n * Only the new route readout needs local translations.\n */\nconst TEXT = {\n zh: {\n 'route.effort': '思考强度',\n 'route.effortDefault': '默认',\n 'route.loading': '读取中…',\n 'route.failed': '模型信息读取失败,点击重试',\n 'route.notApplicable': '不适用',\n 'route.noRequest': '尚未发起模型请求',\n },\n en: {\n 'route.effort': 'Reasoning',\n 'route.effortDefault': 'Default',\n 'route.loading': 'Loading…',\n 'route.failed': 'Could not load model information. Click to retry.',\n 'route.notApplicable': 'Not applicable',\n 'route.noRequest': 'No model request yet',\n },\n}\n/** Exported so the spec can check zh/en key alignment. */\nexport const subagentCatalogCopy = TEXT\ntype TextKey = keyof typeof TEXT.zh\ntype TextParams = Record<string, string | number>\nexport type Translator = (key: TextKey, params?: TextParams) => string\nexport type HostTranslator = (key: string, params?: TextParams) => string\n\ntype LocaleLike = string | { getSnapshot?: () => { active?: string }; subscribe?: (fn: () => void) => () => void } | undefined\nexport type { LocaleLike }\n\n/** Replace `{name}` placeholders; unknown names keep the placeholder. */\nfunction interpolate(template: string, params?: TextParams): string {\n if (!params) return template\n return template.replace(/\\{(\\w+)\\}/g, (match, name: string) => {\n const value = params[name]\n return value === undefined ? match : String(value)\n })\n}\n\n/** The host locale, one language at a time; missing services read as English. */\nfunction useText(locale: LocaleLike): Translator {\n const subscribe = useCallback(\n (notify: () => void) => typeof locale === 'object' ? locale.subscribe?.(notify) ?? (() => {}) : () => {},\n [locale],\n )\n const snapshot = useCallback(\n () => String(typeof locale === 'string' ? locale : locale?.getSnapshot?.()?.active ?? 'en'),\n [locale],\n )\n const active = useSyncExternalStore(subscribe, snapshot, snapshot)\n const table = active.toLowerCase().startsWith('zh') ? TEXT.zh : TEXT.en\n return useCallback<Translator>((key, params) => interpolate(table[key], params), [table])\n}\n\n/* ------------------------------------------------------------------ *\n * Styling\n * ------------------------------------------------------------------ */\n\n/**\n * The host's CSS-module class names for the subagent catalog, as of host\n * 0.2.2-rc.1. The host's stylesheet is injected into the document, so these\n * names keep the popup on the host's own look; the `mh-` classes below carry\n * a fallback stylesheet for hosts that renamed them.\n */\nconst NATIVE_CLASS = {\n activitySlot: 'rezYhW_activitySlot',\n ancestorSwitcherTrigger: 'rezYhW_ancestorSwitcherTrigger',\n children: 'rezYhW_children',\n clickarea: 'rezYhW_clickarea',\n content: 'rezYhW_content',\n currentLabel: 'rezYhW_currentLabel',\n disclosure: 'rezYhW_disclosure',\n disclosureOpen: 'rezYhW_disclosureOpen',\n disclosureSpace: 'rezYhW_disclosureSpace',\n error: 'rezYhW_error',\n label: 'rezYhW_label',\n menu: 'rezYhW_menu',\n menuBody: 'rezYhW_menuBody',\n metricDuration: 'rezYhW_metricDuration',\n metricToken: 'rezYhW_metricToken',\n metrics: 'rezYhW_metrics',\n node: 'rezYhW_node',\n notice: 'rezYhW_notice',\n refresh: 'rezYhW_refresh',\n root: 'rezYhW_root',\n row: 'rezYhW_row',\n rowActivitySlot: 'rezYhW_rowActivitySlot',\n sidebarButton: 'rezYhW_sidebarButton',\n sidebarSpace: 'rezYhW_sidebarSpace',\n summary: 'rezYhW_summary',\n switcherRoot: 'rezYhW_switcherRoot',\n switcherTitle: 'rezYhW_switcherTitle',\n switcherTrigger: 'rezYhW_switcherTrigger',\n trigger: 'rezYhW_trigger',\n triggerOpen: 'rezYhW_triggerOpen',\n} as const\n\n/** Join class names, dropping empty ones. */\nfunction cx(...parts: Array<string | false | undefined>): string {\n return parts.filter(Boolean).join(' ')\n}\n\n/**\n * Fallback stylesheet. Every selector is wrapped in `:where()` so it carries\n * no specificity: while the host's own stylesheet is present, the host wins;\n * when the host renamed its classes, these rules keep the popup readable.\n */\nconst css = `\n.dsh-model-hub-subagent :where(.mh-root){position:relative;display:inline-flex;align-items:center;gap:10px;min-width:0}\n.dsh-model-hub-subagent :where(.mh-switcher-root){min-width:0;margin-left:6px}\n.dsh-model-hub-subagent :where(.mh-trigger),.dsh-model-hub-subagent :where(.mh-switcher-trigger){display:inline-flex;align-items:center;gap:4px;min-height:28px;padding:3px 2px;border:0;border-radius:var(--dsw-radius-sm);background:transparent;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;cursor:pointer}\n.dsh-model-hub-subagent :where(.mh-switcher-trigger){min-width:0;max-width:244px;color:var(--dsw-alias-label-primary);font-weight:500}\n.dsh-model-hub-subagent :where(.mh-ancestor-switcher-trigger){color:var(--dsw-alias-label-tertiary);font-weight:400}\n.dsh-model-hub-subagent :where(.mh-switcher-title){flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dsh-model-hub-subagent :where(.mh-activity-slot){display:inline-flex;flex:none;align-items:center;justify-content:center;width:14px;height:14px}\n.dsh-model-hub-subagent :where(.mh-trigger-open){transform:rotate(180deg)}\n.dsh-model-hub-subagent :where(.mh-menu){position:fixed;z-index:100;box-sizing:border-box;display:flex;flex-direction:column;width:336px;max-width:min(400px,calc(100vw - 32px));max-height:min(560px,calc(100vh - 140px));padding:3px;overflow:hidden;border-radius:var(--dsw-radius-lg);box-shadow:var(--dsw-elevation-prominent);background:var(--dsw-alias-bg-layer-3)}\n.dsh-model-hub-subagent :where(.mh-menu-body){display:flex;flex-direction:column;flex:1 1 auto;min-height:0;overflow:auto}\n.dsh-model-hub-subagent :where(.mh-node){position:relative;min-width:0}\n.dsh-model-hub-subagent :where(.mh-row){position:relative;display:flex;align-items:flex-start;gap:6px;box-sizing:border-box;width:100%;min-height:44px;padding:6px 7px 6px 9px;border:0;border-radius:var(--dsw-radius-lg);background:transparent;color:var(--dsw-alias-label-primary);font-size:12px;line-height:17px;text-align:left;cursor:pointer;outline:none}\n.dsh-model-hub-subagent :where(.mh-clickarea){box-sizing:border-box;display:flex;flex:1;align-self:stretch;align-items:flex-start;gap:6px;min-width:0;margin:-6px -7px;padding:6px 7px;border-radius:var(--dsw-radius-lg)}\n.dsh-model-hub-subagent :where(.mh-row-activity-slot){display:inline-flex;flex:none;align-items:center;justify-content:center;width:14px;height:17px}\n.dsh-model-hub-subagent :where(.mh-disclosure),.dsh-model-hub-subagent :where(.mh-disclosure-space){flex:none;width:14px;height:17px}\n.dsh-model-hub-subagent :where(.mh-disclosure){display:inline-flex;align-items:center;justify-content:center;padding:0;border:0;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer}\n.dsh-model-hub-subagent :where(.mh-disclosure-open){transform:rotate(90deg)}\n.dsh-model-hub-subagent :where(.mh-content){display:flex;flex:1;flex-direction:column;min-width:0}\n.dsh-model-hub-subagent :where(.mh-label),.dsh-model-hub-subagent :where(.mh-summary){overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dsh-model-hub-subagent :where(.mh-summary),.dsh-model-hub-subagent :where(.mh-metrics){color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:15px}\n.dsh-model-hub-subagent :where(.mh-metrics){display:grid;grid-template-rows:17px 15px;flex:none;font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}\n.dsh-model-hub-subagent :where(.mh-sidebar-button){display:inline-flex;flex:none;align-items:center;justify-content:center;width:28px;height:28px;margin:4px 0;padding:6px;border:0;border-radius:var(--dsw-radius-sm);background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer}\n.dsh-model-hub-subagent :where(.mh-children){position:relative;margin-left:16px;padding-left:3px}\n.dsh-model-hub-subagent :where(.mh-notice),.dsh-model-hub-subagent :where(.mh-error){padding:8px 10px;color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}\n.dsh-model-hub-subagent :where(.mh-error){display:flex;align-items:center;justify-content:space-between;gap:10px;color:var(--dsw-alias-state-error-primary)}\n.dsh-model-hub-subagent :where(.mh-refresh){display:inline-flex;flex:none;align-items:center;gap:3px;padding:3px 5px;border:0;border-radius:var(--dsw-radius-sm);background:transparent;color:inherit;cursor:pointer}\n.dsh-model-hub-subagent :where(.mh-route){display:block;min-width:0;color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:15px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}\n.dsh-model-hub-subagent :where(.mh-route-retry){padding:0;border:0;background:transparent;color:inherit;font:inherit;cursor:pointer;text-decoration:underline}\n.dsh-model-hub-subagent :where(.mh-sidebar-space){flex:none;width:28px}\n`\n\n/* ------------------------------------------------------------------ *\n * Route readout\n * ------------------------------------------------------------------ */\n\n/** What the readout knows about one child's route. */\ntype RouteState =\n /** The child's route is not readable from this session (external/unknown). */\n | { kind: 'notApplicable' }\n /** The child's projections are not loaded yet. */\n | { kind: 'loading' }\n /** The host reported a failed projection read. */\n | { kind: 'failed' }\n /** The child is loaded and never made a model request. */\n | { kind: 'none' }\n /** The child made a model request; this is the route it used. */\n | { kind: 'used'; selection: SubagentModelSelection }\n\n/**\n * Read one child's route.\n *\n * Only `lastUsed` counts: it is the selection a request really used. A child\n * whose projections are not loaded yet is `loading` (the host is asked for\n * them); a loaded child that never requested a model is `none`; the pending\n * `next` selection is never presented as an already-used route.\n */\nfunction readRoute(entry: SubagentCatalogEntry, summary: SubagentSessionSummary | undefined, projection?: SubagentProjectionSnapshot): RouteState {\n if (entry.mode === 'external' || entry.mode === 'unknown') return { kind: 'notApplicable' }\n const selection = summary?.projectionValues?.modelSelection\n if (selection === undefined) {\n if (projection?.state === 'error' || (projection?.state === 'idle' && projection.error)) return { kind: 'failed' }\n return { kind: 'loading' }\n }\n const lastUsed = selection.lastUsed\n if (lastUsed === undefined) return { kind: 'loading' }\n if (lastUsed === null) return { kind: 'none' }\n return { kind: 'used', selection: lastUsed }\n}\n\n/** One line of readout text for a child row. */\nfunction routeText(state: RouteState, t: Translator): string {\n switch (state.kind) {\n case 'notApplicable': return t('route.notApplicable')\n case 'loading': return t('route.loading')\n case 'failed': return t('route.failed')\n case 'none': return t('route.noRequest')\n case 'used': {\n const effort = state.selection.reasoningEffort ?? t('route.effortDefault')\n const model = state.selection.model.split('/').filter(Boolean).at(-1) || state.selection.model\n return `${model} · ${effort}`\n }\n }\n}\n\n/* ------------------------------------------------------------------ *\n * Catalog tree\n * ------------------------------------------------------------------ */\n\ninterface CatalogSnapshot {\n state: 'loading' | 'ready' | 'error' | 'migration-required'\n error?: { message?: string } | null\n entries: (SubagentCatalogEntry & { activity: 'running' | 'inactive' })[]\n}\ntype Catalogs = Readonly<Record<string, CatalogSnapshot>>\n\n/** Focusable rows of one rendered tree. */\nfunction treeItems(root: HTMLDivElement | null): HTMLElement[] {\n if (root === null) return []\n return Array.from(root.querySelectorAll<HTMLElement>('[role=\"treeitem\"]:not([aria-disabled=\"true\"])'))\n}\n\n/** Compact token count shared in shape with the conversation stats strip. */\nfunction formatTokens(value: number, t: HostTranslator): string {\n const scaled = (next: number): string => next >= 100 ? String(Math.round(next)) : String(Math.round(next * 10) / 10)\n if (value < 1_000) return String(value)\n if (value < 1_000_000) return t('tokens.thousand', { value: scaled(value / 1_000) })\n return t('tokens.million', { value: scaled(value / 1_000_000) })\n}\n\n/** Sum the four disjoint durable provider-usage buckets. */\nfunction tokenTotal(usage: SubagentProjectionValues['tokenUsage']): number | undefined {\n if (usage === undefined) return undefined\n return usage.uncachedInputTokens + usage.outputTokens + usage.cacheReadTokens + usage.cacheWriteTokens\n}\n\ninterface DurationParts {\n seconds: number\n minutes: number\n hours: number\n days: number\n totalMinutes: number\n totalHours: number\n}\n\nfunction splitDuration(ms: number): DurationParts {\n const totalSeconds = Math.floor(Math.max(0, ms) / 1_000)\n const totalMinutes = Math.floor(totalSeconds / 60)\n const totalHours = Math.floor(totalMinutes / 60)\n const days = Math.floor(totalHours / 24)\n return {\n seconds: totalSeconds % 60,\n minutes: totalMinutes % 60,\n hours: totalHours % 24,\n days,\n totalMinutes,\n totalHours,\n }\n}\n\n/** Format a duration with decreasing visual precision at larger scales. */\nfunction formatDuration(ms: number, t: HostTranslator): string {\n const { seconds, minutes, hours, days, totalMinutes, totalHours } = splitDuration(ms)\n if (days >= 365) {\n const years = Math.floor(days / 365)\n const months = Math.floor(days % 365 / 30)\n return months === 0 ? t('duration.years', { years }) : t('duration.yearsMonths', { years, months })\n }\n if (days >= 30) {\n const months = Math.floor(days / 30)\n const remainingDays = days % 30\n return remainingDays === 0 ? t('duration.months', { months }) : t('duration.monthsDays', { months, days: remainingDays })\n }\n if (days > 0) return hours === 0 ? t('duration.days', { days }) : t('duration.daysHours', { days, hours })\n if (totalHours > 0) {\n return t('duration.hours', { hours, minutes: String(minutes).padStart(2, '0'), seconds: String(seconds).padStart(2, '0') })\n }\n if (totalMinutes > 0) {\n return t('duration.minutes', { minutes: String(minutes).padStart(2, '0'), seconds: String(seconds).padStart(2, '0') })\n }\n return t('duration.seconds', { seconds: String(seconds).padStart(2, '0') })\n}\n\n/** Preserve exact whole seconds for hover and accessible naming. */\nfunction formatExactDuration(ms: number, t: HostTranslator): string {\n const { seconds, minutes, hours, days } = splitDuration(ms)\n if (days === 0) return formatDuration(ms, t)\n return t('duration.exactDays', {\n days,\n hours: String(hours).padStart(2, '0'),\n minutes: String(minutes).padStart(2, '0'),\n seconds: String(seconds).padStart(2, '0'),\n })\n}\n\n/** Exact whole-second active-turn duration for one catalog row. */\nfunction activityDuration(\n summary: SubagentSessionSummary | undefined,\n activity: 'running' | 'inactive',\n now: number,\n): number | undefined {\n if (summary === undefined) return undefined\n const timing = summary.projectionValues?.subagentTiming\n if (timing === undefined) return undefined\n if (timing.active === undefined) return timing.settledMs\n const end = activity === 'running' ? now : timing.active.through\n return timing.settledMs + Math.max(0, end - timing.active.since)\n}\n\ninterface CatalogRowsProps {\n parentSessionId: string\n currentSessionId: string | undefined\n catalog: CatalogSnapshot\n catalogs: Catalogs\n projections: Readonly<Record<string, SubagentProjectionSnapshot>>\n summaries: Record<string, SubagentSessionSummary>\n expanded: ReadonlySet<string>\n level: number\n openChild: (address: SubagentAddress) => void\n openChildAside: (address: SubagentAddress) => void\n refreshProjection: (sessionId: string) => void\n requestProjection: (sessionId: string, retry?: boolean) => void\n toggleBranch: (childSessionId: string) => void\n closeCatalog: () => void\n t: HostTranslator\n routeT: Translator\n}\n\n/** Render one catalog level and recurse only through explicitly expanded rows. */\nfunction CatalogRows({\n parentSessionId, currentSessionId, catalog, catalogs, projections, summaries, expanded, level,\n openChild, openChildAside, refreshProjection, requestProjection, toggleBranch, closeCatalog, t, routeT,\n}: CatalogRowsProps) {\n const [now, setNow] = useState(() => Date.now())\n const running = catalog.entries.some((entry) => entry.activity === 'running')\n useEffect(() => {\n if (!running) return\n const timer = setInterval(() => setNow(Date.now()), 1_000)\n return () => clearInterval(timer)\n }, [running])\n const emptyLoading = catalog.state === 'loading' && catalog.entries.length === 0\n const reserveDisclosure = catalog.entries.some((entry) =>\n entry.mode !== 'external' && !isKnownLeaf(catalogs[entry.id])\n && summaries[entry.id]?.formatStatus !== 'migration-required'\n && catalogs[entry.id]?.state !== 'migration-required')\n\n /* A child whose projections are not loaded yet is asked for them once. The\n * request is deduplicated by the caller, so a child that stays unreadable\n * never turns into a request loop. */\n useEffect(() => {\n for (const entry of catalog.entries) {\n if (readRoute(entry, summaries[entry.id], projections[entry.id]).kind !== 'loading') continue\n requestProjection(entry.id)\n }\n }, [catalog, projections, summaries, requestProjection])\n\n return <>\n {emptyLoading ? <div className={cx(NATIVE_CLASS.notice, 'mh-notice')}>{t('loading.label')}</div> : null}\n {catalog.state === 'error' ? <div className={cx(NATIVE_CLASS.error, 'mh-error')}>\n <span>{catalog.error?.message ?? t('load.error')}</span>\n <button type=\"button\" className={cx(NATIVE_CLASS.refresh, 'mh-refresh')} onClick={() => refreshProjection(parentSessionId)}>\n <IconRefreshOutlineRegular size={14} />{t('retry')}\n </button>\n </div> : null}\n {catalog.entries.map((entry) => {\n const external = entry.mode === 'external'\n const childCatalog = catalogs[entry.id]\n const isCurrent = entry.id === currentSessionId\n const knownLeaf = external || isKnownLeaf(childCatalog)\n const requiresOpening = summaries[entry.id]?.formatStatus === 'migration-required' || childCatalog?.state === 'migration-required'\n const canExpand = !knownLeaf && !requiresOpening\n const isExpanded = canExpand && expanded.has(entry.id)\n const childLoading = childCatalog === undefined || (childCatalog.state === 'loading' && childCatalog.entries.length === 0)\n const summary = summaries[entry.id]\n const label = entry.label ?? entry.id\n const mode = external ? t('mode.external')\n : entry.mode === 'unknown' ? t('mode.unknown')\n : entry.mode === 'one-shot' ? t('mode.oneShot') : t('mode.continuable')\n const completed = !external && entry.activity === 'inactive' && summary?.projectionValues?.subagentTiming?.lastTurnCompleted === true\n const activity = external ? undefined\n : entry.activity === 'running' ? t('activity.running')\n : completed ? t('activity.completed') : t('activity.inactive')\n const secondary = [summary?.title, requiresOpening ? t('catalog.migrationRequired') : mode, activity]\n .filter((value) => value !== undefined).join(' · ')\n const totalTokens = tokenTotal(summary?.projectionValues?.tokenUsage)\n const durationMs = activityDuration(summary, entry.activity, now)\n const tokenMetric = totalTokens === undefined ? undefined : t('tokens.total', { value: formatTokens(totalTokens, t) })\n const durationMetric = durationMs === undefined ? undefined : {\n compact: formatDuration(durationMs, t),\n exact: formatExactDuration(durationMs, t),\n }\n const metrics = [tokenMetric, durationMetric?.exact].filter((value) => value !== undefined).join(' · ')\n const route = readRoute(entry, summary, projections[entry.id])\n const routeLine = routeText(route, routeT)\n const open = () => {\n if (external) return\n openChild({ parentSessionId, childSessionId: entry.id, mode: addressMode(entry) })\n closeCatalog()\n }\n const handleKey = (event: KeyboardEvent<HTMLDivElement>) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n event.stopPropagation()\n open()\n } else if ((event.key === 'ArrowRight' && canExpand && !isExpanded) || (event.key === 'ArrowLeft' && isExpanded)) {\n event.preventDefault()\n event.stopPropagation()\n toggleBranch(entry.id)\n }\n }\n const toggle = (event: MouseEvent<HTMLButtonElement>) => {\n event.preventDefault()\n event.stopPropagation()\n toggleBranch(entry.id)\n }\n return <div key={entry.id} className={cx(NATIVE_CLASS.node, 'mh-node')}>\n <div\n role=\"treeitem\"\n tabIndex={external ? -1 : 0}\n aria-disabled={external || undefined}\n aria-level={level}\n aria-current={isCurrent || undefined}\n aria-label={[label, secondary, metrics, routeLine].filter((value) => value !== '').join(' ')}\n {...canExpand ? { 'aria-expanded': isExpanded } : {}}\n className={cx(NATIVE_CLASS.row, 'mh-row')}\n onClick={open}\n onKeyDown={handleKey}\n >\n {!canExpand ? (reserveDisclosure ? <span className={cx(NATIVE_CLASS.disclosureSpace, 'mh-disclosure-space')} /> : null)\n : <button type=\"button\" tabIndex={-1}\n className={cx(NATIVE_CLASS.disclosure, 'mh-disclosure', isExpanded ? NATIVE_CLASS.disclosureOpen : '', isExpanded ? 'mh-disclosure-open' : '')}\n aria-label={t(isExpanded ? 'branch.collapse' : 'branch.expand', { label })}\n onClick={toggle}\n >\n <IconChevronRightOutlineRegular />\n </button>}\n <div className={cx(NATIVE_CLASS.clickarea, 'mh-clickarea')}>\n <span className={cx(NATIVE_CLASS.rowActivitySlot, 'mh-row-activity-slot')}>\n <StateDot state={entry.activity === 'running' ? 'ongoing' : completed ? 'done' : 'idle'} />\n </span>\n <span className={cx(NATIVE_CLASS.content, 'mh-content')}>\n <span className={cx(NATIVE_CLASS.label, 'mh-label', isCurrent ? NATIVE_CLASS.currentLabel : '')}>{label}</span>\n <span className={cx(NATIVE_CLASS.summary, 'mh-summary')}>{secondary}</span>\n {route.kind === 'failed'\n ? <button type=\"button\" className=\"mh-route mh-route-retry\" onClick={(event) => { event.stopPropagation(); requestProjection(entry.id, true) }}>{routeLine}</button>\n : <span className=\"mh-route\" title={route.kind === 'used' ? `${route.selection.provider} / ${route.selection.model} · ${route.selection.reasoningEffort ?? routeT('route.effortDefault')}` : undefined}>{routeLine}</span>}\n </span>\n {metrics !== '' ? <span className={cx(NATIVE_CLASS.metrics, 'mh-metrics')}>\n {tokenMetric !== undefined ? <span className={cx(NATIVE_CLASS.metricToken, 'mh-metric-token')}>{tokenMetric}</span> : null}\n {durationMetric !== undefined ? <span className={cx(NATIVE_CLASS.metricDuration, 'mh-metric-duration')} title={t('duration.exactTitle', { duration: durationMetric.exact })}>{durationMetric.compact}</span> : null}\n </span> : null}\n {isCurrent || external ? <span className={cx(NATIVE_CLASS.sidebarSpace, 'mh-sidebar-space')} />\n : <Tooltip label={t('open.sidebar')} side=\"bottom\" align=\"end\">\n <button type=\"button\" className={cx(NATIVE_CLASS.sidebarButton, 'mh-sidebar-button')}\n aria-label={t('open.sidebar.aria', { label })}\n onClick={(event) => {\n event.preventDefault()\n event.stopPropagation()\n openChildAside({ parentSessionId, childSessionId: entry.id, mode: addressMode(entry) })\n closeCatalog()\n }}\n onKeyDown={(event) => { event.stopPropagation() }}\n >\n <IconChevronRightOutlineRegular />\n </button>\n </Tooltip>}\n </div>\n </div>\n {isExpanded ? <div role=\"group\" className={cx(NATIVE_CLASS.children, 'mh-children')} aria-busy={childLoading || undefined}>\n {childCatalog === undefined ? <div className={cx(NATIVE_CLASS.notice, 'mh-notice')}>{t('loading.label')}</div>\n : <CatalogRows\n parentSessionId={entry.id}\n currentSessionId={currentSessionId}\n catalog={childCatalog}\n catalogs={catalogs}\n projections={projections}\n summaries={summaries}\n expanded={expanded}\n level={level + 1}\n openChild={openChild}\n openChildAside={openChildAside}\n refreshProjection={refreshProjection}\n requestProjection={requestProjection}\n toggleBranch={toggleBranch}\n closeCatalog={closeCatalog}\n t={t}\n routeT={routeT}\n />}\n </div> : null}\n </div>\n })}\n </>\n}\n\n/** A child becomes a known leaf only after its own authoritative catalog loads empty. */\nfunction isKnownLeaf(catalog: CatalogSnapshot | undefined): boolean {\n return catalog?.state === 'ready' && catalog.entries.length === 0\n}\n\n/** The addressable mode of one catalog entry; unreadable modes stay unknown. */\nfunction addressMode(entry: SubagentCatalogEntry): SubagentAddress['mode'] {\n return entry.mode === 'one-shot' || entry.mode === 'continuable' ? entry.mode : 'unknown'\n}\n\nconst MENU_VIEWPORT_MARGIN = 16\n\n/** Place a portaled catalog below its trigger without crossing the viewport edge. */\nfunction catalogMenuPosition(trigger: HTMLButtonElement): CSSProperties {\n const rect = trigger.getBoundingClientRect()\n const width = Math.min(336, window.innerWidth - MENU_VIEWPORT_MARGIN * 2)\n return {\n top: rect.bottom + 5,\n left: Math.min(Math.max(MENU_VIEWPORT_MARGIN, rect.left), window.innerWidth - width - MENU_VIEWPORT_MARGIN),\n }\n}\n\ninterface CatalogDropdownProps {\n rootSessionId: string\n currentSessionId?: string\n displayTitle?: string\n openTitle?: () => void\n variant: 'count' | 'switcher'\n useSessions: <T>(selector: (state: SubagentSessionsState) => T) => T\n useSessionStatus: <T>(selector: (state: ReadonlyMap<string, { running?: boolean }>) => T) => T\n openChild: (address: SubagentAddress) => void\n openChildAside: (address: SubagentAddress) => void\n refreshProjection: (sessionId: string) => void\n t: HostTranslator\n routeT: Translator\n}\n\n/** One trigger-plus-tree dropdown over the catalog rooted at `rootSessionId`. */\nfunction CatalogDropdown({\n rootSessionId, currentSessionId, displayTitle, openTitle, variant,\n useSessions, useSessionStatus, openChild, openChildAside, refreshProjection, t, routeT,\n}: CatalogDropdownProps) {\n const ancestorSwitcher = variant === 'switcher' && openTitle !== undefined\n const projections = useSessions((state) => state.projectionsBySession)\n const summaries = useSessions((state) => state.byId)\n const statuses = useSessionStatus((value) => value)\n const catalogs = useMemo<Catalogs>(() => Object.fromEntries(Object.entries(projections).map(([id, snapshot]) => {\n const projected = snapshot.values.subagentCatalog\n return [id, {\n state: snapshot.state === 'idle'\n ? projected === undefined ? 'loading' as const : 'ready' as const\n : snapshot.state === 'migration-required' && projected !== undefined ? 'ready' as const : snapshot.state,\n error: snapshot.error,\n entries: (projected ?? []).map((entry) => ({\n ...entry,\n activity: (statuses.get(entry.id)?.running ?? summaries[entry.id]?.running) === true ? 'running' as const : 'inactive' as const,\n })),\n }]\n })), [projections, summaries, statuses])\n const catalog = catalogs[rootSessionId]\n const [open, setOpen] = useState(false)\n const [menuPosition, setMenuPosition] = useState<CSSProperties>()\n const [expanded, setExpanded] = useState<ReadonlySet<string>>(() => new Set())\n const rootRef = useRef<HTMLDivElement>(null)\n const triggerRef = useRef<HTMLButtonElement>(null)\n const menuRef = useRef<HTMLDivElement>(null)\n const hoverOpenTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n const hoverCloseTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n /* A click-opened (pinned) menu ignores hover-out; only explicit dismissal closes it. */\n const pinnedRef = useRef(false)\n /* One projection request per child: a child that stays unreadable must not\n * turn the readout into a request loop. */\n const requestedRef = useRef<Set<string>>(new Set())\n const currentEntry = currentSessionId === undefined\n ? undefined\n : catalog?.entries.find((entry) => entry.id === currentSessionId)\n const switcherDisplayTitle = currentEntry !== undefined ? currentEntry.label ?? currentEntry.id : displayTitle ?? rootSessionId\n const directChildren = catalog?.entries ?? []\n const directCount = directChildren.length\n const runningCount = directChildren.filter((entry) => entry.activity === 'running').length\n const totalCountKey = directCount === 1 ? 'count.total.one' : 'count.total.other'\n const runningCountKey = runningCount === 1 ? 'count.running.one' : 'count.running.other'\n const presentedCatalog: CatalogSnapshot | undefined = catalog ?? (variant === 'switcher'\n ? { entries: [], state: 'loading', error: null }\n : undefined)\n\n const cancelHoverClose = (): void => {\n if (hoverCloseTimer.current === undefined) return\n clearTimeout(hoverCloseTimer.current)\n hoverCloseTimer.current = undefined\n }\n const cancelHoverOpen = (): void => {\n if (hoverOpenTimer.current === undefined) return\n clearTimeout(hoverOpenTimer.current)\n hoverOpenTimer.current = undefined\n }\n const changeOpen = (next: boolean, restoreFocus = false): void => {\n cancelHoverOpen()\n cancelHoverClose()\n if (next) {\n const trigger = triggerRef.current\n if (trigger === null) return\n setOpen(true)\n setMenuPosition(catalogMenuPosition(trigger))\n } else {\n pinnedRef.current = false\n setOpen(false)\n setMenuPosition(undefined)\n setExpanded(new Set())\n }\n if (restoreFocus) queueMicrotask(() => { triggerRef.current?.focus() })\n }\n const scheduleHoverOpen = (): void => {\n cancelHoverOpen()\n cancelHoverClose()\n if (open) return\n hoverOpenTimer.current = setTimeout(() => {\n hoverOpenTimer.current = undefined\n changeOpen(true)\n }, 150)\n }\n const scheduleHoverClose = (): void => {\n cancelHoverOpen()\n cancelHoverClose()\n if (pinnedRef.current) return\n hoverCloseTimer.current = setTimeout(() => {\n hoverCloseTimer.current = undefined\n changeOpen(false)\n }, 120)\n }\n const closeBranch = (root: string): void => {\n const closing = new Set<string>()\n const visit = (parentSessionId: string): void => {\n if (closing.has(parentSessionId) || !expanded.has(parentSessionId)) return\n closing.add(parentSessionId)\n const branch = catalogs[parentSessionId]\n for (const entry of branch?.entries ?? []) visit(entry.id)\n }\n visit(root)\n setExpanded((current) => new Set([...current].filter((id) => !closing.has(id))))\n }\n const toggleBranch = (childSessionId: string): void => {\n if (expanded.has(childSessionId)) {\n closeBranch(childSessionId)\n return\n }\n setExpanded((current) => new Set(current).add(childSessionId))\n requestProjection(childSessionId)\n }\n /** Ask the host for one child's projections, at most once per dropdown. */\n const requestProjection = useCallback((childSessionId: string, retry = false): void => {\n if (requestedRef.current.has(childSessionId) && !retry) return\n requestedRef.current.add(childSessionId)\n try {\n refreshProjection(childSessionId)\n } catch {\n // A failed projection read leaves the row on its loading state; the\n // host's own retry control reloads the catalog.\n }\n }, [refreshProjection])\n\n useEffect(() => {\n if (!open) return\n const closeOutside = (event: Event): void => {\n const target = event.target\n if (target instanceof Node\n && !rootRef.current?.contains(target) && !menuRef.current?.contains(target)) changeOpen(false)\n }\n document.addEventListener('pointerdown', closeOutside)\n return () => document.removeEventListener('pointerdown', closeOutside)\n }, [open])\n useEffect(() => {\n if (!open) return\n const placeMenu = (): void => {\n const trigger = triggerRef.current\n if (trigger === null) return\n setMenuPosition(catalogMenuPosition(trigger))\n }\n window.addEventListener('resize', placeMenu)\n document.addEventListener('scroll', placeMenu, true)\n return () => {\n window.removeEventListener('resize', placeMenu)\n document.removeEventListener('scroll', placeMenu, true)\n }\n }, [open])\n /* Hover timers outlive an unmount otherwise: a pending open would publish\n * into a tree that is no longer mounted. */\n useEffect(() => () => {\n cancelHoverOpen()\n cancelHoverClose()\n }, [])\n const visible = presentedCatalog !== undefined && (variant === 'switcher' || presentedCatalog.state === 'error' || presentedCatalog.entries.length > 0)\n useEffect(() => {\n if (visible) return\n cancelHoverOpen()\n cancelHoverClose()\n if (!open) return\n pinnedRef.current = false\n setOpen(false)\n setExpanded(new Set())\n }, [visible, open])\n if (!visible) return null\n\n const focusAt = (index: number): void => {\n const items = treeItems(menuRef.current)\n if (items.length === 0) return\n items[(index + items.length) % items.length]?.focus()\n }\n const navigate = (event: KeyboardEvent<HTMLDivElement>): void => {\n const items = treeItems(menuRef.current)\n const index = items.indexOf(document.activeElement as HTMLElement)\n if (event.key === 'Escape') {\n event.preventDefault()\n changeOpen(false, true)\n } else if (event.key === 'Home') {\n event.preventDefault()\n focusAt(0)\n } else if (event.key === 'End') {\n event.preventDefault()\n focusAt(items.length - 1)\n } else if (event.key === 'ArrowDown') {\n event.preventDefault()\n focusAt(index + 1)\n } else if (event.key === 'ArrowUp') {\n event.preventDefault()\n focusAt(index < 0 ? items.length - 1 : index - 1)\n }\n }\n return <div className={cx('dsh-model-hub-subagent', NATIVE_CLASS.root, 'mh-root', variant === 'switcher' ? NATIVE_CLASS.switcherRoot : '', variant === 'switcher' ? 'mh-switcher-root' : '')}\n ref={rootRef}\n onKeyDown={navigate}\n onPointerLeave={scheduleHoverClose}\n >\n <button\n ref={triggerRef}\n onPointerEnter={(event) => { if (event.pointerType !== 'touch') scheduleHoverOpen() }}\n type=\"button\"\n className={variant === 'switcher'\n ? cx(NATIVE_CLASS.switcherTrigger, 'mh-switcher-trigger', ancestorSwitcher ? NATIVE_CLASS.ancestorSwitcherTrigger : '', ancestorSwitcher ? 'mh-ancestor-switcher-trigger' : '')\n : cx(NATIVE_CLASS.trigger, 'mh-trigger')}\n aria-haspopup=\"tree\"\n aria-expanded={open}\n aria-label={variant === 'switcher'\n ? t('switcher.aria', { title: switcherDisplayTitle })\n : t(runningCount > 0 ? runningCountKey : totalCountKey, { count: runningCount > 0 ? runningCount : directCount })}\n onClick={openTitle === undefined ? () => {\n cancelHoverOpen()\n cancelHoverClose()\n pinnedRef.current = true\n if (!open) changeOpen(true)\n } : () => {\n cancelHoverOpen()\n if (open) changeOpen(false)\n openTitle()\n }}\n onKeyDown={(event) => {\n if (event.key !== 'ArrowDown') return\n event.preventDefault()\n if (!open) changeOpen(true)\n queueMicrotask(() => { focusAt(0) })\n }}\n >\n {variant === 'switcher'\n ? <span className={cx(NATIVE_CLASS.switcherTitle, 'mh-switcher-title')}>{switcherDisplayTitle}</span>\n : <>\n {runningCount > 0 ? <span className={cx(NATIVE_CLASS.activitySlot, 'mh-activity-slot')}><StateDot state=\"ongoing\" /></span> : null}\n <span className=\"mh-count\">{t(totalCountKey, { count: directCount })}</span>\n </>}\n {variant === 'switcher' ? <SubagentSwitcherIcon />\n : <IconChevronDownOutlineRegular className={open ? cx(NATIVE_CLASS.triggerOpen, 'mh-trigger-open') : undefined} />}\n </button>\n {open ? createPortal(<div\n ref={menuRef}\n className={cx('dsh-model-hub-subagent', NATIVE_CLASS.menu, 'mh-menu')}\n style={menuPosition}\n onPointerEnter={(event) => { if (event.pointerType !== 'touch') cancelHoverClose() }}\n onPointerLeave={scheduleHoverClose}\n >\n <div className={cx(NATIVE_CLASS.menuBody, 'mh-menu-body')} role=\"tree\" aria-label={t('tree.aria')}>\n <CatalogRows\n parentSessionId={rootSessionId}\n currentSessionId={currentSessionId}\n catalog={presentedCatalog}\n catalogs={catalogs}\n projections={projections}\n summaries={summaries}\n expanded={expanded}\n level={1}\n openChild={openChild}\n openChildAside={openChildAside}\n refreshProjection={refreshProjection}\n requestProjection={requestProjection}\n toggleBranch={toggleBranch}\n closeCatalog={() => { changeOpen(false) }}\n t={t}\n routeT={routeT}\n />\n </div>\n </div>, document.body) : null}\n </div>\n}\n\n/** The host's chevron pair, used by the lineage switcher. */\nfunction SubagentSwitcherIcon() {\n return <svg width=\"16\" height=\"16\" viewBox=\"0 0 20 20\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M5.99951 12.7L8.95546 14.9478C9.40011 15.2859 9.62244 15.455 9.87526 15.488C9.95774 15.4988 10.0413 15.4988 10.1238 15.488C10.3766 15.455 10.5989 15.2859 11.0436 14.9478L13.9995 12.7\"\n stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <path d=\"M13.9995 7.7417L11.0436 5.49387C10.5989 5.15574 10.3766 4.98668 10.1238 4.95362C10.0413 4.94283 9.95775 4.94283 9.87527 4.95362C9.62245 4.98668 9.40012 5.15574 8.95547 5.49387L5.99952 7.7417\"\n stroke=\"currentColor\" strokeWidth=\"1.5\" />\n </svg>\n}\n\n/* ------------------------------------------------------------------ *\n * Cells\n * ------------------------------------------------------------------ */\n\n/**\n * Session-header catalog action for root sessions: the descendant count and\n * its dropdown after the preset label in the header actions band. Child\n * sessions render nothing here — their breadcrumb switcher in the lineage\n * slot owns the same navigation.\n */\nexport function SubagentCatalogAction(props: SubagentCatalogOwnerProps & SubagentCatalogInjected) {\n const t = useText(props.locale)\n const nativeT = (key: string, params?: Record<string, string | number>) => props.hostT(key, params)\n const isChild = props.useSessions((state) => state.byId[props.sessionId]?.origin === 'subagent')\n if (isChild) return null\n return <>\n <style>{css}</style>\n <CatalogDropdown\n rootSessionId={props.sessionId}\n variant=\"count\"\n useSessions={props.useSessions}\n useSessionStatus={props.useSessionStatus}\n openChild={props.openChild}\n openChildAside={props.openChildAside}\n refreshProjection={props.refreshProjection}\n t={nativeT}\n routeT={t}\n />\n </>\n}\n\n/**\n * Render one breadcrumb title together with its subagent navigation: the\n * ancestor switcher and, on a child session, its own descendant count.\n */\nexport function SubagentHeaderLineage(props: SubagentLineageOwnerProps & SubagentCatalogInjected) {\n const routeT = useText(props.locale)\n const address = props.useSession((session) => session.subagent?.address)\n const parentId = props.useSessions((state) => {\n if (address !== undefined && address.childSessionId === props.lineageSessionId) return address.parentSessionId\n for (const [candidate, snapshot] of Object.entries(state.projectionsBySession)) {\n if (snapshot.values.subagentCatalog?.some((entry) => entry.id === props.lineageSessionId)) return candidate\n }\n const summary = state.byId[props.lineageSessionId]\n return summary?.origin === 'subagent' ? summary.parentId : undefined\n })\n if (parentId === undefined) return null\n const shared = {\n useSessions: props.useSessions,\n useSessionStatus: props.useSessionStatus,\n openChild: props.openChild,\n openChildAside: props.openChildAside,\n refreshProjection: props.refreshProjection,\n t: props.hostT,\n routeT,\n }\n return <>\n <style>{css}</style>\n <CatalogDropdown\n rootSessionId={parentId}\n currentSessionId={props.lineageSessionId}\n variant=\"switcher\"\n displayTitle={props.displayTitle}\n {...props.openTitle === undefined ? {} : { openTitle: props.openTitle }}\n {...shared}\n />\n {props.openTitle === undefined ? <CatalogDropdown rootSessionId={props.lineageSessionId} variant=\"count\" {...shared} /> : null}\n </>\n}\n","/** Subagent model preferences and read-only route labels in the native catalog. */\nimport type { Context } from '@deepseek-ai/cordis'\nimport { officialUiCss } from '@klarkxy/dsh-plugin-kit/official-ui'\nimport { modelSettingsChangesIdentity } from '@klarkxy/dsh-plugin-kit/contracts'\nimport { IconModelNetworkSettings, registerSettingsSectionIcon } from '@klarkxy/dsh-plugin-kit/client-utils'\nimport { createModelSettingsSubscriber, mountModelSettingsChanges, type ModelSettingsSubscriberContext } from '@klarkxy/dsh-plugin-kit/model-settings-client'\nimport { MODEL_CATALOG_INJECT, readModelCatalog } from '@klarkxy/dsh-model-route'\nimport { modelMenuCss } from '@klarkxy/dsh-model-route/ui'\nimport { CAST_WATCH_NAMESPACES, CastPage, type CastApi } from './client-cast.tsx'\nimport { SubagentCatalogAction, SubagentHeaderLineage, type SubagentAddress, type LocaleLike } from './client-subagent-catalog.tsx'\n\nexport const name = 'dsh-subagent-models-client'\nexport const inject = ['slots', 'connection', ...MODEL_CATALOG_INJECT, 'locale', 'sessions', 'uiWorkspace', 'sidebarRight']\nexport const CHANNEL = '/dsh-model-hub'\nexport const BUNDLE = '@klarkxy/dsh-model-hub'\n\ntype Locale = LocaleLike & { bind(namespace: string): (key: string, params?: Record<string, string | number>) => string }\nfunction localeActive(locale: Locale): string {\n return String(typeof locale === 'string' ? locale : locale?.getSnapshot?.()?.active ?? 'en')\n}\n\nconst css = `${officialUiCss('dsh-model-hub')}${modelMenuCss}`\nexport function SubagentModelsPage({ api, locale }: { api: CastApi; locale: Locale }) {\n return <section className=\"dsh-model-hub dsh-ui-page\" aria-label={localeActive(locale).toLowerCase().startsWith('zh') ? '子代理' : 'Subagents'}>\n <style>{css}</style>\n <CastPage api={api} locale={locale} />\n </section>\n}\n\ninterface HubClientContext {\n slots: {\n inject(name: string, callback: () => unknown): unknown\n register(options: unknown, component: unknown): unknown\n }\n connection: { rpc: { call(channel: string, endpoint: string, payload: unknown): Promise<{ ok: boolean; value?: unknown; error?: { message?: string } }> } }\n remote: { session: { modelCatalog(): Promise<unknown> } }\n effect(callback: () => () => void | Promise<void>): unknown\n locale: Locale\n sessions: { refreshProjections(sessionId: string): Promise<void> }\n uiWorkspace: { openSession(target: SubagentAddress): void }\n sidebarRight: { openResource(address: string, options?: { kind?: string; preferNewPane?: boolean }): void }\n get?(name: string): unknown\n}\n\nfunction subagentChatAddress(address: SubagentAddress): string {\n const query = new URLSearchParams({ parent: address.parentSessionId, mode: address.mode })\n return `dsh-resource://subagentchat/session/${encodeURIComponent(address.childSessionId)}?${query}`\n}\n\nexport function apply(ctx: unknown): void {\n const client = ctx as HubClientContext\n mountModelSettingsChanges(ctx as ModelSettingsSubscriberContext, BUNDLE)\n const changes = createModelSettingsSubscriber(ctx as ModelSettingsSubscriberContext, BUNDLE, modelSettingsChangesIdentity(BUNDLE), namespace => CAST_WATCH_NAMESPACES.some(own => own === namespace))\n const call = async (endpoint: string, payload: unknown): Promise<never> => {\n const result = await client.connection.rpc.call(CHANNEL, endpoint, payload)\n if (!result?.ok) throw new Error(result?.error?.message || 'Request failed')\n return result.value as never\n }\n const api: CastApi = Object.freeze({\n modelCatalog: () => readModelCatalog(client),\n subscribeChanges: changes.subscribe,\n getCast: () => call('cast.get', {}),\n setCastEnabled: (payload: { enabled: boolean; expectedRevision: number }) => call('cast.setEnabled', payload),\n addCastRoute: (payload: { route: unknown; expectedRevision: number }) => call('cast.addRoute', payload),\n setCastRoute: (payload: { index: number; route: unknown; expectedRevision: number }) => call('cast.setRoute', payload),\n removeCastRoute: (payload: { index: number; expectedRevision: number }) => call('cast.removeRoute', payload),\n setCastTendency: (payload: { provider: string; model: string; tendency: string; expectedRevision: number }) => call('cast.setTendency', payload),\n setCastRoutePreferences: (payload: { provider: string; model: string; preferences: { tendency?: string; reasoningEffort?: string }; expectedRevision: number }) => call('cast.setPreferences', payload),\n })\n const locale = client.locale\n client.slots.inject('settings.section', () => [\n client.slots.register({\n name: 'settings.section', id: 'model-hub', order: 180,\n label: () => localeActive(locale).toLowerCase().startsWith('zh') ? '子代理' : 'Subagents',\n inject: () => ({ api, locale }),\n }, SubagentModelsPage),\n registerSettingsSectionIcon(ctx as Context, 'model-hub', 180, IconModelNetworkSettings),\n ])\n\n /* Replace the native catalog cell; the original returns on plugin unload. */\n const sidebarChatAvailable = Boolean(client.get?.('resources'))\n const catalogActions = (_parentSessionId: string) => ({\n openChild: (address: SubagentAddress) => { client.uiWorkspace.openSession(address) },\n openChildAside: (address: SubagentAddress) => {\n if (!sidebarChatAvailable) { client.uiWorkspace.openSession(address); return }\n client.sidebarRight.openResource(subagentChatAddress(address), { kind: 'subagentchat', preferNewPane: true })\n },\n refreshProjection: (sessionId: string) => {\n void Promise.resolve(client.sessions.refreshProjections(sessionId)).catch(() => {})\n },\n hostT: locale.bind('subagent'),\n locale,\n })\n client.slots.inject('conversation.session.header.lineage', () => client.slots.register({\n name: 'conversation.session.header.lineage', priority: -10, inject: catalogActions,\n }, SubagentHeaderLineage))\n client.slots.inject('conversation.session.header.actions', () => client.slots.register({\n name: 'conversation.session.header.actions', id: 'subagent-catalog', order: 10, priority: -10, inject: catalogActions,\n }, SubagentCatalogAction))\n}\n"],"mappings":"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"}
|