@fonlan/dsh-model-router 0.3.1 → 0.3.3

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/lib/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["useCallback","useSyncExternalStore","useState","useMemo","useSyncExternalStore","useState","useCallback","useRef","useMemo","Menu","IconGlobeOutline14","IconChevronDownOutline14"],"sources":["../../../src/client/locales.ts","../../../src/client/api.ts","../../../src/client/settings-card.tsx","../../../src/client/route-switcher.tsx","../../../src/client/index.tsx"],"sourcesContent":["// Locale namespace = the plugin's cordis id (kebab). DSH flat namespace keys\n// (settings + locale) use the internal id `model-router`; the scoped npm\n// package name is reserved for package-bound identifiers (exported `name`,\n// module-loader id, the /plugins/<pkg>/… route base).\nexport const LOCALE_NS = 'model-router'\n\nexport const zh = {\n settingsTitle: '模型路由',\n settingsCardDescription: '模型聚合、提供商切换与优先级顺序',\n expand: '展开',\n collapse: '收起',\n readOnly: '本部署的设置为只读。',\n loading: '加载中…',\n loadFailed: '加载失败:{message}',\n retry: '重试',\n refresh: '刷新',\n empty: '没有可路由的提供商或模型,请先在设置中添加提供商。',\n modelsCount: '共 {count} 个模型',\n activeBadge: '当前',\n noCredential: '未配置 API 密钥,不可选',\n dragHint: '拖拽调整优先级顺序',\n switchFailed: '切换失败:{message}',\n reorderFailed: '排序失败:{message}',\n providerCount: '{count} 个提供商',\n routeButtonLabel: '快速切换模型路由',\n routeButtonTitle: '切换当前模型的提供商',\n routeButtonAria: '切换当前模型提供商,当前为 {provider}',\n routeMenuTitle: '{model} · 选择提供商',\n routeLoading: '加载路由…',\n unknownProvider: '未知提供商',\n noCredentialShort: '未配置凭据',\n globalRouteHint: '切换后对所有会话的后续请求生效',\n showQuickSwitchLabel: '在输入栏显示快速路由切换按钮',\n showQuickSwitchDescription: '开启后,当当前模型是 model-router 路由时,在输入框模型选择器右侧显示 provider 快速切换按钮。',\n ignorePrefixLabel: '匹配时忽略模型 ID 前缀',\n ignorePrefixDescription: '开启后,deepseek/deepseek-v4-flash 与 deepseek-v4-flash 视为同一模型,统一显示不带前缀的模型 id(默认开启)。',\n}\n\nexport const en = {\n settingsTitle: 'Model Router',\n settingsCardDescription: 'Model aggregation, provider switching and preference order',\n expand: 'Expand',\n collapse: 'Collapse',\n readOnly: 'This deployment stores settings read-only.',\n loading: 'Loading…',\n loadFailed: 'Load failed: {message}',\n retry: 'Retry',\n refresh: 'Refresh',\n empty: 'No routable providers or models yet — add providers in settings first.',\n modelsCount: '{count} models',\n activeBadge: 'active',\n noCredential: 'No API key configured — not selectable',\n dragHint: 'Drag to adjust preference order',\n switchFailed: 'Switch failed: {message}',\n reorderFailed: 'Reorder failed: {message}',\n providerCount: '{count} providers',\n routeButtonLabel: 'Quick model route switcher',\n routeButtonTitle: 'Switch the current model provider',\n routeButtonAria: 'Switch current model provider, currently {provider}',\n routeMenuTitle: '{model} · Choose provider',\n routeLoading: 'Loading routes…',\n unknownProvider: 'Unknown provider',\n noCredentialShort: 'No credentials',\n globalRouteHint: 'Changes apply to subsequent requests in all sessions',\n showQuickSwitchLabel: 'Show quick route switcher in the composer',\n showQuickSwitchDescription: 'When enabled, a provider quick-switch button appears next to the model selector when the current model is a model-router route.',\n ignorePrefixLabel: 'Ignore model ID prefix when matching',\n ignorePrefixDescription: 'When enabled, deepseek/deepseek-v4-flash and deepseek-v4-flash are treated as the same model and shown without the prefix (on by default).',\n}\n","/** Client transport for the model-router settings API. */\nexport interface RouterProviderView {\n id: string\n name: string\n credentialConfigured: boolean\n}\n\nexport interface RouterModelView {\n id: string\n name: string\n active: string | null\n order: string[]\n providers: RouterProviderView[]\n}\n\nexport interface ModelRouterState {\n /** Whether the composer quick route-switcher button is enabled. */\n showQuickSwitch: boolean\n /** Whether model ids are matched with their leading vendor/ prefix ignored. */\n ignoreModelIdPrefix: boolean\n providers: RouterProviderView[]\n models: RouterModelView[]\n}\n\nexport class ModelRouterApiError extends Error {\n constructor(readonly code: string, message: string) {\n super(message)\n }\n}\n\nasync function call<T>(method: string, payload: Record<string, unknown> = {}): Promise<T> {\n let response: Response\n try {\n response = await fetch(`/plugins/@fonlan/dsh-model-router/api/${method}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n })\n } catch (error) {\n throw new ModelRouterApiError('network', error instanceof Error ? error.message : String(error))\n }\n const parsed: { ok?: boolean; value?: unknown; error?: { code?: string; message?: string } } | null\n = await response.json().catch(() => null)\n if (!response.ok || parsed === null || parsed.ok !== true || parsed.value === undefined) {\n throw new ModelRouterApiError(\n parsed?.error?.code ?? 'http',\n parsed?.error?.message ?? `HTTP ${response.status}`,\n )\n }\n return parsed.value as T\n}\n\nexport const api = {\n state: () => call<ModelRouterState>('state'),\n switchActive: (modelId: string, providerId: string) =>\n call<ModelRouterState>('switch-active', { modelId, providerId }),\n reorder: (modelId: string, order: string[]) =>\n call<ModelRouterState>('reorder', { modelId, order }),\n refresh: () => call<ModelRouterState>('refresh'),\n setShowQuickSwitch: (value: boolean) =>\n call<ModelRouterState>('set-show-quick-switch', { value }),\n setIgnoreModelIdPrefix: (value: boolean) =>\n call<ModelRouterState>('set-ignore-model-id-prefix', { value }),\n}\n","/**\n * The Model Router Settings Card (设置 → 插件 → 插件配置 → 模型路由).\n *\n * Renders its own expandable chrome aligned with the built-in plugin cards\n * (external plugins cannot import PluginCard): a header naming the plugin and\n * what its settings govern, disclosing the router controls in place. All\n * reads/mutations go through the plugin's fenced API; the server persists\n * through the `model-router` settings namespace, so a switch here is live for\n * the next request globally.\n *\n * The bound settings scope (the same `model-router` namespace the host half\n * registers) supplies the card's dispatch state: while the namespace is merely\n * loading the card stays mounted, and when it is unavailable (deployment\n * without the host half) nothing renders — matching the built-in cards. A\n * read-only deployment shows the built-in card's banner and disables the\n * mutation controls.\n */\nimport { useCallback, useEffect, useMemo, useState, useSyncExternalStore } from 'react'\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type { Translate } from '@deepseek-ai/dsh-client-ui-slots'\nimport { LOCALE_NS } from './locales'\nimport { api, type ModelRouterState, type RouterModelView } from './api'\nimport './settings-card.css'\n\n/** Client settings scope face (subset of @deepseek-ai/dsh-client-runtime). */\nexport interface SettingsScopeFace {\n getSnapshot(): {\n status: 'loading' | 'ready' | 'unavailable'\n writable: boolean\n }\n subscribe(listener: () => void): () => void\n}\n\nexport interface SettingsCardProps {\n /** The bound `model-router` settings scope (from the slot entry's inject face). */\n scope: SettingsScopeFace\n}\n\nfunction arrayMove<T>(list: readonly T[], from: number, to: number): T[] {\n const next = [...list]\n const [item] = next.splice(from, 1)\n next.splice(to, 0, item)\n return next\n}\n\nfunction useLocaleRevision(ctx: ClientContext): number {\n const subscribe = useCallback(\n (onChange: () => void) => {\n try {\n return ctx.locale.subscribe(onChange)\n } catch {\n return () => {}\n }\n },\n [ctx],\n )\n const getSnapshot = useCallback(() => {\n try {\n return ctx.locale.getLocale().revision\n } catch {\n return 0\n }\n }, [ctx])\n return useSyncExternalStore(subscribe, getSnapshot)\n}\n\nexport function makeSettingsCard(ctx: ClientContext): (props: SettingsCardProps) => JSX.Element | null {\n // Bound translation is namespace-typed; the card's props use the plain\n // Translate face (string keys), which the dict satisfies structurally.\n const t: Translate = (() => {\n try {\n return ctx.locale.bind(LOCALE_NS) as unknown as Translate\n } catch {\n return (key: string) => key\n }\n })()\n\n return function ModelRouterSettingsCard(props: SettingsCardProps): JSX.Element | null {\n const { scope } = props\n // Bind the methods: React invokes getSnapshot/subscribe as bare functions,\n // and SettingsScopeController's methods depend on `this`.\n const snapshot = useSyncExternalStore(\n (listener) => scope.subscribe(listener),\n () => scope.getSnapshot(),\n )\n useLocaleRevision(ctx)\n // Card-local disclosure: collapsed by default, like the built-in plugin cards.\n const [open, setOpen] = useState(false)\n const [state, setState] = useState<ModelRouterState | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [loading, setLoading] = useState(true)\n const [busyModel, setBusyModel] = useState<string | null>(null)\n const [drag, setDrag] = useState<{ modelId: string; index: number } | null>(null)\n const [quickSwitchBusy, setQuickSwitchBusy] = useState(false)\n const [ignorePrefixBusy, setIgnorePrefixBusy] = useState(false)\n\n const load = useCallback(async () => {\n setLoading(true)\n try {\n setState(await api.state())\n setError(null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setLoading(false)\n }\n }, [])\n\n useEffect(() => {\n void load()\n }, [load])\n\n const switchActive = useCallback(async (model: RouterModelView, providerId: string) => {\n if (model.active === providerId) return\n setBusyModel(model.id)\n try {\n setState(await api.switchActive(model.id, providerId))\n setError(null)\n } catch (cause) {\n setError(t('switchFailed', { message: cause instanceof Error ? cause.message : String(cause) }))\n } finally {\n setBusyModel(null)\n }\n }, [t])\n\n const reorder = useCallback(async (model: RouterModelView, from: number, to: number) => {\n if (from === to) return\n const order = arrayMove(model.order, from, to)\n setState(prev => prev === null ? prev : {\n ...prev,\n models: prev.models.map(m => (m.id === model.id ? { ...m, order } : m)),\n })\n setBusyModel(model.id)\n try {\n setState(await api.reorder(model.id, order))\n setError(null)\n } catch (cause) {\n setError(t('reorderFailed', { message: cause instanceof Error ? cause.message : String(cause) }))\n setState(prev => prev === null ? prev : {\n ...prev,\n models: prev.models.map(m => (m.id === model.id ? { ...m, order: model.order } : m)),\n })\n } finally {\n setBusyModel(null)\n }\n }, [t])\n\n const toggleQuickSwitch = useCallback(async (value: boolean) => {\n if (state === null) return\n const previous = state.showQuickSwitch\n setState(prev => prev === null ? prev : { ...prev, showQuickSwitch: value })\n setQuickSwitchBusy(true)\n try {\n setState(await api.setShowQuickSwitch(value))\n setError(null)\n } catch (cause) {\n setState(prev => prev === null ? prev : { ...prev, showQuickSwitch: previous })\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setQuickSwitchBusy(false)\n }\n }, [state])\n\n const toggleIgnorePrefix = useCallback(async (value: boolean) => {\n if (state === null) return\n const previous = state.ignoreModelIdPrefix\n setState(prev => prev === null ? prev : { ...prev, ignoreModelIdPrefix: value })\n setIgnorePrefixBusy(true)\n try {\n setState(await api.setIgnoreModelIdPrefix(value))\n setError(null)\n } catch (cause) {\n setState(prev => prev === null ? prev : { ...prev, ignoreModelIdPrefix: previous })\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setIgnorePrefixBusy(false)\n }\n }, [state])\n\n // The namespace is served by the host once the scope is ready. While it is\n // merely loading, keep the card mounted (the tab already dispatched it);\n // if it is unavailable (deployment without the host half), render nothing.\n if (snapshot.status === 'unavailable') return null\n const writable = snapshot.writable\n\n const models = useMemo(() => state?.models ?? [], [state])\n\n return (\n <li className=\"mr-settings-card\" data-open={open ? '' : undefined}>\n <button\n type=\"button\"\n className=\"mr-settings-head\"\n aria-expanded={open}\n aria-label={(open ? t('collapse') : t('expand')) + ':' + t('settingsTitle')}\n onClick={() => setOpen(!open)}\n >\n <span className=\"mr-settings-head-text\">\n <span className=\"mr-settings-title\">{t('settingsTitle')}</span>\n <span className=\"mr-settings-sub\">{t('settingsCardDescription')}</span>\n </span>\n <span className=\"mr-settings-chevron\" data-open={open ? '' : undefined} aria-hidden=\"true\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path d=\"M3.5 5.25L7 8.75L10.5 5.25\" stroke=\"currentColor\" strokeWidth=\"1.5\"\n strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </span>\n </button>\n {open && (\n <div className=\"mr-settings-body\">\n {!writable && (\n <p className=\"mr-settings-readonly\" role=\"status\">{t('readOnly')}</p>\n )}\n <div className=\"mr-root\">\n <label className=\"mr-quick-switch\">\n <input\n type=\"checkbox\"\n checked={state?.showQuickSwitch ?? true}\n disabled={loading || quickSwitchBusy || !writable}\n onChange={(event) => void toggleQuickSwitch(event.target.checked)}\n />\n <span className=\"mr-quick-switch-copy\">\n <span className=\"mr-quick-switch-label\">{t('showQuickSwitchLabel')}</span>\n <span className=\"mr-quick-switch-desc\">{t('showQuickSwitchDescription')}</span>\n </span>\n </label>\n <label className=\"mr-quick-switch\">\n <input\n type=\"checkbox\"\n checked={state?.ignoreModelIdPrefix ?? true}\n disabled={loading || ignorePrefixBusy || !writable}\n onChange={(event) => void toggleIgnorePrefix(event.target.checked)}\n />\n <span className=\"mr-quick-switch-copy\">\n <span className=\"mr-quick-switch-label\">{t('ignorePrefixLabel')}</span>\n <span className=\"mr-quick-switch-desc\">{t('ignorePrefixDescription')}</span>\n </span>\n </label>\n <div className=\"mr-toolbar\">\n <span className=\"mr-count\">{t('modelsCount', { count: models.length })}</span>\n <button type=\"button\" className=\"mr-button\" onClick={() => void load()} disabled={loading}>\n {t('refresh')}\n </button>\n </div>\n {error !== null && (\n <div className=\"mr-error\" role=\"alert\">{error}</div>\n )}\n {loading && models.length === 0 && (\n <div className=\"mr-empty\">{t('loading')}</div>\n )}\n {!loading && models.length === 0 && (\n <div className=\"mr-empty\">{t('empty')}</div>\n )}\n <div className=\"mr-models\">\n {models.map(model => (\n <ModelCard\n key={model.id}\n model={model}\n t={t}\n readOnly={!writable}\n busy={busyModel === model.id}\n dragging={drag}\n onDragStart={index => setDrag({ modelId: model.id, index })}\n onDragEnd={() => setDrag(null)}\n onDrop={index => {\n if (drag !== null && drag.modelId === model.id) {\n void reorder(model, drag.index, index)\n }\n setDrag(null)\n }}\n onSwitch={providerId => void switchActive(model, providerId)}\n />\n ))}\n </div>\n </div>\n </div>\n )}\n </li>\n )\n }\n}\n\ninterface ModelCardProps {\n model: RouterModelView\n t: Translate\n readOnly: boolean\n busy: boolean\n dragging: { modelId: string; index: number } | null\n onDragStart: (index: number) => void\n onDragEnd: () => void\n onDrop: (index: number) => void\n onSwitch: (providerId: string) => void\n}\n\nfunction ModelCard(props: ModelCardProps): JSX.Element {\n const { model, t, readOnly, busy, dragging } = props\n return (\n <section className={`mr-card${busy ? ' mr-card-busy' : ''}`}>\n <header className=\"mr-card-header\">\n <span className=\"mr-model-name\">{model.name}</span>\n <span className=\"mr-model-id\">{model.id}</span>\n <span className=\"mr-provider-count\">{t('providerCount', { count: model.providers.length })}</span>\n </header>\n <p className=\"mr-drag-hint\">{t('dragHint')}</p>\n <ul className=\"mr-providers\">\n {model.providers.map((provider, index) => {\n const active = provider.id === model.active\n const selectable = provider.credentialConfigured\n const dropTarget = dragging !== null && dragging.modelId === model.id && dragging.index !== index\n return (\n <li\n key={provider.id}\n className={[\n 'mr-provider',\n active ? 'mr-provider-active' : '',\n !selectable ? 'mr-provider-nocred' : '',\n dropTarget ? 'mr-provider-drop' : '',\n ].filter(Boolean).join(' ')}\n draggable={!busy && !readOnly && model.providers.length > 1}\n title={selectable ? undefined : t('noCredential')}\n onDragStart={(event) => {\n props.onDragStart(index)\n event.dataTransfer.effectAllowed = 'move'\n try {\n event.dataTransfer.setData('text/plain', model.id)\n } catch {\n // drag data is cosmetic for our own handler\n }\n }}\n onDragOver={(event) => {\n if (dragging !== null && dragging.modelId === model.id && dragging.index !== index) {\n event.preventDefault()\n event.dataTransfer.dropEffect = 'move'\n }\n }}\n onDrop={(event) => {\n if (dragging !== null && dragging.modelId === model.id) {\n event.preventDefault()\n props.onDrop(index)\n }\n }}\n onDragEnd={() => props.onDragEnd()}\n >\n <span className=\"mr-grip\" aria-hidden=\"true\">⠿</span>\n <button\n type=\"button\"\n className=\"mr-provider-button\"\n disabled={!selectable || busy || active || readOnly}\n onClick={() => props.onSwitch(provider.id)}\n >\n <span className=\"mr-provider-name\">{provider.name}</span>\n {!selectable && <span className=\"mr-provider-nocred-label\">· {t('noCredential')}</span>}\n </button>\n {active && <span className=\"mr-active-badge\">{t('activeBadge')}</span>}\n </li>\n )\n })}\n </ul>\n </section>\n )\n}\n","import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'\nimport type { ClientContext, SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client'\nimport type { ModelDirectoryState } from '@deepseek-ai/dsh-client-ui-model-selection/client'\nimport type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport { IconChevronDownOutline14, IconGlobeOutline14, Menu, type MenuEntry } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-model-selection/client'\nimport { api, type ModelRouterState, type RouterModelView } from './api'\nimport { LOCALE_NS } from './locales'\nimport './route-switcher.css'\n\nconst ROUTER_PROVIDER_ID = 'model-router'\n\ninterface RouteSwitcherInjected {\n available: boolean\n directory: SnapshotStore<ModelDirectoryState>\n load: () => void\n}\n\ntype RouteSwitcherProps = PropsRuntime<'conversation.input.right'>\n & PropsLocale<typeof LOCALE_NS>\n & RouteSwitcherInjected\n\ntype RouteProvider = RouterModelView['providers'][number]\n\n/**\n * The quick route switcher lives beside DSH's model seat in the composer row.\n * It reads the same per-session model directory as the host model picker, but\n * only appears when the selected model is the virtual model-router route.\n */\nexport function RouteSwitcher({\n session,\n available,\n directory,\n load,\n t,\n}: RouteSwitcherProps): JSX.Element | null {\n const directoryState = useSyncExternalStore(\n onChange => directory.subscribe(onChange),\n () => directory.getSnapshot(),\n () => directory.getSnapshot(),\n )\n const current = directoryState.current\n const [routerState, setRouterState] = useState<ModelRouterState | null>(null)\n const [routerLoading, setRouterLoading] = useState(false)\n const [routerError, setRouterError] = useState<string | null>(null)\n const [open, setOpen] = useState(false)\n const [busyProvider, setBusyProvider] = useState<string | null>(null)\n\n const isRouterModel = available && current?.provider === ROUTER_PROVIDER_ID\n const modelId = isRouterModel ? current.model : null\n\n /**\n * Fetch the router state. `silent` skips the busy state: background\n * refreshes (directory-ready, model switch) should never gray out the\n * button — only the initial load and explicit user actions do.\n */\n const loadRouterState = useCallback(async (silent = false) => {\n if (!silent) setRouterLoading(true)\n try {\n setRouterState(await api.state())\n setRouterError(null)\n } catch (cause) {\n setRouterError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n if (!silent) setRouterLoading(false)\n }\n }, [])\n\n useEffect(() => {\n if (!available) return\n load()\n }, [available, load])\n\n // Fetch the global toggle (and the model's provider list) on mount too, so a\n // \"hide quick switcher\" setting applies even before the model directory\n // settles. The button stays visible while the value is unknown (default on).\n useEffect(() => {\n if (!available) return\n void loadRouterState()\n }, [available])\n\n useEffect(() => {\n setOpen(false)\n setBusyProvider(null)\n // Keep the last-known router state across model switches: the global\n // provider count stays valid while the per-model row refetches, so a\n // single-provider router hides the button without a loading flash.\n setRouterError(null)\n }, [modelId])\n\n // The model-selection directory is refreshed when another session changes\n // the router settings document. Re-read the global router state after that\n // refresh so this button never shows a stale active provider. Include the\n // model id: switching between two router models can leave the directory in\n // the same ready state while changing the API row we need to display.\n //\n // This refresh is debounced and silent: directory refreshes fire in bursts\n // (each settings change re-loads it), and the whole point of the silent\n // mode is that background refreshes never gray out the button.\n const refreshTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n useEffect(() => {\n if (!isRouterModel || modelId === null || directoryState.status !== 'ready') return\n if (refreshTimer.current !== null) clearTimeout(refreshTimer.current)\n refreshTimer.current = setTimeout(() => {\n refreshTimer.current = null\n void loadRouterState(true)\n }, 300)\n return () => {\n if (refreshTimer.current !== null) clearTimeout(refreshTimer.current)\n refreshTimer.current = null\n }\n }, [directoryState.status, isRouterModel, loadRouterState, modelId])\n\n const routeModel = useMemo(\n () => modelId === null\n ? undefined\n : routerState?.models.find(model => model.id === modelId),\n [modelId, routerState],\n )\n\n const providers = useMemo(() => {\n if (routeModel === undefined) return []\n const byId = new Map(routeModel.providers.map(provider => [provider.id, provider]))\n const ordered = routeModel.order\n .map(id => byId.get(id))\n .filter((provider): provider is RouteProvider => provider !== undefined)\n const seen = new Set(ordered.map(provider => provider.id))\n return [...ordered, ...routeModel.providers.filter(provider => !seen.has(provider.id))]\n }, [routeModel])\n\n const switchProvider = useCallback(async (providerId: string) => {\n if (modelId === null || routeModel === undefined || routeModel.active === providerId) {\n setOpen(false)\n return\n }\n setBusyProvider(providerId)\n try {\n const next = await api.switchActive(modelId, providerId)\n setRouterState(next)\n setRouterError(null)\n setOpen(false)\n // The model directory also listens for settings updates, but an explicit\n // refresh keeps the host model picker description in sync immediately.\n load()\n } catch (cause) {\n setRouterError(t('switchFailed', { message: cause instanceof Error ? cause.message : String(cause) }))\n } finally {\n setBusyProvider(null)\n }\n }, [load, modelId, routeModel, t])\n\n if (session.removed || !isRouterModel) return null\n if (routerState?.showQuickSwitch === false) return null\n\n const activeProvider = providers.find(provider => provider.id === routeModel?.active)\n const activeName = activeProvider?.name ?? routeModel?.active ?? t('routeLoading')\n // Nothing to switch between: hide when the router serves fewer than two\n // providers in total (known as soon as the global state resolves, even\n // while the per-model row is still loading), or when the current model\n // is served by a single provider.\n if (routerState !== null && routerState.providers.length < 2) return null\n if (routeModel !== undefined && providers.length < 2) return null\n\n const menuItems: MenuEntry[] = routeModel === undefined\n ? [{\n type: 'label',\n id: 'route-status',\n text: routerError ?? t('routeLoading'),\n }]\n : [\n {\n type: 'label',\n id: 'route-model',\n text: t('routeMenuTitle', { model: modelId }),\n },\n ...providers.map(provider => ({\n id: provider.id,\n label: (\n <span className=\"mr-route-item-copy\">\n <span className=\"mr-route-item-name\">{provider.name}</span>\n {!provider.credentialConfigured && (\n <span className=\"mr-route-item-note\">{t('noCredentialShort')}</span>\n )}\n </span>\n ),\n disabled: !provider.credentialConfigured || busyProvider !== null,\n })),\n ...(routerError === null ? [] : [{\n id: 'route-error',\n label: routerError,\n disabled: true,\n danger: true,\n }]),\n ]\n\n return (\n <Menu\n className=\"mr-route-anchor\"\n open={open}\n side=\"top\"\n align=\"end\"\n portal\n compact\n dense\n items={menuItems}\n selectedId={routeModel?.active ?? undefined}\n onSelect={id => {\n if (id === 'route-error' || routeModel === undefined) {\n void loadRouterState()\n load()\n return\n }\n void switchProvider(id)\n }}\n onClose={() => setOpen(false)}\n footer={[\n {\n type: 'label',\n id: 'route-global-hint',\n text: t('globalRouteHint'),\n },\n ]}\n anchor={(\n <button\n type=\"button\"\n className=\"mr-route-trigger\"\n aria-label={t('routeButtonAria', { provider: activeName })}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n disabled={routerLoading || busyProvider !== null}\n onClick={() => {\n setOpen(value => !value)\n if (!open) {\n void loadRouterState()\n load()\n }\n }}\n title={t('routeButtonTitle')}\n >\n <IconGlobeOutline14 />\n <span className=\"mr-route-trigger-label\">{activeName}</span>\n <span className=\"mr-route-trigger-chevron\" aria-hidden>\n <IconChevronDownOutline14 />\n </span>\n </button>\n )}\n />\n )\n}\n\n/** Register the quick route switcher into the composer right-side tool row. */\nexport function registerRouteSwitcher(ctx: ClientContext): void {\n const t = ctx.locale.bind(LOCALE_NS)\n ctx.inject(['slots', 'modelDirectories'], scope => {\n const models = scope.modelDirectories\n const sessions = scope.sessions\n scope.slots.inject('conversation.input.right', () => scope.slots.register({\n name: 'conversation.input.right',\n id: 'model-router-route-switcher',\n order: 100,\n label: () => t('routeButtonLabel'),\n locale: LOCALE_NS,\n inject: (sessionId) => {\n const directory = models.directoryFor(sessionId)\n const available = sessions.subagentAddress(sessionId) === undefined\n return {\n available,\n directory: directory.store,\n load: () => {\n if (available) directory.load().catch(() => {})\n },\n }\n },\n }, RouteSwitcher as never))\n })\n}","/**\n * @fonlan/dsh-model-router client half: the plugin's own Settings Card\n * (设置 → 插件 → 插件配置 → 模型路由) plus a quick provider switcher beside\n * DSH's composer model selector.\n */\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-slots'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-model-selection/client'\nimport { LOCALE_NS, zh, en } from './locales'\nimport { makeSettingsCard, type SettingsScopeFace } from './settings-card'\nimport { registerRouteSwitcher } from './route-switcher'\n\n/** The settings namespace this card edits (must match the host half). */\nconst ROUTER_NS = 'model-router'\n\n/** Slots face: the keyed `settings.plugin.item` declaration ships with the web\n * app's ui-settings-plugins package, which external plugins do not depend on;\n * the register call below is typed through this local face (erased at build). */\ninterface Slots {\n inject(name: string, callback: () => unknown): unknown\n register(def: { name: string; key: string; inject?: () => unknown }, component: unknown): unknown\n}\n\n/** Services required before mounting (provided by the client runtime). */\nexport const inject = ['slots', 'locale', 'modelDirectories', 'sessions', 'settingsScope', 'connection', 'remote']\n\n/** Client plugin body. */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => {\n const off = ctx.locale.register(LOCALE_NS, { zh, en })\n return () => off()\n }, 'model-router: dictionaries')\n\n const SettingsCard = makeSettingsCard(ctx)\n\n // The card registers on the `settings.plugin.item` slot keyed by the\n // `model-router` settings namespace (the same string the host half\n // registers), so it appears inside 设置 → 插件 → 插件配置, paired with the\n // namespace by the tab.\n const services = ctx as unknown as {\n slots: Slots\n settingsScope: { bind(spec: { namespace: string }): SettingsScopeFace }\n }\n const scope = services.settingsScope.bind({ namespace: ROUTER_NS })\n\n services.slots.inject('settings.plugin.item', () =>\n services.slots.register(\n {\n name: 'settings.plugin.item',\n key: ROUTER_NS,\n inject: () => ({ scope }),\n },\n SettingsCard,\n ),\n )\n\n registerRouteSwitcher(ctx)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["useCallback","useSyncExternalStore","useState","useMemo","useSyncExternalStore","useState","useRef","useId","useCallback","useMemo","IconChevronDownOutline14","IconChevronRightOutline14","IconCheckOutline16","Toast","IconWarningOutline16"],"sources":["../../../src/client/locales.ts","../../../src/client/api.ts","../../../src/client/settings-card.tsx","../../../src/client/model-seat.tsx","../../../src/client/index.tsx"],"sourcesContent":["// Locale namespace = the plugin's cordis id (kebab). DSH flat namespace keys\n// (settings + locale) use the internal id `model-router`; the scoped npm\n// package name is reserved for package-bound identifiers (exported `name`,\n// module-loader id, the /plugins/<pkg>/… route base).\nexport const LOCALE_NS = 'model-router'\n\nexport const zh = {\n settingsTitle: '模型路由',\n settingsCardDescription: '模型聚合、提供商切换与优先级顺序',\n expand: '展开',\n collapse: '收起',\n readOnly: '本部署的设置为只读。',\n loading: '加载中…',\n loadFailed: '加载失败:{message}',\n retry: '重试',\n refresh: '刷新',\n empty: '没有可路由的提供商或模型,请先在设置中添加提供商。',\n modelsCount: '共 {count} 个模型',\n activeBadge: '当前',\n noCredential: '未配置 API 密钥,不可选',\n dragHint: '拖拽调整优先级顺序',\n switchFailed: '切换失败:{message}',\n reorderFailed: '排序失败:{message}',\n providerCount: '{count} 个提供商',\n seatLabel: '模型选择(含提供商切换)',\n menuAria: '模型、提供商与推理等级',\n menuModel: '模型',\n menuProvider: '提供商',\n menuEffort: '推理等级',\n triggerFallback: '选择模型',\n triggerSelectAria: '选择模型',\n triggerAria: '选择模型,当前 {model}',\n triggerAriaEffort: '选择模型,当前 {model},推理等级 {effort}',\n effortProviderDefault: 'Default',\n statusLoading: '正在刷新模型列表…',\n errorAction: '模型操作失败:{message}',\n actionReload: '重新加载',\n warningGroupLoad: '{name} 加载失败:{message}',\n emptyModels: '没有可用的模型。',\n emptyEfforts: '当前模型未提供推理等级。',\n routeMenuTitle: '{model} · 选择提供商',\n routeLoading: '加载路由…',\n noCredentialShort: '未配置凭据',\n globalRouteHint: '切换后对所有会话的后续请求生效',\n showQuickSwitchLabel: '在模型选择菜单中显示提供商切换',\n showQuickSwitchDescription: '开启后,当当前模型是 model-router 路由时,模型选择弹出菜单会显示提供商列表入口,可直接切换该模型的激活提供商。',\n ignorePrefixLabel: '匹配时忽略模型 ID 前缀',\n ignorePrefixDescription: '开启后,deepseek/deepseek-v4-flash 与 deepseek-v4-flash 视为同一模型,统一显示不带前缀的模型 id(默认开启)。',\n sortTitle: '模型显示顺序',\n sortDescription: '模型选择列表中 model-router 分组内模型的排列方式。',\n sortModeCustom: '自定义',\n sortModeName: '按名称',\n sortModeRecent: '最近使用',\n sortModeDescCustom: '按下方拖拽的手动顺序排列',\n sortModeDescName: '按模型名称排序(数字感知)',\n sortModeDescRecent: '最近用过的模型排在最前',\n sortCustomHint: '拖拽调整模型在模型选择列表中的显示顺序',\n sortFailed: '排序设置失败:{message}',\n}\n\nexport const en = {\n settingsTitle: 'Model Router',\n settingsCardDescription: 'Model aggregation, provider switching and preference order',\n expand: 'Expand',\n collapse: 'Collapse',\n readOnly: 'This deployment stores settings read-only.',\n loading: 'Loading…',\n loadFailed: 'Load failed: {message}',\n retry: 'Retry',\n refresh: 'Refresh',\n empty: 'No routable providers or models yet — add providers in settings first.',\n modelsCount: '{count} models',\n activeBadge: 'active',\n noCredential: 'No API key configured — not selectable',\n dragHint: 'Drag to adjust preference order',\n switchFailed: 'Switch failed: {message}',\n reorderFailed: 'Reorder failed: {message}',\n providerCount: '{count} providers',\n seatLabel: 'Model selection (with provider switching)',\n menuAria: 'Model, provider and reasoning effort',\n menuModel: 'Model',\n menuProvider: 'Provider',\n menuEffort: 'Effort',\n triggerFallback: 'Select model',\n triggerSelectAria: 'Select model',\n triggerAria: 'Select model, current {model}',\n triggerAriaEffort: 'Select model, current {model}, reasoning effort {effort}',\n effortProviderDefault: 'Default',\n statusLoading: 'Refreshing model list…',\n errorAction: 'Model operation failed: {message}',\n actionReload: 'Reload',\n warningGroupLoad: '{name} failed to load: {message}',\n emptyModels: 'No models available.',\n emptyEfforts: 'This model provides no reasoning effort levels.',\n routeMenuTitle: '{model} · Choose provider',\n routeLoading: 'Loading routes…',\n noCredentialShort: 'No credentials',\n globalRouteHint: 'Changes apply to subsequent requests in all sessions',\n showQuickSwitchLabel: 'Show provider switching in the model picker',\n showQuickSwitchDescription: 'When enabled, the model picker menu shows a provider list entry that switches the active provider, for model-router routes.',\n ignorePrefixLabel: 'Ignore model ID prefix when matching',\n ignorePrefixDescription: 'When enabled, deepseek/deepseek-v4-flash and deepseek-v4-flash are treated as the same model and shown without the prefix (on by default).',\n sortTitle: 'Model display order',\n sortDescription: 'How models inside the model-router group are ordered in the model picker.',\n sortModeCustom: 'Custom',\n sortModeName: 'By name',\n sortModeRecent: 'Recently used',\n sortModeDescCustom: 'Manual order via drag below',\n sortModeDescName: 'Sort by model name (numeric-aware)',\n sortModeDescRecent: 'Most recently used models first',\n sortCustomHint: 'Drag to reorder models in the model picker',\n sortFailed: 'Sort setting failed: {message}',\n}\n","/** Client transport for the model-router settings API. */\nexport interface RouterProviderView {\n id: string\n name: string\n credentialConfigured: boolean\n}\n\nexport type ModelSortMode = 'custom' | 'name' | 'recent'\n\nexport interface RouterModelView {\n id: string\n name: string\n active: string | null\n order: string[]\n providers: RouterProviderView[]\n}\n\nexport interface ModelRouterState {\n /** Whether provider switching is shown inside the composer model picker menu. */\n showQuickSwitch: boolean\n /** Whether model ids are matched with their leading vendor/ prefix ignored. */\n ignoreModelIdPrefix: boolean\n /** The model-list display order mode (custom | name | recent). */\n modelSort: ModelSortMode\n /** Explicit model id order for custom mode (display order). */\n modelOrder: string[]\n providers: RouterProviderView[]\n models: RouterModelView[]\n}\n\nexport class ModelRouterApiError extends Error {\n constructor(readonly code: string, message: string) {\n super(message)\n }\n}\n\nasync function call<T>(method: string, payload: Record<string, unknown> = {}): Promise<T> {\n let response: Response\n try {\n response = await fetch(`/plugins/@fonlan/dsh-model-router/api/${method}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n })\n } catch (error) {\n throw new ModelRouterApiError('network', error instanceof Error ? error.message : String(error))\n }\n const parsed: { ok?: boolean; value?: unknown; error?: { code?: string; message?: string } } | null\n = await response.json().catch(() => null)\n if (!response.ok || parsed === null || parsed.ok !== true || parsed.value === undefined) {\n throw new ModelRouterApiError(\n parsed?.error?.code ?? 'http',\n parsed?.error?.message ?? `HTTP ${response.status}`,\n )\n }\n return parsed.value as T\n}\n\nexport const api = {\n state: () => call<ModelRouterState>('state'),\n switchActive: (modelId: string, providerId: string) =>\n call<ModelRouterState>('switch-active', { modelId, providerId }),\n reorder: (modelId: string, order: string[]) =>\n call<ModelRouterState>('reorder', { modelId, order }),\n refresh: () => call<ModelRouterState>('refresh'),\n setShowQuickSwitch: (value: boolean) =>\n call<ModelRouterState>('set-show-quick-switch', { value }),\n setIgnoreModelIdPrefix: (value: boolean) =>\n call<ModelRouterState>('set-ignore-model-id-prefix', { value }),\n setModelSort: (mode: ModelSortMode) =>\n call<ModelRouterState>('set-model-sort', { mode }),\n setModelOrder: (order: string[]) =>\n call<ModelRouterState>('set-model-order', { order }),\n}\n","/**\n * The Model Router Settings Card (设置 → 插件 → 插件配置 → 模型路由).\n *\n * Renders its own expandable chrome aligned with the built-in plugin cards\n * (external plugins cannot import PluginCard): a header naming the plugin and\n * what its settings govern, disclosing the router controls in place. All\n * reads/mutations go through the plugin's fenced API; the server persists\n * through the `model-router` settings namespace, so a switch here is live for\n * the next request globally.\n *\n * The bound settings scope (the same `model-router` namespace the host half\n * registers) supplies the card's dispatch state: while the namespace is merely\n * loading the card stays mounted, and when it is unavailable (deployment\n * without the host half) nothing renders — matching the built-in cards. A\n * read-only deployment shows the built-in card's banner and disables the\n * mutation controls.\n */\nimport { useCallback, useEffect, useMemo, useState, useSyncExternalStore } from 'react'\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type { Translate } from '@deepseek-ai/dsh-client-ui-slots'\nimport { LOCALE_NS } from './locales'\nimport { api, type ModelRouterState, type ModelSortMode, type RouterModelView } from './api'\nimport './settings-card.css'\n\n/** Client settings scope face (subset of @deepseek-ai/dsh-client-runtime). */\nexport interface SettingsScopeFace {\n getSnapshot(): {\n status: 'loading' | 'ready' | 'unavailable'\n writable: boolean\n }\n subscribe(listener: () => void): () => void\n}\n\nexport interface SettingsCardProps {\n /** The bound `model-router` settings scope (from the slot entry's inject face). */\n scope: SettingsScopeFace\n}\n\nfunction arrayMove<T>(list: readonly T[], from: number, to: number): T[] {\n const next = [...list]\n const [item] = next.splice(from, 1)\n next.splice(to, 0, item)\n return next\n}\n\nfunction useLocaleRevision(ctx: ClientContext): number {\n const subscribe = useCallback(\n (onChange: () => void) => {\n try {\n return ctx.locale.subscribe(onChange)\n } catch {\n return () => {}\n }\n },\n [ctx],\n )\n const getSnapshot = useCallback(() => {\n try {\n return ctx.locale.getLocale().revision\n } catch {\n return 0\n }\n }, [ctx])\n return useSyncExternalStore(subscribe, getSnapshot)\n}\n\nexport function makeSettingsCard(ctx: ClientContext): (props: SettingsCardProps) => JSX.Element | null {\n // Bound translation is namespace-typed; the card's props use the plain\n // Translate face (string keys), which the dict satisfies structurally.\n const t: Translate = (() => {\n try {\n return ctx.locale.bind(LOCALE_NS) as unknown as Translate\n } catch {\n return (key: string) => key\n }\n })()\n\n return function ModelRouterSettingsCard(props: SettingsCardProps): JSX.Element | null {\n const { scope } = props\n // Bind the methods: React invokes getSnapshot/subscribe as bare functions,\n // and SettingsScopeController's methods depend on `this`.\n const snapshot = useSyncExternalStore(\n (listener) => scope.subscribe(listener),\n () => scope.getSnapshot(),\n )\n useLocaleRevision(ctx)\n // Card-local disclosure: collapsed by default, like the built-in plugin cards.\n const [open, setOpen] = useState(false)\n const [state, setState] = useState<ModelRouterState | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [loading, setLoading] = useState(true)\n const [busyModel, setBusyModel] = useState<string | null>(null)\n const [drag, setDrag] = useState<{ modelId: string; index: number } | null>(null)\n const [quickSwitchBusy, setQuickSwitchBusy] = useState(false)\n const [ignorePrefixBusy, setIgnorePrefixBusy] = useState(false)\n const [sortBusy, setSortBusy] = useState(false)\n const [modelDrag, setModelDrag] = useState<{ index: number } | null>(null)\n\n const load = useCallback(async () => {\n setLoading(true)\n try {\n setState(await api.state())\n setError(null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setLoading(false)\n }\n }, [])\n\n useEffect(() => {\n void load()\n }, [load])\n\n const switchActive = useCallback(async (model: RouterModelView, providerId: string) => {\n if (model.active === providerId) return\n setBusyModel(model.id)\n try {\n setState(await api.switchActive(model.id, providerId))\n setError(null)\n } catch (cause) {\n setError(t('switchFailed', { message: cause instanceof Error ? cause.message : String(cause) }))\n } finally {\n setBusyModel(null)\n }\n }, [t])\n\n const reorder = useCallback(async (model: RouterModelView, from: number, to: number) => {\n if (from === to) return\n const order = arrayMove(model.order, from, to)\n setState(prev => prev === null ? prev : {\n ...prev,\n models: prev.models.map(m => (m.id === model.id ? { ...m, order } : m)),\n })\n setBusyModel(model.id)\n try {\n setState(await api.reorder(model.id, order))\n setError(null)\n } catch (cause) {\n setError(t('reorderFailed', { message: cause instanceof Error ? cause.message : String(cause) }))\n setState(prev => prev === null ? prev : {\n ...prev,\n models: prev.models.map(m => (m.id === model.id ? { ...m, order: model.order } : m)),\n })\n } finally {\n setBusyModel(null)\n }\n }, [t])\n\n const toggleQuickSwitch = useCallback(async (value: boolean) => {\n if (state === null) return\n const previous = state.showQuickSwitch\n setState(prev => prev === null ? prev : { ...prev, showQuickSwitch: value })\n setQuickSwitchBusy(true)\n try {\n setState(await api.setShowQuickSwitch(value))\n setError(null)\n } catch (cause) {\n setState(prev => prev === null ? prev : { ...prev, showQuickSwitch: previous })\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setQuickSwitchBusy(false)\n }\n }, [state])\n\n const toggleIgnorePrefix = useCallback(async (value: boolean) => {\n if (state === null) return\n const previous = state.ignoreModelIdPrefix\n setState(prev => prev === null ? prev : { ...prev, ignoreModelIdPrefix: value })\n setIgnorePrefixBusy(true)\n try {\n setState(await api.setIgnoreModelIdPrefix(value))\n setError(null)\n } catch (cause) {\n setState(prev => prev === null ? prev : { ...prev, ignoreModelIdPrefix: previous })\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setIgnorePrefixBusy(false)\n }\n }, [state])\n\n const changeModelSort = useCallback(async (mode: ModelSortMode) => {\n if (state === null || state.modelSort === mode) return\n const previous = state.modelSort\n setState(prev => prev === null ? prev : { ...prev, modelSort: mode })\n setSortBusy(true)\n try {\n setState(await api.setModelSort(mode))\n setError(null)\n } catch (cause) {\n setState(prev => prev === null ? prev : { ...prev, modelSort: previous })\n setError(t('sortFailed', { message: cause instanceof Error ? cause.message : String(cause) }))\n } finally {\n setSortBusy(false)\n }\n }, [state, t])\n\n const moveModel = useCallback(async (from: number, to: number) => {\n if (state === null || from === to) return\n // The drag list shows the full display order (modelOrder + catalog\n // tail); persist the whole reordered id list as the new custom order.\n const ids = state.models.map(model => model.id)\n const order = arrayMove(ids, from, to)\n setState(prev => prev === null ? prev : { ...prev, modelOrder: order })\n setSortBusy(true)\n try {\n setState(await api.setModelOrder(order))\n setError(null)\n } catch (cause) {\n setState(prev => prev === null ? prev : { ...prev, modelOrder: state.modelOrder })\n setError(t('sortFailed', { message: cause instanceof Error ? cause.message : String(cause) }))\n } finally {\n setSortBusy(false)\n }\n }, [state, t])\n\n // The namespace is served by the host once the scope is ready. While it is\n // merely loading, keep the card mounted (the tab already dispatched it);\n // if it is unavailable (deployment without the host half), render nothing.\n if (snapshot.status === 'unavailable') return null\n const writable = snapshot.writable\n\n const models = useMemo(() => state?.models ?? [], [state])\n\n return (\n <li className=\"mr-settings-card\" data-open={open ? '' : undefined}>\n <button\n type=\"button\"\n className=\"mr-settings-head\"\n aria-expanded={open}\n aria-label={(open ? t('collapse') : t('expand')) + ':' + t('settingsTitle')}\n onClick={() => setOpen(!open)}\n >\n <span className=\"mr-settings-head-text\">\n <span className=\"mr-settings-title\">{t('settingsTitle')}</span>\n <span className=\"mr-settings-sub\">{t('settingsCardDescription')}</span>\n </span>\n <span className=\"mr-settings-chevron\" data-open={open ? '' : undefined} aria-hidden=\"true\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path d=\"M3.5 5.25L7 8.75L10.5 5.25\" stroke=\"currentColor\" strokeWidth=\"1.5\"\n strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </span>\n </button>\n {open && (\n <div className=\"mr-settings-body\">\n {!writable && (\n <p className=\"mr-settings-readonly\" role=\"status\">{t('readOnly')}</p>\n )}\n <div className=\"mr-root\">\n <label className=\"mr-quick-switch\">\n <input\n type=\"checkbox\"\n checked={state?.showQuickSwitch ?? true}\n disabled={loading || quickSwitchBusy || !writable}\n onChange={(event) => void toggleQuickSwitch(event.target.checked)}\n />\n <span className=\"mr-quick-switch-copy\">\n <span className=\"mr-quick-switch-label\">{t('showQuickSwitchLabel')}</span>\n <span className=\"mr-quick-switch-desc\">{t('showQuickSwitchDescription')}</span>\n </span>\n </label>\n <label className=\"mr-quick-switch\">\n <input\n type=\"checkbox\"\n checked={state?.ignoreModelIdPrefix ?? true}\n disabled={loading || ignorePrefixBusy || !writable}\n onChange={(event) => void toggleIgnorePrefix(event.target.checked)}\n />\n <span className=\"mr-quick-switch-copy\">\n <span className=\"mr-quick-switch-label\">{t('ignorePrefixLabel')}</span>\n <span className=\"mr-quick-switch-desc\">{t('ignorePrefixDescription')}</span>\n </span>\n </label>\n <div className=\"mr-sort\">\n <div className=\"mr-sort-head\">\n <span className=\"mr-sort-title\">{t('sortTitle')}</span>\n <span className=\"mr-sort-desc\">{t('sortDescription')}</span>\n </div>\n <div className=\"mr-sort-modes\" role=\"radiogroup\" aria-label={t('sortTitle')}>\n {(['custom', 'name', 'recent'] as const).map(mode => (\n <label key={mode} className=\"mr-sort-mode\">\n <input\n type=\"radio\"\n name=\"mr-model-sort\"\n checked={state?.modelSort === mode}\n disabled={loading || sortBusy || !writable}\n onChange={() => void changeModelSort(mode)}\n />\n <span className=\"mr-sort-mode-copy\">\n <span className=\"mr-sort-mode-label\">{t(`sortMode${mode[0].toUpperCase()}${mode.slice(1)}`)}</span>\n <span className=\"mr-sort-mode-desc\">{t(`sortModeDesc${mode[0].toUpperCase()}${mode.slice(1)}`)}</span>\n </span>\n </label>\n ))}\n </div>\n {state?.modelSort === 'custom' && (\n <div className=\"mr-sort-custom\">\n <p className=\"mr-sort-hint\">{t('sortCustomHint')}</p>\n <ol className=\"mr-sort-list\">\n {models.map((model, index) => {\n const dropTarget = modelDrag !== null && modelDrag.index !== index\n return (\n <li\n key={model.id}\n className={[\n 'mr-sort-item',\n dropTarget ? 'mr-sort-item-drop' : '',\n sortBusy ? 'mr-sort-item-busy' : '',\n ].filter(Boolean).join(' ')}\n draggable={!sortBusy && writable}\n onDragStart={(event) => {\n setModelDrag({ index })\n event.dataTransfer.effectAllowed = 'move'\n try {\n event.dataTransfer.setData('text/plain', model.id)\n } catch {\n // drag data is cosmetic for our own handler\n }\n }}\n onDragOver={(event) => {\n if (modelDrag !== null && modelDrag.index !== index) {\n event.preventDefault()\n event.dataTransfer.dropEffect = 'move'\n }\n }}\n onDrop={(event) => {\n if (modelDrag !== null && modelDrag.index !== index) {\n event.preventDefault()\n moveModel(modelDrag.index, index)\n }\n setModelDrag(null)\n }}\n onDragEnd={() => setModelDrag(null)}\n >\n <span className=\"mr-grip\" aria-hidden=\"true\">⠿</span>\n <span className=\"mr-sort-model-name\">{model.name}</span>\n <span className=\"mr-sort-model-id\">{model.id}</span>\n </li>\n )\n })}\n </ol>\n </div>\n )}\n </div>\n <div className=\"mr-toolbar\">\n <span className=\"mr-count\">{t('modelsCount', { count: models.length })}</span>\n <button type=\"button\" className=\"mr-button\" onClick={() => void load()} disabled={loading}>\n {t('refresh')}\n </button>\n </div>\n {error !== null && (\n <div className=\"mr-error\" role=\"alert\">{error}</div>\n )}\n {loading && models.length === 0 && (\n <div className=\"mr-empty\">{t('loading')}</div>\n )}\n {!loading && models.length === 0 && (\n <div className=\"mr-empty\">{t('empty')}</div>\n )}\n <div className=\"mr-models\">\n {models.map(model => (\n <ModelCard\n key={model.id}\n model={model}\n t={t}\n readOnly={!writable}\n busy={busyModel === model.id}\n dragging={drag}\n onDragStart={index => setDrag({ modelId: model.id, index })}\n onDragEnd={() => setDrag(null)}\n onDrop={index => {\n if (drag !== null && drag.modelId === model.id) {\n void reorder(model, drag.index, index)\n }\n setDrag(null)\n }}\n onSwitch={providerId => void switchActive(model, providerId)}\n />\n ))}\n </div>\n </div>\n </div>\n )}\n </li>\n )\n }\n}\n\ninterface ModelCardProps {\n model: RouterModelView\n t: Translate\n readOnly: boolean\n busy: boolean\n dragging: { modelId: string; index: number } | null\n onDragStart: (index: number) => void\n onDragEnd: () => void\n onDrop: (index: number) => void\n onSwitch: (providerId: string) => void\n}\n\nfunction ModelCard(props: ModelCardProps): JSX.Element {\n const { model, t, readOnly, busy, dragging } = props\n return (\n <section className={`mr-card${busy ? ' mr-card-busy' : ''}`}>\n <header className=\"mr-card-header\">\n <span className=\"mr-model-name\">{model.name}</span>\n <span className=\"mr-model-id\">{model.id}</span>\n <span className=\"mr-provider-count\">{t('providerCount', { count: model.providers.length })}</span>\n </header>\n <p className=\"mr-drag-hint\">{t('dragHint')}</p>\n <ul className=\"mr-providers\">\n {model.providers.map((provider, index) => {\n const active = provider.id === model.active\n const selectable = provider.credentialConfigured\n const dropTarget = dragging !== null && dragging.modelId === model.id && dragging.index !== index\n return (\n <li\n key={provider.id}\n className={[\n 'mr-provider',\n active ? 'mr-provider-active' : '',\n !selectable ? 'mr-provider-nocred' : '',\n dropTarget ? 'mr-provider-drop' : '',\n ].filter(Boolean).join(' ')}\n draggable={!busy && !readOnly && model.providers.length > 1}\n title={selectable ? undefined : t('noCredential')}\n onDragStart={(event) => {\n props.onDragStart(index)\n event.dataTransfer.effectAllowed = 'move'\n try {\n event.dataTransfer.setData('text/plain', model.id)\n } catch {\n // drag data is cosmetic for our own handler\n }\n }}\n onDragOver={(event) => {\n if (dragging !== null && dragging.modelId === model.id && dragging.index !== index) {\n event.preventDefault()\n event.dataTransfer.dropEffect = 'move'\n }\n }}\n onDrop={(event) => {\n if (dragging !== null && dragging.modelId === model.id) {\n event.preventDefault()\n props.onDrop(index)\n }\n }}\n onDragEnd={() => props.onDragEnd()}\n >\n <span className=\"mr-grip\" aria-hidden=\"true\">⠿</span>\n <button\n type=\"button\"\n className=\"mr-provider-button\"\n disabled={!selectable || busy || active || readOnly}\n onClick={() => props.onSwitch(provider.id)}\n >\n <span className=\"mr-provider-name\">{provider.name}</span>\n {!selectable && <span className=\"mr-provider-nocred-label\">· {t('noCredential')}</span>}\n </button>\n {active && <span className=\"mr-active-badge\">{t('activeBadge')}</span>}\n </li>\n )\n })}\n </ul>\n </section>\n )\n}\n","import {\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n type FocusEvent as ReactFocusEvent,\n type KeyboardEvent as ReactKeyboardEvent,\n} from 'react'\nimport type { ClientContext, SessionId, SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client'\nimport type { ModelDirectoryState } from '@deepseek-ai/dsh-client-ui-model-selection/client'\nimport type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport {\n IconCheckOutline16,\n IconChevronDownOutline14,\n IconChevronRightOutline14,\n IconWarningOutline16,\n Toast,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-model-selection/client'\nimport { api, type ModelRouterState, type RouterModelView } from './api'\nimport { LOCALE_NS } from './locales'\nimport './model-seat.css'\n\nconst ROUTER_PROVIDER_ID = 'model-router'\n\n/**\n * Minimal structural ModelSelection (wire shape: provider / model /\n * reasoningEffort). Declared locally to avoid pulling a new peer dependency\n * for a type-only surface; structurally identical to the host wire type.\n */\ninterface ModelSelection {\n provider: string\n model: string\n reasoningEffort?: string\n}\n\n/** The injected business face of the composer model seat (same share the host ModelSelect receives). */\ninterface ModelSeatInjected {\n available: boolean\n directory: SnapshotStore<ModelDirectoryState>\n load: () => void\n select: (selection: ModelSelection) => Promise<boolean>\n}\n\ntype ModelSeatProps = PropsRuntime<'conversation.input.model'>\n & ModelSeatInjected\n & PropsLocale<typeof LOCALE_NS>\n\ntype RouteProvider = RouterModelView['providers'][number]\n\n/**\n * The composer model seat, shadowing the host ModelSelect at a lower slot\n * priority. It renders the same two-level Model / Effort menu as the host\n * (model list grouped by provider, reasoning effort levels), plus a third\n * Provider row that opens the model-router provider list — the former quick\n * route-switcher button moved into the model picker, on par with the model\n * and effort menus.\n *\n * Shadowing contract: the host ui-model-selection registers the\n * `conversation.input.model` occupant at priority 0; this entry registers at\n * priority -1, so the renderer projects this component as the single-slot\n * winner while the host entry stays as the abdication fallback. Both entries\n * share the same per-session ModelDirectory, so selections stay consistent\n * with the /model popup and the host picker.\n */\nexport function ModelRouterSeat({\n locked,\n available,\n directory,\n load,\n select,\n t,\n}: ModelSeatProps): JSX.Element | null {\n const directoryState = useSyncExternalStore(\n onChange => directory.subscribe(onChange),\n () => directory.getSnapshot(),\n () => directory.getSnapshot(),\n )\n const current = directoryState.current\n\n const [open, setOpen] = useState(false)\n const [pane, setPane] = useState<'root' | 'model' | 'provider' | 'effort'>('root')\n const lastActionRef = useRef<'load' | 'select'>('load')\n const [toast, setToast] = useState<{ seq: number; text: string } | null>(null)\n const toastSeq = useRef(0)\n const rootRef = useRef<HTMLDivElement | null>(null)\n const triggerRef = useRef<HTMLButtonElement | null>(null)\n const itemRefs = useRef<(HTMLButtonElement | null)[]>([])\n const id = useId()\n\n // ---- model-router state (moved from the quick route switcher) ----\n const [routerState, setRouterState] = useState<ModelRouterState | null>(null)\n const [routerLoading, setRouterLoading] = useState(false)\n const [routerError, setRouterError] = useState<string | null>(null)\n const [busyProvider, setBusyProvider] = useState<string | null>(null)\n\n const isRouterModel = available && current?.provider === ROUTER_PROVIDER_ID\n const modelId = isRouterModel ? current.model : null\n\n const loadRouterState = useCallback(async (silent = false) => {\n if (!silent) setRouterLoading(true)\n try {\n setRouterState(await api.state())\n setRouterError(null)\n } catch (cause) {\n setRouterError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n if (!silent) setRouterLoading(false)\n }\n }, [])\n\n // Load the advisory directory on mount (host behavior).\n useEffect(() => {\n if (!available) return\n load()\n }, [available, load])\n\n // Fetch the router state (and thus the global toggle) on mount too, so the\n // \"hide provider switching\" setting applies as soon as it resolves.\n useEffect(() => {\n if (!available) return\n void loadRouterState()\n }, [available, loadRouterState])\n\n // Reset the open pane when the selected model changes (a different model may\n // no longer be a model-router route).\n useEffect(() => {\n setPane('root')\n setBusyProvider(null)\n setRouterError(null)\n }, [modelId])\n\n // Silent debounced refresh of the router state after directory refreshes\n // (settings edits, adapter updates), so the provider row never shows a stale\n // active provider.\n const refreshTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n useEffect(() => {\n if (!isRouterModel || modelId === null || directoryState.status !== 'ready') return\n if (refreshTimer.current !== null) clearTimeout(refreshTimer.current)\n refreshTimer.current = setTimeout(() => {\n refreshTimer.current = null\n void loadRouterState(true)\n }, 300)\n return () => {\n if (refreshTimer.current !== null) clearTimeout(refreshTimer.current)\n refreshTimer.current = null\n }\n }, [directoryState.status, isRouterModel, loadRouterState, modelId])\n\n const routeModel = useMemo(\n () => modelId === null\n ? undefined\n : routerState?.models.find(model => model.id === modelId),\n [modelId, routerState],\n )\n\n const providers = useMemo(() => {\n if (routeModel === undefined) return []\n const byId = new Map(routeModel.providers.map(provider => [provider.id, provider]))\n const ordered = routeModel.order\n .map(id => byId.get(id))\n .filter((provider): provider is RouteProvider => provider !== undefined)\n const seen = new Set(ordered.map(provider => provider.id))\n return [...ordered, ...routeModel.providers.filter(provider => !seen.has(provider.id))]\n }, [routeModel])\n\n const switchProvider = useCallback(async (providerId: string) => {\n if (modelId === null || routeModel === undefined || routeModel.active === providerId) {\n setOpen(false)\n return\n }\n setBusyProvider(providerId)\n try {\n const next = await api.switchActive(modelId, providerId)\n setRouterState(next)\n setRouterError(null)\n setOpen(false)\n // Keep the host model picker description in sync immediately.\n load()\n } catch (cause) {\n setRouterError(t('switchFailed', { message: cause instanceof Error ? cause.message : String(cause) }))\n } finally {\n setBusyProvider(null)\n }\n }, [load, modelId, routeModel, t])\n\n // ---- host ModelSelect logic (faithful copy) ----\n const choices = useMemo(() => directoryState.groups.flatMap(group => group.models.map(model => ({\n group,\n model,\n selection: {\n provider: group.id,\n model: model.id,\n ...model.reasoning?.defaultEffort === undefined ? {} : { reasoningEffort: model.reasoning.defaultEffort },\n },\n }))), [directoryState.groups])\n const currentChoice = choices[current === null ? -1 : choices.findIndex(c =>\n c.selection.provider === current?.provider && c.selection.model === current.model)]\n const reasoning = currentChoice?.model.reasoning\n const effectiveEffort = current?.reasoningEffort ?? reasoning?.defaultEffort\n const effortLabel = reasoning === undefined ? undefined\n : effectiveEffort === undefined ? t('effortProviderDefault')\n : reasoning.efforts.find(level => level.id === effectiveEffort)?.name ?? effectiveEffort\n const effortChoices = useMemo<Array<{ key: string; effort: string | undefined; label: string; description?: string }>>(() => reasoning === undefined ? [] : [\n ...(reasoning.defaultEffort === undefined ? [{\n key: 'provider-default',\n effort: undefined as string | undefined,\n label: t('effortProviderDefault'),\n }] : []),\n ...reasoning.efforts.map(effort => ({\n key: `effort:${effort.id}`,\n effort: effort.id,\n label: effort.name,\n ...effort.description === undefined ? {} : { description: effort.description },\n })),\n ], [reasoning, t])\n\n const busy = directoryState.status === 'selecting'\n const reload = () => {\n lastActionRef.current = 'load'\n load()\n }\n\n // Close on outside mousedown (host behavior).\n useEffect(() => {\n if (!open) return\n const closeOutside = (event: MouseEvent) => {\n if (!rootRef.current?.contains(event.target as Node)) setOpen(false)\n }\n document.addEventListener('mousedown', closeOutside)\n return () => {\n document.removeEventListener('mousedown', closeOutside)\n }\n }, [open])\n\n if (!available) return null\n\n const show = () => {\n setPane('root')\n setOpen(true)\n reload()\n void loadRouterState()\n }\n const close = (restoreFocus = false) => {\n setOpen(false)\n setPane('root')\n if (restoreFocus) queueMicrotask(() => {\n triggerRef.current?.focus()\n })\n }\n const moveFocus = (offset: number) => {\n const items = itemRefs.current.filter((item): item is HTMLButtonElement => item !== null)\n if (items.length === 0) return\n const active = items.findIndex(item => item === document.activeElement)\n items[(Math.max(active, 0) + offset + items.length) % items.length]?.focus()\n }\n const onRootKeyDown = (event: ReactKeyboardEvent) => {\n if (event.key === 'Escape' && open) {\n event.preventDefault()\n if (pane !== 'root') setPane('root')\n else close(true)\n return\n }\n if (!open) return\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault()\n moveFocus(event.key === 'ArrowDown' ? 1 : -1)\n }\n }\n const onBlur = (event: ReactFocusEvent) => {\n if (event.relatedTarget instanceof Node && rootRef.current?.contains(event.relatedTarget)) return\n close()\n }\n const settleSelection = (accepted: boolean) => {\n if (accepted) {\n if (rootRef.current !== null) close(true)\n return\n }\n const message = directory.getSnapshot().error\n if (message !== null) {\n toastSeq.current += 1\n setToast({ seq: toastSeq.current, text: t('errorAction', { message }) })\n }\n }\n const choose = (selection: ModelSelection) => {\n if (current !== null && current.provider === selection.provider && current.model === selection.model) {\n close(true)\n return\n }\n lastActionRef.current = 'select'\n select(selection).then(settleSelection)\n }\n const chooseEffort = (effort: string | undefined) => {\n if (current === null) return\n if (effectiveEffort === effort) {\n close(true)\n return\n }\n const selection: ModelSelection = {\n provider: current.provider,\n model: current.model,\n ...effort === undefined ? {} : { reasoningEffort: effort },\n }\n lastActionRef.current = 'select'\n select(selection).then(settleSelection)\n }\n\n const modelLabel = currentChoice?.model.name ?? t('triggerFallback')\n const triggerLabel = effortLabel === undefined ? modelLabel : `${modelLabel} · ${effortLabel}`\n const triggerAria = currentChoice === undefined ? t('triggerSelectAria')\n : effortLabel === undefined ? t('triggerAria', { model: modelLabel })\n : t('triggerAriaEffort', { model: modelLabel, effort: effortLabel })\n\n // ---- provider row visibility (the former quick-switch button conditions) ----\n const activeProvider = providers.find(provider => provider.id === routeModel?.active)\n const activeProviderName = activeProvider?.name ?? routeModel?.active ?? t('routeLoading')\n const providerRowVisible = isRouterModel\n && routerState !== null\n && routerState.showQuickSwitch !== false\n && routerState.providers.length >= 2\n && routeModel !== undefined\n && providers.length >= 2\n\n itemRefs.current = []\n let itemIndex = 0\n const itemRef = () => {\n const at = itemIndex++\n return (node: HTMLButtonElement | null) => {\n itemRefs.current[at] = node\n }\n }\n\n return (\n <div\n ref={rootRef}\n className=\"mr-seat-root\"\n onKeyDown={onRootKeyDown}\n onBlur={onBlur}\n >\n <button\n ref={triggerRef}\n type=\"button\"\n className=\"mr-seat-trigger\"\n aria-label={triggerAria}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-controls={open ? `${id}-menu` : undefined}\n title={triggerLabel}\n disabled={locked}\n onClick={() => {\n if (open) close()\n else show()\n }}\n >\n <span className=\"mr-seat-triggerLabel\">{modelLabel}</span>\n {effortLabel !== undefined && (\n <span className=\"mr-seat-triggerEffort\">{effortLabel}</span>\n )}\n <span className={`mr-seat-chevron${open ? ' mr-seat-chevronOpen' : ''}`} aria-hidden>\n <IconChevronDownOutline14 />\n </span>\n </button>\n {open && (\n <div\n id={`${id}-menu`}\n className=\"mr-seat-menu\"\n role=\"menu\"\n aria-label={t('menuAria')}\n aria-busy={directoryState.status === 'loading' || busy}\n >\n {pane === 'root' && (\n <>\n <button\n ref={itemRef()}\n type=\"button\"\n role=\"menuitem\"\n className=\"mr-seat-cell\"\n onClick={() => setPane('model')}\n >\n <span className=\"mr-seat-cellLabel\">{t('menuModel')}</span>\n <span className=\"mr-seat-cellValue\">{modelLabel}</span>\n <span className=\"mr-seat-cellChevron\" aria-hidden>\n <IconChevronRightOutline14 />\n </span>\n </button>\n {providerRowVisible && (\n <button\n ref={itemRef()}\n type=\"button\"\n role=\"menuitem\"\n className=\"mr-seat-cell\"\n onClick={() => setPane('provider')}\n >\n <span className=\"mr-seat-cellLabel\">{t('menuProvider')}</span>\n <span className=\"mr-seat-cellValue\">{activeProviderName}</span>\n <span className=\"mr-seat-cellChevron\" aria-hidden>\n <IconChevronRightOutline14 />\n </span>\n </button>\n )}\n {reasoning !== undefined && (\n <button\n ref={itemRef()}\n type=\"button\"\n role=\"menuitem\"\n className=\"mr-seat-cell\"\n onClick={() => setPane('effort')}\n >\n <span className=\"mr-seat-cellLabel\">{t('menuEffort')}</span>\n <span className=\"mr-seat-cellValue\">{effortLabel}</span>\n <span className=\"mr-seat-cellChevron\" aria-hidden>\n <IconChevronRightOutline14 />\n </span>\n </button>\n )}\n </>\n )}\n {pane === 'model' && (\n <>\n {directoryState.status === 'loading' && (\n <div className=\"mr-seat-status\">{t('statusLoading')}</div>\n )}\n {directoryState.error !== null && lastActionRef.current === 'load' && (\n <div className=\"mr-seat-error\">\n <span>{t('errorAction', { message: directoryState.error })}</span>\n <button type=\"button\" className=\"mr-seat-retry\" onClick={reload}>\n {t('retry')}\n </button>\n </div>\n )}\n {directoryState.failures.map(failure => (\n <div key={failure.id} className=\"mr-seat-warning\">\n <span>{t('warningGroupLoad', { name: failure.name, message: failure.message })}</span>\n <button type=\"button\" className=\"mr-seat-retry\" onClick={reload}>\n {t('retry')}\n </button>\n </div>\n ))}\n <div className=\"mr-seat-groups\">\n {directoryState.groups.map(group => {\n const headingId = `${id}-${group.id}`\n return (\n <section\n key={group.id}\n role=\"group\"\n aria-labelledby={headingId}\n className=\"mr-seat-group\"\n >\n <div className=\"mr-seat-groupTitle\" id={headingId}>\n {group.name}\n </div>\n {group.models.map(model => {\n const selected = current?.provider === group.id && current.model === model.id\n return (\n <button\n key={model.id}\n ref={itemRef()}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={selected}\n className={`mr-seat-option${selected ? ' mr-seat-selected' : ''}`}\n title={model.name}\n disabled={busy}\n onClick={() => choose({ provider: group.id, model: model.id })}\n >\n <span className=\"mr-seat-optionCopy\">\n <span className=\"mr-seat-modelName\">{model.name}</span>\n {model.description !== undefined && (\n <span className=\"mr-seat-description\">{model.description}</span>\n )}\n </span>\n <span className=\"mr-seat-check\" aria-hidden>\n {selected ? <IconCheckOutline16 /> : null}\n </span>\n </button>\n )\n })}\n </section>\n )\n })}\n </div>\n {directoryState.status === 'ready' && choices.length === 0 && (\n <div className=\"mr-seat-empty\">{t('emptyModels')}</div>\n )}\n </>\n )}\n {pane === 'provider' && (\n <>\n {routerError !== null && (\n <div className=\"mr-seat-error\">\n <span>{routerError}</span>\n <button\n type=\"button\"\n className=\"mr-seat-retry\"\n onClick={() => {\n void loadRouterState()\n load()\n }}\n >\n {t('retry')}\n </button>\n </div>\n )}\n {routeModel === undefined ? (\n <div className=\"mr-seat-status\">{t('routeLoading')}</div>\n ) : (\n <>\n <div className=\"mr-seat-title\">{t('routeMenuTitle', { model: modelId ?? '' })}</div>\n <div className=\"mr-seat-groups\">\n {providers.map(provider => {\n const selected = routeModel.active === provider.id\n return (\n <button\n key={provider.id}\n ref={itemRef()}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={selected}\n className={`mr-seat-option${selected ? ' mr-seat-selected' : ''}`}\n disabled={!provider.credentialConfigured || busyProvider !== null}\n onClick={() => void switchProvider(provider.id)}\n >\n <span className=\"mr-seat-optionCopy\">\n <span className=\"mr-seat-modelName\">{provider.name}</span>\n {!provider.credentialConfigured && (\n <span className=\"mr-seat-description\">{t('noCredentialShort')}</span>\n )}\n </span>\n <span className=\"mr-seat-check\" aria-hidden>\n {selected ? <IconCheckOutline16 /> : null}\n </span>\n </button>\n )\n })}\n </div>\n <div className=\"mr-seat-hint\">{t('globalRouteHint')}</div>\n </>\n )}\n </>\n )}\n {pane === 'effort' && (\n <>\n {directoryState.error !== null && lastActionRef.current === 'load' && (\n <div className=\"mr-seat-error\">\n <span>{t('errorAction', { message: directoryState.error })}</span>\n <button type=\"button\" className=\"mr-seat-retry\" onClick={reload}>\n {t('actionReload')}\n </button>\n </div>\n )}\n {effortChoices.length === 0 ? (\n <div className=\"mr-seat-empty\">{t('emptyEfforts')}</div>\n ) : effortChoices.map(level => (\n <button\n key={level.key}\n ref={itemRef()}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={effectiveEffort === level.effort}\n className={`mr-seat-option${effectiveEffort === level.effort ? ' mr-seat-selected' : ''}`}\n disabled={busy}\n onClick={() => chooseEffort(level.effort)}\n >\n <span className=\"mr-seat-optionCopy\">\n <span className=\"mr-seat-modelName\">{level.label}</span>\n {level.description !== undefined && (\n <span className=\"mr-seat-description\">{level.description}</span>\n )}\n </span>\n <span className=\"mr-seat-check\" aria-hidden>\n {effectiveEffort === level.effort ? <IconCheckOutline16 /> : null}\n </span>\n </button>\n ))}\n </>\n )}\n </div>\n )}\n {toast !== null && (\n <Toast\n key={toast.seq}\n text={toast.text}\n icon={<IconWarningOutline16 />}\n anchor={rootRef.current?.closest('[data-composer-card]') ?? null}\n onDone={() => setToast(null)}\n />\n )}\n </div>\n )\n}\n\n/** Register the model seat onto the composer's named model slot (priority -1 shadows the host seat). */\nexport function registerModelRouterSeat(ctx: ClientContext): void {\n const t = ctx.locale.bind(LOCALE_NS)\n ctx.inject(['slots', 'modelDirectories'], scope => {\n const models = scope.modelDirectories\n const sessions = scope.sessions\n scope.slots.inject('conversation.input.model', () => scope.slots.register({\n name: 'conversation.input.model',\n id: 'model-router-model-seat',\n priority: -1,\n label: () => t('seatLabel'),\n locale: LOCALE_NS,\n inject: (sessionId: SessionId) => {\n const directory = models.directoryFor(sessionId)\n const available = sessions.subagentAddress(sessionId) === undefined\n return {\n available,\n directory: directory.store,\n load: () => {\n if (available) directory.load().catch(() => {})\n },\n select: (selection: ModelSelection) =>\n available ? directory.select(selection).then(() => true, () => false) : Promise.resolve(false),\n }\n },\n } as never, ModelRouterSeat as never))\n })\n}\n","/**\n * @fonlan/dsh-model-router client half: the plugin's own Settings Card\n * (设置 → 插件 → 插件配置 → 模型路由) plus the model seat that merges the\n * provider switcher into DSH's composer model picker menu.\n */\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-slots'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-model-selection/client'\nimport { LOCALE_NS, zh, en } from './locales'\nimport { makeSettingsCard, type SettingsScopeFace } from './settings-card'\nimport { registerModelRouterSeat } from './model-seat'\n\n/** The settings namespace this card edits (must match the host half). */\nconst ROUTER_NS = 'model-router'\n\n/** Slots face: the keyed `settings.plugin.item` declaration ships with the web\n * app's ui-settings-plugins package, which external plugins do not depend on;\n * the register call below is typed through this local face (erased at build). */\ninterface Slots {\n inject(name: string, callback: () => unknown): unknown\n register(def: { name: string; key: string; inject?: () => unknown }, component: unknown): unknown\n}\n\n/** Services required before mounting (provided by the client runtime). */\nexport const inject = ['slots', 'locale', 'modelDirectories', 'sessions', 'settingsScope', 'connection', 'remote']\n\n/** Client plugin body. */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => {\n const off = ctx.locale.register(LOCALE_NS, { zh, en })\n return () => off()\n }, 'model-router: dictionaries')\n\n const SettingsCard = makeSettingsCard(ctx)\n\n // The card registers on the `settings.plugin.item` slot keyed by the\n // `model-router` settings namespace (the same string the host half\n // registers), so it appears inside 设置 → 插件 → 插件配置, paired with the\n // namespace by the tab.\n const services = ctx as unknown as {\n slots: Slots\n settingsScope: { bind(spec: { namespace: string }): SettingsScopeFace }\n }\n const scope = services.settingsScope.bind({ namespace: ROUTER_NS })\n\n services.slots.inject('settings.plugin.item', () =>\n services.slots.register(\n {\n name: 'settings.plugin.item',\n key: ROUTER_NS,\n inject: () => ({ scope }),\n },\n SettingsCard,\n ),\n )\n\n registerModelRouterSeat(ctx)\n}\n"],"mappings":"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"}