@fonlan/dsh-model-parameters 0.1.9 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -74,6 +74,26 @@ Models with no catalog match (e.g. a local gateway model like
74
74
  - The settings card has an **Update catalog & fill now** button for a forced
75
75
  refresh, and shows the last update time and freshness.
76
76
 
77
+ ### System proxy
78
+
79
+ The catalog download follows proxy settings, on Windows too:
80
+
81
+ - With `HTTP_PROXY` / `HTTPS_PROXY` / `ALL_PROXY` (either casing) set, the
82
+ harness's global proxy policy applies — the same route as every other
83
+ outbound request.
84
+ - With none of those variables set, the operating system's proxy is read:
85
+ Windows Internet Settings (the `ProxyEnable` / `ProxyServer` /
86
+ `ProxyOverride` values under the registry's `Internet Settings` key), or the
87
+ manual HTTP/HTTPS proxy plus exceptions list in macOS Network settings.
88
+ - Otherwise the download connects directly.
89
+ - The settings page shows the **download route** of the last download: direct /
90
+ environment proxy / Windows system proxy / macOS system proxy (proxy address
91
+ masked), together with the error when a download failed.
92
+ - Limits: SOCKS proxies and PAC scripts are never evaluated (a PAC-only
93
+ configuration stays direct and warns — set `HTTPS_PROXY` instead); CIDR
94
+ bypass entries (`10.0.0.0/8`) are not matched; proxy credentials stored in the
95
+ OS credential manager are not sent.
96
+
77
97
  ## Settings card
78
98
 
79
99
  An expandable "模型参数补全 / Model Parameters" card appears in DSH
@@ -140,6 +160,7 @@ dsh plugin --profile web remove @fonlan/dsh-model-parameters
140
160
  pnpm install
141
161
  pnpm build # tsc types + tsdown host & client bundles
142
162
  pnpm typecheck
163
+ pnpm test # builds, then checks system-proxy detection, routing and the CONNECT tunnel (scripts/verify-proxy.mjs)
143
164
  node scripts/verify-catalog.mjs # matching-logic check against a models.dev dump
144
165
  ```
145
166
 
package/README.md CHANGED
@@ -46,6 +46,16 @@ models.dev 把同一模型挂在许多 provider 名下(`deepseek-v4-flash` 出
46
46
  - 拉取失败则保留上次成功的缓存;完全没有缓存时插件什么都不补,直到刷新成功。
47
47
  - 设置卡片有 **立即更新目录并补全** 按钮可强制刷新,并显示上次更新时间与新鲜度。
48
48
 
49
+ ### 系统代理
50
+
51
+ 目录下载遵循代理设置(包括 Windows):
52
+
53
+ - 设置了 `HTTP_PROXY` / `HTTPS_PROXY` / `ALL_PROXY`(大小写均可)时,沿用 DSH 宿主的全局代理策略——与插件其他出站请求走同一条路由。
54
+ - 没有设置这些变量时,自动读取操作系统代理:Windows 的 Internet 选项(注册表 `Internet Settings` 中的 `ProxyEnable` / `ProxyServer` / `ProxyOverride`),macOS 网络设置里的手动 HTTP/HTTPS 代理与排除列表。
55
+ - 两者都没有时直连。
56
+ - 设置页「模型目录」会显示最近一次下载的 **下载经由**:直连 / 环境变量代理 / Windows 系统代理 / macOS 系统代理(代理地址已脱敏);下载失败时一并显示错误。
57
+ - 限制:SOCKS 代理与 PAC 脚本不会被求值(只配置了 PAC 时保持直连并告警,可改用 `HTTPS_PROXY` 显式指定);CIDR 形式的绕过条目(如 `10.0.0.0/8`)不匹配;系统凭据管理器保存的代理密码不会发送。
58
+
49
59
  ## 设置卡片
50
60
 
51
61
  在 DSH 设置 → **插件 → 插件配置** 中会出现一张 "模型参数补全 / Model Parameters" 可展开卡片(样式与内置插件卡片一致,默认折叠):
@@ -107,6 +117,7 @@ dsh plugin --profile web remove @fonlan/dsh-model-parameters
107
117
  pnpm install
108
118
  pnpm build # tsc 类型 + tsdown host 与 client bundle
109
119
  pnpm typecheck
120
+ pnpm test # 构建后校验系统代理探测、路由选择与 CONNECT 隧道(scripts/verify-proxy.mjs)
110
121
  node scripts/verify-catalog.mjs # 用 models.dev dump 校验匹配逻辑
111
122
  ```
112
123
 
package/lib/client.js CHANGED
@@ -41,6 +41,12 @@ window.__ModuleLoader__.load({
41
41
  catalogFresh: "新鲜",
42
42
  catalogStale: "已过期",
43
43
  catalogNever: "尚未获取",
44
+ catalogRoute: "下载经由",
45
+ routeDirect: "直连",
46
+ routeEnv: "环境变量代理",
47
+ routeMacos: "macOS 系统代理",
48
+ routeWindows: "Windows 系统代理",
49
+ catalogDownloadFailed: "上次下载失败",
44
50
  refresh: "立即更新目录并补全",
45
51
  refreshBusy: "更新中…",
46
52
  reconcileNow: "立即补全一次",
@@ -85,6 +91,12 @@ window.__ModuleLoader__.load({
85
91
  catalogFresh: "fresh",
86
92
  catalogStale: "stale",
87
93
  catalogNever: "not fetched yet",
94
+ catalogRoute: "Download route",
95
+ routeDirect: "direct",
96
+ routeEnv: "environment proxy",
97
+ routeMacos: "macOS system proxy",
98
+ routeWindows: "Windows system proxy",
99
+ catalogDownloadFailed: "Last download failed",
88
100
  refresh: "Update catalog & fill now",
89
101
  refreshBusy: "Updating…",
90
102
  reconcileNow: "Fill now",
@@ -180,6 +192,15 @@ window.__ModuleLoader__.load({
180
192
  return String(epochMs);
181
193
  }
182
194
  }
195
+ /** Localized label for the route the last catalog download took. */
196
+ function routeLabel(t, transport) {
197
+ switch (transport.kind) {
198
+ case "env": return t("routeEnv");
199
+ case "macos": return t("routeMacos");
200
+ case "windows": return t("routeWindows");
201
+ default: return t("routeDirect");
202
+ }
203
+ }
183
204
  function makeSettingsSection(ctx) {
184
205
  const t = (() => {
185
206
  try {
@@ -431,7 +452,25 @@ window.__ModuleLoader__.load({
431
452
  if (Number.isFinite(days) && days >= 1 && days <= 90) onPatchConfig({ ttlDays: Math.round(days) });
432
453
  }
433
454
  })]
434
- })
455
+ }),
456
+ catalog.transport != null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
457
+ t("catalogRoute"),
458
+ ":",
459
+ " ",
460
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: routeLabel(t, catalog.transport) }),
461
+ catalog.transport.proxy !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [" ", /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
462
+ className: "mp-code",
463
+ children: catalog.transport.proxy
464
+ })] })
465
+ ] })
466
+ ]
467
+ }),
468
+ catalog.error != null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
469
+ className: "mp-error",
470
+ children: [
471
+ t("catalogDownloadFailed"),
472
+ ": ",
473
+ catalog.error
435
474
  ]
436
475
  }),
437
476
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
package/lib/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["useCallback","useSyncExternalStore","useState"],"sources":["../../../src/client/locales.ts","../../../src/client/api.ts","../../../src/client/settings-section.tsx","../../../src/client/index.tsx"],"sourcesContent":["/**\n * Locale dictionaries for @fonlan/dsh-model-parameters settings page.\n * zh is the key source of truth; en must carry the exact same key set.\n */\nexport const LOCALE_NS = 'model-parameters'\n\nexport const zh = {\n settingsTitle: '模型参数补全',\n sectionSub: '补全字段、目录刷新、Provider 映射与补全报告。',\n master: '启用自动补全',\n masterDesc: '关闭后不再自动补全任何字段(已补全的值保留)。',\n fields: '补全字段',\n fillName: '显示名称',\n fillNameDesc: '模型条目缺 name 时写入目录中的显示名称。',\n fillContext: '最大上下文',\n fillContextDesc: '缺 contextWindow 时写入目录的上下文上限。',\n fillMaxTokens: '最大输出',\n fillMaxTokensDesc: '缺 maxTokens 时写入目录的输出上限。',\n fillReasoning: '推理强度',\n fillReasoningDesc: '缺 reasoningEfforts 时按目录 effort 档位写入 identity 字典(如 {high:\"high\", max:\"max\"})。',\n fillInput: '输入模态',\n fillInputDesc: '缺 input 时写入目录中的 text/image 模态。',\n ttl: '目录更新周期(天)',\n ttlDesc: '缓存的 models.dev 目录超过该天数后,在下次补全时自动刷新。',\n providerMap: 'Provider 映射',\n providerMapDesc: 'dsh provider → models.dev provider 的匹配覆盖(可选)。',\n addMapping: '添加映射',\n removeMapping: '移除',\n catalog: '模型目录',\n catalogEntries: '目录条目',\n catalogProviders: '覆盖 Provider',\n catalogFetched: '上次更新',\n catalogFresh: '新鲜',\n catalogStale: '已过期',\n catalogNever: '尚未获取',\n refresh: '立即更新目录并补全',\n refreshBusy: '更新中…',\n reconcileNow: '立即补全一次',\n report: '最近一次补全',\n reportNever: '尚未执行',\n reportFilled: '补全字段',\n reportTouched: '涉及 Provider',\n reportUnmatched: '未匹配模型',\n reportEmpty: '全部匹配,无未匹配项',\n reportAt: '时间',\n error: '加载失败',\n saving: '保存中…',\n officialProviders: '官方厂商优先级',\n officialProvidersDesc: '同一模型 id 在多处出现时,优先采用这些 models.dev provider 的条目。',\n} as const\n\nexport const en: Record<keyof typeof zh, string> = {\n settingsTitle: 'Model Parameters',\n sectionSub: 'Field toggles, catalog refresh, provider mapping and the fill report.',\n master: 'Enable auto-fill',\n masterDesc: 'When off, no fields are filled (already-filled values are kept).',\n fields: 'Fields to fill',\n fillName: 'Display name',\n fillNameDesc: 'Write the catalog display name when a model entry lacks name.',\n fillContext: 'Context window',\n fillContextDesc: 'Write the catalog context limit when contextWindow is missing.',\n fillMaxTokens: 'Max output',\n fillMaxTokensDesc: 'Write the catalog output limit when maxTokens is missing.',\n fillReasoning: 'Reasoning efforts',\n fillReasoningDesc: 'Write an identity reasoningEfforts dict (e.g. {high:\"high\", max:\"max\"}) from catalog effort levels when missing.',\n fillInput: 'Input modalities',\n fillInputDesc: 'Write text/image modalities from the catalog when input is missing.',\n ttl: 'Catalog refresh interval (days)',\n ttlDesc: 'The cached models.dev catalog is refreshed on the next fill once older than this many days.',\n providerMap: 'Provider mapping',\n providerMapDesc: 'Optional dsh provider → models.dev provider matching overrides.',\n addMapping: 'Add mapping',\n removeMapping: 'Remove',\n catalog: 'Model catalog',\n catalogEntries: 'Catalog entries',\n catalogProviders: 'Providers covered',\n catalogFetched: 'Last updated',\n catalogFresh: 'fresh',\n catalogStale: 'stale',\n catalogNever: 'not fetched yet',\n refresh: 'Update catalog & fill now',\n refreshBusy: 'Updating…',\n reconcileNow: 'Fill now',\n report: 'Last fill',\n reportNever: 'never run',\n reportFilled: 'fields filled',\n reportTouched: 'providers touched',\n reportUnmatched: 'unmatched models',\n reportEmpty: 'all matched, nothing unmatched',\n reportAt: 'time',\n error: 'Failed to load',\n saving: 'Saving…',\n officialProviders: 'Official provider priority',\n officialProvidersDesc: 'When one model id appears under several providers, prefer entries from these models.dev providers.',\n}\n","/** Client transport for the model-parameters settings API. */\nimport type { ModelParametersConfig } from '../shared/config.js'\n\nexport interface CatalogView {\n entries: number\n providers: number\n fetchedAt: number\n fresh: boolean\n ttlDays: number\n}\n\nexport interface FillReportView {\n at: number\n filled: number\n touched: number\n unmatched: string[]\n}\n\nexport interface PluginState {\n config: ModelParametersConfig\n catalog: CatalogView\n report: FillReportView | null\n}\n\nexport class ModelParametersApiError 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-parameters/api/${method}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n })\n } catch (error) {\n throw new ModelParametersApiError('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 ModelParametersApiError(\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<PluginState>('state'),\n refresh: () => call<PluginState>('refresh'),\n reconcile: () => call<PluginState>('reconcile'),\n setConfig: (patch: Partial<ModelParametersConfig>) =>\n call<PluginState>('set-config', { patch }),\n}\n","/**\n * The Model Parameters settings page (设置 → 侧栏「模型参数补全」).\n *\n * Registers into the `settings.section` slot, so the page owns one entry in\n * the settings sidebar and renders its content in the panel's content column.\n * Content: master + per-field toggles, catalog TTL, provider→models.dev\n * mapping overrides, a manual refresh/fill action, the catalog freshness line,\n * and the last fill report (filled / touched / unmatched).\n *\n * All reads/mutations go through the plugin's fenced API; config persists into\n * the `model-parameters` profile entry — the plugin's own loader entry config,\n * written through the host settings service.\n */\nimport { useCallback, useEffect, useState, useSyncExternalStore } from 'react'\nimport type { Context } from '@deepseek-ai/cordis'\ntype ClientContext = Context\nimport type { Translate } from '@deepseek-ai/dsh-client-ui-slots'\nimport { LOCALE_NS } from './locales'\nimport { api, type PluginState } from './api'\nimport type { ModelParametersConfig } from '../shared/config.js'\nimport './settings-section.css'\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\nfunction formatTime(epochMs: number): string {\n try {\n return new Date(epochMs).toLocaleString()\n } catch {\n return String(epochMs)\n }\n}\n\nexport function makeSettingsSection(ctx: ClientContext): () => JSX.Element {\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 ModelParametersSettingsSection(): JSX.Element {\n useLocaleRevision(ctx)\n const [state, setState] = useState<PluginState | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [loading, setLoading] = useState(true)\n const [busy, setBusy] = useState(false)\n const [saving, setSaving] = useState(false)\n const [mappingRows, setMappingRows] = useState<Array<{ from: string; to: string }>>([])\n const [newFrom, setNewFrom] = useState('')\n const [newTo, setNewTo] = useState('')\n\n const load = useCallback(async () => {\n setLoading(true)\n try {\n const next = await api.state()\n setState(next)\n setMappingRows(Object.entries(next.config.providerMap).map(([from, to]) => ({ from, to })))\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 patchConfig = useCallback(async (patch: Partial<ModelParametersConfig>) => {\n setSaving(true)\n try {\n const next = await api.setConfig(patch)\n setState(next)\n setMappingRows(Object.entries(next.config.providerMap).map(([from, to]) => ({ from, to })))\n setError(null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setSaving(false)\n }\n }, [])\n\n const refresh = useCallback(async () => {\n setBusy(true)\n try {\n setState(await api.refresh())\n setError(null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }, [])\n\n const reconcileNow = useCallback(async () => {\n setBusy(true)\n try {\n setState(await api.reconcile())\n setError(null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }, [])\n\n const applyMappings = useCallback(async () => {\n const providerMap: Record<string, string> = {}\n for (const row of mappingRows) {\n const from = row.from.trim()\n const to = row.to.trim()\n if (from.length > 0 && to.length > 0) providerMap[from] = to\n }\n await patchConfig({ providerMap })\n }, [mappingRows, patchConfig])\n\n return (\n <div className=\"mp-page\">\n <header className=\"mp-page-head\">\n <h3 className=\"mp-page-title\">{t('settingsTitle')}</h3>\n <p className=\"mp-page-sub\">{t('sectionSub')}</p>\n </header>\n {error !== null && state === null ? (\n <p className=\"mp-error\">{t('error')}: {error}</p>\n ) : loading || state === null ? (\n <p className=\"mp-muted\">{t('saving')}</p>\n ) : (\n <ModelParametersBody\n t={t}\n state={state}\n error={error}\n saving={saving}\n busy={busy}\n mappingRows={mappingRows}\n newFrom={newFrom}\n newTo={newTo}\n setNewFrom={setNewFrom}\n setNewTo={setNewTo}\n setMappingRows={setMappingRows}\n onPatchConfig={patchConfig}\n onRefresh={refresh}\n onReconcile={reconcileNow}\n onApplyMappings={applyMappings}\n />\n )}\n </div>\n )\n }\n}\n\n/** The page body: divider-separated control groups. */\nfunction ModelParametersBody(props: {\n t: Translate\n state: PluginState\n error: string | null\n saving: boolean\n busy: boolean\n mappingRows: Array<{ from: string; to: string }>\n newFrom: string\n newTo: string\n setNewFrom: (value: string) => void\n setNewTo: (value: string) => void\n setMappingRows: (rows: Array<{ from: string; to: string }>) => void\n onPatchConfig: (patch: Partial<ModelParametersConfig>) => Promise<void>\n onRefresh: () => Promise<void>\n onReconcile: () => Promise<void>\n onApplyMappings: () => Promise<void>\n}): JSX.Element {\n const {\n t, state, error, saving, busy,\n mappingRows, newFrom, newTo,\n setNewFrom, setNewTo, setMappingRows,\n onPatchConfig, onRefresh, onReconcile, onApplyMappings,\n } = props\n\n const config = state.config\n const catalog = state.catalog\n const report = state.report\n\n return (\n <div className=\"mp-body\">\n <section className=\"mp-group\">\n <h4 className=\"mp-group-title\">{t('fields')}</h4>\n <label className=\"mp-toggle\">\n <input\n type=\"checkbox\"\n checked={config.enabled}\n disabled={saving}\n onChange={(event) => void onPatchConfig({ enabled: event.target.checked })}\n />\n <span className=\"mp-toggle-body\">\n <span className=\"mp-toggle-label\">{t('master')}</span>\n <span className=\"mp-toggle-desc\">{t('masterDesc')}</span>\n </span>\n </label>\n {([\n ['fillName', t('fillName'), t('fillNameDesc')],\n ['fillContext', t('fillContext'), t('fillContextDesc')],\n ['fillMaxTokens', t('fillMaxTokens'), t('fillMaxTokensDesc')],\n ['fillReasoning', t('fillReasoning'), t('fillReasoningDesc')],\n ['fillInput', t('fillInput'), t('fillInputDesc')],\n ] as const).map(([key, label, desc]) => (\n <label className=\"mp-toggle mp-toggle-sub\" key={key}>\n <input\n type=\"checkbox\"\n checked={config[key]}\n disabled={saving || !config.enabled}\n onChange={(event) => void onPatchConfig({ [key]: event.target.checked })}\n />\n <span className=\"mp-toggle-body\">\n <span className=\"mp-toggle-label\">{label}</span>\n <span className=\"mp-toggle-desc\">{desc}</span>\n </span>\n </label>\n ))}\n </section>\n\n <hr className=\"mp-divider\" />\n\n <section className=\"mp-group\">\n <h4 className=\"mp-group-title\">{t('catalog')}</h4>\n <div className=\"mp-meta\">\n <span>{t('catalogEntries')}: <strong>{catalog.entries.toLocaleString()}</strong></span>\n <span>{t('catalogProviders')}: <strong>{catalog.providers.toLocaleString()}</strong></span>\n <span>\n {t('catalogFetched')}:{' '}\n <strong>{catalog.fetchedAt > 0 ? formatTime(catalog.fetchedAt) : t('catalogNever')}</strong>{' '}\n {catalog.fetchedAt > 0 && (\n <span className={catalog.fresh ? 'mp-badge mp-badge-ok' : 'mp-badge mp-badge-warn'}>\n {catalog.fresh ? t('catalogFresh') : t('catalogStale')}\n </span>\n )}\n </span>\n <label className=\"mp-ttl\">\n {t('ttl')}\n <input\n className=\"mp-input mp-input-narrow\"\n type=\"number\"\n min={1}\n max={90}\n value={config.ttlDays}\n disabled={saving}\n onChange={(event) => {\n const days = Number(event.target.value)\n if (Number.isFinite(days) && days >= 1 && days <= 90) void onPatchConfig({ ttlDays: Math.round(days) })\n }}\n />\n </label>\n </div>\n <div className=\"mp-actions\">\n <button className=\"mp-button\" disabled={busy} onClick={() => void onRefresh()}>\n {busy ? t('refreshBusy') : t('refresh')}\n </button>\n <button className=\"mp-button mp-button-ghost\" disabled={busy} onClick={() => void onReconcile()}>\n {t('reconcileNow')}\n </button>\n </div>\n </section>\n\n <hr className=\"mp-divider\" />\n\n <section className=\"mp-group\">\n <h4 className=\"mp-group-title\">{t('providerMap')}</h4>\n <p className=\"mp-desc\">{t('providerMapDesc')}</p>\n {mappingRows.map((row, index) => (\n <div className=\"mp-map-row\" key={index}>\n <input\n className=\"mp-input\"\n value={row.from}\n disabled={saving}\n onChange={(event) => {\n const next = [...mappingRows]\n next[index] = { ...row, from: event.target.value }\n setMappingRows(next)\n }}\n />\n <span className=\"mp-map-arrow\">→</span>\n <input\n className=\"mp-input\"\n value={row.to}\n disabled={saving}\n onChange={(event) => {\n const next = [...mappingRows]\n next[index] = { ...row, to: event.target.value }\n setMappingRows(next)\n }}\n />\n <button\n className=\"mp-button mp-button-ghost\"\n disabled={saving}\n onClick={() => setMappingRows(mappingRows.filter((_, i) => i !== index))}\n >\n {t('removeMapping')}\n </button>\n </div>\n ))}\n <div className=\"mp-map-row\">\n <input\n className=\"mp-input\"\n placeholder=\"dsh provider\"\n value={newFrom}\n onChange={(event) => setNewFrom(event.target.value)}\n />\n <span className=\"mp-map-arrow\">→</span>\n <input\n className=\"mp-input\"\n placeholder=\"models.dev provider\"\n value={newTo}\n onChange={(event) => setNewTo(event.target.value)}\n />\n <button\n className=\"mp-button mp-button-ghost\"\n disabled={newFrom.trim().length === 0 || newTo.trim().length === 0}\n onClick={() => {\n setMappingRows([...mappingRows, { from: newFrom.trim(), to: newTo.trim() }])\n setNewFrom('')\n setNewTo('')\n }}\n >\n {t('addMapping')}\n </button>\n </div>\n <div className=\"mp-actions\">\n <button className=\"mp-button\" disabled={saving} onClick={() => void onApplyMappings()}>\n {saving ? t('saving') : '✓ ' + t('providerMap')}\n </button>\n </div>\n </section>\n\n <hr className=\"mp-divider\" />\n\n <section className=\"mp-group\">\n <h4 className=\"mp-group-title\">{t('report')}</h4>\n {report === null ? (\n <p className=\"mp-muted\">{t('reportNever')}</p>\n ) : (\n <ul className=\"mp-report\">\n <li>{t('reportAt')}: {formatTime(report.at)}</li>\n <li>{t('reportFilled')}: <strong>{report.filled}</strong></li>\n <li>{t('reportTouched')}: <strong>{report.touched}</strong></li>\n <li>\n {t('reportUnmatched')}:{' '}\n {report.unmatched.length === 0\n ? t('reportEmpty')\n : <code className=\"mp-code\">{report.unmatched.join(', ')}</code>}\n </li>\n </ul>\n )}\n </section>\n\n {error !== null && <p className=\"mp-error\">{error}</p>}\n </div>\n )\n}\n","/**\n * @fonlan/dsh-model-parameters client half: the plugin's own Settings section.\n *\n * Registers into the settings.section slot, so the page owns one entry in the\n * settings sidebar and renders in the panel's content column. The page itself\n * lives in ./settings-section.\n *\n * Deps resolved from the browser module table: react only. The slots service\n * is reached through the cordis context; types come from devDependencies and\n * are erased at build time.\n */\nimport type { Context } from '@deepseek-ai/cordis'\ntype ClientContext = Context\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-slots'\nimport { LOCALE_NS, zh, en } from './locales'\nimport { makeSettingsSection } from './settings-section'\n\n/** The settings sidebar entry this page owns (must stay stable). */\nconst SECTION_ID = 'model-parameters'\n\n/** The slots service face (subset of @deepseek-ai/dsh-client-ui-slots). */\ninterface SlotEntry {\n name: string\n id?: string\n order?: number\n label?: () => string\n locale?: string\n}\n\ninterface Slots {\n inject(name: string, register: () => unknown): unknown\n register(def: SlotEntry, component: unknown): unknown\n}\n\n/** Services required before mounting (provided by the client runtime). */\nexport const inject = ['slots', 'locale']\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-parameters: dictionaries')\n\n const t = ctx.locale.bind(LOCALE_NS) as unknown as (key: string) => string\n const Section = makeSettingsSection(ctx)\n const slots = (ctx as unknown as { slots: Slots }).slots\n slots.inject('settings.section', () =>\n slots.register({\n name: 'settings.section',\n id: SECTION_ID,\n order: 320,\n label: () => t('settingsTitle'),\n locale: LOCALE_NS,\n }, Section),\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["useCallback","useSyncExternalStore","useState"],"sources":["../../../src/client/locales.ts","../../../src/client/api.ts","../../../src/client/settings-section.tsx","../../../src/client/index.tsx"],"sourcesContent":["/**\n * Locale dictionaries for @fonlan/dsh-model-parameters settings page.\n * zh is the key source of truth; en must carry the exact same key set.\n */\nexport const LOCALE_NS = 'model-parameters'\n\nexport const zh = {\n settingsTitle: '模型参数补全',\n sectionSub: '补全字段、目录刷新、Provider 映射与补全报告。',\n master: '启用自动补全',\n masterDesc: '关闭后不再自动补全任何字段(已补全的值保留)。',\n fields: '补全字段',\n fillName: '显示名称',\n fillNameDesc: '模型条目缺 name 时写入目录中的显示名称。',\n fillContext: '最大上下文',\n fillContextDesc: '缺 contextWindow 时写入目录的上下文上限。',\n fillMaxTokens: '最大输出',\n fillMaxTokensDesc: '缺 maxTokens 时写入目录的输出上限。',\n fillReasoning: '推理强度',\n fillReasoningDesc: '缺 reasoningEfforts 时按目录 effort 档位写入 identity 字典(如 {high:\"high\", max:\"max\"})。',\n fillInput: '输入模态',\n fillInputDesc: '缺 input 时写入目录中的 text/image 模态。',\n ttl: '目录更新周期(天)',\n ttlDesc: '缓存的 models.dev 目录超过该天数后,在下次补全时自动刷新。',\n providerMap: 'Provider 映射',\n providerMapDesc: 'dsh provider → models.dev provider 的匹配覆盖(可选)。',\n addMapping: '添加映射',\n removeMapping: '移除',\n catalog: '模型目录',\n catalogEntries: '目录条目',\n catalogProviders: '覆盖 Provider',\n catalogFetched: '上次更新',\n catalogFresh: '新鲜',\n catalogStale: '已过期',\n catalogNever: '尚未获取',\n catalogRoute: '下载经由',\n routeDirect: '直连',\n routeEnv: '环境变量代理',\n routeMacos: 'macOS 系统代理',\n routeWindows: 'Windows 系统代理',\n catalogDownloadFailed: '上次下载失败',\n refresh: '立即更新目录并补全',\n refreshBusy: '更新中…',\n reconcileNow: '立即补全一次',\n report: '最近一次补全',\n reportNever: '尚未执行',\n reportFilled: '补全字段',\n reportTouched: '涉及 Provider',\n reportUnmatched: '未匹配模型',\n reportEmpty: '全部匹配,无未匹配项',\n reportAt: '时间',\n error: '加载失败',\n saving: '保存中…',\n officialProviders: '官方厂商优先级',\n officialProvidersDesc: '同一模型 id 在多处出现时,优先采用这些 models.dev provider 的条目。',\n} as const\n\nexport const en: Record<keyof typeof zh, string> = {\n settingsTitle: 'Model Parameters',\n sectionSub: 'Field toggles, catalog refresh, provider mapping and the fill report.',\n master: 'Enable auto-fill',\n masterDesc: 'When off, no fields are filled (already-filled values are kept).',\n fields: 'Fields to fill',\n fillName: 'Display name',\n fillNameDesc: 'Write the catalog display name when a model entry lacks name.',\n fillContext: 'Context window',\n fillContextDesc: 'Write the catalog context limit when contextWindow is missing.',\n fillMaxTokens: 'Max output',\n fillMaxTokensDesc: 'Write the catalog output limit when maxTokens is missing.',\n fillReasoning: 'Reasoning efforts',\n fillReasoningDesc: 'Write an identity reasoningEfforts dict (e.g. {high:\"high\", max:\"max\"}) from catalog effort levels when missing.',\n fillInput: 'Input modalities',\n fillInputDesc: 'Write text/image modalities from the catalog when input is missing.',\n ttl: 'Catalog refresh interval (days)',\n ttlDesc: 'The cached models.dev catalog is refreshed on the next fill once older than this many days.',\n providerMap: 'Provider mapping',\n providerMapDesc: 'Optional dsh provider → models.dev provider matching overrides.',\n addMapping: 'Add mapping',\n removeMapping: 'Remove',\n catalog: 'Model catalog',\n catalogEntries: 'Catalog entries',\n catalogProviders: 'Providers covered',\n catalogFetched: 'Last updated',\n catalogFresh: 'fresh',\n catalogStale: 'stale',\n catalogNever: 'not fetched yet',\n catalogRoute: 'Download route',\n routeDirect: 'direct',\n routeEnv: 'environment proxy',\n routeMacos: 'macOS system proxy',\n routeWindows: 'Windows system proxy',\n catalogDownloadFailed: 'Last download failed',\n refresh: 'Update catalog & fill now',\n refreshBusy: 'Updating…',\n reconcileNow: 'Fill now',\n report: 'Last fill',\n reportNever: 'never run',\n reportFilled: 'fields filled',\n reportTouched: 'providers touched',\n reportUnmatched: 'unmatched models',\n reportEmpty: 'all matched, nothing unmatched',\n reportAt: 'time',\n error: 'Failed to load',\n saving: 'Saving…',\n officialProviders: 'Official provider priority',\n officialProvidersDesc: 'When one model id appears under several providers, prefer entries from these models.dev providers.',\n}\n","/** Client transport for the model-parameters settings API. */\nimport type { ModelParametersConfig } from '../shared/config.js'\n\nexport interface CatalogTransportView {\n kind: 'direct' | 'env' | 'macos' | 'windows'\n /** Masked proxy URL (no credentials), present when a proxy is actually used. */\n proxy?: string\n}\n\nexport interface CatalogView {\n entries: number\n providers: number\n fetchedAt: number\n fresh: boolean\n ttlDays: number\n /** Route the last download attempt took (null until one runs). */\n transport: CatalogTransportView | null\n /** Message of the last failed download (cleared on success). */\n error: string | null\n}\n\nexport interface FillReportView {\n at: number\n filled: number\n touched: number\n unmatched: string[]\n}\n\nexport interface PluginState {\n config: ModelParametersConfig\n catalog: CatalogView\n report: FillReportView | null\n}\n\nexport class ModelParametersApiError 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-parameters/api/${method}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n })\n } catch (error) {\n throw new ModelParametersApiError('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 ModelParametersApiError(\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<PluginState>('state'),\n refresh: () => call<PluginState>('refresh'),\n reconcile: () => call<PluginState>('reconcile'),\n setConfig: (patch: Partial<ModelParametersConfig>) =>\n call<PluginState>('set-config', { patch }),\n}\n","/**\n * The Model Parameters settings page (设置 → 侧栏「模型参数补全」).\n *\n * Registers into the `settings.section` slot, so the page owns one entry in\n * the settings sidebar and renders its content in the panel's content column.\n * Content: master + per-field toggles, catalog TTL, provider→models.dev\n * mapping overrides, a manual refresh/fill action, the catalog freshness line,\n * and the last fill report (filled / touched / unmatched).\n *\n * All reads/mutations go through the plugin's fenced API; config persists into\n * the `model-parameters` profile entry — the plugin's own loader entry config,\n * written through the host settings service.\n */\nimport { useCallback, useEffect, useState, useSyncExternalStore } from 'react'\nimport type { Context } from '@deepseek-ai/cordis'\ntype ClientContext = Context\nimport type { Translate } from '@deepseek-ai/dsh-client-ui-slots'\nimport { LOCALE_NS } from './locales'\nimport { api, type CatalogTransportView, type PluginState } from './api'\nimport type { ModelParametersConfig } from '../shared/config.js'\nimport './settings-section.css'\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\nfunction formatTime(epochMs: number): string {\n try {\n return new Date(epochMs).toLocaleString()\n } catch {\n return String(epochMs)\n }\n}\n\n/** Localized label for the route the last catalog download took. */\nfunction routeLabel(t: Translate, transport: CatalogTransportView): string {\n switch (transport.kind) {\n case 'env':\n return t('routeEnv')\n case 'macos':\n return t('routeMacos')\n case 'windows':\n return t('routeWindows')\n default:\n return t('routeDirect')\n }\n}\n\nexport function makeSettingsSection(ctx: ClientContext): () => JSX.Element {\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 ModelParametersSettingsSection(): JSX.Element {\n useLocaleRevision(ctx)\n const [state, setState] = useState<PluginState | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [loading, setLoading] = useState(true)\n const [busy, setBusy] = useState(false)\n const [saving, setSaving] = useState(false)\n const [mappingRows, setMappingRows] = useState<Array<{ from: string; to: string }>>([])\n const [newFrom, setNewFrom] = useState('')\n const [newTo, setNewTo] = useState('')\n\n const load = useCallback(async () => {\n setLoading(true)\n try {\n const next = await api.state()\n setState(next)\n setMappingRows(Object.entries(next.config.providerMap).map(([from, to]) => ({ from, to })))\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 patchConfig = useCallback(async (patch: Partial<ModelParametersConfig>) => {\n setSaving(true)\n try {\n const next = await api.setConfig(patch)\n setState(next)\n setMappingRows(Object.entries(next.config.providerMap).map(([from, to]) => ({ from, to })))\n setError(null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setSaving(false)\n }\n }, [])\n\n const refresh = useCallback(async () => {\n setBusy(true)\n try {\n setState(await api.refresh())\n setError(null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }, [])\n\n const reconcileNow = useCallback(async () => {\n setBusy(true)\n try {\n setState(await api.reconcile())\n setError(null)\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause))\n } finally {\n setBusy(false)\n }\n }, [])\n\n const applyMappings = useCallback(async () => {\n const providerMap: Record<string, string> = {}\n for (const row of mappingRows) {\n const from = row.from.trim()\n const to = row.to.trim()\n if (from.length > 0 && to.length > 0) providerMap[from] = to\n }\n await patchConfig({ providerMap })\n }, [mappingRows, patchConfig])\n\n return (\n <div className=\"mp-page\">\n <header className=\"mp-page-head\">\n <h3 className=\"mp-page-title\">{t('settingsTitle')}</h3>\n <p className=\"mp-page-sub\">{t('sectionSub')}</p>\n </header>\n {error !== null && state === null ? (\n <p className=\"mp-error\">{t('error')}: {error}</p>\n ) : loading || state === null ? (\n <p className=\"mp-muted\">{t('saving')}</p>\n ) : (\n <ModelParametersBody\n t={t}\n state={state}\n error={error}\n saving={saving}\n busy={busy}\n mappingRows={mappingRows}\n newFrom={newFrom}\n newTo={newTo}\n setNewFrom={setNewFrom}\n setNewTo={setNewTo}\n setMappingRows={setMappingRows}\n onPatchConfig={patchConfig}\n onRefresh={refresh}\n onReconcile={reconcileNow}\n onApplyMappings={applyMappings}\n />\n )}\n </div>\n )\n }\n}\n\n/** The page body: divider-separated control groups. */\nfunction ModelParametersBody(props: {\n t: Translate\n state: PluginState\n error: string | null\n saving: boolean\n busy: boolean\n mappingRows: Array<{ from: string; to: string }>\n newFrom: string\n newTo: string\n setNewFrom: (value: string) => void\n setNewTo: (value: string) => void\n setMappingRows: (rows: Array<{ from: string; to: string }>) => void\n onPatchConfig: (patch: Partial<ModelParametersConfig>) => Promise<void>\n onRefresh: () => Promise<void>\n onReconcile: () => Promise<void>\n onApplyMappings: () => Promise<void>\n}): JSX.Element {\n const {\n t, state, error, saving, busy,\n mappingRows, newFrom, newTo,\n setNewFrom, setNewTo, setMappingRows,\n onPatchConfig, onRefresh, onReconcile, onApplyMappings,\n } = props\n\n const config = state.config\n const catalog = state.catalog\n const report = state.report\n\n return (\n <div className=\"mp-body\">\n <section className=\"mp-group\">\n <h4 className=\"mp-group-title\">{t('fields')}</h4>\n <label className=\"mp-toggle\">\n <input\n type=\"checkbox\"\n checked={config.enabled}\n disabled={saving}\n onChange={(event) => void onPatchConfig({ enabled: event.target.checked })}\n />\n <span className=\"mp-toggle-body\">\n <span className=\"mp-toggle-label\">{t('master')}</span>\n <span className=\"mp-toggle-desc\">{t('masterDesc')}</span>\n </span>\n </label>\n {([\n ['fillName', t('fillName'), t('fillNameDesc')],\n ['fillContext', t('fillContext'), t('fillContextDesc')],\n ['fillMaxTokens', t('fillMaxTokens'), t('fillMaxTokensDesc')],\n ['fillReasoning', t('fillReasoning'), t('fillReasoningDesc')],\n ['fillInput', t('fillInput'), t('fillInputDesc')],\n ] as const).map(([key, label, desc]) => (\n <label className=\"mp-toggle mp-toggle-sub\" key={key}>\n <input\n type=\"checkbox\"\n checked={config[key]}\n disabled={saving || !config.enabled}\n onChange={(event) => void onPatchConfig({ [key]: event.target.checked })}\n />\n <span className=\"mp-toggle-body\">\n <span className=\"mp-toggle-label\">{label}</span>\n <span className=\"mp-toggle-desc\">{desc}</span>\n </span>\n </label>\n ))}\n </section>\n\n <hr className=\"mp-divider\" />\n\n <section className=\"mp-group\">\n <h4 className=\"mp-group-title\">{t('catalog')}</h4>\n <div className=\"mp-meta\">\n <span>{t('catalogEntries')}: <strong>{catalog.entries.toLocaleString()}</strong></span>\n <span>{t('catalogProviders')}: <strong>{catalog.providers.toLocaleString()}</strong></span>\n <span>\n {t('catalogFetched')}:{' '}\n <strong>{catalog.fetchedAt > 0 ? formatTime(catalog.fetchedAt) : t('catalogNever')}</strong>{' '}\n {catalog.fetchedAt > 0 && (\n <span className={catalog.fresh ? 'mp-badge mp-badge-ok' : 'mp-badge mp-badge-warn'}>\n {catalog.fresh ? t('catalogFresh') : t('catalogStale')}\n </span>\n )}\n </span>\n <label className=\"mp-ttl\">\n {t('ttl')}\n <input\n className=\"mp-input mp-input-narrow\"\n type=\"number\"\n min={1}\n max={90}\n value={config.ttlDays}\n disabled={saving}\n onChange={(event) => {\n const days = Number(event.target.value)\n if (Number.isFinite(days) && days >= 1 && days <= 90) void onPatchConfig({ ttlDays: Math.round(days) })\n }}\n />\n </label>\n {catalog.transport != null && (\n <span>\n {t('catalogRoute')}:{' '}\n <strong>{routeLabel(t, catalog.transport)}</strong>\n {catalog.transport.proxy !== undefined && <> <code className=\"mp-code\">{catalog.transport.proxy}</code></>}\n </span>\n )}\n </div>\n {catalog.error != null && (\n <p className=\"mp-error\">{t('catalogDownloadFailed')}: {catalog.error}</p>\n )}\n <div className=\"mp-actions\">\n <button className=\"mp-button\" disabled={busy} onClick={() => void onRefresh()}>\n {busy ? t('refreshBusy') : t('refresh')}\n </button>\n <button className=\"mp-button mp-button-ghost\" disabled={busy} onClick={() => void onReconcile()}>\n {t('reconcileNow')}\n </button>\n </div>\n </section>\n\n <hr className=\"mp-divider\" />\n\n <section className=\"mp-group\">\n <h4 className=\"mp-group-title\">{t('providerMap')}</h4>\n <p className=\"mp-desc\">{t('providerMapDesc')}</p>\n {mappingRows.map((row, index) => (\n <div className=\"mp-map-row\" key={index}>\n <input\n className=\"mp-input\"\n value={row.from}\n disabled={saving}\n onChange={(event) => {\n const next = [...mappingRows]\n next[index] = { ...row, from: event.target.value }\n setMappingRows(next)\n }}\n />\n <span className=\"mp-map-arrow\">→</span>\n <input\n className=\"mp-input\"\n value={row.to}\n disabled={saving}\n onChange={(event) => {\n const next = [...mappingRows]\n next[index] = { ...row, to: event.target.value }\n setMappingRows(next)\n }}\n />\n <button\n className=\"mp-button mp-button-ghost\"\n disabled={saving}\n onClick={() => setMappingRows(mappingRows.filter((_, i) => i !== index))}\n >\n {t('removeMapping')}\n </button>\n </div>\n ))}\n <div className=\"mp-map-row\">\n <input\n className=\"mp-input\"\n placeholder=\"dsh provider\"\n value={newFrom}\n onChange={(event) => setNewFrom(event.target.value)}\n />\n <span className=\"mp-map-arrow\">→</span>\n <input\n className=\"mp-input\"\n placeholder=\"models.dev provider\"\n value={newTo}\n onChange={(event) => setNewTo(event.target.value)}\n />\n <button\n className=\"mp-button mp-button-ghost\"\n disabled={newFrom.trim().length === 0 || newTo.trim().length === 0}\n onClick={() => {\n setMappingRows([...mappingRows, { from: newFrom.trim(), to: newTo.trim() }])\n setNewFrom('')\n setNewTo('')\n }}\n >\n {t('addMapping')}\n </button>\n </div>\n <div className=\"mp-actions\">\n <button className=\"mp-button\" disabled={saving} onClick={() => void onApplyMappings()}>\n {saving ? t('saving') : '✓ ' + t('providerMap')}\n </button>\n </div>\n </section>\n\n <hr className=\"mp-divider\" />\n\n <section className=\"mp-group\">\n <h4 className=\"mp-group-title\">{t('report')}</h4>\n {report === null ? (\n <p className=\"mp-muted\">{t('reportNever')}</p>\n ) : (\n <ul className=\"mp-report\">\n <li>{t('reportAt')}: {formatTime(report.at)}</li>\n <li>{t('reportFilled')}: <strong>{report.filled}</strong></li>\n <li>{t('reportTouched')}: <strong>{report.touched}</strong></li>\n <li>\n {t('reportUnmatched')}:{' '}\n {report.unmatched.length === 0\n ? t('reportEmpty')\n : <code className=\"mp-code\">{report.unmatched.join(', ')}</code>}\n </li>\n </ul>\n )}\n </section>\n\n {error !== null && <p className=\"mp-error\">{error}</p>}\n </div>\n )\n}\n","/**\n * @fonlan/dsh-model-parameters client half: the plugin's own Settings section.\n *\n * Registers into the settings.section slot, so the page owns one entry in the\n * settings sidebar and renders in the panel's content column. The page itself\n * lives in ./settings-section.\n *\n * Deps resolved from the browser module table: react only. The slots service\n * is reached through the cordis context; types come from devDependencies and\n * are erased at build time.\n */\nimport type { Context } from '@deepseek-ai/cordis'\ntype ClientContext = Context\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-slots'\nimport { LOCALE_NS, zh, en } from './locales'\nimport { makeSettingsSection } from './settings-section'\n\n/** The settings sidebar entry this page owns (must stay stable). */\nconst SECTION_ID = 'model-parameters'\n\n/** The slots service face (subset of @deepseek-ai/dsh-client-ui-slots). */\ninterface SlotEntry {\n name: string\n id?: string\n order?: number\n label?: () => string\n locale?: string\n}\n\ninterface Slots {\n inject(name: string, register: () => unknown): unknown\n register(def: SlotEntry, component: unknown): unknown\n}\n\n/** Services required before mounting (provided by the client runtime). */\nexport const inject = ['slots', 'locale']\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-parameters: dictionaries')\n\n const t = ctx.locale.bind(LOCALE_NS) as unknown as (key: string) => string\n const Section = makeSettingsSection(ctx)\n const slots = (ctx as unknown as { slots: Slots }).slots\n slots.inject('settings.section', () =>\n slots.register({\n name: 'settings.section',\n id: SECTION_ID,\n order: 320,\n label: () => t('settingsTitle'),\n locale: LOCALE_NS,\n }, Section),\n )\n}\n"],"mappings":"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"}