dsh-model-extension 1.2.3-alpha.2 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -9
- package/lib/client.js +77 -22
- package/lib/client.js.map +1 -1
- package/lib/index.js +17 -47
- package/lib/index.js.map +1 -1
- package/package.json +1 -2
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["createSnapshotStore","useState","useRef","styles","useState","styles","useState","styles","Modal","useState","useMemo","styles","useState","styles","useState","styles","Modal","extensionZh","extensionEn"],"sources":["official/src/client/vendor/store.ts","official/src/client/models-plus/models-index.ts","official/src/client/extension-meta.ts","official/src/client/models-plus/compat.ts","official/src/client/models-plus/presets.ts","official/src/client/models-plus/prefill.ts","official/src/client/models-plus/models-plus.module.css","official/src/client/models-plus/QuickLoad.tsx","official/src/client/models-plus/ModelEntryPanel.tsx","official/src/client/models-plus/ModelCatalog.tsx","official/src/client/models-plus/ProviderEditor.tsx","official/src/client/models-plus/CreateProviderCard.tsx","official/src/client/models-plus/ModelsPlusSection.tsx","official/src/client/vendor/operations.ts","official/src/client/vendor/schema-operations.ts","official/src/client/index-extension.ts"],"sourcesContent":["/**\n * VENDORED from @deepseek-ai/dsh-client-ui-settings-models @ 0.1.5-rc.1\n * (host tree packages/client/ui-settings-models/src/client/store.ts) — copied\n * VERBATIM so the build is self-contained (no host checkout required).\n * Re-diff against the host source on every adapter-anchor bump.\n */\n/**\n * Models settings page store: one snapshot joining the configurable-provider\n * directory (`llm/listProviders` joined with `llm/listConfigurableProviders`),\n * the settings namespaces (shared settings mirror),\n * and the referenced credentials (`credentials/describe`). The host stays the\n * single fact source — every mutation writes through the wire and the page\n * re-renders from the next describe, pushed or refetched.\n */\n\nimport type { Context as ClientContext } from '@deepseek-ai/cordis'\nimport type {\n CredentialInfo, LlmConfigurableProvider, LlmProviderInfo, SettingsNamespaceView,\n} from '@deepseek-ai/dsh-api-remotes/client'\nimport type { SnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport { createSnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport type { SettingsDescribeFace } from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type { SettingsSchemaOperations } from './schema-operations.ts'\n\n/**\n * Any route key walks a dict schema to the same profile node, so the lookup\n * names one that cannot collide with a configured route.\n */\nconst PROBE_ROUTE = '\\u0000probe'\n\n/** One provider row after joining the configurable directory with live routes. */\nexport interface ProviderDirectoryEntry {\n readonly provider: string\n readonly displayName: string\n readonly settingsNs: string\n readonly settingsPath: readonly string[]\n readonly active: boolean\n readonly declared?: boolean\n readonly error?: string\n}\n\n/**\n * Join declared configurable providers with the currently registered routes.\n * @param registered - live provider routes in registration order.\n * @param directory - declared configurable providers in declaration order.\n * @returns declared rows followed by live routes with no declaration.\n */\nexport function joinProviderDirectory(\n registered: readonly LlmProviderInfo[],\n directory: readonly LlmConfigurableProvider[],\n): ProviderDirectoryEntry[] {\n const active = new Set(registered.map(provider => provider.id))\n const declared = new Set(directory.map(entry => entry.provider))\n const rows: ProviderDirectoryEntry[] = directory.map(entry => ({\n provider: entry.provider,\n displayName: entry.displayName,\n settingsNs: entry.settingsNs,\n settingsPath: [...entry.settingsPath],\n active: active.has(entry.provider),\n ...entry.declared === undefined ? {} : { declared: entry.declared },\n ...entry.error === undefined ? {} : { error: entry.error },\n }))\n for (const provider of registered) {\n if (declared.has(provider.id)) continue\n rows.push({\n provider: provider.id,\n displayName: provider.name,\n settingsNs: '',\n settingsPath: [],\n active: true,\n })\n }\n return rows\n}\n\n/** One provider row the page renders. */\nexport interface ProviderRow {\n /** The directory entry (route id, display name, settings address, live state). */\n entry: ProviderDirectoryEntry\n /** Whether any layer configures this provider (its profile resolves). */\n configured: boolean\n /** Whether the user layer alone carries the profile (removal restores the base). */\n removable: boolean\n /** The credential reference the resolved profile names, when one does. */\n apiKeyEnv: string | undefined\n /** Credential state for {@link apiKeyEnv}, once described. */\n credential: CredentialInfo | undefined\n /**\n * Credential state for the page's derived `<ROUTE>_API_KEY`, described only\n * while the profile names no reference — the provider-card seat's\n * `keyConfigured` fact for dormant and keyless rows, matching the editor's\n * own derivation rule.\n */\n derivedCredential?: CredentialInfo\n}\n\n/** Page snapshot. */\nexport interface ModelsSettingsState {\n status: 'idle' | 'loading' | 'ready' | 'error'\n /** Whole-load failure text; row-level write failures stay in the editor. */\n error: string | null\n /** Credential enrichment failure; provider/settings rows remain usable. */\n credentialError: string | null\n /** Whether the settings provider accepts writes. */\n writable: boolean\n /** Every configurable provider joined with its configured/credential state. */\n rows: readonly ProviderRow[]\n /** Namespace views by ns, for the editor's schema/layers/secrets. */\n namespaces: ReadonlyMap<string, SettingsNamespaceView>\n}\n\n/**\n * Derive the conventional credential reference for a provider route: the v1\n * page never asks for an environment-variable name, so a typed key stores\n * under this derived reference and the profile records it as `apiKeyEnv`.\n * @param provider - provider route id (e.g. `anthropic`, `minimax-cn`).\n * @returns the derived reference name (e.g. `MINIMAX_CN_API_KEY`).\n */\nexport function deriveKeyRef(provider: string): string {\n return `${provider.toUpperCase().replace(/[^A-Z0-9]+/g, '_')}_API_KEY`\n}\n\n/**\n * The wire protocols a hand-declared route may name, read out of the owning\n * namespace's own schema. This stays a schema read rather than a wire field so\n * the choices the page offers cannot drift from the ones the adapter accepts:\n * both come from the same `Config`.\n * @param namespace - the namespace view whose schema declares the profile shape.\n * @param schema - settings schema operations.\n * @returns the protocol identifiers, or an empty list when the schema has none.\n */\nexport function protocolChoices(\n namespace: SettingsNamespaceView | undefined,\n schema: SettingsSchemaOperations,\n): string[] {\n if (namespace === undefined) return []\n const node = schema.nodeAtPath(schema.rehydrate(namespace.schema), ['providers', PROBE_ROUTE, 'api'])\n const list = (node as { type?: string; list?: readonly { value?: unknown }[] } | undefined)\n if (list?.type !== 'union' || list.list === undefined) return []\n return list.list.map(entry => entry.value).filter((value): value is string => typeof value === 'string')\n}\n\n/** The credential reference a resolved profile names (its `apiKeyEnv` field). */\nfunction apiKeyEnvOf(\n namespace: SettingsNamespaceView | undefined,\n path: readonly string[],\n schema: SettingsSchemaOperations,\n): string | undefined {\n if (namespace === undefined) return undefined\n const profile = schema.getPath(namespace.value, path)\n if (typeof profile !== 'object' || profile === null) return undefined\n const ref = (profile as { apiKeyEnv?: unknown }).apiKeyEnv\n return typeof ref === 'string' && ref.length > 0 ? ref : undefined\n}\n\n/** The models settings page controller (one per settings surface). */\nexport class ModelsSettingsStore {\n /** The snapshot the section renders from (uSES-safe store). */\n readonly store: SnapshotStore<ModelsSettingsState> = createSnapshotStore<ModelsSettingsState>({\n status: 'idle', error: null, credentialError: null, writable: false, rows: [], namespaces: new Map(),\n })\n\n /** Latest load wins; an older response never overwrites a newer one. */\n private generation = 0\n\n /**\n * @param ctx - the page plugin's context, whose `remote.llm` and\n * `remote.credentials` namespaces carry the directory and credential reads.\n * @param schema - settings-owned schema and immutable path operations.\n * @param describeFace - the shared mirror's describe face (namespace views and writability).\n */\n constructor(\n private readonly ctx: ClientContext,\n private readonly schema: SettingsSchemaOperations,\n private readonly describeFace: SettingsDescribeFace,\n ) {}\n\n /**\n * Refresh the whole page snapshot: the provider directory and the mirror's\n * settings answer in parallel, then one batched credential describe over\n * every referenced ref. Provider failure or absence of an initial settings\n * answer keeps the last good rows and surfaces an error; a failed settings\n * refresh reuses the mirror's held view.\n * @returns nothing; the snapshot carries the outcome.\n */\n async load(): Promise<void> {\n const generation = ++this.generation\n this.store.update((s) => { s.status = 'loading'; s.error = null })\n const [registered, declared] = await Promise.all([\n this.ctx.remote.llm.listProviders(),\n this.ctx.remote.llm.listConfigurableProviders(),\n this.describeFace.ensure(),\n ])\n if (!registered.ok) { this.failLoad(generation, registered.error.message); return }\n if (!declared.ok) { this.failLoad(generation, declared.error.message); return }\n const mirrored = this.describeFace.getSnapshot()\n if (mirrored.view === undefined) {\n this.failLoad(generation, mirrored.error ?? 'settings are unavailable in this browser')\n return\n }\n const providers = joinProviderDirectory(registered.value, declared.value)\n const writable = mirrored.view.writable\n const views: readonly SettingsNamespaceView[] = mirrored.view.namespaces\n const namespaces = new Map(views.map(view => [view.ns, view]))\n const rows: ProviderRow[] = providers.map((entry) => {\n const namespace = namespaces.get(entry.settingsNs)\n const configured = namespace !== undefined\n && (entry.settingsPath.length === 0 || this.schema.getPath(namespace.value, entry.settingsPath) !== undefined)\n const removable = namespace !== undefined\n && entry.settingsPath.length > 0\n && this.schema.hasPath(namespace.user, entry.settingsPath)\n && !this.schema.hasPath(namespace.base, entry.settingsPath)\n return {\n entry,\n configured,\n removable,\n apiKeyEnv: apiKeyEnvOf(namespace, entry.settingsPath, this.schema),\n credential: undefined,\n }\n })\n const refs = [...new Set(rows.map(row => row.apiKeyEnv ?? deriveKeyRef(row.entry.provider)))]\n let credentials: Record<string, CredentialInfo> = {}\n let credentialError: string | null = null\n if (refs.length > 0) {\n const response = await this.ctx.remote.credentials.describe(refs)\n // Credential state is an enrichment for the Models page: a failure\n // degrades the badge instead of failing the load. The onboarding\n // projection below retains the failure distinction.\n if (response.ok) credentials = response.value\n else credentialError = response.error.message\n }\n if (generation !== this.generation) return\n this.store.update((s) => {\n s.status = 'ready'\n s.error = null\n s.credentialError = credentialError\n s.writable = writable\n s.rows = rows.map((row) => {\n const named = row.apiKeyEnv === undefined ? undefined : credentials[row.apiKeyEnv]\n const derived = row.apiKeyEnv !== undefined ? undefined : credentials[deriveKeyRef(row.entry.provider)]\n return {\n ...row,\n ...named === undefined ? {} : { credential: named },\n ...derived === undefined ? {} : { derivedCredential: derived },\n }\n })\n s.namespaces = namespaces\n })\n }\n\n /** Publish one load's failure text, unless a newer load already took over. */\n private failLoad(generation: number, message: string): void {\n if (generation !== this.generation) return\n this.store.update((s) => {\n s.status = 'error'\n s.error = message\n })\n }\n}\n\n/**\n * Whether a joined row can serve model requests as it stands: the route is\n * registered with the adapter registry, and whatever credential its resolved\n * profile names is stored. A profile naming no reference authenticates through\n * the provider's own path (the Bedrock chain, Vertex ADC, a gateway that needs\n * nothing), as does a live route with no settings address at all, so neither\n * owes this page a key.\n * @param row - one joined provider row.\n * @returns whether the user already has this provider to talk to.\n */\nexport function providerUsable(row: ProviderRow): boolean {\n if (!row.entry.active) return false\n if (row.apiKeyEnv === undefined) return true\n return row.credential?.configured === true\n}\n\n/** First-run onboarding readiness derived only from the shared Models join. */\nexport type OnboardingReadiness =\n | { kind: 'loading' }\n | { kind: 'adapter-absent' }\n | { kind: 'provider-ready' }\n | { kind: 'credential-missing' }\n | {\n kind: 'unavailable'\n reason:\n | 'load-failed'\n | 'provider-inactive'\n | 'credentials-unavailable'\n | 'settings-read-only'\n | 'credential-read-only'\n }\n\n/**\n * Project first-run readiness from the provider/settings/credential join used\n * by the Models page. The step exists to leave the user with a model to talk\n * to, so ANY usable provider ends it; only when none exists does the official\n * DeepSeek route — the one route the prompt can offer a key field for — decide\n * whether prompting can help. A missing official configurable-provider\n * declaration means the adapter is not repairable by navigating to Models.\n * @param state - current shared Models join snapshot.\n * @returns the onboarding state without reading a parallel fact source.\n */\nexport function onboardingReadiness(state: ModelsSettingsState): OnboardingReadiness {\n if ((state.status === 'idle' || state.status === 'loading') && state.rows.length === 0) {\n return { kind: 'loading' }\n }\n if (state.status === 'error') {\n return {\n kind: 'unavailable',\n reason: 'load-failed',\n }\n }\n if (state.rows.some(providerUsable)) return { kind: 'provider-ready' }\n const row = state.rows.find(candidate =>\n candidate.entry.provider === 'deepseek-official'\n && candidate.entry.settingsNs === 'llm-deepseek'\n && candidate.entry.settingsPath.length === 0)\n if (row === undefined) return { kind: 'adapter-absent' }\n if (!row.entry.active) {\n return {\n kind: 'unavailable',\n reason: 'provider-inactive',\n }\n }\n // Past the usable gate an active route names a reference it has no stored\n // credential for, so the remaining questions are all about that credential.\n if (state.credentialError !== null || row.credential === undefined) {\n return {\n kind: 'unavailable',\n reason: 'credentials-unavailable',\n }\n }\n if (!state.writable) {\n return {\n kind: 'unavailable',\n reason: 'settings-read-only',\n }\n }\n if (!row.credential.writable) {\n return {\n kind: 'unavailable',\n reason: 'credential-read-only',\n }\n }\n return { kind: 'credential-missing' }\n}\n","/**\n * Client access to the prefill index.\n *\n * Two sources, one search surface:\n *\n * - **pi-ai** — the installed `@earendil-works/pi-ai` catalog, served by this\n * plugin's own route straight from the package the host adapter loads. It is\n * the source carrying the reasoning and compat surface models.dev has no\n * concept of, and it costs no network call.\n * - **models.dev** — a flat metadata file, fetched ONLY when the user clicks\n * the title-row button and cached next to settings.yaml under DSH home.\n *\n * pi-ai candidates lead (richer, and faithful to what the host will actually\n * do); models.dev follows as the fallback for routes pi-ai ships nothing\n * about. An unavailable pi-ai source is not an error — the index simply\n * carries an empty pi-ai list and the search degrades to models.dev alone.\n */\n\n/** Which source a prefill candidate came from. */\nexport type PrefillSource = 'pi-ai' | 'models.dev'\n\n/** One prefill candidate, normalized across both sources. */\nexport interface PrefillEntry {\n readonly source: PrefillSource\n /** Unique within the fetched index (source, provider and id combined). */\n readonly key: string\n /** The source's own model id — also what the candidate list renders. */\n readonly id: string\n /**\n * Owning provider: pi-ai's provider id (the route key a catalog route is\n * named after), or the leading segment of a models.dev directory path.\n * Absent when the source does not name one.\n */\n readonly provider?: string\n /** Display name, when the source carries one. */\n readonly name?: string\n /** Maximum combined request and response context in tokens. */\n readonly context: number | undefined\n /** Maximum output tokens. */\n readonly output: number | undefined\n /** Accepted request modalities, already narrowed to what this UI offers. */\n readonly input: readonly string[]\n /** Whether the model reasons at all. */\n readonly reasoning: boolean\n /**\n * pi-ai only: its own level→wire-spelling map. Semantically our\n * `reasoningEfforts`, except that `null` means *unsupported* here while our\n * dict reads it as *supported, send nothing* — the panel maps it, never\n * copies it across.\n */\n readonly thinkingLevelMap?: Readonly<Record<string, string | null>>\n /** pi-ai only: the wire protocol the model speaks, which picks its compat set. */\n readonly api?: string\n /** pi-ai only: the wire-compatibility switches the catalog records. */\n readonly compat?: Readonly<Record<string, unknown>>\n}\n\n/** The fetched prefill index: pi-ai leads, models.dev follows. */\nexport interface PrefillIndex {\n /** Candidates from the installed pi-ai catalog; empty when unavailable. */\n readonly piAi: readonly PrefillEntry[]\n /** Candidates from the cached models.dev file; empty when not downloaded. */\n readonly modelsDev: readonly PrefillEntry[]\n /** Installed pi-ai version, for the source note in the UI. */\n readonly piAiVersion?: string\n /** Generation timestamp of the pi-ai catalog snapshot. */\n readonly piAiGeneratedAt?: string\n /**\n * Drift findings reported alongside the catalog: a pi-ai version outside the\n * verified set, a resolution path that had to be guessed, several pi-ai\n * copies on the host, or records that did not project cleanly.\n *\n * Surfaced verbatim and unconditionally — a warning nobody sees is a silent\n * failure with extra steps, which is exactly the state this field exists to\n * rule out.\n */\n readonly piAiWarnings: readonly string[]\n /**\n * Why the pi-ai source is empty, when it was *refused* rather than simply\n * absent. The server names the concrete cause (no package found, the catalog\n * API unreachable), which is the difference between a diagnosis and a shrug.\n */\n readonly piAiFailure?: string\n}\n\n/** Same-origin routes served by the server half. */\nconst INDEX_URL = '/plugins/dsh-model-extension/models-index'\nconst DOWNLOAD_URL = '/plugins/dsh-model-extension/models-download'\nconst PI_AI_URL = '/plugins/dsh-model-extension/pi-ai-catalog'\n\n/** Precise entry the models.dev route returns (a subset of the raw record). */\nexport interface MetadataEntry {\n readonly id: string\n readonly context: number | undefined\n readonly output: number | undefined\n readonly input: readonly string[]\n readonly reasoning: boolean\n}\n\n/** Module-level cache: one page load fetches each source at most once. */\nlet cachedIndex: PrefillIndex | undefined\n\n/** Normalize the models.dev route payload. */\nfunction normalize(raw: unknown): readonly MetadataEntry[] {\n if (!Array.isArray(raw)) return []\n const entries: MetadataEntry[] = []\n for (const item of raw) {\n if (typeof item !== 'object' || item === null) continue\n const row = item as Record<string, unknown>\n if (typeof row['id'] !== 'string' || row['id'].length === 0) continue\n const modalities = Array.isArray(row['input'])\n ? row['input'].filter((m): m is string => typeof m === 'string')\n : []\n entries.push({\n id: row['id'],\n context: typeof row['context'] === 'number' ? row['context'] : undefined,\n output: typeof row['output'] === 'number' ? row['output'] : undefined,\n input: modalities,\n reasoning: row['reasoning'] === true,\n })\n }\n return entries\n}\n\n/** Narrow a modality list to what this UI offers. */\nfunction supportedInput(value: unknown): string[] {\n if (!Array.isArray(value)) return []\n return value.filter((m): m is string => typeof m === 'string' && (m === 'text' || m === 'image'))\n}\n\n/** Read one object-valued field off a raw record. */\nfunction objectField(source: Record<string, unknown>, key: string): Record<string, unknown> | undefined {\n const value = source[key]\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? value as Record<string, unknown>\n : undefined\n}\n\n/**\n * The provider a models.dev id belongs to.\n *\n * models.dev ids are directory paths (`zhipuai/glm-5.3-flash`), so the leading\n * segment names the provider. Reading it here gives the picker the same\n * provider-first navigation that pi-ai's per-provider catalog has for free —\n * and it is what lets a user narrow by vendor instead of guessing between\n * same-named ids.\n * @param id - the models.dev directory id.\n * @returns the provider segment, or undefined when the id carries none.\n */\nfunction modelsDevProvider(id: string): string | undefined {\n const slash = id.indexOf('/')\n return slash > 0 ? id.slice(0, slash) : undefined\n}\n\n/** Turn models.dev rows into prefill candidates. */\nfunction toModelsDevEntries(rows: readonly MetadataEntry[]): readonly PrefillEntry[] {\n return rows.map((row): PrefillEntry => ({\n source: 'models.dev',\n key: `models.dev\\u0000${row.id}`,\n id: row.id,\n provider: modelsDevProvider(row.id),\n context: row.context,\n output: row.output,\n input: row.input,\n reasoning: row.reasoning,\n }))\n}\n\n/** Read the diagnostics warnings the server attaches to a catalog payload. */\nfunction diagnosticsWarnings(payload: unknown): readonly string[] {\n if (typeof payload !== 'object' || payload === null) return []\n const diagnostics = (payload as Record<string, unknown>)['diagnostics']\n if (typeof diagnostics !== 'object' || diagnostics === null) return []\n const warnings = (diagnostics as Record<string, unknown>)['warnings']\n if (!Array.isArray(warnings)) return []\n return warnings.filter((warning): warning is string => typeof warning === 'string')\n}\n\n/** Turn a pi-ai route payload into prefill candidates, keeping both ids' provenance. */\nfunction toPiAiEntries(payload: unknown): {\n entries: readonly PrefillEntry[]\n version?: string\n generatedAt?: string\n warnings: readonly string[]\n} {\n const warnings = diagnosticsWarnings(payload)\n if (typeof payload !== 'object' || payload === null) return { entries: [], warnings }\n const body = payload as Record<string, unknown>\n if (!Array.isArray(body['models'])) return { entries: [], warnings }\n\n // One id can live in several providers (zai, opencode and two gateways all\n // ship `glm-5.3-flash`), so ownership travels per entry instead of being\n // disambiguated inside a display string — the picker filters by provider\n // rather than asking the user to decode a suffix.\n const entries: PrefillEntry[] = []\n for (const item of body['models']) {\n if (typeof item !== 'object' || item === null) continue\n const row = item as Record<string, unknown>\n const id = row['id']\n const provider = row['provider']\n if (typeof id !== 'string' || id.length === 0) continue\n if (typeof provider !== 'string' || provider.length === 0) continue\n entries.push({\n source: 'pi-ai',\n key: `pi-ai\\u0000${provider}\\u0000${id}`,\n id,\n provider,\n name: typeof row['name'] === 'string' && row['name'].length > 0 ? row['name'] : undefined,\n context: typeof row['contextWindow'] === 'number' ? row['contextWindow'] : undefined,\n output: typeof row['maxTokens'] === 'number' ? row['maxTokens'] : undefined,\n input: supportedInput(row['input']),\n reasoning: row['reasoning'] === true,\n api: typeof row['api'] === 'string' ? row['api'] : undefined,\n thinkingLevelMap: objectField(row, 'thinkingLevelMap') as Record<string, string | null> | undefined,\n compat: objectField(row, 'compat'),\n })\n }\n\n return {\n entries,\n warnings,\n version: typeof body['piAiVersion'] === 'string' ? body['piAiVersion'] : undefined,\n generatedAt: typeof body['generatedAt'] === 'string' ? body['generatedAt'] : undefined,\n }\n}\n\n/**\n * Fetch one JSON route, keeping a refusal distinguishable from an empty source.\n *\n * The distinction matters for the pi-ai half: \"the host ships no catalog\" and\n * \"the host's catalog could not be called\" both leave the list empty, but only\n * the second one has a fix, and the server names it in the refusal body.\n * @param url - the same-origin route.\n * @returns the parsed payload, or the reason it is missing.\n */\nasync function fetchJson(url: string): Promise<{ payload?: unknown; failure?: string }> {\n try {\n const response = await fetch(url)\n const payload: unknown = await response.json().catch(() => undefined)\n if (response.ok) return { payload }\n const message = typeof payload === 'object' && payload !== null\n ? (payload as Record<string, unknown>)['message']\n : undefined\n return { failure: typeof message === 'string' ? message : `HTTP ${String(response.status)}` }\n } catch (error) {\n return { failure: error instanceof Error ? error.message : String(error) }\n }\n}\n\n/**\n * The prefill index, fetched once per page load. Both sources are requested\n * together and either may come back empty; an entirely empty index is a\n * legitimate answer the caller renders as \"nothing to load yet\".\n * @returns the merged index.\n */\nexport async function getPrefillIndex(): Promise<PrefillIndex> {\n if (cachedIndex !== undefined) return cachedIndex\n\n const [piAiResult, modelsDevResult] = await Promise.all([fetchJson(PI_AI_URL), fetchJson(INDEX_URL)])\n const piAi = toPiAiEntries(piAiResult.payload)\n\n cachedIndex = {\n piAi: piAi.entries,\n modelsDev: toModelsDevEntries(normalize(modelsDevResult.payload)),\n piAiVersion: piAi.version,\n piAiGeneratedAt: piAi.generatedAt,\n piAiWarnings: piAi.warnings,\n ...(piAiResult.failure !== undefined ? { piAiFailure: piAiResult.failure } : {}),\n }\n return cachedIndex\n}\n\n/**\n * The one wire protocol one catalog provider's entries agree on.\n *\n * This mirrors the host's own `sharedCatalogApi`: a route whose installed\n * entries all speak the same protocol needs no `api` in configuration, because\n * the host resolves every model — including ones the catalog does not describe\n * — to that shared protocol. Reading it here is what lets the panel judge a\n * row's compat switches the way the adapter will. A provider whose entries\n * disagree (an OpenAI-style catalog spanning Responses and Chat Completions)\n * has no such answer, and neither does an index that has not loaded yet.\n * @param index - the fetched index, or undefined while the page still loads.\n * @param provider - the route key to inspect.\n * @returns the shared protocol, or undefined when none settles it.\n */\nexport function sharedCatalogApi(index: PrefillIndex | undefined, provider: string | undefined): string | undefined {\n if (index === undefined || provider === undefined || provider.length === 0) return undefined\n const apis = new Set<string>()\n for (const entry of index.piAi) {\n if (entry.provider !== provider || entry.api === undefined) continue\n apis.add(entry.api)\n }\n return apis.size === 1 ? [...apis][0] : undefined\n}\n\n/** The outcome of an explicit user-triggered download. */\nexport type MetadataDownload = { readonly ok: true } | { readonly ok: false; readonly message: string }\n\n/**\n * Download/refresh the models.dev file through the server half (user-triggered\n * from the title-row button). A success also refreshes the local cache.\n */\nexport async function downloadMetadata(): Promise<MetadataDownload> {\n try {\n const response = await fetch(DOWNLOAD_URL, { method: 'POST' })\n const body = await response.json().catch(() => undefined) as\n | { ok?: boolean; message?: string }\n | undefined\n if (!response.ok || body?.ok !== true) {\n return { ok: false, message: body?.message ?? `HTTP ${String(response.status)}` }\n }\n cachedIndex = undefined\n return { ok: true }\n } catch (error) {\n return { ok: false, message: error instanceof Error ? error.message : String(error) }\n }\n}\n\n/**\n * How many candidates the picker renders before it stops and reports the rest.\n *\n * Ten was too few once one id could arrive from a dozen providers; fifty shows\n * a vendor's catalog without pouring a 1354-row index into the DOM.\n */\nconst DEFAULT_PREFILL_LIMIT = 50\n\n/** How one prefill lookup is narrowed. */\nexport interface PrefillQuery {\n /** Which source to search; the picker always names exactly one. */\n readonly source: PrefillSource\n /** Restrict to one provider; blank means every provider in the source. */\n readonly provider?: string\n /** Model-id substring, case-insensitive; blank means every model. */\n readonly text?: string\n /** Maximum candidates to return; the caller reports the remainder. */\n readonly limit?: number\n}\n\n/** The candidates a lookup produced, plus how many matched in total. */\nexport interface PrefillHits {\n /** The candidates to render, capped at the query's limit. */\n readonly hits: readonly PrefillEntry[]\n /** Every match, so a capped list can say what it is hiding. */\n readonly total: number\n}\n\n/**\n * The providers a source offers, alphabetically.\n *\n * This is what turns \"which `glm-5.3-flash` did you mean?\" into a choice the\n * user can actually make: the same id ships under several providers, and each\n * provider's copy can carry different capacities and compat switches.\n * @param index - the fetched index, or undefined while the page still loads.\n * @param source - the source to enumerate.\n * @returns the provider names; empty when the source has none.\n */\nexport function providersOf(index: PrefillIndex | undefined, source: PrefillSource): readonly string[] {\n if (index === undefined) return []\n const entries = source === 'pi-ai' ? index.piAi : index.modelsDev\n const providers = new Set<string>()\n for (const entry of entries) {\n if (entry.provider !== undefined && entry.provider.length > 0) providers.add(entry.provider)\n }\n return [...providers].sort((a, b) => a.localeCompare(b))\n}\n\n/**\n * Candidates matching one source, one provider and one id substring.\n *\n * Either filter may be blank, and a blank one *widens* rather than matching\n * nothing: a provider with no id typed lists that provider's whole catalog,\n * which is how a user browses a vendor whose model names they have not\n * memorized. Both blank lists the source's first page.\n * @param index - the fetched index, or undefined while the page still loads.\n * @param query - the source, provider, id substring and cap.\n * @returns the capped candidates and the total match count.\n */\nexport function searchPrefill(\n index: PrefillIndex | undefined,\n query: PrefillQuery,\n): PrefillHits {\n if (index === undefined) return { hits: [], total: 0 }\n const entries = query.source === 'pi-ai' ? index.piAi : index.modelsDev\n const provider = query.provider?.trim() ?? ''\n const needle = query.text?.trim().toLowerCase() ?? ''\n const limit = query.limit ?? DEFAULT_PREFILL_LIMIT\n\n const hits: PrefillEntry[] = []\n let total = 0\n for (const entry of entries) {\n if (provider.length > 0 && entry.provider !== provider) continue\n if (needle.length > 0 && !entry.id.toLowerCase().includes(needle)) continue\n total += 1\n if (hits.length < limit) hits.push(entry)\n }\n return { hits, total }\n}\n","/**\n * Shared extension metadata: enums pinned to the adapter anchor version, and\n * the extra locale keys the extension adds on top of the official Models page\n * dictionaries. The anchor constant itself is injected at build time.\n */\n\n/** Adapter anchor (build-time define from package.json dsh.adapter). */\ndeclare const __DSH_ADAPTER_VERSION__: string\nexport const ADAPTER_VERSION: string =\n typeof __DSH_ADAPTER_VERSION__ === 'string' ? __DSH_ADAPTER_VERSION__ : '0.0.0-unknown'\n\n/** Thinking levels offered by llm-pi-ai (THINKING_LEVEL_GATE @ 0.1.2-alpha.4). Only `off` may carry an empty wire value. */\nexport const THINKING_LEVELS = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'] as const\nexport type ThinkingLevel = (typeof THINKING_LEVELS)[number]\n\n/** Input modalities accepted by llm-pi-ai (MODALITY_GATE @ 0.1.2-alpha.4). */\nexport const MODALITIES = ['text', 'image'] as const\nexport type Modality = (typeof MODALITIES)[number]\n\n/** Reasoning wire formats understood by llm-pi-ai (SUPPORTED_THINKING_FORMATS @ 0.1.2-alpha.4). */\nexport const THINKING_FORMATS = [\n 'openai',\n 'deepseek',\n 'openrouter',\n 'together',\n 'baseten',\n 'zai',\n 'qwen',\n 'chat-template',\n 'qwen-chat-template',\n 'string-thinking',\n 'ant-ling',\n] as const\nexport type ThinkingFormat = (typeof THINKING_FORMATS)[number]\n\n/**\n * The compatibility switches llm-pi-ai *offers*, by wire protocol (the `offer`\n * set of its COMPAT_GATES @ 0.1.5-rc.2). Only these may reach a model row: the\n * adapter refuses a switch no protocol offers rather than ignoring it, so\n * copying pi-ai's catalog `compat` across verbatim would fail resolution on\n * the withheld fields it also records (routing preferences, session affinity,\n * deferred tools, grammar tools). Re-check against the host's COMPAT_GATES on\n * every adapter-anchor bump — the same drift gate the host keeps for itself.\n */\nexport const COMPAT_FIELDS: Readonly<Record<string, readonly string[]>> = {\n 'openai-completions': [\n 'supportsStore',\n 'supportsDeveloperRole',\n 'supportsReasoningEffort',\n 'supportsUsageInStreaming',\n 'supportsFinishReason',\n 'maxTokensField',\n 'requiresToolResultName',\n 'requiresAssistantAfterToolResult',\n 'requiresThinkingAsText',\n 'requiresReasoningContentOnAssistantMessages',\n 'thinkingFormat',\n 'chatTemplateKwargs',\n 'chatTemplateArgs',\n 'supportsThinkingTokenBudget',\n 'thinkingTokenBudgetField',\n 'vllmPriority',\n 'supportsStrictMode',\n 'cacheControlFormat',\n 'supportsLongCacheRetention',\n ],\n 'openai-responses': [\n 'supportsDeveloperRole',\n 'supportsMaxOutputTokens',\n 'supportsStrictMode',\n 'supportsLongCacheRetention',\n ],\n 'azure-openai-responses': [\n 'supportsDeveloperRole',\n 'supportsMaxOutputTokens',\n 'supportsStrictMode',\n 'supportsLongCacheRetention',\n ],\n 'openai-codex-responses': [\n 'supportsDeveloperRole',\n 'supportsMaxOutputTokens',\n 'supportsStrictMode',\n 'supportsLongCacheRetention',\n ],\n 'anthropic-messages': [\n 'supportsEagerToolInputStreaming',\n 'supportsLongCacheRetention',\n 'supportsCacheControlOnTools',\n 'supportsTemperature',\n 'forceAdaptiveThinking',\n 'allowEmptySignature',\n 'supportsStrictTools',\n ],\n 'bedrock-converse-stream': ['supportsStrictMode'],\n}\n\n/**\n * Switches the base panel already renders a dedicated control for; the\n * \"other compatibility switches\" block lists everything else.\n */\nexport const COMPAT_BASE_FIELDS: readonly string[] = [\n 'supportsDeveloperRole',\n 'supportsReasoningEffort',\n 'thinkingFormat',\n]\n\n/**\n * The offered compat field names for one wire protocol.\n * @param api - the model's protocol, when known.\n * @returns the field names; empty for an unknown or absent protocol.\n */\nexport function offeredCompatFields(api: string | undefined): readonly string[] {\n if (api === undefined) return []\n const fields = COMPAT_FIELDS[api]\n return fields === undefined ? [] : fields\n}\n\n/**\n * Whether one protocol takes one compat switch.\n *\n * The adapter *refuses* a switch its protocol does not declare rather than\n * ignoring it, so this is the difference between a control that can be offered\n * and one that would fail the save. An unknown protocol takes nothing: its\n * field set cannot be read, and the adapter resolves it to the same refusal.\n * @param api - the model's wire protocol, when known.\n * @param field - the compat field name.\n * @returns true when the protocol offers the field.\n */\nexport function protocolOffers(api: string | undefined, field: string): boolean {\n return offeredCompatFields(api).includes(field)\n}\n\n/** Extra copy for the extension, keyed like the official dictionaries (en is authoritative). */\nexport const en = {\n // --- official Models-page keys the forked components still render -------\n nav: 'Models+',\n title: 'Models+',\n intro: 'Enter your API keys to use models from the following providers.',\n edit: 'Edit',\n editProvider: 'Edit {provider}',\n remove: 'Delete',\n removeProvider: 'Delete {provider}',\n deleteTitle: 'Delete {provider}?',\n deleteDescription: 'Deleting {provider} removes its configuration. Any credential it uses is managed elsewhere and will be kept.',\n deleteDescriptionWithCredential: 'Deleting {provider} removes its configuration and stored API key.',\n deleteConfirm: 'Delete {provider}',\n deleting: 'Deleting {provider}…',\n add: 'Add provider',\n provider: 'Provider',\n close: 'Close',\n cancel: 'Cancel',\n apply: 'Apply',\n applying: 'Applying…',\n savedProvider: 'Saved {provider}.',\n credentialConfigured: 'API key configured',\n credentialMissing: 'API key missing',\n readOnly: 'The settings document is read-only in this deployment.',\n loadFailed: 'Loading the provider directory failed',\n conflict: 'Someone else changed these settings while this card was open. Close it and reopen to edit the current values.',\n retry: 'Retry',\n keyInput: 'API key',\n keyPlaceholder: 'Enter your API key',\n keyPlaceholderNative: 'Enter an API key, or leave blank to use environment authentication',\n keyStored: 'Configured — enter a new value to replace',\n keyEnvLocked: 'Provided by the launch environment (read-only)',\n customized: 'Customized settings',\n baseUrl: 'Base URL',\n baseUrlDefault: 'Provider default',\n models: 'Models',\n modelsInherited: 'Using the adapter defaults',\n modelsCustomized: 'Customized model catalog',\n resetModels: 'Restore defaults',\n model: 'Model',\n modelId: 'Model ID',\n modelName: 'Display name',\n modelNamePlaceholder: 'Uses the model ID when empty',\n contextWindow: 'Context window',\n contextWindowPlaceholder: 'Uses the provider default',\n maxTokens: 'Max output tokens',\n maxTokensPlaceholder: 'Uses the provider default',\n modelAdvanced: 'Capacities',\n addModel: 'Add model',\n removeModel: 'Delete model',\n modelsEmpty: 'No models will be shown in the selector. Unlisted IDs can still be sent directly.',\n keyBlank: 'Enter the API key, or leave the field empty to keep the stored one.',\n keyBlankNew: 'Enter the API key, or leave the field empty if this provider authenticates another way.',\n keyIllegalCharacters: 'This API key is not in a valid format. Please check it.',\n modelIdRequired: 'Model ID is required.',\n modelIdDuplicate: 'Model ID must be unique.',\n modelNameInvalid: 'Display name cannot be empty.',\n modelContextInvalid: 'Context window must be a positive count, like 131072, 256K, or 1M.',\n modelMaxTokensInvalid: 'Max output tokens must be a positive count, like 8192, 64K, or 1M.',\n advancedHint: 'Other fields live in settings.yaml; edit that section directly.',\n modelCapacityInvalid: 'A capacity must be a number, optionally suffixed K or M.',\n modelDuplicate: 'Each model ID may appear once.',\n modelContextWindow: 'Context window',\n modelMaxTokens: 'Max output tokens',\n fetchModels: 'Fetch available models',\n fetching: 'Asking the provider…',\n fetchNeedsBaseUrl: 'Enter the base URL first, then fetch.',\n fetchEmpty: 'The provider listed no models. Add them by hand.',\n fetchTitle: 'Choose models to add',\n fetchDescription: 'These are the models this provider has available. Choose the ones to add.',\n fetchSelectAll: 'Select all',\n fetchDeselectAll: 'Deselect all',\n fetchAdopt: 'Add selected',\n customAdd: 'Add a custom provider',\n customTitle: 'Custom provider',\n customTag: 'Custom',\n customRoute: 'Provider ID',\n customRouteHint: 'Lowercase identifier, starting with a letter, that uniquely names this provider in requests and as its credential name.',\n customRouteInvalid: 'Start with a lowercase letter; then lowercase letters, digits, and dashes.',\n customRouteTaken: 'A provider already uses this ID.',\n customDisplayName: 'Display name',\n customApi: 'API protocol',\n customApiUnset: 'Not selected',\n customNeedsBaseUrl: 'A custom provider needs a base URL.',\n customBaseUrlInvalid: 'Enter a valid HTTP or HTTPS URL.',\n customNeedsModels: 'A custom provider needs at least one model.',\n customBaseUrlPlaceholder: 'https://gateway.example/v1',\n settingsPathUnresolvable: 'unresolvable settings path',\n create: 'Create provider',\n creating: 'Creating…',\n onboardingTitle: 'Add an API key to get started',\n onboardingDescription: 'Configure the official DeepSeek provider to start building.',\n onboardingLater: 'Configure later',\n onboardingSave: 'Save and continue',\n onboardingSaving: 'Saving…',\n keyRequired: 'Enter an API key to continue.',\n\n // --- extension-only keys ------------------------------------------------\n extDeclare: 'Declared',\n extSection: 'Model extensions',\n extSectionHint: 'Extra per-model fields that live in settings.yaml.',\n supportsReasoningEffort: 'Endpoint accepts reasoning effort',\n supportsDeveloperRole: 'System prompt may use the developer role',\n supportsDeveloperRoleHint: 'Reasoning-model system prompts go out as \"developer\"; uncheck to keep \"system\" for gateways that reject it.',\n reasoningEfforts: 'Reasoning efforts',\n reasoningEffortLevel: 'Level',\n reasoningEffortWire: 'Wire value',\n reasoningEffortOffHint: '\"off\" takes no wire value.',\n reasoningEffortEmptyWire: 'A checked level other than \"off\" needs a wire value.',\n reasoningEffortsNeedNonOff: 'Declare at least one level beyond \"off\".',\n inputModalities: 'Input modalities',\n inputNeedOne: 'Keep at least one modality checked.',\n thinkingFormat: 'Thinking format',\n} as const\n\nexport type ExtensionKey = keyof typeof en\n\n/** Chinese strings — same key set as {@link en}. */\nexport const zh: { [K in ExtensionKey]: string } = {\n // --- official Models-page keys (upstream zh values) ----------------------\n nav: '模型+',\n title: '模型+',\n intro: '填入各提供方的 API 密钥即可使用其模型。',\n edit: '编辑',\n editProvider: '编辑 {provider}',\n remove: '删除',\n removeProvider: '删除 {provider}',\n deleteTitle: '删除 {provider}?',\n deleteDescription: '删除 {provider} 会移除其配置;其使用的凭证(如有)由其他位置管理,将会保留。',\n deleteDescriptionWithCredential: '删除 {provider} 会移除其配置和存储的 API 密钥。',\n deleteConfirm: '删除 {provider}',\n deleting: '正在删除 {provider}…',\n add: '添加提供方',\n provider: '提供方',\n close: '关闭',\n cancel: '取消',\n apply: '保存',\n applying: '保存中…',\n savedProvider: '已保存 {provider}。',\n credentialConfigured: 'API 密钥已配置',\n credentialMissing: 'API 密钥缺失',\n readOnly: '当前部署的设置文档为只读。',\n loadFailed: '加载提供方目录失败',\n conflict: '这张卡片打开期间,这些设置已被其他地方改动。请关闭后重新打开,在当前值上编辑。',\n retry: '重试',\n keyInput: 'API 密钥',\n keyPlaceholder: '输入 API 密钥',\n keyPlaceholderNative: '输入 API 密钥,或留空使用环境认证',\n keyStored: '已配置——输入新值可替换',\n keyEnvLocked: '由启动环境提供(只读)',\n customized: '自定义设置',\n baseUrl: 'API 地址',\n baseUrlDefault: '提供方默认',\n models: '模型目录',\n modelsInherited: '正在使用适配器默认模型',\n modelsCustomized: '已自定义模型目录',\n resetModels: '恢复默认模型',\n model: '模型',\n modelId: '模型 ID',\n modelName: '显示名称',\n modelNamePlaceholder: '留空时使用模型 ID',\n contextWindow: '上下文窗口',\n contextWindowPlaceholder: '使用提供方默认值',\n maxTokens: '最大输出 token 数',\n maxTokensPlaceholder: '使用提供方默认值',\n modelAdvanced: '容量',\n addModel: '添加模型',\n removeModel: '删除模型',\n modelsEmpty: '模型选择器中将不显示任何模型;目录外 ID 仍可直接发送。',\n keyBlank: '请输入 API 密钥;留空则保持已存储的密钥。',\n keyBlankNew: '请输入 API 密钥;若该提供方以其他方式鉴权,可以留空。',\n keyIllegalCharacters: '此 API 密钥格式无效,请检查。',\n modelIdRequired: '模型 ID 必填。',\n modelIdDuplicate: '模型 ID 不能重复。',\n modelNameInvalid: '显示名称不能为空。',\n modelContextInvalid: '上下文窗口须为正数,如 131072、256K、1M。',\n modelMaxTokensInvalid: '最大输出 token 数须为正数,如 8192、64K、1M。',\n advancedHint: '其余字段存于 settings.yaml;请直接编辑该节。',\n modelCapacityInvalid: '容量须为数字,可带 K 或 M 后缀。',\n modelDuplicate: '每个模型 ID 只能出现一次。',\n modelContextWindow: '上下文窗口',\n modelMaxTokens: '最大输出 token 数',\n fetchModels: '获取可用模型',\n fetching: '正在询问提供方…',\n fetchNeedsBaseUrl: '请先填写 API 地址再获取。',\n fetchEmpty: '该提供方未列出任何模型,请手动添加。',\n fetchTitle: '选择要添加的模型',\n fetchDescription: '这些是该提供方可用的模型,选择要添加的项。',\n fetchSelectAll: '全选',\n fetchDeselectAll: '取消全选',\n fetchAdopt: '添加所选',\n customAdd: '添加自定义提供方',\n customTitle: '自定义提供方',\n customTag: '自定义',\n customRoute: '提供方 ID',\n customRouteHint: '小写字母开头的唯一标识符,用于请求与凭证命名。',\n customRouteInvalid: '以小写字母开头;其后为小写字母、数字和短横线。',\n customRouteTaken: '已有提供方使用此 ID。',\n customDisplayName: '显示名称',\n customApi: 'API 协议',\n customApiUnset: '未选择',\n customNeedsBaseUrl: '自定义提供方需要 API 地址。',\n customBaseUrlInvalid: '请输入有效的 HTTP 或 HTTPS 地址。',\n customNeedsModels: '自定义提供方至少需要一个模型。',\n customBaseUrlPlaceholder: 'https://gateway.example/v1',\n settingsPathUnresolvable: '无法解析设置路径',\n create: '创建提供方',\n creating: '创建中…',\n onboardingTitle: '先添加一个 API 密钥即可开始',\n onboardingDescription: '配置官方 DeepSeek 提供方以开始构建。',\n onboardingLater: '稍后配置',\n onboardingSave: '保存并继续',\n onboardingSaving: '保存中…',\n keyRequired: '请输入 API 密钥以继续。',\n\n // --- extension-only keys ------------------------------------------------\n extDeclare: '声明',\n extSection: '模型扩展',\n extSectionHint: 'settings.yaml 中按模型生效的扩展字段。',\n supportsReasoningEffort: '端点接受推理挡位参数(reasoning_effort)',\n supportsDeveloperRole: '允许以 developer 角色发送系统提示',\n supportsDeveloperRoleHint: '推理模型的系统提示将以 developer 角色发出;网关拒绝该角色时取消勾选,改用 system。',\n reasoningEfforts: '推理挡位',\n reasoningEffortLevel: '挡位',\n reasoningEffortWire: '线上取值',\n reasoningEffortOffHint: '“off”不需要线上取值。',\n reasoningEffortEmptyWire: '除 off 外勾选的挡位必须填写线上取值。',\n reasoningEffortsNeedNonOff: '至少声明一个 off 以外的挡位。',\n inputModalities: '输入模态',\n inputNeedOne: '至少保留一个模态。',\n thinkingFormat: '思考格式',\n}\n","/**\n * Pure helpers copied from the host's ui-settings-models UI component files\n * (they live inside components there, so they cannot be inlined as standalone\n * modules like operations/store/schema-operations are).\n *\n * ⚠️ Fork-copy risk: these must be re-checked against the pinned host sources\n * (packages/client/ui-settings-models/src/client/{ProviderEditor,DeepSeekModelsEditor}.tsx\n * @ 0.1.6-alpha.2) on every adapter-anchor bump.\n */\n\n/** One model entry kept structurally open so hidden or future fields survive an edit. */\nexport type ModelDraft = Record<string, unknown>\n\n// ---------------------------------------------------------------------------\n// pathOps — copied from ProviderEditor.tsx @ 0.1.5-rc.1\n// ---------------------------------------------------------------------------\n\nimport type { JsonValue } from '@deepseek-ai/dsh-util-values'\nimport type { SettingsPathOpView } from '@deepseek-ai/dsh-api-remotes/client'\nimport { offeredCompatFields, protocolOffers } from '../extension-meta.ts'\n\n/**\n * The minimal path ops carrying `after` over `before`, both as the card sees\n * them. Only keys the card observed are named; fields absent from both sides\n * produce no op, which is why edits are path-addressed rather than a rebuilt\n * section.\n * @param base - path of the edited subtree inside the user section.\n * @param before - the subtree as loaded, or undefined when it is new.\n * @param after - the subtree as edited.\n * @returns ordered set/unset ops; empty when nothing changed.\n */\nexport function pathOps(\n base: readonly string[],\n before: unknown,\n after: Record<string, unknown>,\n): SettingsPathOpView[] {\n const previous = typeof before === 'object' && before !== null && !Array.isArray(before)\n ? before as Record<string, unknown>\n : {}\n const ops: SettingsPathOpView[] = []\n for (const [key, value] of Object.entries(after)) {\n if (JSON.stringify(previous[key]) === JSON.stringify(value)) continue\n ops.push({ op: 'set', path: [...base, key], value: value as JsonValue })\n }\n for (const key of Object.keys(previous)) {\n if (!(key in after)) ops.push({ op: 'unset', path: [...base, key] })\n }\n return ops\n}\n\n// ---------------------------------------------------------------------------\n// capacity parsing/formatting — copied from DeepSeekModelsEditor.tsx @ 0.1.5-rc.1\n// ---------------------------------------------------------------------------\n\n/** Accepted capacity spellings: a decimal count with an optional K/M suffix. */\nconst CAPACITY_PATTERN = /^(\\d+(?:\\.\\d+)?)([km])?$/i\n\n/** Decimal suffix scales — `1M` is 1000K, matching how model capacities are quoted. */\nconst CAPACITY_SCALE = { k: 1_000, m: 1_000_000 } as const\n\n/**\n * Read a typed capacity, so a user can write `256K` or `1M` instead of counting\n * zeroes. The stored value stays a plain token count.\n * @param text - raw field text.\n * @returns the count; `undefined` when blank (inherit), `NaN` when unreadable\n * (rejected by {@link validateModelRows} before any write).\n */\nexport function parseCapacity(text: string): number | undefined {\n const trimmed = text.trim()\n if (trimmed.length === 0) return undefined\n const match = CAPACITY_PATTERN.exec(trimmed)\n if (match === null) return Number.NaN\n const suffix = match[2]?.toLowerCase()\n const scale = suffix === 'k' || suffix === 'm' ? CAPACITY_SCALE[suffix] : 1\n const scaled = Number(match[1]) * scale\n // A decimal multiple is exact in intent but not in binary floating point\n // (2.3 * 1e6 lands a few ULPs high), so an integral intent snaps back.\n const rounded = Math.round(scaled)\n return Math.abs(scaled - rounded) < 1e-6 ? rounded : scaled\n}\n\n/**\n * Spell a stored count back in the shortest form that survives a round trip\n * through {@link parseCapacity}; a count that is not a whole number of\n * thousands stays written out.\n * @param value - stored capacity.\n * @returns the field text.\n */\nexport function formatCapacity(value: number): string {\n if (!Number.isInteger(value) || value <= 0) return String(value)\n if (value % CAPACITY_SCALE.m === 0) return `${String(value / CAPACITY_SCALE.m)}M`\n if (value % CAPACITY_SCALE.k === 0) return `${String(value / CAPACITY_SCALE.k)}K`\n return String(value)\n}\n\n// ---------------------------------------------------------------------------\n// model-row validation — copied from DeepSeekModelsEditor.tsx @ 0.1.5-rc.1\n// ---------------------------------------------------------------------------\n\n/** A localized validation failure for one user-owned model array. */\nexport interface ModelRowsValidationFailure {\n /** Zero-based model position. */\n index: number\n /** Message key owned by the Models+ dictionary. */\n key: 'modelIdRequired' | 'modelIdDuplicate' | 'modelNameInvalid' | 'modelContextInvalid'\n | 'modelMaxTokensInvalid' | 'modelCompatNotOffered'\n /** For `modelCompatNotOffered`: the switch the protocol refuses. */\n field?: string\n /** For `modelCompatNotOffered`: the protocol the row resolves to. */\n api?: string\n /** For `modelCompatNotOffered`: the switches that protocol does take. */\n offered?: readonly string[]\n}\n\n/** Convert a schema-validated catalog value into records without dropping hidden fields. */\nexport function modelDrafts(value: unknown): ModelDraft[] {\n if (!Array.isArray(value)) return []\n return value.map(entry =>\n typeof entry === 'object' && entry !== null && !Array.isArray(entry)\n ? entry as ModelDraft\n : {})\n}\n\n// ---------------------------------------------------------------------------\n// row key-order normalization (plugin addition, v1.0.0: stable YAML key order)\n// ---------------------------------------------------------------------------\n\n/** Canonical key order for one models[] row (plugin-known fields first). */\nconst ROW_KEY_ORDER = ['id', 'name', 'contextWindow', 'maxTokens', 'input', 'reasoningEfforts', 'compat']\n\n/** Canonical key order for the row's compat sub-object. */\nconst COMPAT_KEY_ORDER = ['supportsDeveloperRole', 'supportsReasoningEffort', 'thinkingFormat']\n\n/**\n * Re-key one model row into the canonical order (plugin-known fields in\n * order, unknown/future fields kept at the tail so nothing is dropped).\n * YAML emits keys in object insertion order, and interactive edits append\n * keys at the tail — without this, rows saved after quick-load or gated-key\n * removals come out with scrambled key orders (purely cosmetic, but noisy\n * in settings.yaml diffs).\n * @param row - the drafted row.\n * @returns the re-keyed row (shallow copy).\n */\nexport function normalizeModelRow(row: ModelDraft): ModelDraft {\n const next: ModelDraft = {}\n for (const key of ROW_KEY_ORDER) {\n if (key in row) next[key] = row[key]\n }\n for (const key of Object.keys(row)) {\n if (!ROW_KEY_ORDER.includes(key)) next[key] = row[key]\n }\n const compat = next['compat']\n if (typeof compat === 'object' && compat !== null && !Array.isArray(compat)) {\n const source = compat as Record<string, unknown>\n const normalized: Record<string, unknown> = {}\n for (const key of COMPAT_KEY_ORDER) {\n if (key in source) normalized[key] = source[key]\n }\n for (const key of Object.keys(source)) {\n if (!COMPAT_KEY_ORDER.includes(key)) normalized[key] = source[key]\n }\n next['compat'] = normalized\n }\n return next\n}\n\n/**\n * The message for a refused compat switch, shared by both provider cards so the\n * same failure reads the same way wherever it is hit.\n * @param failure - a `modelCompatNotOffered` failure from {@link validateModelRows}.\n * @returns the localised sentence.\n */\nexport function compatFailureMessage(failure: ModelRowsValidationFailure): string {\n const offered = failure.offered ?? []\n const available = offered.length === 0\n ? ',该协议不接受任何可配置开关'\n : `,该协议可用:${offered.join('、')}`\n return `模型 ${String(failure.index + 1)}:compat 开关 ${String(failure.field)} 不适用于当前协议`\n + `(${String(failure.api)})${available}。请在展开的「其他兼容开关」中清空该项以移除,`\n + '或回到供应商页把协议改成端点真正使用的协议。'\n}\n\n/**\n * Validate adapter constraints that the serialized schema cannot express.\n *\n * The compat half of the check exists because the adapter *refuses* a switch a\n * model's protocol does not declare rather than ignoring it — and the protocol\n * a row resolves to is `route.api` first, the installed catalog entry second.\n * A row can therefore hold switches that were legal when it was written (a\n * protocol change on the route, or a prefill taken from another protocol's\n * catalog entry) and only fail at save time, in English, from the host. This\n * turns that into a positioned, named, localised refusal.\n *\n * An unknown protocol is skipped on purpose: the route's protocol could not be\n * resolved, so the row's real one is unknowable here, and a guess would refuse\n * a configuration the host accepts. The host's own diagnostic still covers it.\n * @param value - user-owned `models` value, or undefined while inherited.\n * @param api - the protocol every row resolves to, when the route settles one.\n * @returns the first invalid row, or undefined when the adapter will accept it.\n */\nexport function validateModelRows(value: unknown, api?: string): ModelRowsValidationFailure | undefined {\n if (value === undefined) return undefined\n const models = modelDrafts(value)\n const seen = new Set<string>()\n for (const [index, model] of models.entries()) {\n // Compared trimmed: surrounding whitespace is a paste artifact the adapter\n // would never match, and an untrimmed compare lets `model ` slip past the\n // duplicate check against its own twin.\n const id = model['id']\n const trimmed = typeof id === 'string' ? id.trim() : undefined\n if (trimmed === undefined || trimmed.length === 0) return { index, key: 'modelIdRequired' }\n if (seen.has(trimmed)) return { index, key: 'modelIdDuplicate' }\n seen.add(trimmed)\n const name = model['name']\n if (name !== undefined && (typeof name !== 'string' || name.length === 0)) {\n return { index, key: 'modelNameInvalid' }\n }\n const contextWindow = model['contextWindow']\n if (contextWindow !== undefined\n && (typeof contextWindow !== 'number' || !Number.isInteger(contextWindow) || contextWindow <= 0)) {\n return { index, key: 'modelContextInvalid' }\n }\n const maxTokens = model['maxTokens']\n if (maxTokens !== undefined\n && (typeof maxTokens !== 'number' || !Number.isInteger(maxTokens) || maxTokens <= 0)) {\n return { index, key: 'modelMaxTokensInvalid' }\n }\n const compat = model['compat']\n if (api !== undefined && typeof compat === 'object' && compat !== null && !Array.isArray(compat)) {\n for (const field of Object.keys(compat)) {\n if (protocolOffers(api, field)) continue\n return { index, key: 'modelCompatNotOffered', field, api, offered: offeredCompatFields(api) }\n }\n }\n }\n return undefined\n}\n","/**\n * Draft defaults for a NEW model row (added by hand or adopted from a fetch),\n * per the v1.0.0 plan: reasoning effort ON with every level declared, thinking\n * format `openai`, both input modalities checked. These are draft seeds that\n * land in settings.yaml when the row is saved — they are not inherited-state\n * sentinels, except `supportsDeveloperRole`, which stays UNWRITTEN (its\n * tri-state reads an absent key as checked, so only an explicit user uncheck\n * ever writes `false`).\n *\n * The compat half of the seed is PROTOCOL-DEPENDENT, and that is load-bearing:\n * `supportsReasoningEffort` and `thinkingFormat` belong to `openai-completions`\n * alone, and the adapter refuses a switch its protocol does not declare rather\n * than ignoring it. Seeding them onto an `anthropic-messages` route — which is\n * what a fixed vocabulary here did — made every hand-added model on such a\n * route fail the save over a switch the user never wrote. So the seed asks\n * {@link protocolOffers} first and writes nothing its protocol would refuse.\n * `reasoningEfforts` is unaffected: the levels travel through each protocol's\n * own thinking parameter, so every protocol takes them.\n */\n\nimport { protocolOffers } from '../extension-meta.ts'\nimport type { ModelDraft } from './compat.ts'\n\n/** The tri-state `compat.supportsDeveloperRole` seed: absent (reads checked). */\nconst DEVELOPER_ROLE_SEED: Record<string, unknown> = {}\n\n/**\n * Draft seed for one new model row.\n *\n * An UNKNOWN protocol (no route-level `api`, and the installed catalog does not\n * describe the route) seeds no compat at all: nothing can say which switches\n * its endpoint would take, and a guessed `supportsReasoningEffort` on an\n * Anthropic-shaped route is refused rather than dropped. The levels stay seeded\n * — they are protocol-independent — so the row still opens with its effort\n * table populated.\n * @param api - the wire protocol this row will resolve to, when known.\n * @returns the draft row.\n */\nexport function newModelDraft(api?: string): ModelDraft {\n const compat: Record<string, unknown> = { ...DEVELOPER_ROLE_SEED }\n if (protocolOffers(api, 'supportsReasoningEffort')) compat['supportsReasoningEffort'] = true\n if (protocolOffers(api, 'thinkingFormat')) compat['thinkingFormat'] = 'openai'\n return {\n id: '',\n input: ['text', 'image'],\n reasoningEfforts: {\n off: null,\n minimal: 'minimal',\n low: 'low',\n medium: 'medium',\n high: 'high',\n xhigh: 'xhigh',\n max: 'max',\n },\n ...Object.keys(compat).length === 0 ? {} : { compat },\n }\n}\n","/**\n * Mapping pi-ai catalog values onto a Models+ row.\n *\n * The two sides describe the same thing, but two conventions differ in a way\n * that makes a straight copy wrong:\n *\n * 1. **`null` means the opposite in each.** pi-ai's `thinkingLevelMap[level]`\n * is *unsupported* when null; our `reasoningEfforts[level]` is *supported,\n * send nothing* when null (the adapter then drops the key entirely, and\n * pi-ai reads an absent `off` key as \"supported but send no parameter\").\n * Copying one across would invert the meaning for 338 of the catalog's\n * models, so values are mapped rather than copied: a pi-ai `null` becomes\n * \"omit our key\", and an absent pi-ai key becomes an explicit entry.\n * 2. **An absent base level has a protocol-specific default.** pi-ai resolves\n * an absent `off`/`minimal`/`low`/`medium`/`high` by falling back to the\n * level name — except on the Anthropic protocols, where `minimal` collapses\n * onto `low`, and on Mistral, where every level resolves to `high`. Writing\n * the level name there would send a spelling those providers never see.\n *\n * `xhigh` and `max` are the one pair pi-ai treats as unsupported when absent,\n * so they are only written when the catalog declares them.\n *\n * @module dsh-model-extension/prefill\n */\n\nimport { offeredCompatFields } from '../extension-meta.ts'\n\n/** The seven levels, in pi-ai's escalation order. */\nconst LEVELS: readonly string[] = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max']\n\n/**\n * The wire spelling pi-ai falls back to for one absent base level, per\n * protocol. This mirrors the fallbacks inside pi-ai's own dispatch branches.\n * @param api - the model's wire protocol.\n * @param level - the level whose key was absent.\n * @returns the spelling pi-ai would send for that level.\n */\nexport function defaultWireSpelling(api: string | undefined, level: string): string {\n // anthropic-messages: mapThinkingLevelToEffort collapses minimal onto low and\n // passes the rest through. bedrock shares the mapper.\n if (api === 'anthropic-messages' || api === 'bedrock-converse-stream') {\n return level === 'minimal' ? 'low' : level\n }\n // mistral-conversations: mapReasoningEffort ends in `?? \"high\"`.\n if (api === 'mistral-conversations') return 'high'\n return level\n}\n\n/**\n * Convert a catalog `thinkingLevelMap` into our `reasoningEfforts` dict.\n *\n * A model that does not reason gets `false`. An outcome that offers nothing\n * beyond `off` also becomes `false`, because the adapter rejects a dict whose\n * only level is `off` — and the two describe the same request anyway.\n * @param levelMap - the catalog's map, when it carries one.\n * @param api - the model's wire protocol, which picks the fallback spellings.\n * @param reasoning - whether the model reasons at all.\n * @returns the dict to write into the row, or `false` for a non-reasoning model.\n */\nexport function reasoningEffortsFrom(\n levelMap: Readonly<Record<string, string | null>> | undefined,\n api: string | undefined,\n reasoning: boolean,\n): Record<string, string | null> | false {\n if (!reasoning) return false\n\n const map = levelMap ?? {}\n const efforts: Record<string, string | null> = {}\n for (const level of LEVELS) {\n if (!(level in map)) {\n if (level === 'off') {\n // Absent `off` is pi-ai's \"supported, send nothing\"; our spelling of\n // that is an explicit null, which the adapter drops before handing the\n // map over.\n efforts[level] = null\n continue\n }\n if (level === 'xhigh' || level === 'max') continue\n efforts[level] = defaultWireSpelling(api, level)\n continue\n }\n const wire = map[level]\n // pi-ai's null means unsupported, so the key is simply left out.\n if (wire === null) continue\n efforts[level] = wire\n }\n\n const beyondOff = Object.keys(efforts).some(level => level !== 'off')\n return beyondOff ? efforts : false\n}\n\n/**\n * Project a catalog `compat` block onto the switches the host offers for one\n * protocol.\n *\n * The filter is load-bearing twice over. It drops pi-ai's withheld switches\n * (routing preferences, session affinity, deferred tools, grammar tools), which\n * the adapter *refuses* rather than ignores — a verbatim copy would make the\n * route fail to resolve. And it filters by the protocol the row will be JUDGED\n * by, which is not always the catalog entry's own: a hand-declared route states\n * its `api`, that value overrides the catalog for every model on the route, and\n * a block taken from another protocol's entry (`supportsStore` on a gateway\n * that speaks `anthropic-messages`) is refused at save time.\n * @param compat - the catalog's compat record, when it carries one.\n * @param api - the protocol the row resolves to, as the adapter resolves it.\n * @returns the writable subset; empty when nothing survives.\n */\nexport function compatFrom(\n compat: Readonly<Record<string, unknown>> | undefined,\n api: string | undefined,\n): Record<string, unknown> {\n const offered = offeredCompatFields(api)\n if (offered.length === 0 || compat === undefined) return {}\n const next: Record<string, unknown> = {}\n for (const field of offered) {\n if (field in compat) next[field] = compat[field]\n }\n return next\n}\n","/* models-plus styles — the official ModelsSection.module.css classes (as\n * transcribed and verified in docs/models-settings-demo.html) plus the\n * extension-block styles, all on --dsw-alias tokens. */\n\n.section { display: flex; flex-direction: column; gap: 12px; max-width: 720px; color: var(--dsw-alias-label-primary); }\n.titleRow { display: flex; align-items: center; gap: 10px; }\n.title { margin: 0; font-size: 16px; line-height: 24px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n.intro { margin: 0; font-size: 14px; line-height: 22px; color: var(--dsw-alias-label-tertiary); }\n.savedNotice { margin: 0; font-size: 12px; line-height: 18px; color: var(--dsw-alias-state-success-primary); }\n.error { margin: 0; font-size: 12px; line-height: 18px; color: var(--dsw-alias-state-error-primary); }\n\n.rows { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }\n.rowCard { border: 0.5px solid var(--dsw-alias-border-l4); border-radius: 16px; padding: 12px 14px; display: flex; flex-direction: column; gap: 12px; }\n.rowHead { display: flex; align-items: center; gap: 10px; }\n.rowIdentity { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }\n.rowName { font-size: 14px; line-height: 22px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n.rowTag { flex: none; padding: 1px 6px; border: 0.5px solid var(--dsw-alias-border-l3); border-radius: 4px; font-size: 11px; line-height: 16px; color: var(--dsw-alias-label-secondary); }\n.credentialDot { box-sizing: border-box; display: inline-block; flex: none; width: 8px; height: 8px; border-radius: 50%; }\n.credentialDotConfigured { background: var(--dsw-alias-state-success-primary); }\n.credentialDotMissing { background: var(--dsw-alias-state-error-primary); }\n.rowActions { display: inline-flex; align-items: center; gap: 4px; margin-left: auto; }\n\n.primaryButton, .secondaryButton, .addButton { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; gap: 4px; height: 36px; padding: 0 14px; border: none; border-radius: 18px; font: inherit; font-size: 14px; line-height: 22px; cursor: pointer; }\n.primaryButton { background: var(--dsw-alias-button-primary-fill); color: var(--dsw-alias-label-primary-foreground); }\n.primaryButton:hover:not(:disabled) { background: var(--dsw-alias-button-primary-hover); }\n.secondaryButton, .addButton { border: 0.5px solid var(--dsw-alias-border-l3); background: transparent; color: var(--dsw-alias-label-primary); }\n.secondaryButton:hover:not(:disabled), .addButton:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }\n.secondaryButton:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover-solid); }\n.dangerButton { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; height: 36px; padding: 0 14px; border: none; border-radius: 18px; background: transparent; color: var(--dsw-alias-state-error-primary); font: inherit; font-size: 14px; line-height: 22px; cursor: pointer; }\n.dangerButton:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover-danger); }\n.rowActions .secondaryButton, .rowActions .dangerButton { height: 28px; padding: 0 10px; border-radius: 14px; font-size: 12px; line-height: 18px; }\n.primaryButton:disabled, .secondaryButton:disabled, .dangerButton:disabled, .addButton:disabled, .linkButton:disabled, .addModelButton:disabled { opacity: 0.4; cursor: default; }\n.primaryButton:focus-visible, .secondaryButton:focus-visible, .dangerButton:focus-visible, .addButton:focus-visible, .linkButton:focus-visible, .addModelButton:focus-visible, .iconButton:focus-visible, .customizedSummary:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--dsw-alias-border-l3); }\n\n.editor { border-radius: 12px; background: var(--dsw-alias-bg-module-platform); padding: 14px 16px; display: flex; flex-direction: column; gap: 14px; }\n.field { display: flex; flex-direction: column; gap: 6px; }\n.fieldLabel { display: inline-flex; align-items: center; gap: 10px; font-size: 12px; line-height: 18px; font-weight: 500; color: var(--dsw-alias-label-secondary); }\n.linkButton { box-sizing: border-box; display: inline-flex; align-items: center; height: 28px; padding: 0 10px; border: none; border-radius: 14px; background: transparent; color: var(--dsw-alias-label-tertiary); font: inherit; font-size: 12px; line-height: 18px; cursor: pointer; }\n.linkButton:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); color: var(--dsw-alias-label-secondary); }\n.advancedHint { margin: 0; font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n.editorActions { display: flex; justify-content: flex-end; gap: 8px; }\n\n.addBlock { display: flex; flex-direction: column; gap: 12px; }\n.addActions { display: flex; flex-wrap: wrap; gap: 10px; }\n.addButton { flex: 1 1 0; min-width: 180px; gap: 6px; height: 44px; border: 1px dashed var(--dsw-alias-border-l3); border-radius: 16px; }\n.addCard { border-radius: 12px; background: var(--dsw-alias-bg-module-platform); padding: 14px 16px; display: flex; flex-direction: column; gap: 14px; list-style: none; }\n.addCard .editor, .setupCard .editor { background: none; padding: 0; }\n\n\n.tabs { display: flex; flex-direction: column; gap: 12px; }\n.tabBar { display: flex; gap: 4px; border-bottom: 0.5px solid var(--dsw-alias-border-l2); }\n.tabButton { appearance: none; border: none; background: transparent; padding: 6px 12px 8px; font: inherit; font-size: 13px; line-height: 20px; color: var(--dsw-alias-label-tertiary); cursor: pointer; position: relative; }\n.tabButton:hover { color: var(--dsw-alias-label-primary); }\n.tabButton:disabled { opacity: 0.4; cursor: default; }\n.tabButtonActive { color: var(--dsw-alias-label-primary); font-weight: 500; }\n.tabButtonActive::after { content: ''; position: absolute; left: 10px; right: 10px; bottom: -1px; height: 2px; border-radius: 2px; background: var(--dsw-alias-brand-primary); }\n.tabPanel { display: flex; flex-direction: column; gap: 12px; }\n.modelCatalog { display: flex; flex-direction: column; gap: 10px; }\n.modelCatalogHeading { display: flex; flex-direction: column; gap: 2px; }\n.modelCatalogTitle { font-size: 12px; line-height: 18px; font-weight: 500; color: var(--dsw-alias-label-secondary); }\n.modelCatalogMeta, .modelEmpty { margin: 0; color: var(--dsw-alias-label-tertiary); font-size: 12px; line-height: 18px; }\n.modelList { display: flex; flex-direction: column; gap: 8px; }\n.modelListHead { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }\n.modelEntry { border: 0.5px solid var(--dsw-alias-border-l4); border-radius: 10px; padding: 6px; }\n.modelRow { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) auto auto; align-items: center; gap: 6px; }\n.iconButton { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-tertiary); cursor: pointer; }\n.iconButton:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); color: var(--dsw-alias-label-primary); }\n.iconButton:disabled { cursor: default; opacity: 0.4; }\n.iconButtonDanger:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover-danger); color: var(--dsw-alias-state-error-primary); }\n.modelAdvanced { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 8px; padding: 8px 4px 2px; }\n.modelField { display: flex; flex-direction: column; gap: 4px; }\n.modelFieldLabel { color: var(--dsw-alias-label-tertiary); font-size: 12px; line-height: 18px; }\n.modelEmpty { padding: 12px; border: 1px dashed var(--dsw-alias-border-l3); border-radius: 8px; text-align: center; }\n.addModelButton { box-sizing: border-box; align-self: flex-start; display: inline-flex; align-items: center; gap: 4px; height: 28px; padding: 0 10px; border: 0.5px solid var(--dsw-alias-border-l3); border-radius: 14px; background: transparent; color: var(--dsw-alias-label-primary); font: inherit; font-size: 12px; line-height: 18px; cursor: pointer; }\n.addModelButton:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }\n\n.input { box-sizing: border-box; width: 100%; height: 32px; padding: 0 10px; border: 0.5px solid var(--dsw-alias-border-l4); border-radius: 8px; font: inherit; font-size: 14px; line-height: 22px; background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); }\nselect.input { max-width: 240px; cursor: pointer; }\n.input:focus { outline: none; border-color: var(--dsw-alias-brand-primary); }\n.input::placeholder { color: var(--dsw-alias-label-dimmed); }\n.input:disabled { opacity: 0.6; cursor: default; }\n.selectInput { appearance: none; padding-right: 32px; background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\"); background-repeat: no-repeat; background-position: right 12px center; background-size: 12px 12px; }\n\n.deleteDialog { width: min(480px, 100%); }\n.deleteConfirm:not(:disabled) { border-color: var(--dsw-alias-state-error-primary); color: var(--dsw-alias-state-error-primary); }\n.deleteConfirm:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover-danger); }\n\n.fetchDialog { max-width: 520px; }\n.candidateToolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }\n.candidateSearch { min-width: 0; flex: 1 1 240px; }\n.candidateList { display: flex; flex-direction: column; gap: 2px; max-height: 320px; margin: 0; overflow-y: auto; padding: 0; list-style: none; }\n.candidate { border-radius: 6px; }\n.candidateLabel { display: flex; align-items: center; gap: 8px; padding: 6px 8px; cursor: pointer; }\n.candidateId { flex: 1 1 auto; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; overflow-wrap: anywhere; }\n.candidateEmpty { margin: 24px 0; color: var(--dsw-alias-label-secondary); font-size: 13px; line-height: 20px; text-align: center; }\n\n/* ---- extension block (plugin-owned; official token palette) ---- */\n[hidden] { display: none !important; }\n.extBlock { border: 0.5px solid var(--dsw-alias-border-l3); border-radius: 10px; padding: 10px; margin: 8px 4px 2px; background: var(--dsw-alias-bg-layer-1); display: flex; flex-direction: column; gap: 10px; }\n.extGroup { border-top: 0.5px solid var(--dsw-alias-border-l2); padding-top: 12px; }\n.extGroupFirst { border-top: none; padding-top: 0; }\n.extCheck { display: flex; align-items: flex-start; gap: 8px; cursor: pointer; }\n.extCheckLabel { font-size: 14px; line-height: 22px; color: var(--dsw-alias-label-primary); }\n.extHint { font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n.extGated { display: flex; flex-direction: column; gap: 12px; padding-left: 2px; }\n.extField { display: flex; flex-direction: column; gap: 6px; }\n.extLabel { font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n.extTable { border: 0.5px solid var(--dsw-alias-border-l4); border-radius: 8px; overflow: hidden; }\n.extTHead { display: grid; grid-template-columns: 64px minmax(0,1fr) minmax(0,1.2fr); font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); background: var(--dsw-alias-bg-module-platform); }\n.extTHead > div { padding: 6px 10px; }\n.extTHead > div + div { border-left: 0.5px solid var(--dsw-alias-border-l2); }\n.extTRow { display: grid; grid-template-columns: 64px minmax(0,1fr) minmax(0,1.2fr); align-items: center; border-top: 0.5px solid var(--dsw-alias-border-l2); }\n.extTRow > div { padding: 6px 10px; font-size: 14px; }\n.extTRow > div + div { border-left: 0.5px solid var(--dsw-alias-border-l2); }\n.extTRow input[type=\"text\"] { box-sizing: border-box; width: 100%; height: 32px; padding: 0 10px; border: 0.5px solid var(--dsw-alias-border-l4); border-radius: 8px; font: inherit; font-size: 14px; background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); }\n.extTRow input[type=\"text\"]:disabled { opacity: 0.6; cursor: default; }\n.extCheckbox { accent-color: var(--dsw-alias-brand-primary); width: 15px; height: 15px; flex: none; }\n.switchRow { display: flex; align-items: center; gap: 8px; font-size: 14px; line-height: 22px; cursor: pointer; }\n.extTag { flex: none; padding: 1px 6px; border: 0.5px solid rgba(65,118,230,0.35); border-radius: 4px; background: var(--dsw-static-deepseek-100); color: var(--dsw-static-deepseek-600); font-size: 11px; line-height: 16px; font-weight: 500; }\n\n/* ---- modal (matches the ui-primitives look closely enough for these two dialogs) ---- */\n.modalMask { position: fixed; inset: 0; background: var(--dsw-alias-bg-mask-1); display: flex; align-items: center; justify-content: center; z-index: 100; padding: 24px; }\n.modal { background: var(--dsw-specific-menu); border-radius: 16px; padding: 20px; width: 100%; box-shadow: 0 12px 40px rgba(0,0,0,0.18); }\n.modalTitle { font-size: 16px; line-height: 24px; font-weight: 500; margin-bottom: 8px; color: var(--dsw-alias-label-primary); }\n.modalDesc { font-size: 14px; line-height: 22px; color: var(--dsw-alias-label-secondary); margin-bottom: 16px; }\n.modalFoot { display: flex; justify-content: flex-end; gap: 8px; }\n\n/* ---- quick-load dropdown (filtered and capped, plugin-rendered for both the\n provider and the model list — never a native datalist, whose popup position\n and styling the page cannot control) ---- */\n.quickWrap { position: relative; display: flex; flex-direction: column; gap: 6px; }\n.quickList { position: absolute; top: 100%; left: 0; right: 0; z-index: 20; margin-top: 2px; padding: 4px; border: 0.5px solid var(--dsw-alias-border-l3); border-radius: 8px; background: var(--dsw-specific-menu); box-shadow: 0 8px 24px rgba(0,0,0,0.12); max-height: 264px; overflow-y: auto; }\n.quickItem { display: flex; flex-direction: column; gap: 1px; width: 100%; padding: 6px 8px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-primary); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; text-align: left; cursor: pointer; }\n.quickItemId { overflow-wrap: anywhere; }\n.quickItemApi { font-size: 11px; line-height: 14px; color: var(--dsw-alias-label-tertiary); letter-spacing: 0.2px; }\n.quickItem:hover { background: var(--dsw-alias-interactive-bg-hover); }\n.quickEmpty { padding: 6px 8px; font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n\n@media (prefers-reduced-motion: reduce) {\n .customizedSummary::before { transition: none; }\n}\n","/**\n * Quick-load: source → provider → model id, three narrowing steps.\n *\n * The single search box could not answer the question it raised. One model id\n * ships under a dozen providers (`glm-5.3-flash` exists in zai, opencode,\n * opencode-go, baseten, together, huggingface and two gateways), and each\n * provider's copy can carry different capacities and compat switches — so a\n * flat list of ten same-looking ids left the user to pick blind, or to decode\n * a suffix the plugin had appended for want of a better idea.\n *\n * Splitting the axis fixes it at the source: the user states *which catalog*\n * and *whose copy* first, and the id search then runs inside that slice.\n *\n * Both drop-downs are plugin-rendered rather than native. A `<datalist>` was\n * tried for the provider field and abandoned: the browser positions its popup\n * itself (it opened across unrelated fields) and none of it is themeable, so\n * it could not look like the list beside it. One `quickList` now serves both,\n * which also keeps only one popup on screen at a time.\n */\n\nimport { useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport { getPrefillIndex, providersOf, searchPrefill } from './models-index.ts'\nimport type { PrefillEntry, PrefillIndex, PrefillSource } from './models-index.ts'\nimport styles from './models-plus.module.css'\n\n/** Props of {@link QuickLoad}. */\nexport interface QuickLoadProps {\n /** Apply one prefill candidate to the current model draft. */\n onPick: (entry: PrefillEntry) => void\n /** Disable while a write is in flight. */\n disabled: boolean\n}\n\n/** The two sources, in the order the picker offers them; pi-ai leads by default. */\nconst SOURCES: readonly { readonly id: PrefillSource; readonly label: string }[] = [\n { id: 'pi-ai', label: 'llm-pi-ai' },\n { id: 'models.dev', label: 'models.dev' },\n]\n\n/** Which drop-down is showing; at most one at a time. */\ntype OpenPanel = 'provider' | 'model' | null\n\n/**\n * One line describing what the selected source currently offers, shown while\n * nothing is typed. The pi-ai version and snapshot date matter here: a DSH home\n * can hold more than one pi-ai copy, and knowing which one answered is the\n * difference between a diagnosis and a mystery.\n * @param index - the fetched index.\n * @param source - the selected source.\n * @returns the summary line.\n */\nfunction sourceSummary(index: PrefillIndex, source: PrefillSource): string {\n if (source === 'pi-ai') {\n if (index.piAi.length === 0) {\n return index.piAiFailure === undefined\n ? 'pi-ai 目录不可用'\n : `pi-ai 目录不可用:${index.piAiFailure}`\n }\n const version = index.piAiVersion === undefined ? '' : ` v${index.piAiVersion}`\n const when = index.piAiGeneratedAt === undefined ? '' : ` · ${index.piAiGeneratedAt.slice(0, 10)}`\n return `pi-ai 目录${version},${String(index.piAi.length)} 个模型${when};选择提供方或输入 model id`\n }\n if (index.modelsDev.length === 0) {\n return 'models.dev 元数据未下载——点击页首「下载/更新元数据」'\n }\n return `models.dev,${String(index.modelsDev.length)} 条;选择提供方或输入 model id`\n}\n\n/**\n * Render the three-step quick-load picker and its candidate list.\n * @param props - the pick handler and disabled flag.\n * @returns the quick-load block.\n */\nexport function QuickLoad(props: QuickLoadProps): ReactNode {\n const [source, setSource] = useState<PrefillSource>('pi-ai')\n const [provider, setProvider] = useState('')\n const [text, setText] = useState('')\n const [panel, setPanel] = useState<OpenPanel>(null)\n const [index, setIndex] = useState<PrefillIndex | undefined>(undefined)\n const textField = useRef<HTMLInputElement>(null)\n\n // Re-asked on every focus: getPrefillIndex() memoizes per page load, so a\n // warm index costs nothing, while a download that just invalidated the cache\n // is picked up without a reload. (Keeping the first result forever would\n // leave the picker stuck on \"未下载\" right after the user clicked download.)\n const ensureIndex = (): void => {\n void getPrefillIndex().then((loaded) => { setIndex(loaded) })\n }\n\n const providers = providersOf(index, source)\n // The provider field doubles as the filter for its own candidate list, so a\n // half-typed name must not narrow the model list yet — only a name that\n // actually is a provider does. Typing the full name counts, which is what\n // makes the field usable both ways.\n const chosenProvider = providers.includes(provider) ? provider : ''\n const { hits, total } = searchPrefill(index, { source, provider: chosenProvider, text })\n\n const pick = (entry: PrefillEntry): void => {\n setPanel(null)\n // Keep the chosen id on screen rather than clearing the field: an emptied\n // box right after a pick leaves no trace of what was just loaded, and the\n // id is also the natural starting point for narrowing to a sibling model.\n setText(entry.id)\n props.onPick(entry)\n }\n\n const switchSource = (next: PrefillSource): void => {\n setSource(next)\n // The provider list belongs to the source, so a stale pick would filter\n // every candidate away and read as \"the source is empty\".\n setProvider('')\n setText('')\n setPanel(null)\n }\n\n /**\n * Commit one provider choice and move straight on to the id field, so the\n * flow is pick → type rather than pick → click → type.\n * @param name - the provider to select; blank means \"every provider\".\n */\n const chooseProvider = (name: string): void => {\n setProvider(name)\n setText('')\n textField.current?.focus()\n }\n\n const providerBody = (): ReactNode => {\n if (index === undefined) return <span className={styles['quickEmpty']}>正在载入预填数据…</span>\n const needle = provider.trim().toLowerCase()\n const matches = needle.length === 0\n ? providers\n : providers.filter(name => name.toLowerCase().includes(needle))\n if (providers.length === 0) {\n return <span className={styles['quickEmpty']}>该数据源没有提供方信息</span>\n }\n return (\n <>\n <button\n type=\"button\"\n className={styles['quickItem']}\n onMouseDown={(event) => { event.preventDefault(); chooseProvider('') }}\n >\n 全部(不限提供方)\n </button>\n {matches.map(name => (\n <button\n type=\"button\"\n key={name}\n className={styles['quickItem']}\n onMouseDown={(event) => { event.preventDefault(); chooseProvider(name) }}\n >\n {name}\n </button>\n ))}\n {matches.length === 0\n ? <span className={styles['quickEmpty']}>没有匹配的提供方</span>\n : null}\n </>\n )\n }\n\n const modelBody = (): ReactNode => {\n if (index === undefined) return <span className={styles['quickEmpty']}>正在载入预填数据…</span>\n\n const nothingNarrowed = chosenProvider.length === 0 && text.trim().length === 0\n if (nothingNarrowed) {\n return (\n <>\n <span className={styles['quickEmpty']}>{sourceSummary(index, source)}</span>\n {source === 'pi-ai' && index.piAiWarnings.length > 0\n ? <span className={styles['error']}>{index.piAiWarnings.join(';')}</span>\n : null}\n </>\n )\n }\n\n if (hits.length === 0) {\n return <span className={styles['quickEmpty']}>没有匹配的模型</span>\n }\n\n return (\n <>\n {hits.map(entry => (\n <button\n type=\"button\"\n key={entry.key}\n className={styles['quickItem']}\n onMouseDown={(event) => {\n // mousedown beats the input's blur handler.\n event.preventDefault()\n pick(entry)\n }}\n >\n <span className={styles['quickItemId']}>{entry.id}</span>\n {/* The protocol of each candidate, because the SAME id ships under\n several of them (`claude-fable-5` exists in anthropic,\n github-copilot and openrouter — one speaks anthropic-messages,\n two speak openai-completions). Which one a row gets decides its\n whole compat surface, so it belongs beside the id and not in a\n later surprise. models.dev candidates carry no protocol, which\n is why the line is conditional rather than a placeholder. */}\n {entry.api === undefined\n ? null\n : <span className={styles['quickItemApi']}>{entry.api}</span>}\n </button>\n ))}\n {total > hits.length\n ? (\n <span className={styles['quickEmpty']}>\n 另有 {total - hits.length} 项匹配——继续输入或选定提供方以缩小范围\n </span>\n )\n : null}\n </>\n )\n }\n\n return (\n <div className={styles['quickWrap']}>\n <span className={styles['extLabel']}>快速装入</span>\n <div style={{ display: 'flex', gap: 6, alignItems: 'center' }}>\n <select\n className={`${styles['input']} ${styles['selectInput']}`}\n style={{ flex: '0 0 108px', minWidth: 0 }}\n value={source}\n disabled={props.disabled}\n aria-label=\"数据源\"\n onChange={(event) => { switchSource(event.target.value as PrefillSource) }}\n >\n {SOURCES.map(option => <option key={option.id} value={option.id}>{option.label}</option>)}\n </select>\n\n <input\n className={styles['input']}\n style={{ flex: '0 0 132px', minWidth: 0 }}\n type=\"text\"\n value={provider}\n placeholder=\"提供方:全部\"\n aria-label=\"提供方\"\n autoComplete=\"off\"\n disabled={props.disabled}\n onFocus={() => { ensureIndex(); setPanel('provider') }}\n onBlur={() => { setPanel(null) }}\n onChange={(event) => { setProvider(event.target.value); setPanel('provider') }}\n />\n\n <input\n className={styles['input']}\n style={{ flex: '1 1 auto', minWidth: 0 }}\n type=\"text\"\n ref={textField}\n value={text}\n placeholder=\"model id(如 glm)…\"\n aria-label=\"model id\"\n autoComplete=\"off\"\n disabled={props.disabled}\n onFocus={() => { ensureIndex(); setPanel('model') }}\n onBlur={() => { setPanel(null) }}\n onChange={(event) => { setText(event.target.value); setPanel('model') }}\n />\n </div>\n\n {panel === 'provider' ? <div className={styles['quickList']}>{providerBody()}</div> : null}\n {panel === 'model' ? <div className={styles['quickList']}>{modelBody()}</div> : null}\n </div>\n )\n}\n","/**\n * One model entry's expanded panel: quick-load, capacities (the official\n * modelAdvanced fields, merged into this block per the v1.0.0 design), input\n * modalities, the developer-role tri-state, the reasoning-effort gate and its\n * gated area (thinking format, then the seven-level effort table).\n *\n * Every edit patches the row's draft object through `onChange` — persistence\n * rides the card's existing path-ops save with no extra wire calls. Clearing\n * the effort gate drops `reasoningEfforts` AND `compat.thinkingFormat` in ONE\n * commit so partial updates never overwrite each other (no orphan settings).\n *\n * Which compat switches this panel may write at all is decided by `api` (see\n * {@link ModelEntryPanelProps.api}): the adapter refuses a switch the model's\n * protocol does not declare instead of ignoring it, so a control offered on the\n * wrong protocol is a save that cannot succeed. An UNKNOWN protocol hides\n * nothing — nothing can be judged — and the host's own diagnostic still covers\n * that case.\n */\n\nimport { useState } from 'react'\nimport type { ReactNode } from 'react'\nimport { COMPAT_BASE_FIELDS, THINKING_FORMATS, THINKING_LEVELS, offeredCompatFields } from '../extension-meta.ts'\nimport type { ModelDraft } from './compat.ts'\nimport { formatCapacity, parseCapacity } from './compat.ts'\nimport { compatFrom, reasoningEffortsFrom } from './prefill.ts'\nimport { QuickLoad } from './QuickLoad.tsx'\nimport type { PrefillEntry } from './models-index.ts'\nimport styles from './models-plus.module.css'\n\n/**\n * Whether a draft field is absent or whitespace-only.\n * @param value - the field's current value.\n * @returns true when the field carries nothing worth keeping.\n */\nfunction isBlank(value: unknown): boolean {\n if (value === undefined || value === null) return true\n return typeof value === 'string' && value.trim().length === 0\n}\n\n/** The row's compat sub-object as a plain record (absent → empty). */\nfunction compatOf(model: ModelDraft): Record<string, unknown> {\n const value = model['compat']\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? value as Record<string, unknown>\n : {}\n}\n\n/** The row's reasoningEfforts dict (absent/invalid → undefined = not declared). */\nfunction effortsOf(model: ModelDraft): Record<string, string | null> | undefined {\n const value = model['reasoningEfforts']\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined\n return value as Record<string, string | null>\n}\n\n/** The row's input modality list (absent → empty, matching the host reader). */\nfunction inputsOf(model: ModelDraft): readonly string[] {\n const value = model['input']\n return Array.isArray(value) ? value.filter((m): m is string => typeof m === 'string') : []\n}\n\n/** Props of {@link ModelEntryPanel}. */\nexport interface ModelEntryPanelProps {\n /** The row's current draft (read). */\n model: ModelDraft\n /** Replace the row with this next draft; `undefined`-valued keys clear them. */\n onChange: (next: ModelDraft) => void\n /** Disable every control (read-only deployment or a pending write). */\n disabled: boolean\n /**\n * The wire protocol this row resolves to, when the route settles one — the\n * route's own `api` for a hand-declared route, the installed catalog's shared\n * api for a catalog route, `undefined` when neither settles it.\n *\n * This is the protocol the ADAPTER will judge the row by (`route.api` wins\n * over the catalog entry), which is why it — and not the catalog entry's own\n * api — decides which compat switches may be written here.\n */\n api?: string\n}\n\n/**\n * Render one model entry's expanded panel.\n * @param props - the row draft, its writer, and the disabled flag.\n * @returns the expanded panel.\n */\nexport function ModelEntryPanel(props: ModelEntryPanelProps): ReactNode {\n const { model, onChange, disabled, api } = props\n\n /**\n * Whether this panel may OFFER a control for one compat switch.\n *\n * Not the same question as `protocolOffers`, and deliberately so: an\n * unresolvable protocol answers `true` throughout, because with no protocol to\n * read nothing can be judged — hiding a control on a guess would remove a\n * switch the route may well take, while the host still names anything it\n * refuses. A resolved protocol that offers nothing (one pi-ai gives no compat\n * type) answers `false` throughout, which is exactly what the adapter says.\n */\n const mayOffer = (field: string): boolean => api === undefined || offeredCompatFields(api).includes(field)\n\n // Capacities are text-edited, so keystrokes live in this buffer rather than\n // being re-derived from the parsed count (which would rewrite `1000` to\n // `1K` mid-word). Unreadable text stays on screen for the save-time check.\n const [capacityText, setCapacityText] = useState<ReadonlyMap<string, string>>(() => new Map())\n\n /** Patch one key onto the row; `undefined` clears it. */\n const setKey = (key: string, value: unknown): void => {\n const next = { ...model }\n if (value === undefined) Reflect.deleteProperty(next, key)\n else next[key] = value\n onChange(next)\n }\n\n /** Patch one key inside `compat`; an emptied compat leaves no trace. */\n const setCompatKey = (key: string, value: unknown): void => {\n const compat = { ...compatOf(model) }\n if (value === undefined) Reflect.deleteProperty(compat, key)\n else compat[key] = value\n setKey('compat', Object.keys(compat).length === 0 ? undefined : compat)\n }\n\n const setEfforts = (efforts: Record<string, string | null> | undefined): void => {\n setKey('reasoningEfforts', efforts)\n }\n\n const setInput = (modalities: readonly string[]): void => {\n setKey('input', modalities.length === 0 ? undefined : [...modalities])\n }\n\n // --- quick load ----------------------------------------------------------\n /**\n * Apply one prefill candidate.\n *\n * Every value is *restated* from the picked source rather than merged into\n * whatever was already there: capacities, modalities, reasoning levels and\n * compat are replaced wholesale. A prefill answers \"what does this catalog\n * say about the model\", so an absent field clears — leaving another source's\n * value behind would describe a model neither catalog claims, and switching\n * sources then re-picking is meant to be a clean rewrite.\n *\n * Two things do not follow that rule. `id` and `name` are filled only into a\n * blank row, because a catalog id is the request id for the vendor's *own*\n * endpoint while behind a gateway the string on the wire is often different.\n * And pi-ai's level map is *mapped* rather than copied, because `null` means\n * the opposite on each side.\n * @param entry - the picked candidate.\n */\n const applyMetadata = (entry: PrefillEntry): void => {\n const next = { ...model }\n // The protocol the row will be judged by, which is the route's when the\n // route states one. A catalog entry taken from another protocol's provider\n // (`deepseek-v4-pro` picked while the route speaks Anthropic) carries that\n // other protocol's compat block, and filtering it with the ENTRY's api is\n // what wrote `supportsStore` onto an `anthropic-messages` route.\n const judgedBy = props.api ?? entry.api\n if (entry.context === undefined) Reflect.deleteProperty(next, 'contextWindow')\n else next['contextWindow'] = entry.context\n if (entry.output === undefined) Reflect.deleteProperty(next, 'maxTokens')\n else next['maxTokens'] = entry.output\n // A prefill states what *this* source knows, so an absent value clears\n // rather than merges — leaving the other catalog's modality list behind\n // would describe a model neither source claims.\n const modality = entry.input.filter(m => m === 'text' || m === 'image')\n if (modality.length > 0) next['input'] = modality\n else Reflect.deleteProperty(next, 'input')\n\n if (entry.source === 'pi-ai') {\n // The id and name are filled into an *empty* row and never written over a\n // typed one. A catalog id is the request id for the vendor's own\n // endpoint; behind a gateway the string that actually reaches the wire is\n // often different (`v2.5-pro` vs `mimo-v2.5-pro`), so overwriting a typed\n // id would silently repoint the row at a model the endpoint does not\n // serve — the failure would surface later, as a 404 from the provider.\n if (isBlank(next['id'])) next['id'] = entry.id\n if (isBlank(next['name']) && entry.name !== undefined) next['name'] = entry.name\n\n next['reasoningEfforts'] = reasoningEffortsFrom(entry.thinkingLevelMap, judgedBy, entry.reasoning)\n\n // Catalog values only. `supportsReasoningEffort` is deliberately NOT\n // inferred from `reasoning`: the two answer different questions (does\n // the endpoint accept the field, vs. does the model think), and an\n // absent key is pi-ai's way of saying \"auto-detect from the endpoint\".\n // Writing our guess there would replace a detection with a claim we\n // cannot check, and a wrong `true` makes the adapter send a parameter\n // the endpoint may refuse.\n const compat = compatFrom(entry.compat, judgedBy)\n if (Object.keys(compat).length === 0) Reflect.deleteProperty(next, 'compat')\n else next['compat'] = compat\n } else {\n // models.dev: its ids are directory paths (`zhipuai/glm-5.3-flash`) and\n // the file carries no reasoning or compat surface at all — so the whole\n // block is REPLACED by the one fact this source can support.\n //\n // Merging here (as an earlier revision did) leaves a previous pi-ai\n // prefill's switches in place, and the row goes on claiming a thinking\n // format — or a reasoning-content requirement — that the source you just\n // switched to says nothing about. Switching sources is asking for the\n // other catalog's answer, not for a blend of the two.\n Reflect.deleteProperty(next, 'reasoningEfforts')\n // This one fact is itself protocol-bound: `supportsReasoningEffort`\n // exists on `openai-completions` alone, so claiming it for a models.dev\n // candidate on any other route is a save the adapter refuses.\n if (entry.reasoning && mayOffer('supportsReasoningEffort')) next['compat'] = { supportsReasoningEffort: true }\n else Reflect.deleteProperty(next, 'compat')\n }\n\n onChange(next)\n setCapacityText(new Map())\n }\n\n // --- capacities ----------------------------------------------------------\n const capacityField = (field: 'contextWindow' | 'maxTokens', label: string): ReactNode => {\n const stored = model[field]\n const typed = capacityText.get(field)\n const text = typed ?? (typeof stored === 'number' ? formatCapacity(stored) : '')\n return (\n <label className={styles['modelField']}>\n <span className={styles['modelFieldLabel']}>{label}</span>\n <input\n className={styles['input']}\n type=\"text\"\n inputMode=\"numeric\"\n value={text}\n placeholder=\"使用提供方默认值\"\n aria-label={label}\n disabled={disabled}\n onChange={(event) => {\n setCapacityText(current => new Map(current).set(field, event.target.value))\n setKey(field, parseCapacity(event.target.value))\n }}\n onBlur={() => {\n const raw = capacityText.get(field)\n if (raw === undefined) return\n const parsed = parseCapacity(raw)\n // Unreadable text stays on screen; the save-time check names it.\n if (parsed !== undefined && Number.isNaN(parsed)) return\n setCapacityText(current => {\n const next = new Map(current)\n next.delete(field)\n return next\n })\n }}\n />\n </label>\n )\n }\n\n // --- developer role (tri-state, NOT gated) -------------------------------\n const compat = compatOf(model)\n const developerRole = compat['supportsDeveloperRole'] !== false\n\n // --- compat switches with no dedicated control ---------------------------\n /**\n * Switches a prefill wrote that no control above stands for. Listing them\n * keeps a prefilled value from becoming invisible state: the pi-ai catalog\n * records far more of the compat surface than this panel models explicitly,\n * and that API refuses an unknown switch rather than ignoring it — so a value\n * the user cannot see is a value the user cannot fix.\n *\n * The set is the panel's base list narrowed to what this protocol takes. A\n * switch the protocol refuses keeps NO control — writing it would fail the\n * save — so it lands here instead, where it is named as refused and can be\n * cleared. That is the only way out of a row written before a protocol change\n * on the route, which no amount of hiding would repair.\n */\n const dedicated = COMPAT_BASE_FIELDS.filter(field => mayOffer(field))\n const extraCompat = Object.entries(compat)\n .filter(([key]) => !dedicated.includes(key))\n .sort(([a], [b]) => a.localeCompare(b))\n\n /**\n * Read an edited switch back as the type it already had.\n * @param previous - the value the switch carried when rendered.\n * @param raw - the field text.\n * @returns the coerced value, or the previous one when the text is unreadable.\n */\n const readCompatValue = (previous: unknown, raw: string): unknown => {\n if (typeof previous === 'boolean') return raw === 'true'\n if (typeof previous === 'number') {\n const parsed = Number(raw)\n return Number.isNaN(parsed) ? previous : parsed\n }\n if (typeof previous === 'string') return raw\n try {\n return JSON.parse(raw) as unknown\n } catch {\n return previous\n }\n }\n\n // --- effort gate ----------------------------------------------------------\n /**\n * The switch as a wire field: whether the endpoint takes `reasoning_effort`.\n *\n * Gated on the protocol as well as on the stored value: on a protocol that\n * does not take the switch a leftover `true` describes nothing this route can\n * act on, and the field's real home is the refused-switch list below.\n */\n const gateOn = mayOffer('supportsReasoningEffort') && compat['supportsReasoningEffort'] === true\n const efforts = effortsOf(model)\n /**\n * Whether the reasoning area is worth showing.\n *\n * The switch and the area answer different questions: the switch tells the\n * adapter the endpoint accepts `reasoning_effort`, while the area edits what\n * *this model* offers. A pi-ai prefill can leave the switch unset on purpose\n * — an absent key lets the adapter auto-detect from the endpoint — while\n * still carrying levels worth editing, and those levels reach the provider\n * through the protocol's own thinking parameter either way. So the area keys\n * off either signal, not the switch alone.\n */\n const reasoningAreaShown = gateOn || efforts !== undefined\n || (mayOffer('thinkingFormat') && compat['thinkingFormat'] !== undefined)\n\n const toggleGate = (checked: boolean): void => {\n if (checked) {\n setCompatKey('supportsReasoningEffort', true)\n return\n }\n // One commit clears the flag AND every gated node — no orphan settings.\n const nextCompat = { ...compat }\n Reflect.deleteProperty(nextCompat, 'supportsReasoningEffort')\n Reflect.deleteProperty(nextCompat, 'thinkingFormat')\n const next = { ...model, compat: Object.keys(nextCompat).length === 0 ? undefined : nextCompat }\n Reflect.deleteProperty(next, 'reasoningEfforts')\n onChange(next)\n }\n\n const toggleLevel = (level: string, checked: boolean): void => {\n const current = { ...(efforts ?? {}) }\n if (checked) current[level] = level === 'off' ? null : level\n else Reflect.deleteProperty(current, level)\n setEfforts(Object.keys(current).length === 0 ? undefined : current)\n }\n\n const setWireValue = (level: string, text: string): void => {\n if (efforts === undefined || !(level in efforts)) return\n const current = { ...efforts }\n current[level] = text.trim().length === 0 ? null : text.trim()\n setEfforts(current)\n }\n\n // --- validation (mirrors the host checks) --------------------------------\n const declaredLevels = efforts === undefined ? [] : THINKING_LEVELS.filter(level => level in efforts)\n const hasEmptyWire = declaredLevels.some(level =>\n level !== 'off' && String(efforts?.[level] ?? '').trim().length === 0)\n const onlyOffDeclared = efforts !== undefined\n && declaredLevels.length > 0\n && !declaredLevels.some(level => level !== 'off')\n\n // --- input modalities ------------------------------------------------------\n const inputList = inputsOf(model)\n const toggleModality = (modality: string, checked: boolean): void => {\n // Reading defaults to text-bearing rows; an explicit list wins.\n const base = inputList.length === 0 && model['input'] === undefined ? ['text'] : [...inputList]\n setInput(checked ? [...new Set([...base, modality])] : base.filter(m => m !== modality))\n }\n\n return (\n <div className={styles['extBlock']}>\n <div className={`${styles['extGroup']} ${styles['extGroupFirst']}`}>\n <QuickLoad onPick={applyMetadata} disabled={disabled} />\n </div>\n\n <div className={styles['extGroup']}>\n <div className={styles['modelField']} style={{ padding: '0 4px' }}>\n {capacityField('contextWindow', '上下文窗口')}\n {capacityField('maxTokens', '最大输出 token')}\n </div>\n </div>\n\n <div className={styles['extGroup']}>\n <span className={styles['extLabel']} style={{ marginBottom: 6 }}>输入模态</span>\n <div style={{ display: 'flex', gap: 18 }}>\n {['text', 'image'].map(modality => (\n <label key={modality} className={styles['switchRow']}>\n <input\n type=\"checkbox\"\n className={styles['extCheckbox']}\n checked={inputList.includes(modality)}\n disabled={disabled}\n onChange={(event) => { toggleModality(modality, event.target.checked) }}\n />\n {modality === 'text' ? '文本' : '图像'}\n </label>\n ))}\n </div>\n </div>\n\n {mayOffer('supportsDeveloperRole')\n ? (\n <div className={styles['extGroup']}>\n <label className={styles['extCheck']}>\n <input\n type=\"checkbox\"\n className={styles['extCheckbox']}\n style={{ marginTop: 3 }}\n checked={developerRole}\n disabled={disabled}\n onChange={(event) => {\n // Checked is the natural default, so a check REMOVES the key;\n // only an explicit uncheck writes `false`.\n setCompatKey('supportsDeveloperRole', event.target.checked ? undefined : false)\n }}\n />\n <span style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <span className={styles['extCheckLabel']}>允许以 developer 角色发送系统提示</span>\n <span className={styles['extHint']}>\n 推理模型的系统提示将以 developer 角色发出;网关拒绝该角色时取消勾选,改用 system。\n </span>\n </span>\n </label>\n </div>\n )\n : null}\n\n <div className={styles['extGroup']}>\n {mayOffer('supportsReasoningEffort')\n ? (\n <label className={styles['switchRow']}>\n <input\n type=\"checkbox\"\n className={styles['extCheckbox']}\n checked={gateOn}\n disabled={disabled}\n onChange={(event) => { toggleGate(event.target.checked) }}\n />\n 端点接受推理挡位参数(reasoning_effort)\n </label>\n )\n : (\n <p className={styles['extHint']}>\n 当前协议({String(api)})不接受 reasoning_effort 开关,故此处不提供;下面的挡位仍通过该协议自身的\n thinking 参数生效。\n </p>\n )}\n {mayOffer('supportsReasoningEffort') && !gateOn && reasoningAreaShown\n ? (\n <p className={styles['extHint']} style={{ marginTop: 6 }}>\n 此项未设置:由 llm-pi-ai 按其 baseURL 检测结果决定是否发送 reasoning_effort;\n 下面的挡位不受影响,仍通过各协议自己的 thinking 参数生效。\n </p>\n )\n : null}\n </div>\n\n {/* Gated area: HIDDEN (not dimmed) while the gate is off. */}\n <div className={styles['extGated']} hidden={!reasoningAreaShown}>\n {mayOffer('thinkingFormat')\n ? (\n <div className={styles['extField']}>\n <span className={styles['extLabel']}>思考格式</span>\n <select\n className={`${styles['input']} ${styles['selectInput']}`}\n value={typeof compat['thinkingFormat'] === 'string' ? compat['thinkingFormat'] : ''}\n disabled={disabled}\n onChange={(event) => { setCompatKey('thinkingFormat', event.target.value === '' ? undefined : event.target.value) }}\n >\n <option value=\"\">—</option>\n {THINKING_FORMATS.map(format => <option key={format} value={format}>{format}</option>)}\n </select>\n </div>\n )\n : null}\n\n <div className={styles['extField']}>\n <span className={styles['extLabel']}>推理挡位</span>\n <div className={styles['extTable']}>\n <div className={styles['extTHead']}>\n <div>声明</div><div>挡位</div><div>线上取值</div>\n </div>\n {THINKING_LEVELS.map((level) => {\n const declared = efforts !== undefined && level in efforts\n const isOff = level === 'off'\n const wire = declared ? String(efforts?.[level] ?? '') : ''\n return (\n <div key={level} className={styles['extTRow']}>\n <div style={{ display: 'flex', justifyContent: 'center' }}>\n <input\n type=\"checkbox\"\n className={styles['extCheckbox']}\n checked={declared}\n disabled={disabled}\n aria-label={`声明 ${level}`}\n onChange={(event) => { toggleLevel(level, event.target.checked) }}\n />\n </div>\n <div style={{ opacity: declared ? 1 : 0.5 }}>{level}</div>\n <div style={{ opacity: declared ? 1 : 0.4 }}>\n {declared && !isOff\n ? (\n <input\n type=\"text\"\n value={wire}\n placeholder={level}\n aria-label={`${level} 线上取值`}\n disabled={disabled}\n onChange={(event) => { setWireValue(level, event.target.value) }}\n />\n )\n : <span style={{ fontSize: 12, color: 'var(--dsw-alias-label-tertiary)' }}>—</span>}\n </div>\n </div>\n )\n })}\n </div>\n {hasEmptyWire || onlyOffDeclared\n ? (\n <p className={styles['error']} style={{ marginTop: 6 }}>\n {hasEmptyWire ? '除 off 外勾选的挡位必须填写线上取值。' : '至少声明一个 off 以外的挡位。'}\n </p>\n )\n : null}\n </div>\n </div>\n\n {extraCompat.length > 0\n ? (\n <div className={styles['extGroup']}>\n <span className={styles['extLabel']} style={{ marginBottom: 6 }}>其他兼容开关</span>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n {extraCompat.map(([key, value]) => {\n // A switch this protocol refuses is the one state the panel\n // cannot leave implicit: the save fails until the key is\n // gone, and this field is the only place it can go.\n const refused = !mayOffer(key)\n return (\n <label key={key} style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <span className={refused ? styles['error'] : styles['extHint']}>\n {refused\n ? `${key} —— 当前协议(${String(api)})不接受此开关,请清空输入框以移除`\n : key}\n </span>\n <input\n className={styles['input']}\n type=\"text\"\n defaultValue={typeof value === 'string' ? value : JSON.stringify(value) ?? ''}\n aria-label={key}\n disabled={disabled}\n onBlur={(event) => {\n const raw = event.target.value.trim()\n // An emptied field drops the switch, handing the\n // decision back to the installed catalog.\n setCompatKey(key, raw.length === 0 ? undefined : readCompatValue(value, raw))\n }}\n />\n </label>\n )\n })}\n </div>\n <p className={styles['extHint']} style={{ marginTop: 6 }}>\n 这些开关由 pi-ai 目录预填;清空输入框即移除该开关,回到目录默认。\n </p>\n </div>\n )\n : null}\n </div>\n )\n}\n\n","/**\n * One provider profile's model catalog: rows joined from the draft's `models`\n * array, the fetch action (interrogating the endpoint the form currently\n * shows), and the candidate-picker modal. Each row's expanded panel is the\n * plugin's ModelEntryPanel — capacities and extension fields in one block.\n */\n\nimport { useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { LlmDiscoveredModel } from '@deepseek-ai/dsh-api-remotes/client'\nimport { Modal } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { ModelDraft } from './compat.ts'\nimport { newModelDraft } from './presets.ts'\nimport { ModelEntryPanel } from './ModelEntryPanel.tsx'\nimport type { ModelsOperations } from '../vendor/operations.ts'\nimport styles from './models-plus.module.css'\n\n/** Endpoint facts for the fetch action, taken from the live form. */\nexport interface ProbeTarget {\n readonly settingsNs: string\n readonly provider?: string\n readonly baseURL?: string\n readonly api?: string\n readonly apiKey?: string\n}\n\n/** Props of {@link ModelCatalog}. */\nexport interface ModelCatalogProps {\n /** The drafted rows (inherited rows until the first edit materializes an override). */\n models: readonly ModelDraft[]\n /** Whether the user layer owns the whole array. */\n overridden: boolean\n /** DeepSeek-family route-level fallbacks (undefined on the pi-ai family). */\n defaultContextWindow: number | undefined\n defaultMaxTokens: number | undefined\n /** Endpoint facts for the fetch action. */\n probe: ProbeTarget\n /**\n * The wire protocol every row of this route resolves to, when the route\n * settles one (a hand-declared route's own `api`, or the api its installed\n * catalog entries agree on). Rows seed and validate their compat against it;\n * see {@link ModelEntryPanelProps.api}.\n */\n routeApi?: string\n /** Why the fetch action is unavailable, or undefined when it is. */\n probeBlocked?: string\n /**\n * Hide the fetch action entirely. The host registers model discovery only\n * for `llm-pi-ai` (the sole `registerModelDiscovery` caller across the host\n * tree), so a deepseek-family card would otherwise offer an action that can\n * only ever fail with `NO_DISCOVERY` — mirroring the official page, whose\n * DeepSeekModelsEditor has no fetch button at all.\n */\n hideFetch?: boolean\n /** The Host operations whose interrogation answers the fetch action. */\n operations: ModelsOperations\n /** Disable every control (read-only deployment or a pending write). */\n disabled: boolean\n /** Replace the drafted rows. */\n onChange: (models: ModelDraft[]) => void\n /** Remove the user-owned array and return to inheritance. */\n onReset?: () => void\n}\n\n/** A row's text field, or the empty string when unset or not a string. */\nfunction textOf(model: ModelDraft, key: string): string {\n const value = model[key]\n return typeof value === 'string' ? value : ''\n}\n\n/** Adopt one candidate, v1.0.0 defaults + the endpoint's disclosed capacities. */\nfunction adopt(candidate: LlmDiscoveredModel, routeApi: string | undefined): ModelDraft {\n const row = newModelDraft(routeApi)\n row['id'] = candidate.id\n row['name'] = candidate.name ?? candidate.id\n if (candidate.contextWindow !== undefined) row['contextWindow'] = candidate.contextWindow\n if (candidate.maxTokens !== undefined) row['maxTokens'] = candidate.maxTokens\n return row\n}\n\n/**\n * Render the model catalog with its fetch action.\n * @param props - the drafted rows, probe target, wire face, and mutators.\n * @returns the catalog editor.\n */\nexport function ModelCatalog(props: ModelCatalogProps): ReactNode {\n const { models, onChange, probe, operations, disabled } = props\n\n const [busy, setBusy] = useState(false)\n const [failure, setFailure] = useState<string | undefined>(undefined)\n const [candidates, setCandidates] = useState<readonly LlmDiscoveredModel[] | undefined>(undefined)\n const [picked, setPicked] = useState<ReadonlySet<string>>(() => new Set())\n const [query, setQuery] = useState('')\n const [expanded, setExpanded] = useState<ReadonlySet<number>>(() => new Set())\n\n const patch = (index: number, next: Record<string, string | number | undefined>): void => {\n onChange(models.map((model, at) => {\n if (at !== index) return model\n const cleared = new Set(\n Object.entries(next).filter(([, value]) => value === undefined || value === '').map(([key]) => key),\n )\n return Object.fromEntries(\n Object.entries({ ...model, ...next }).filter(([key]) => !cleared.has(key)),\n )\n }))\n }\n\n const toggleExpanded = (index: number): void => {\n setExpanded((current) => {\n const next = new Set(current)\n if (!next.delete(index)) next.add(index)\n return next\n })\n }\n\n const removeRow = (index: number): void => {\n onChange(models.filter((_model, at) => at !== index))\n // Both stores are keyed by position; shift the rows after this one down.\n setExpanded((current) => {\n const next = new Set<number>()\n for (const at of current) {\n if (at < index) next.add(at)\n else if (at > index) next.add(at - 1)\n }\n return next\n })\n }\n\n const fetchModels = async (): Promise<void> => {\n setBusy(true)\n setFailure(undefined)\n try {\n const answer = await operations.discoverModels(probe.settingsNs, {\n ...probe.provider === undefined ? {} : { provider: probe.provider },\n ...probe.baseURL === undefined || probe.baseURL.length === 0 ? {} : { baseURL: probe.baseURL },\n ...probe.api === undefined ? {} : { api: probe.api },\n ...probe.apiKey === undefined ? {} : { apiKey: probe.apiKey },\n })\n if (answer.kind === 'refused') {\n setFailure(answer.message)\n return\n }\n const found = answer.models\n if (found.length === 0) {\n setFailure('该提供方没有列出任何模型,请手动添加。')\n return\n }\n const known = new Set(models.map(model => textOf(model, 'id')))\n setQuery('')\n setCandidates(found)\n setPicked(new Set(found.filter(model => !known.has(model.id)).map(model => model.id)))\n } finally {\n setBusy(false)\n }\n }\n\n const closePicker = (): void => {\n setCandidates(undefined)\n setPicked(new Set())\n setQuery('')\n }\n\n const adoptPicked = (): void => {\n if (candidates === undefined) return\n const byId = new Map(models.map(model => [textOf(model, 'id'), model]))\n for (const candidate of candidates) {\n if (!picked.has(candidate.id)) continue\n // A row the user already tuned wins over the provider's own numbers.\n byId.set(candidate.id, byId.get(candidate.id) ?? adopt(candidate, props.routeApi))\n }\n onChange([...byId.values()])\n closePicker()\n }\n\n const toggle = (id: string): void => {\n setPicked((current) => {\n const next = new Set(current)\n if (!next.delete(id)) next.add(id)\n return next\n })\n }\n\n const activeCandidates = candidates ?? []\n const needle = query.trim().toLowerCase()\n const visible = needle.length === 0\n ? activeCandidates\n : activeCandidates.filter(candidate => candidate.id.toLowerCase().includes(needle))\n const allPicked = visible.length > 0 && visible.every(candidate => picked.has(candidate.id))\n\n // A route the adapter already describes answers without an endpoint.\n const askable = probe.provider !== undefined || (probe.baseURL !== undefined && probe.baseURL.length > 0)\n\n return (\n <section className={styles['modelCatalog']} aria-label=\"模型目录\">\n <div className={styles['modelListHead']}>\n <div className={styles['modelCatalogHeading']}>\n <span className={styles['modelCatalogTitle']}>模型目录</span>\n <span className={styles['modelCatalogMeta']}>\n {props.overridden ? '已自定义模型目录' : '正在使用适配器默认模型'}\n </span>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>\n {props.overridden && props.onReset !== undefined\n ? (\n <button\n type=\"button\"\n className={styles['linkButton']}\n disabled={disabled}\n onClick={props.onReset}\n >\n 恢复默认模型\n </button>\n )\n : null}\n {props.hideFetch === true\n ? null\n : (\n <button\n type=\"button\"\n className={styles['linkButton']}\n disabled={disabled || busy || !askable || props.probeBlocked !== undefined}\n title={props.probeBlocked !== undefined\n ? props.probeBlocked\n : askable ? undefined : '请先填写 API 地址,再获取。'}\n onClick={() => { void fetchModels() }}\n >\n {busy ? '正在询问提供方…' : '获取可用模型'}\n </button>\n )}\n </div>\n </div>\n\n {models.length === 0\n ? <p className={styles['modelEmpty']}>模型选择器中将不显示任何模型;目录外 ID 仍可直接发送。</p>\n : (\n <div className={styles['modelList']}>\n {models.map((model, index) => (\n // Keyed by position alone. A key derived from the row's content\n // — the id especially — changes on every keystroke, so React\n // unmounts and remounts the row and the field being typed into\n // loses focus after each character. Nothing in this subtree\n // needs resetting when the id changes, so position is correct.\n <div\n key={String(index)}\n className={styles['modelEntry']}\n >\n <div className={styles['modelRow']}>\n <input\n className={styles['input']}\n type=\"text\"\n value={textOf(model, 'id')}\n placeholder=\"模型 ID\"\n aria-label={`模型 ID ${String(index + 1)}`}\n disabled={disabled}\n onChange={(event) => { patch(index, { id: event.target.value }) }}\n />\n <input\n className={styles['input']}\n type=\"text\"\n value={textOf(model, 'name')}\n placeholder=\"显示名称\"\n aria-label={`显示名称 ${String(index + 1)}`}\n disabled={disabled}\n onChange={(event) => { patch(index, { name: event.target.value === '' ? undefined : event.target.value }) }}\n />\n <button\n type=\"button\"\n className={styles['iconButton']}\n aria-label={`容量 ${String(index + 1)}`}\n aria-expanded={expanded.has(index)}\n title=\"容量\"\n onClick={() => { toggleExpanded(index) }}\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\" style={{ transform: expanded.has(index) ? 'rotate(90deg)' : undefined, transition: 'transform 120ms ease' }}>\n <path d=\"M6 3.5L10.5 8L6 12.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </button>\n <button\n type=\"button\"\n className={`${styles['iconButton']} ${styles['iconButtonDanger']}`}\n aria-label={`删除模型 ${String(index + 1)}`}\n title=\"删除模型\"\n disabled={disabled}\n onClick={() => { removeRow(index) }}\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M2.5 4h11M6.5 4V2.5h3V4M4 4l.7 9a1 1 0 001 .9h4.6a1 1 0 001-.9L12 4M6.5 6.8v4.4M9.5 6.8v4.4\" stroke=\"currentColor\" strokeWidth=\"1.3\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </button>\n </div>\n {expanded.has(index)\n ? (\n <ModelEntryPanel\n model={model}\n api={props.routeApi}\n disabled={disabled}\n onChange={(next) => {\n onChange(models.map((row, at) => (at === index ? next : row)))\n }}\n />\n )\n : null}\n </div>\n ))}\n </div>\n )}\n\n <button\n type=\"button\"\n className={styles['addModelButton']}\n disabled={disabled}\n onClick={() => { onChange([...models, newModelDraft(props.routeApi)]) }}\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M8 3.5v9M3.5 8h9\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n 添加模型\n </button>\n\n {failure !== undefined ? <p className={styles['error']}>{failure}</p> : null}\n\n <Modal\n open={candidates !== undefined}\n onClose={closePicker}\n title=\"选择要添加的模型\"\n closeLabel=\"关闭\"\n description=\"以下是模型提供方的可用模型,勾选要添加的模型。\"\n className={styles['fetchDialog'] as string}\n footer={(\n <>\n <button type=\"button\" className={styles['secondaryButton']} onClick={closePicker}>取消</button>\n <button type=\"button\" className={styles['primaryButton']} onClick={adoptPicked}>添加所选</button>\n </>\n )}\n >\n <div className={styles['candidateToolbar']}>\n <input\n className={`${styles['input']} ${styles['candidateSearch']}`}\n type=\"search\"\n value={query}\n placeholder=\"搜索模型\"\n aria-label=\"搜索模型\"\n onChange={(event) => { setQuery(event.target.value) }}\n />\n <button\n type=\"button\"\n className={styles['linkButton']}\n disabled={visible.length === 0}\n onClick={() => {\n setPicked(current => {\n if (visible.every(candidate => current.has(candidate.id))) {\n return new Set([...current].filter(id => !visible.some(candidate => candidate.id === id)))\n }\n return new Set([...current, ...visible.map(candidate => candidate.id)])\n })\n }}\n >\n {allPicked ? '取消全选' : '全选'}\n </button>\n </div>\n {visible.length === 0\n ? <p className={styles['candidateEmpty']} role=\"status\">没有匹配的模型。</p>\n : (\n <ul className={styles['candidateList']}>\n {visible.map(candidate => (\n <li key={candidate.id} className={styles['candidate']}>\n <label className={styles['candidateLabel']}>\n <input\n type=\"checkbox\"\n checked={picked.has(candidate.id)}\n onChange={() => { toggle(candidate.id) }}\n />\n <span className={styles['candidateId']}>{candidate.id}</span>\n </label>\n </li>\n ))}\n </ul>\n )}\n </Modal>\n </section>\n )\n}\n\n","/**\n * One existing provider's editor card, fully plugin-owned (v1.0.0 rewrite).\n * Primary field: a single write-only API key input; the collapsed\n * 「供应商」 section carries baseURL (plus displayName/protocol for a\n * hand-declared route), the 「模型」 section the model catalog with the\n * extension panel. Save semantics mirror the host card: minimal path ops\n * against the stored section with a revision fence, then the credential\n * write — the draft comes from the user layer, so a wholesale replace can\n * never delete fields outside the card.\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { CredentialInfo, SettingsNamespaceView } from '@deepseek-ai/dsh-api-remotes/client'\nimport { deriveKeyRef, protocolChoices } from '../vendor/store.ts'\nimport type { ModelsOperations } from '../vendor/operations.ts'\nimport type { SettingsSchemaOperations } from '../vendor/schema-operations.ts'\nimport type { ModelDraft } from './compat.ts'\nimport { compatFailureMessage, modelDrafts, normalizeModelRow, pathOps, validateModelRows } from './compat.ts'\nimport { getPrefillIndex, sharedCatalogApi } from './models-index.ts'\nimport type { PrefillIndex } from './models-index.ts'\nimport { ModelCatalog } from './ModelCatalog.tsx'\nimport styles from './models-plus.module.css'\n\n/** The official DeepSeek roots, chosen by the profile's resolved protocol.\n * Host @ 0.1.6-alpha.2 kept both keys (deepSeekChatBaseUrl / deepSeekMessagesBaseUrl)\n * with Messages as the default; @ 0.1.7-alpha.1 it collapsed to a single\n * deepSeekBaseUrl (https://api.deepseek.com/anthropic) with an Anthropic-only\n * hint. We keep the protocol-aware pair so a chat-protocol route still prefills\n * the bare root — prefill only, the saved draft is whatever the user set. */\nconst DEEPSEEK_CHAT_BASE_URL = 'https://api.deepseek.com'\nconst DEEPSEEK_MESSAGES_BASE_URL = 'https://api.deepseek.com/anthropic'\n\n/** Per-adapter-family curated field sets (unknown namespaces get the hint alone). */\nexport type EditorLayout = 'deepseek' | 'pi-ai' | 'unknown'\n\n/** The editor layout the owning namespace selects. */\nexport function layoutOf(ns: string): EditorLayout {\n if (ns === 'llm-deepseek') return 'deepseek'\n if (ns === 'llm-pi-ai') return 'pi-ai'\n return 'unknown'\n}\n\n/** A user-section subtree as a plain draft object (absent → empty). */\nexport function draftAt(\n schema: SettingsSchemaOperations,\n namespace: SettingsNamespaceView,\n path: readonly string[],\n): Record<string, unknown> {\n const subtree = schema.getPath(namespace.user, path)\n if (typeof subtree !== 'object' || subtree === null || Array.isArray(subtree)) return {}\n return structuredClone(subtree) as Record<string, unknown>\n}\n\n/** The credential reference this profile resolves keys through. */\nfunction refFor(\n schema: SettingsSchemaOperations,\n namespace: SettingsNamespaceView,\n path: readonly string[],\n provider: string,\n): string {\n const profile = schema.getPath(namespace.value, path)\n const named = typeof profile === 'object' && profile !== null\n ? (profile as { apiKeyEnv?: unknown }).apiKeyEnv\n : undefined\n return typeof named === 'string' && named.length > 0 ? named : deriveKeyRef(provider)\n}\n\n/** Props of {@link ProviderEditor}. */\nexport interface ProviderEditorProps {\n /** Provider route id. */\n provider: string\n /** Display name for the card title. */\n displayName: string\n /** Whether the adapter reports this route as hand-declared. */\n declared?: boolean\n /** The owning namespace view (schema, layers, secrets). */\n namespace: SettingsNamespaceView\n /** Settings-owned synchronous schema and immutable path operations. */\n schema: SettingsSchemaOperations\n /** Path from the section root to this provider's profile. */\n settingsPath: readonly string[]\n /** The Host operations this card writes and interrogates through. */\n operations: ModelsOperations\n /** Disable writes (read-only settings provider). */\n readOnly: boolean\n /** Close the editor; `changed` reports whether an Apply committed. */\n onClose: (changed: boolean) => void\n}\n\n/**\n * Render one existing provider's editing card.\n * @param props - the addressed profile plus wire faces.\n * @returns the editor card.\n */\nexport function ProviderEditor(props: ProviderEditorProps): ReactNode {\n const { namespace, schema, settingsPath, operations } = props\n const [draft, setDraft] = useState<Record<string, unknown>>(() => draftAt(schema, namespace, settingsPath))\n const [tab, setTab] = useState<'provider' | 'models'>('provider')\n const [keyDraft, setKeyDraft] = useState('')\n const [keyState, setKeyState] = useState<CredentialInfo | undefined>(undefined)\n const [busy, setBusy] = useState(false)\n const [failure, setFailure] = useState<string | undefined>(undefined)\n const [committedOriginal, setCommittedOriginal] = useState<unknown>(\n () => schema.getPath(namespace.user, settingsPath),\n )\n const [expectedRevision, setExpectedRevision] = useState(() => namespace.revision)\n const root = useMemo(() => schema.rehydrate(namespace.schema), [namespace.schema, schema])\n const node = useMemo(() => schema.nodeAtPath(root, settingsPath), [root, schema, settingsPath])\n const fallback = schema.getPath(namespace.value, settingsPath)\n const disabled = props.readOnly || busy\n const layout = layoutOf(namespace.ns)\n const keyRef = refFor(schema, namespace, settingsPath, props.provider)\n const protocols = useMemo(\n () => layout === 'pi-ai' ? protocolChoices(namespace, schema) : [],\n [layout, namespace, schema],\n )\n /**\n * The pi-ai catalog, loaded only on the family that needs it: it answers the\n * protocol of a route that states none (a catalog route), which is what the\n * model panel judges compat switches by.\n */\n const [prefillIndex, setPrefillIndex] = useState<PrefillIndex | undefined>(undefined)\n useEffect(() => {\n if (layout !== 'pi-ai') return\n let stale = false\n void getPrefillIndex().then((loaded) => {\n if (!stale) setPrefillIndex(loaded)\n })\n return () => { stale = true }\n }, [layout])\n\n useEffect(() => {\n let stale = false\n setKeyState(undefined)\n void operations.describeCredential(keyRef).then((described) => {\n if (stale) return\n setKeyState(described)\n })\n return () => { stale = true }\n }, [operations, keyRef])\n\n const stringAt = (source: unknown, key: string): string | undefined => {\n const value = schema.getPath(source, [key])\n return typeof value === 'string' && value.trim().length > 0 ? value : undefined\n }\n const setField = (key: string, next: string | undefined): void => {\n const value = next === undefined || next.trim().length === 0 ? undefined : next\n setDraft((current) => value === undefined\n ? schema.deletePath(current, [key])\n : schema.setPath(current, [key], value))\n }\n\n /**\n * The protocol every row of this route resolves to, resolved the way the\n * adapter resolves it: a hand-declared route's own `api` first — it overrides\n * the catalog for every model on the route — then the protocol the installed\n * catalog's entries for this route agree on, then nothing.\n *\n * The model panel needs it because the adapter judges each row's compat\n * switches by THIS protocol, not by the catalog entry the row was prefilled\n * from; without it a row can carry switches the route will refuse.\n */\n const routeApi = layout === 'pi-ai'\n ? (props.declared === true ? stringAt(draft, 'api') ?? stringAt(fallback, 'api') : undefined)\n ?? sharedCatalogApi(prefillIndex, props.provider)\n : undefined\n\n const modelFailure = validateModelRows(schema.getPath(draft, ['models']), routeApi)\n const keyFailure = ((): 'keyBlank' | 'keyIllegalCharacters' | undefined => {\n if (keyDraft.length === 0) return undefined\n const value = keyDraft.trim()\n if (value.length === 0) return 'keyBlank'\n // Mirrors the host's apiKeyFailure heuristics (env line / quoted / charset).\n if (/^[A-Z][A-Z0-9_]*=[^=]/.test(value)) return 'keyIllegalCharacters'\n const first = value[0]\n if ((first === '\"' || first === '\\'' || first === '`') && value.length > 1 && value.endsWith(first)) {\n return 'keyIllegalCharacters'\n }\n return /^[\\x21-\\x7E]+$/.test(value) ? undefined : 'keyIllegalCharacters'\n })()\n const keyValue = keyDraft.trim()\n\n const probe = {\n settingsNs: namespace.ns,\n provider: props.provider,\n ...(() => {\n const baseURL = stringAt(draft, 'baseURL') ?? stringAt(fallback, 'baseURL')\n return baseURL === undefined ? {} : { baseURL }\n })(),\n ...(() => {\n const api = layout === 'pi-ai' && props.declared === true\n ? stringAt(draft, 'api') ?? stringAt(fallback, 'api')\n : undefined\n return api === undefined ? {} : { api }\n })(),\n ...keyValue.length === 0 ? {} : { apiKey: keyValue },\n }\n\n /** The write for this card, or a failure message. */\n const applyOnce = async (): Promise<string | undefined> => {\n const ns = namespace.ns\n let next = layout === 'pi-ai' && stringAt(draft, 'apiKeyEnv') === undefined\n && stringAt(fallback, 'apiKeyEnv') === undefined && keyValue.length > 0\n ? schema.setPath(draft, ['apiKeyEnv'], keyRef)\n : draft\n const rowFailure = validateModelRows(schema.getPath(next, ['models']), routeApi)\n if (rowFailure !== undefined) {\n return rowFailure.key === 'modelCompatNotOffered'\n ? compatFailureMessage(rowFailure)\n : `模型 ${String(rowFailure.index + 1)}:${{\n modelIdRequired: '模型 ID 不能为空。',\n modelIdDuplicate: '模型 ID 不能重复。',\n modelNameInvalid: '显示名称不能为空。',\n modelContextInvalid: '上下文窗口须为正数,如 131072、256K、1M。',\n modelMaxTokensInvalid: '最大输出 token 数须为正数,如 8192、64K、1M。',\n }[rowFailure.key]}`\n }\n if (node !== undefined && settingsPath.length === 0) {\n const sectionError = schema.validate(node, next)\n if (sectionError !== undefined) return sectionError\n }\n // Stable YAML key order: normalize every drafted row before diffing.\n if (schema.hasPath(next, ['models'])) {\n next = schema.setPath(\n next,\n ['models'],\n modelDrafts(schema.getPath(next, ['models'])).map(normalizeModelRow),\n )\n }\n // Official semantic: a pi-ai route whose only act is activating the route\n // (no fields the card can see, no key yet) still writes an empty profile\n // so the route exists in the directory at all.\n const materializesNativeProfile = layout === 'pi-ai'\n && fallback === undefined\n && committedOriginal === undefined\n && Object.keys(next).length === 0\n const ops = materializesNativeProfile\n ? [{ op: 'set', path: [...settingsPath], value: {} }]\n : pathOps(settingsPath, committedOriginal, next)\n if (ops.length > 0) {\n const written = await operations.writeSettings(ns, ops, expectedRevision)\n if (written.kind !== 'written') return written.kind === 'conflict'\n ? '这张卡片打开期间,这些设置已被其他地方改动。请关闭后重新打开,在当前值上编辑。'\n : written.message\n setCommittedOriginal(schema.getPath(written.view.user, settingsPath))\n setExpectedRevision(written.view.revision)\n setDraft(next)\n }\n if (keyValue.length > 0) {\n const stored = await operations.storeCredential(keyRef, keyValue)\n if (stored !== undefined) return stored\n }\n setKeyDraft('')\n return undefined\n }\n\n const apply = async (): Promise<void> => {\n setBusy(true)\n setFailure(undefined)\n try {\n const applyFailure = await applyOnce()\n if (applyFailure !== undefined) {\n setFailure(applyFailure)\n return\n }\n props.onClose(true)\n } finally {\n setBusy(false)\n }\n }\n\n if (node === undefined) {\n return <p className={styles['error']}>{props.provider}: 无法解析设置路径</p>\n }\n\n /**\n * The catalog beneath the user layer: the composition entry's pin, or the\n * schema default — reading the effective value would echo the stored\n * override back the moment reset drops it.\n */\n const inheritedModels = (): unknown => {\n const pinned = schema.getPath(namespace.base, [...settingsPath, 'models'])\n return pinned ?? schema.nodeAtPath(root, [...settingsPath, 'models'])?.meta.default\n }\n const customModels = schema.getPath(draft, ['models'])\n const modelsOverridden = schema.hasPath(draft, ['models'])\n const models = modelDrafts(modelsOverridden ? customModels : inheritedModels())\n const defaultContextWindow = schema.getPath(fallback, ['defaultContextWindow'])\n const defaultMaxTokens = schema.getPath(fallback, ['maxTokens'])\n\n const keyPlaceholder = keyState?.writable === false\n ? '由启动环境提供(只读)'\n : keyState?.configured === true\n ? '已配置——输入新值可替换'\n : layout === 'pi-ai' && props.declared === true\n ? '输入 API 密钥,或留空使用环境认证'\n : '输入 API 密钥'\n const keyLocked = keyState?.writable === false\n\n return (\n <div className={styles['editor']}>\n {layout === 'unknown'\n ? <p className={styles['advancedHint']}>其余字段存于 settings.yaml;请直接编辑对应段。({namespace.ns})</p>\n : (\n <>\n <div className={styles['tabs']}>\n <div className={styles['tabBar']} role=\"tablist\">\n <button type=\"button\" role=\"tab\" aria-selected={tab === 'provider'} className={tab === 'provider' ? `${styles['tabButton']} ${styles['tabButtonActive']}` : styles['tabButton']} onClick={() => { setTab('provider') }}>供应商</button>\n <button type=\"button\" role=\"tab\" aria-selected={tab === 'models'} className={tab === 'models' ? `${styles['tabButton']} ${styles['tabButtonActive']}` : styles['tabButton']} onClick={() => { setTab('models') }}>模型</button>\n </div> <div className={styles['tabPanel']} role=\"tabpanel\" hidden={tab !== 'provider'}>\n {/* Offered for every pi-ai route, not only hand-declared ones.\n The display name is a provider-level field the adapter\n defaults to the route key and honours as an override, and\n for a catalog route it is the only way to relabel: the key\n itself cannot change without breaking the catalog match\n and every credential ref derived from it. */}\n {layout === 'pi-ai'\n ? (\n <div className={styles['field']}>\n <label className={styles['fieldLabel']}>显示名称</label>\n <input\n className={styles['input']}\n type=\"text\"\n value={stringAt(draft, 'displayName') ?? ''}\n placeholder={stringAt(schema.getPath(namespace.base, settingsPath), 'displayName')\n ?? props.provider}\n aria-label=\"显示名称\"\n disabled={disabled}\n onChange={(event) => { setField('displayName', event.target.value) }}\n />\n </div>\n )\n : null}\n <div className={styles['field']}>\n <label className={styles['fieldLabel']}>API 密钥</label>\n <input\n className={styles['input']}\n type=\"password\"\n autoComplete=\"off\"\n value={keyDraft}\n placeholder={keyPlaceholder}\n aria-label=\"API 密钥\"\n disabled={disabled || keyLocked}\n onChange={(event) => { setKeyDraft(event.target.value) }}\n />\n {keyFailure === undefined\n ? null\n : <p className={styles['error']}>{keyFailure === 'keyBlank' ? '请输入 API 密钥;留空则保持已存储的密钥。' : '此 API 密钥格式无效,请检查。'}</p>}\n </div>\n <div className={styles['field']}>\n <label className={styles['fieldLabel']}>API 地址</label>\n <input\n className={styles['input']}\n type=\"text\"\n value={stringAt(draft, 'baseURL') ?? ''}\n placeholder={layout === 'deepseek'\n ? (stringAt(fallback, 'protocol') === 'messages' ? DEEPSEEK_MESSAGES_BASE_URL : DEEPSEEK_CHAT_BASE_URL)\n : stringAt(fallback, 'baseURL') ?? '提供方默认'}\n aria-label=\"API 地址\"\n disabled={disabled}\n onChange={(event) => { setField('baseURL', event.target.value === '' ? undefined : event.target.value) }}\n />\n {layout === 'deepseek'\n ? <span className={styles['advancedHint']}>请填写与当前连接配置兼容的 API 地址。</span>\n : null}\n </div>\n {layout === 'pi-ai' && props.declared === true\n ? (\n <div className={styles['field']}>\n <label className={styles['fieldLabel']}>API 协议</label>\n <select\n className={`${styles['input']} ${styles['selectInput']}`}\n value={stringAt(draft, 'api') ?? stringAt(fallback, 'api') ?? ''}\n aria-label=\"API 协议\"\n disabled={disabled}\n onChange={(event) => { setField('api', event.target.value) }}\n >\n {(stringAt(draft, 'api') ?? stringAt(fallback, 'api')) === undefined\n ? <option value=\"\">未选择</option>\n : null}\n {protocols.map(choice => <option key={choice} value={choice}>{choice}</option>)}\n </select>\n </div>\n )\n : null}\n </div>\n <div className={styles['tabPanel']} role=\"tabpanel\" hidden={tab !== 'models'}>\n <ModelCatalog\n models={models}\n overridden={modelsOverridden}\n routeApi={routeApi}\n defaultContextWindow={typeof defaultContextWindow === 'number' ? defaultContextWindow : undefined}\n defaultMaxTokens={typeof defaultMaxTokens === 'number' ? defaultMaxTokens : undefined}\n probe={probe}\n probeBlocked={keyFailure}\n hideFetch={layout === 'deepseek'}\n operations={operations}\n disabled={disabled}\n onChange={(rows: ModelDraft[]) => {\n setDraft(current => schema.setPath(current, ['models'], rows))\n }}\n onReset={() => { setDraft(current => schema.deletePath(current, ['models'])) }}\n />\n </div>\n </div>\n </>\n )}\n\n {failure !== undefined ? <p className={styles['error']}>{failure}</p> : null}\n {modelFailure === undefined\n ? null\n : (\n <p className={styles['advancedHint']}>\n {modelFailure.key === 'modelCompatNotOffered'\n ? compatFailureMessage(modelFailure)\n : `模型 ${String(modelFailure.index + 1)}:${modelFailure.key}`}\n </p>\n )}\n\n <div className={styles['editorActions']}>\n <button\n type=\"button\"\n className={styles['secondaryButton']}\n disabled={busy}\n onClick={() => { props.onClose(false) }}\n >\n 取消\n </button>\n <button\n type=\"button\"\n className={styles['primaryButton']}\n disabled={disabled || layout === 'unknown' || modelFailure !== undefined\n || keyFailure !== undefined}\n onClick={() => { void apply() }}\n >\n {busy ? '保存中…' : '保存'}\n </button>\n </div>\n </div>\n )\n}\n","/**\n * The card that declares a provider pi-ai does not ship — an OpenAI-compatible\n * gateway, a self-hosted server, or a provider newer than the installed\n * catalog. One `settings.mutate` sets the whole profile at `providers.<route>`;\n * the key travels separately through `credentials/set` under the reference\n * the profile records. The three fields a hand-declared route cannot default\n * (endpoint, protocol, at least one model) are required here.\n */\n\nimport { useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { JsonValue } from '@deepseek-ai/dsh-util-values'\nimport { deriveKeyRef } from '../vendor/store.ts'\nimport type { ModelsOperations } from '../vendor/operations.ts'\nimport type { ModelDraft } from './compat.ts'\nimport { compatFailureMessage, normalizeModelRow, validateModelRows } from './compat.ts'\nimport { ModelCatalog } from './ModelCatalog.tsx'\nimport styles from './models-plus.module.css'\n\n/** The settings namespace a hand-declared provider is written into. */\nconst NS = 'llm-pi-ai'\n\n/**\n * A route id usable as a settings key AND as the stem of a credential name.\n */\nconst ROUTE_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/\n\n/** Props of {@link CreateProviderCard}. */\nexport interface CreateProviderCardProps {\n /** Route ids already declared, so the card refuses to shadow one. */\n taken: readonly string[]\n /** Wire protocols the adapter can serve, in the order it reports them. */\n protocols: readonly string[]\n /** Revision of the `llm-pi-ai` user section this card opened at. */\n revision: number\n /** The Host operations this card writes and interrogates through. */\n operations: ModelsOperations\n /** Disable writes (read-only settings provider). */\n readOnly: boolean\n /** Close the card; `changed` reports whether a provider was created. */\n onClose: (changed: boolean) => void\n}\n\n/**\n * Render the custom-provider creation card.\n * @param props - existing routes, protocol choices, wire faces.\n * @returns the creation card.\n */\nexport function CreateProviderCard(props: CreateProviderCardProps): ReactNode {\n const { taken, protocols, operations } = props\n const [openedAt] = useState(() => props.revision)\n const [route, setRoute] = useState('')\n const [displayName, setDisplayName] = useState('')\n const [baseURL, setBaseURL] = useState('')\n const [protocol, setProtocol] = useState(protocols[0] ?? '')\n const [tab, setTab] = useState<'provider' | 'models'>('provider')\n const [keyDraft, setKeyDraft] = useState('')\n const [models, setModels] = useState<readonly ModelDraft[]>([])\n const [busy, setBusy] = useState(false)\n const [failure, setFailure] = useState<string | undefined>(undefined)\n /** The profile write landed; only the key write can still be outstanding. */\n const [committed, setCommitted] = useState(false)\n const disabled = props.readOnly || busy\n const profileDisabled = disabled || committed\n\n const routeInvalid = route.length > 0 && !ROUTE_PATTERN.test(route)\n const routeTaken = taken.includes(route)\n // The card states the protocol itself, so every row it drafts is judged by it\n // — the same protocol the adapter will resolve the route to.\n const modelFailure = validateModelRows(models, protocol)\n const keyFailure = ((): 'keyBlank' | 'keyIllegalCharacters' | undefined => {\n if (keyDraft.length === 0) return undefined\n const value = keyDraft.trim()\n if (value.length === 0) return 'keyBlank'\n if (/^[A-Z][A-Z0-9_]*=[^=]/.test(value)) return 'keyIllegalCharacters'\n const first = value[0]\n if ((first === '\"' || first === '\\'' || first === '`') && value.length > 1 && value.endsWith(first)) {\n return 'keyIllegalCharacters'\n }\n return /^[\\x21-\\x7E]+$/.test(value) ? undefined : 'keyIllegalCharacters'\n })()\n const keyValue = keyDraft.trim()\n const ready = route.length > 0 && !routeInvalid && !routeTaken\n && baseURL.length > 0 && models.length > 0 && modelFailure === undefined\n && keyFailure === undefined\n const hint = failure !== undefined || ready || keyFailure !== undefined\n || route.length === 0 || routeInvalid || routeTaken\n ? undefined\n : baseURL.length === 0\n ? '自定义提供方需要填写 API 地址。'\n : modelFailure !== undefined\n ? modelFailure.key === 'modelCompatNotOffered'\n ? compatFailureMessage(modelFailure)\n : `模型 ${String(modelFailure.index + 1)}:${modelFailure.key}`\n : '自定义提供方至少需要一个模型。'\n\n /** Perform the create, returning a failure message or undefined. */\n const createOnce = async (): Promise<string | undefined> => {\n const keyRef = deriveKeyRef(route)\n const storesKey = keyValue.length > 0\n if (!committed) {\n const profile = {\n ...displayName.length === 0 ? {} : { displayName },\n ...storesKey ? { apiKeyEnv: keyRef } : {},\n api: protocol,\n baseURL,\n models: models.map(normalizeModelRow),\n }\n const written = await operations.writeSettings(\n NS,\n [{ op: 'set', path: ['providers', route], value: profile as JsonValue }],\n openedAt,\n )\n if (written.kind !== 'written') {\n return written.kind === 'conflict'\n ? '这张卡片打开期间,这些设置已被其他地方改动。请关闭后重新打开,在当前值上编辑。'\n : written.message\n }\n // A retry after a failed key write must not re-run this mutate.\n setCommitted(true)\n }\n if (storesKey) {\n const stored = await operations.storeCredential(keyRef, keyValue)\n if (stored !== undefined) return stored\n }\n return undefined\n }\n\n const create = async (): Promise<void> => {\n setBusy(true)\n setFailure(undefined)\n try {\n const outcome = await createOnce()\n if (outcome !== undefined) {\n setFailure(outcome)\n return\n }\n props.onClose(true)\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <div className={styles['editor']}>\n <div className={styles['field']} style={{ paddingTop: 12, borderTop: '0.5px solid var(--dsw-alias-border-l2)' }}>\n <label className={styles['fieldLabel']}>Provider ID</label>\n <input\n className={styles['input']}\n type=\"text\"\n value={route}\n placeholder=\"acme-gateway\"\n aria-label=\"Provider ID\"\n disabled={profileDisabled}\n onChange={(event) => { setRoute(event.target.value) }}\n />\n {routeInvalid || routeTaken\n ? <p className={styles['error']}>{routeInvalid ? '需以小写字母开头,之后可用小写字母、数字和短横线。' : '已有提供方使用了这个 ID。'}</p>\n : <p className={styles['advancedHint']}>以小写字母开头的标识,在请求中唯一标识该提供方,并用于派生凭据名。</p>}\n </div>\n\n <div className={styles['tabs']}>\n <div className={styles['tabBar']} role=\"tablist\">\n <button type=\"button\" role=\"tab\" aria-selected={tab === 'provider'} className={tab === 'provider' ? `${styles['tabButton']} ${styles['tabButtonActive']}` : styles['tabButton']} onClick={() => { setTab('provider') }}>供应商</button>\n <button type=\"button\" role=\"tab\" aria-selected={tab === 'models'} className={tab === 'models' ? `${styles['tabButton']} ${styles['tabButtonActive']}` : styles['tabButton']} onClick={() => { setTab('models') }}>模型</button>\n </div>\n <div className={styles['tabPanel']} role=\"tabpanel\" hidden={tab !== 'provider'}>\n <div className={styles['field']}>\n <label className={styles['fieldLabel']}>显示名称</label>\n <input\n className={styles['input']}\n type=\"text\"\n value={displayName}\n placeholder={route.length === 0 ? '显示名称' : route}\n aria-label=\"显示名称\"\n disabled={profileDisabled}\n onChange={(event) => { setDisplayName(event.target.value) }}\n />\n </div>\n <div className={styles['field']}>\n <label className={styles['fieldLabel']}>API 地址</label>\n <input\n className={styles['input']}\n type=\"text\"\n value={baseURL}\n placeholder=\"https://gateway.example/v1\"\n aria-label=\"API 地址\"\n disabled={profileDisabled}\n onChange={(event) => { setBaseURL(event.target.value) }}\n />\n </div>\n <div className={styles['field']}>\n <label className={styles['fieldLabel']}>API 协议</label>\n <select\n className={`${styles['input']} ${styles['selectInput']}`}\n value={protocol}\n aria-label=\"API 协议\"\n disabled={profileDisabled}\n onChange={(event) => { setProtocol(event.target.value) }}\n >\n {protocols.map(choice => <option key={choice} value={choice}>{choice}</option>)}\n </select>\n </div>\n <div className={styles['field']}>\n <label className={styles['fieldLabel']}>API 密钥</label>\n <input\n className={styles['input']}\n type=\"password\"\n autoComplete=\"off\"\n value={keyDraft}\n placeholder=\"输入 API 密钥,或留空使用环境认证\"\n aria-label=\"API 密钥\"\n disabled={disabled}\n onChange={(event) => { setKeyDraft(event.target.value) }}\n />\n {keyFailure === undefined\n ? null\n : <p className={styles['error']}>{keyFailure === 'keyBlank' ? '请输入 API 密钥;若该提供方以其他方式鉴权,可以留空。' : '此 API 密钥格式无效,请检查。'}</p>}\n </div>\n </div>\n <div className={styles['tabPanel']} role=\"tabpanel\" hidden={tab !== 'models'}>\n <ModelCatalog\n models={models}\n overridden={true}\n routeApi={protocol}\n defaultContextWindow={undefined}\n defaultMaxTokens={undefined}\n probe={{\n settingsNs: NS,\n baseURL,\n api: protocol,\n ...keyValue.length === 0 ? {} : { apiKey: keyValue },\n }}\n probeBlocked={keyFailure === 'keyBlank' ? '请输入 API 密钥;若该提供方以其他方式鉴权,可以留空。' : keyFailure}\n operations={operations}\n disabled={profileDisabled}\n onChange={setModels}\n />\n </div>\n </div>\n\n {failure !== undefined ? <p className={styles['error']}>{failure}</p> : null}\n {hint === undefined ? null : <p className={styles['advancedHint']}>{hint}</p>}\n\n <div className={styles['editorActions']}>\n <button\n type=\"button\"\n className={styles['secondaryButton']}\n disabled={busy}\n onClick={() => { props.onClose(committed) }}\n >\n 取消\n </button>\n <button\n type=\"button\"\n className={styles['primaryButton']}\n disabled={disabled || !ready}\n onClick={() => { void create() }}\n >\n {busy ? '创建中…' : '创建提供方'}\n </button>\n </div>\n </div>\n )\n}\n\n","/**\n * The Models+ settings section (v1.0.0, fully plugin-owned UI): provider rows\n * joined from the configurable directory, settings namespaces, and credential\n * states, one editor card at a time. The title row carries the adapter badge\n * and the metadata download button — the only place models.dev data is ever\n * fetched, on an explicit user click.\n */\n\nimport { useState } from 'react'\nimport type { ReactNode } from 'react'\nimport { Modal } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { ModelsSettingsStore, ProviderRow } from '../vendor/store.ts'\nimport { deriveKeyRef, protocolChoices, providerUsable } from '../vendor/store.ts'\nimport type { ModelsOperations } from './operations.ts'\nimport type { SettingsSchemaOperations } from './schema-operations.ts'\nimport { downloadMetadata } from './models-index.ts'\nimport { ProviderEditor } from './ProviderEditor.tsx'\nimport { CreateProviderCard } from './CreateProviderCard.tsx'\nimport styles from './models-plus.module.css'\n\n/** One existing row or dormant directory entry addressed by an editor action. */\nexport interface EditorTarget {\n readonly provider: string\n readonly displayName: string\n readonly settingsNs: string\n readonly settingsPath: readonly string[]\n /** Writable credential identified under this page's conventional reference. */\n credentialRef?: string\n readonly declared?: boolean\n}\n\n/** Injected dependencies of {@link ModelsPlusSection} (slot `inject`). */\nexport interface ModelsPlusInjected {\n controller: ModelsSettingsStore\n hooks: {\n snapshot: ModelsSettingsStore['store']\n }\n operations: ModelsOperations\n schema: SettingsSchemaOperations\n t: (key: string) => string\n}\n\n/** One fact decides the first-run posture: whether any provider is usable. */\nfunction needsSetup(row: ProviderRow, anyUsable: boolean): boolean {\n if (anyUsable) return false\n if (row.entry.settingsPath.length > 0) return false\n return row.credential?.configured !== true\n}\n\n/** The credential reference a row resolves keys through, confirmed configured. */\nfunction keyConfiguredOf(row: ProviderRow): boolean {\n return row.apiKeyEnv !== undefined\n ? row.credential?.configured === true\n : row.derivedCredential?.configured === true\n}\n\nfunction targetOf(row: ProviderRow): EditorTarget {\n const managedRef = deriveKeyRef(row.entry.provider)\n const credentialRef = row.apiKeyEnv === managedRef\n && row.credential?.configured === true\n && row.credential.writable\n ? managedRef\n : undefined\n return {\n provider: row.entry.provider,\n displayName: row.entry.displayName,\n settingsNs: row.entry.settingsNs,\n settingsPath: row.entry.settingsPath,\n ...credentialRef === undefined ? {} : { credentialRef },\n ...row.entry.declared === true ? { declared: true } : {},\n }\n}\n\n/**\n * Remove one user-added provider and its page-managed credential. Credential\n * removal comes first so a second-step failure leaves the row retryable.\n */\nasync function removeProviderProfile(\n operations: ModelsOperations,\n controller: ModelsSettingsStore,\n target: { settingsNs: string; settingsPath: readonly string[]; credentialRef?: string },\n): Promise<string | undefined> {\n if (target.credentialRef !== undefined) {\n const credential = await operations.removeCredential(target.credentialRef)\n if (credential !== undefined) return credential\n }\n const written = await operations.writeSettings(\n target.settingsNs,\n [{ op: 'unset', path: [...target.settingsPath] }],\n undefined,\n )\n if (written.kind !== 'written') return written.message\n await controller.load()\n return undefined\n}\n\n/** Replace the one provider placeholder in localized destructive copy. */\nfunction providerCopy(template: string, target: { displayName: string; provider: string }): string {\n const label = target.provider === target.displayName\n ? target.provider\n : `${target.displayName} (${target.provider})`\n return template.replace('{provider}', () => label)\n}\n\n/**\n * Render the Models+ section content column.\n * @param props - slot-delivered injected dependencies.\n * @returns the section, or null while the shell has not injected yet.\n */\nexport function ModelsPlusSection(props: {\n controller?: ModelsPlusInjected['controller']\n useSnapshot?: ModelsPlusInjected['hooks']['snapshot']\n operations?: ModelsPlusInjected['operations']\n schema?: ModelsPlusInjected['schema']\n t?: ModelsPlusInjected['t']\n}): ReactNode {\n const { controller, useSnapshot, operations, schema, t } = props\n if (\n controller === undefined || useSnapshot === undefined || operations === undefined\n || schema === undefined || t === undefined\n ) return null\n // Hooks live in the Loaded child (mirrors the host section): the null check\n // above must not change this component's hook count between renders.\n return <Loaded injected={{ controller, useSnapshot, operations, schema, t }} />\n}\n\nfunction Loaded({ injected }: { injected: ModelsPlusInjected }): ReactNode {\n const { controller, operations, schema, t } = injected\n const useSnapshot = injected.useSnapshot\n\n const state = useSnapshot(snapshot => snapshot)\n const [editing, setEditing] = useState<EditorTarget | undefined>(undefined)\n const [adding, setAdding] = useState(false)\n const [declaring, setDeclaring] = useState(false)\n const [deleteTarget, setDeleteTarget] = useState<EditorTarget | undefined>(undefined)\n const [deleting, setDeleting] = useState(false)\n const [deleteFailure, setDeleteFailure] = useState<string | undefined>(undefined)\n const [savedTarget, setSavedTarget] = useState<{ displayName: string; provider: string } | undefined>(undefined)\n const [dismissedSetup, setDismissedSetup] = useState<ReadonlySet<string>>(() => new Set())\n const [metaBusy, setMetaBusy] = useState(false)\n const [metaMessage, setMetaMessage] = useState<{ ok: boolean; text: string } | undefined>(undefined)\n\n const announceSaved = (target: { displayName: string; provider: string }): void => {\n void controller.load().then(() => { setSavedTarget(target) })\n }\n\n const closeEditor = (changed: boolean, target: { displayName: string; provider: string }): void => {\n setEditing(undefined)\n setAdding(false)\n setDeclaring(false)\n if (changed) announceSaved(target)\n }\n\n const closeSetup = (changed: boolean, target: { displayName: string; provider: string }): void => {\n setDismissedSetup(previous => new Set([...previous, target.provider]))\n if (changed) announceSaved(target)\n }\n\n const downloadMeta = async (): Promise<void> => {\n setMetaBusy(true)\n setMetaMessage(undefined)\n try {\n const outcome = await downloadMetadata()\n setMetaMessage(outcome.ok\n ? { ok: true, text: 'models.dev 元数据已下载并就绪。' }\n : { ok: false, text: `元数据下载失败:${outcome.message}` })\n } finally {\n setMetaBusy(false)\n }\n }\n\n if (state.status === 'idle') void controller.load()\n if (state.status === 'error') {\n const errorText = state.error ?? ''\n return (\n <div className={styles['section']}>\n <p className={styles['error']}>{`加载提供方目录失败: ${errorText}`}</p>\n <button type=\"button\" className={styles['secondaryButton']} onClick={() => { void controller.load() }}>\n 重试\n </button>\n </div>\n )\n }\n\n const savedRow = savedTarget === undefined\n ? undefined\n : state.rows.find(row => row.entry.provider === savedTarget.provider)\n const savedIdentity = savedRow === undefined\n ? savedTarget\n : { displayName: savedRow.entry.displayName, provider: savedRow.entry.provider }\n\n const anyUsable = state.rows.some(providerUsable)\n const configured = state.rows.filter(row => row.configured)\n // Mirrors the host page @ 0.1.5-rc.1: a row is addable only when its\n // settings namespace actually resolved — a namespace name the settings\n // document does not carry would open a card that can never save.\n const configurable = state.rows.filter(row => state.namespaces.has(row.entry.settingsNs))\n const addable = configurable.filter(row => !row.configured)\n const addTarget = adding ? editing : undefined\n const addNamespace = addTarget === undefined ? undefined : state.namespaces.get(addTarget.settingsNs)\n const protocols = (() => {\n // The protocol choices a hand-declared route may name (schema read).\n return protocolChoices(state.namespaces.get('llm-pi-ai'), schema)\n })()\n\n const renderEditor = (\n target: EditorTarget,\n namespace: Parameters<typeof ProviderEditor>[0]['namespace'] | undefined,\n onClose: (changed: boolean) => void,\n ): ReactNode => {\n if (namespace === undefined) return null\n return (\n <ProviderEditor\n provider={target.provider}\n displayName={target.displayName}\n settingsPath={target.settingsPath}\n {...target.declared === true ? { declared: true } : {}}\n namespace={namespace}\n schema={schema}\n operations={operations}\n readOnly={!state.writable}\n onClose={onClose}\n />\n )\n }\n\n return (\n <div className={styles['section']}>\n {/* Title row: heading + metadata download button */}\n <div className={styles['titleRow']}>\n <h2 className={styles['title']}>{t('nav')}</h2>\n <span className={styles['rowActions']}>\n <button\n type=\"button\"\n className={styles['linkButton']}\n disabled={metaBusy}\n title=\"下载/更新 models.dev 元数据(供快速装入预填)\"\n onClick={() => { void downloadMeta() }}\n >\n {metaBusy ? '正在下载元数据…' : '下载/更新元数据'}\n </button>\n </span>\n </div>\n {metaMessage === undefined\n ? null\n : <p className={metaMessage.ok ? styles['savedNotice'] : styles['error']}>{metaMessage.text}</p>}\n\n <p className={styles['intro']}>{t('intro')}</p>\n\n {savedIdentity === undefined\n ? null\n : (\n <p className={styles['savedNotice']} role=\"status\" aria-live=\"polite\">\n {providerCopy('已保存 {provider}。', savedIdentity)}\n </p>\n )}\n\n <ul className={styles['rows']}>\n {configured.map((row) => {\n const target = targetOf(row)\n const namespace = state.namespaces.get(target.settingsNs)\n if (namespace === undefined) return null\n // Adapter-reported configuration diagnostic (@ 0.1.5-rc.1): shown\n // above the card so a route that cannot be served still explains why.\n const error = row.entry.error === undefined\n ? null\n : <p role=\"alert\" className={styles['error']}>{row.entry.error}</p>\n if (needsSetup(row, anyUsable) && !dismissedSetup.has(row.entry.provider)) {\n return (\n <li key={row.entry.provider} className={styles['rowCard']}>\n {error}\n {renderEditor(target, namespace, (changed) => { closeSetup(changed, target) })}\n </li>\n )\n }\n const open = !adding && !declaring && editing?.provider === row.entry.provider\n const credentialConfigured = row.credential?.configured === true\n const credentialMissing = !credentialConfigured\n && row.apiKeyEnv !== undefined\n && row.credential?.configured === false\n return (\n <li key={row.entry.provider} className={styles['rowCard']}>\n {error}\n <div className={styles['rowHead']}>\n <span className={styles['rowIdentity']}>\n <span className={styles['rowName']}>{row.entry.displayName}</span>\n {row.entry.declared === true\n ? <span className={styles['rowTag']}>自定义</span>\n : null}\n {credentialConfigured\n ? (\n <span\n className={`${styles['credentialDot']} ${styles['credentialDotConfigured']}`}\n role=\"img\"\n aria-label=\"API 密钥已配置\"\n title=\"API 密钥已配置\"\n />\n )\n : credentialMissing\n ? (\n <span\n className={`${styles['credentialDot']} ${styles['credentialDotMissing']}`}\n role=\"img\"\n aria-label=\"API 密钥缺失\"\n title=\"API 密钥缺失\"\n />\n )\n : null}\n </span>\n <span className={styles['rowActions']}>\n <button\n type=\"button\"\n className={styles['secondaryButton']}\n aria-label={providerCopy('编辑 {provider}', target)}\n onClick={() => {\n setSavedTarget(undefined)\n setDeclaring(false)\n setAdding(false)\n setEditing(open ? undefined : target)\n }}\n >\n 编辑\n </button>\n {row.removable\n ? (\n <button\n type=\"button\"\n className={styles['dangerButton']}\n aria-label={providerCopy('删除 {provider}', target)}\n disabled={!state.writable}\n onClick={() => {\n setSavedTarget(undefined)\n setDeleteFailure(undefined)\n setDeleteTarget(target)\n }}\n >\n 删除\n </button>\n )\n : null}\n </span>\n </div>\n {open\n ? renderEditor(target, namespace, (changed) => { closeEditor(changed, target) })\n : null}\n </li>\n )\n })}\n </ul>\n\n <div className={styles['addBlock']}>\n {addTarget !== undefined && addNamespace !== undefined\n ? (\n <div className={styles['addCard']}>\n <div className={styles['field']}>\n <label className={styles['fieldLabel']}>提供方</label>\n <select\n className={`${styles['input']} ${styles['selectInput']}`}\n value={addTarget.provider}\n aria-label=\"提供方\"\n onChange={(event) => {\n const row = addable.find(candidate => candidate.entry.provider === event.target.value)\n if (row === undefined) return\n setEditing(targetOf(row))\n }}\n >\n {addable.map(row => (\n <option key={row.entry.provider} value={row.entry.provider}>\n {row.entry.displayName}\n </option>\n ))}\n </select>\n </div>\n <ProviderEditor\n key={addTarget.provider}\n provider={addTarget.provider}\n displayName={addTarget.displayName}\n namespace={addNamespace}\n schema={schema}\n settingsPath={addTarget.settingsPath}\n operations={operations}\n readOnly={!state.writable}\n onClose={(changed) => { closeEditor(changed, addTarget) }}\n />\n </div>\n )\n : declaring\n ? (\n <div className={styles['addCard']}>\n <CreateProviderCard\n taken={state.rows.map(row => row.entry.provider)}\n protocols={protocols}\n revision={state.namespaces.get('llm-pi-ai')?.revision ?? 0}\n operations={operations}\n readOnly={!state.writable}\n onClose={(changed) => {\n setDeclaring(false)\n if (changed) void controller.load()\n }}\n />\n </div>\n )\n : (\n <div className={styles['addActions']}>\n {configurable.length > 0 && (\n <button\n type=\"button\"\n className={styles['addButton']}\n disabled={addable.length === 0 || !state.writable}\n onClick={() => {\n const first = addable[0]\n if (first === undefined) return\n setSavedTarget(undefined)\n setDeclaring(false)\n setAdding(true)\n setEditing(targetOf(first))\n }}\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M8 3.5v9M3.5 8h9\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n 添加提供方\n </button>\n )}\n {state.namespaces.has('llm-pi-ai') && (\n <button\n type=\"button\"\n className={styles['addButton']}\n disabled={protocols.length === 0 || !state.writable}\n onClick={() => {\n setSavedTarget(undefined)\n setAdding(false)\n setEditing(undefined)\n setDeclaring(true)\n }}\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M8 3.5v9M3.5 8h9\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n 添加自定义提供方\n </button>\n )}\n </div>\n )}\n </div>\n\n <Modal\n open={deleteTarget !== undefined}\n onClose={() => {\n if (deleting) return\n setDeleteTarget(undefined)\n setDeleteFailure(undefined)\n }}\n title={deleteTarget === undefined ? '' : providerCopy('删除 {provider}?', deleteTarget)}\n closeLabel=\"关闭\"\n description={deleteTarget === undefined\n ? ''\n : providerCopy(\n deleteTarget.credentialRef === undefined\n ? '删除 {provider} 会移除其配置;其使用的凭证(如有)由其他位置管理,将会保留。'\n : '删除 {provider} 会移除其配置和存储的 API 密钥。',\n deleteTarget,\n )}\n className={styles['deleteDialog'] as string}\n footer={(\n <>\n <button\n type=\"button\"\n className={styles['secondaryButton']}\n disabled={deleting}\n onClick={() => {\n setDeleteTarget(undefined)\n setDeleteFailure(undefined)\n }}\n >\n 取消\n </button>\n <button\n type=\"button\"\n className={`${styles['secondaryButton']} ${styles['deleteConfirm']}`}\n disabled={deleting}\n onClick={() => {\n if (deleteTarget === undefined || deleting) return\n setDeleting(true)\n setDeleteFailure(undefined)\n void removeProviderProfile(operations, controller, deleteTarget)\n .then((removeFailure) => {\n if (removeFailure !== undefined) {\n setDeleteFailure(removeFailure)\n return\n }\n setDeleteTarget(undefined)\n })\n .finally(() => { setDeleting(false) })\n }}\n >\n {deleteTarget === undefined ? '' : providerCopy(deleting ? '正在删除 {provider}…' : '删除 {provider}', deleteTarget)}\n </button>\n </>\n )}\n >\n {deleteFailure === undefined ? null : <p className={styles['error']}>{deleteFailure}</p>}\n </Modal>\n </div>\n )\n}\n\n","/**\n * VENDORED from @deepseek-ai/dsh-client-ui-settings-models @ 0.1.5-rc.1\n * (host tree packages/client/ui-settings-models/src/client/operations.ts) — copied\n * VERBATIM so the build is self-contained (no host checkout required).\n * Re-diff against the host source on every adapter-anchor bump.\n */\n/**\n * The Host reads and writes the Models cards perform, as callbacks built in the\n * plugin body. Cards receive these instead of a context: the outcomes name what\n * a card renders — a stored view, a stale revision, a refusal message — so the\n * failure codes and Remote namespaces stay in the apply world.\n */\n\nimport type { Context as ClientContext } from '@deepseek-ai/cordis'\nimport type {\n CredentialInfo, LlmDiscoveredModel, LlmModelDiscoveryRequest,\n SettingsNamespaceView, SettingsPathOpView,\n} from '@deepseek-ai/dsh-api-remotes/client'\n\n/** What one namespace write answered. */\nexport type SettingsWriteOutcome =\n /** Committed; the view carries the stored user subtree and the new revision. */\n | { readonly kind: 'written'; readonly view: SettingsNamespaceView }\n /**\n * The stored revision moved after the card read it, so the draft is stale.\n * The message stays for callers that report the Host diagnostic as it is.\n */\n | { readonly kind: 'conflict'; readonly message: string }\n /** Any other refusal, with the Host's own diagnostic. */\n | { readonly kind: 'refused'; readonly message: string }\n\n/** What one endpoint interrogation answered. */\nexport type ModelDiscoveryOutcome =\n /** The candidates the provider disclosed, in its own order. */\n | { readonly kind: 'found'; readonly models: readonly LlmDiscoveredModel[] }\n /** The interrogation was refused, with the Host's own diagnostic. */\n | { readonly kind: 'refused'; readonly message: string }\n\n/** The Host operations the Models page and its cards invoke. */\nexport interface ModelsOperations {\n /**\n * Read one credential reference's state.\n * @param ref - credential reference name.\n * @returns the state, or undefined when the reference is unknown or the read was refused.\n */\n describeCredential(ref: string): Promise<CredentialInfo | undefined>\n /**\n * Store one credential literal under its reference.\n * @param ref - credential reference name.\n * @param value - the literal to store.\n * @returns the refusal message, or undefined once stored.\n */\n storeCredential(ref: string, value: string): Promise<string | undefined>\n /**\n * Remove one credential reference (idempotent).\n * @param ref - credential reference name.\n * @returns the refusal message, or undefined once removed.\n */\n removeCredential(ref: string): Promise<string | undefined>\n /**\n * Apply path operations to one settings namespace.\n * @param ns - settings namespace identity.\n * @param ops - ordered path operations against the stored section, as the\n * wire takes them (the Remote signature owns the array).\n * @param expectedRevision - revision the draft was opened at, or undefined to write unfenced.\n * @returns the write outcome the card renders from.\n */\n writeSettings(\n ns: string,\n ops: SettingsPathOpView[],\n expectedRevision: number | undefined,\n ): Promise<SettingsWriteOutcome>\n /**\n * Ask a provider endpoint what models it serves.\n * @param settingsNs - namespace whose adapter family answers.\n * @param request - endpoint facts as the form currently shows them.\n * @returns the candidates, or the refusal.\n */\n discoverModels(settingsNs: string, request: LlmModelDiscoveryRequest): Promise<ModelDiscoveryOutcome>\n}\n\n/**\n * Bind the page's Host operations to the plugin's own Remote namespaces.\n * @param ctx - the page plugin's context, which declares `remote.credentials`,\n * `remote.llm`, and `remote.settings` in its own `inject`.\n * @returns the callbacks the section and its cards are injected with.\n */\nexport function createModelsOperations(ctx: ClientContext): ModelsOperations {\n return {\n describeCredential: async (ref) => {\n const response = await ctx.remote.credentials.describe([ref])\n return response.ok ? response.value[ref] : undefined\n },\n storeCredential: async (ref, value) => {\n const response = await ctx.remote.credentials.set(ref, value)\n return response.ok ? undefined : response.error.message\n },\n removeCredential: async (ref) => {\n const response = await ctx.remote.credentials.unset(ref)\n return response.ok ? undefined : response.error.message\n },\n writeSettings: async (ns, ops, expectedRevision) => {\n const response = await ctx.remote.settings.mutate(ns, ops, expectedRevision)\n if (response.ok) return { kind: 'written', view: response.value }\n const { code, message } = response.error\n return code === 'settings/conflict' ? { kind: 'conflict', message } : { kind: 'refused', message }\n },\n discoverModels: async (settingsNs, request) => {\n const response = await ctx.remote.llm.discoverModels(settingsNs, request)\n return response.ok\n ? { kind: 'found', models: response.value }\n : { kind: 'refused', message: response.error.message }\n },\n }\n}\n","/**\n * VENDORED from @deepseek-ai/dsh-client-ui-settings-models @ 0.1.5-rc.1\n * (host tree packages/client/ui-settings-models/src/client/schema-operations.ts) — copied\n * VERBATIM so the build is self-contained (no host checkout required).\n * Re-diff against the host source on every adapter-anchor bump.\n */\nimport type {\n SettingsSchemaService,\n} from '@deepseek-ai/dsh-client-ui-settings/client'\n\n/** Plain schema callbacks exposed to Models stores and presentation components. */\nexport type SettingsSchemaOperations = Pick<\n SettingsSchemaService,\n 'rehydrate' | 'validate' | 'nodeAtPath' | 'getPath' | 'hasPath' | 'setPath' | 'deletePath'\n>\n\n/**\n * Hide the Cordis service identity behind bound schema callbacks.\n * @param service - settings-owned schema service available in the apply context.\n * @returns callbacks that cannot expose the service context to React components.\n */\nexport function createSettingsSchemaOperations(service: SettingsSchemaService): SettingsSchemaOperations {\n return {\n rehydrate: serialized => service.rehydrate(serialized),\n validate: (schema, draft) => service.validate(schema, draft),\n nodeAtPath: (root, path) => service.nodeAtPath(root, path),\n getPath: (value, path) => service.getPath(value, path),\n hasPath: (value, path) => service.hasPath(value, path),\n setPath: (root, path, value) => service.setPath(root, path, value),\n deletePath: (root, path) => service.deletePath(root, path),\n }\n}\n","/**\n * dsh-model-extension — client entry (v1.0.0).\n *\n * Registers the Models+ settings section rendering the fully plugin-owned\n * models-plus component tree (no host component code is bundled). The store,\n * schema operations, Host operations, dictionaries, and invalidation wiring\n * keep the upstream ui-settings-models contracts @ 0.1.5-rc.1 — the logic\n * modules (store/operations/schema-operations) are still inlined from the\n * host tree at build time, only the presentation is ours.\n */\nimport type { Context as ClientContext } from '@deepseek-ai/cordis'\n// Type-only: pulls the shell's SlotMap merge ('settings.section') into this program.\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\n// Type-only: pulls the locale plugin's Context merge (ctx.locale).\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\n// Type-only: pulls the ui renderer's Context merge (useSnapshot and friends on inject faces).\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\n// Type-only: pulls the ctx.remote merge and forwarded-event key face.\nimport type {} from '@deepseek-ai/dsh-api-remotes/client'\nimport { ModelsPlusSection } from './models-plus/ModelsPlusSection.tsx'\nimport type { ModelsPlusInjected } from './models-plus/ModelsPlusSection.tsx'\nimport { ModelsSettingsStore } from './vendor/store.ts'\nimport { createModelsOperations } from './vendor/operations.ts'\nimport { createSettingsSchemaOperations } from './vendor/schema-operations.ts'\nimport { en as extensionEn, zh as extensionZh } from './extension-meta.ts'\n\n/** Cordis service name (distinct from the npm package name). */\nexport const name = 'model-extension-client'\n\n/** Required services — mirrors the upstream Models section registration @ 0.1.7-alpha.1. */\nexport const inject = [\n 'slots', 'locale', 'remote', 'remote.credentials', 'remote.llm', 'remote.settings',\n 'configForms', 'settingsSchema',\n]\n\n/** Refetch the page snapshot only after its first load (upstream helper, inlined). */\nfunction refreshIfLoaded(controller: ModelsSettingsStore): void {\n if (controller.store.getSnapshot().status === 'idle') return\n void controller.load()\n}\n\n/**\n * Apply: register the Models+ section once slot/locale services are up.\n * @param ctx - client root context.\n */\nexport function apply(ctx: ClientContext): void {\n const NS = 'settings.models-extension'\n ctx.effect(() => ctx.locale.register(NS, {\n zh: { ...extensionZh },\n en: { ...extensionEn },\n }), 'dsh-model-extension: copy dictionaries')\n\n const schema = createSettingsSchemaOperations(ctx.settingsSchema)\n const operations = createModelsOperations(ctx)\n const controller = new ModelsSettingsStore(ctx, schema, ctx.configForms.describe())\n const t = ctx.locale.bind(NS) as ModelsPlusInjected['t']\n const injected = (): ModelsPlusInjected => ({\n controller,\n hooks: { snapshot: controller.store },\n operations,\n schema,\n t,\n })\n\n // Pushed invalidations converge every open surface without polling.\n ctx.effect(() => {\n const refreshModels = (): void => { refreshIfLoaded(controller) }\n return () => [\n ctx.remote.$on('settings/document-updated', () => { refreshModels() }),\n ctx.remote.$on('credentials/reference-updated', refreshModels),\n ctx.remote.$on('llm/adapters-updated', refreshModels),\n ctx.on('connection/reset', refreshModels),\n ]\n }, 'dsh-model-extension: pushed invalidations')\n\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: 'models-extension',\n order: 11,\n label: () => t('nav'),\n inject: injected,\n }, ModelsPlusSection))\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["createSnapshotStore","useState","useRef","styles","useState","styles","useState","styles","Modal","useState","useMemo","styles","useState","styles","useState","styles","Modal","extensionZh","extensionEn"],"sources":["official/src/client/vendor/store.ts","official/src/client/models-plus/models-index.ts","official/src/client/extension-meta.ts","official/src/client/models-plus/compat.ts","official/src/client/models-plus/presets.ts","official/src/client/models-plus/prefill.ts","official/src/client/models-plus/models-plus.module.css","official/src/client/models-plus/QuickLoad.tsx","official/src/client/models-plus/ModelEntryPanel.tsx","official/src/client/models-plus/ModelCatalog.tsx","official/src/client/models-plus/ProviderEditor.tsx","official/src/client/models-plus/CreateProviderCard.tsx","official/src/client/models-plus/ModelsPlusSection.tsx","official/src/client/vendor/operations.ts","official/src/client/vendor/schema-operations.ts","official/src/client/index-extension.ts"],"sourcesContent":["/**\n * VENDORED from @deepseek-ai/dsh-client-ui-settings-models @ 0.1.5-rc.1\n * (host tree packages/client/ui-settings-models/src/client/store.ts) — copied\n * VERBATIM so the build is self-contained (no host checkout required).\n * Re-diff against the host source on every host upgrade (last verified\n * byte-identical @ 0.1.7-rc.2).\n */\n/**\n * Models settings page store: one snapshot joining the configurable-provider\n * directory (`llm/listProviders` joined with `llm/listConfigurableProviders`),\n * the settings namespaces (shared settings mirror),\n * and the referenced credentials (`credentials/describe`). The host stays the\n * single fact source — every mutation writes through the wire and the page\n * re-renders from the next describe, pushed or refetched.\n */\n\nimport type { Context as ClientContext } from '@deepseek-ai/cordis'\nimport type {\n CredentialInfo, LlmConfigurableProvider, LlmProviderInfo, SettingsNamespaceView,\n} from '@deepseek-ai/dsh-api-remotes/client'\nimport type { SnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport { createSnapshotStore } from '@deepseek-ai/dsh-client-store'\nimport type { SettingsDescribeFace } from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type { SettingsSchemaOperations } from './schema-operations.ts'\n\n/**\n * Any route key walks a dict schema to the same profile node, so the lookup\n * names one that cannot collide with a configured route.\n */\nconst PROBE_ROUTE = '\\u0000probe'\n\n/** One provider row after joining the configurable directory with live routes. */\nexport interface ProviderDirectoryEntry {\n readonly provider: string\n readonly displayName: string\n readonly settingsNs: string\n readonly settingsPath: readonly string[]\n readonly active: boolean\n readonly declared?: boolean\n readonly error?: string\n}\n\n/**\n * Join declared configurable providers with the currently registered routes.\n * @param registered - live provider routes in registration order.\n * @param directory - declared configurable providers in declaration order.\n * @returns account and official routes first, then other routes in their original order.\n */\nexport function joinProviderDirectory(\n registered: readonly LlmProviderInfo[],\n directory: readonly LlmConfigurableProvider[],\n): ProviderDirectoryEntry[] {\n const active = new Set(registered.map(provider => provider.id))\n const declared = new Set(directory.map(entry => entry.provider))\n const rows: ProviderDirectoryEntry[] = directory.map(entry => ({\n provider: entry.provider,\n displayName: entry.displayName,\n settingsNs: entry.settingsNs,\n settingsPath: [...entry.settingsPath],\n active: active.has(entry.provider),\n ...entry.declared === undefined ? {} : { declared: entry.declared },\n ...entry.error === undefined ? {} : { error: entry.error },\n }))\n for (const provider of registered) {\n if (declared.has(provider.id)) continue\n rows.push({\n provider: provider.id,\n displayName: provider.name,\n settingsNs: '',\n settingsPath: [],\n active: true,\n })\n }\n return rows.toSorted((left, right) =>\n (left.provider === 'deepseek-account' ? 0 : left.provider === 'deepseek-official' ? 1 : 2)\n - (right.provider === 'deepseek-account' ? 0 : right.provider === 'deepseek-official' ? 1 : 2))\n}\n\n/** One provider row the page renders. */\nexport interface ProviderRow {\n /** Account route has usable credentials for the configured inference origin. */\n accountAvailable?: boolean\n /** The directory entry (route id, display name, settings address, live state). */\n entry: ProviderDirectoryEntry\n /** Whether any layer configures this provider (its profile resolves). */\n configured: boolean\n /** Whether the user layer alone carries the profile (removal restores the base). */\n removable: boolean\n /** The credential reference the resolved profile names, when one does. */\n apiKeyEnv: string | undefined\n /** Credential state for {@link apiKeyEnv}, once described. */\n credential: CredentialInfo | undefined\n /**\n * Credential state for the page's derived `<ROUTE>_API_KEY`, described only\n * while the profile names no reference — the provider-card seat's\n * `keyConfigured` fact for dormant and keyless rows, matching the editor's\n * own derivation rule.\n */\n derivedCredential?: CredentialInfo\n}\n\n/** Page snapshot. */\nexport interface ModelsSettingsState {\n status: 'idle' | 'loading' | 'ready' | 'error'\n /** Whole-load failure text; row-level write failures stay in the editor. */\n error: string | null\n /** Credential enrichment failure; provider/settings rows remain usable. */\n credentialError: string | null\n /** Whether the settings provider accepts writes. */\n writable: boolean\n /** Every configurable provider joined with its configured/credential state. */\n rows: readonly ProviderRow[]\n /** Namespace views by ns, for the editor's schema/layers/secrets. */\n namespaces: ReadonlyMap<string, SettingsNamespaceView>\n}\n\n/**\n * Derive the conventional credential reference for a provider route: the v1\n * page never asks for an environment-variable name, so a typed key stores\n * under this derived reference and the profile records it as `apiKeyEnv`.\n * @param provider - provider route id (e.g. `anthropic`, `minimax-cn`).\n * @returns the derived reference name (e.g. `MINIMAX_CN_API_KEY`).\n */\nexport function deriveKeyRef(provider: string): string {\n return `${provider.toUpperCase().replace(/[^A-Z0-9]+/g, '_')}_API_KEY`\n}\n\n/**\n * The wire protocols a hand-declared route may name, read out of the owning\n * namespace's own schema. This stays a schema read rather than a wire field so\n * the choices the page offers cannot drift from the ones the adapter accepts:\n * both come from the same `Config`.\n * @param namespace - the namespace view whose schema declares the profile shape.\n * @param schema - settings schema operations.\n * @returns the protocol identifiers, or an empty list when the schema has none.\n */\nexport function protocolChoices(\n namespace: SettingsNamespaceView | undefined,\n schema: SettingsSchemaOperations,\n): string[] {\n if (namespace === undefined) return []\n const node = schema.nodeAtPath(schema.rehydrate(namespace.schema), ['providers', PROBE_ROUTE, 'api'])\n const list = (node as { type?: string; list?: readonly { value?: unknown }[] } | undefined)\n if (list?.type !== 'union' || list.list === undefined) return []\n return list.list.map(entry => entry.value).filter((value): value is string => typeof value === 'string')\n}\n\n/** The credential reference a resolved profile names (its `apiKeyEnv` field). */\nfunction apiKeyEnvOf(\n namespace: SettingsNamespaceView | undefined,\n path: readonly string[],\n schema: SettingsSchemaOperations,\n): string | undefined {\n if (namespace === undefined) return undefined\n const profile = schema.getPath(namespace.value, path)\n if (typeof profile !== 'object' || profile === null) return undefined\n const ref = (profile as { apiKeyEnv?: unknown }).apiKeyEnv\n return typeof ref === 'string' && ref.length > 0 ? ref : undefined\n}\n\n/** The models settings page controller (one per settings surface). */\nexport class ModelsSettingsStore {\n /** The snapshot the section renders from (uSES-safe store). */\n readonly store: SnapshotStore<ModelsSettingsState> = createSnapshotStore<ModelsSettingsState>({\n status: 'idle', error: null, credentialError: null, writable: false, rows: [], namespaces: new Map(),\n })\n\n /** Latest load wins; an older response never overwrites a newer one. */\n private generation = 0\n\n /**\n * @param ctx - the page plugin's context, whose `remote.llm` and\n * `remote.credentials` namespaces carry the directory and credential reads.\n * @param schema - settings-owned schema and immutable path operations.\n * @param describeFace - the shared mirror's describe face (namespace views and writability).\n */\n constructor(\n private readonly ctx: ClientContext,\n private readonly schema: SettingsSchemaOperations,\n private readonly describeFace: SettingsDescribeFace,\n ) {}\n\n /**\n * Refresh the whole page snapshot: the provider directory and the mirror's\n * settings answer in parallel, then one batched credential describe over\n * every referenced ref. Provider failure or absence of an initial settings\n * answer keeps the last good rows and surfaces an error; a failed settings\n * refresh reuses the mirror's held view.\n * @returns nothing; the snapshot carries the outcome.\n */\n async load(): Promise<void> {\n const generation = ++this.generation\n this.store.update((s) => { s.status = 'loading'; s.error = null })\n const [registered, declared] = await Promise.all([\n this.ctx.remote.llm.listProviders(),\n this.ctx.remote.llm.listConfigurableProviders(),\n this.describeFace.ensure(),\n ])\n if (!registered.ok) { this.failLoad(generation, registered.error.message); return }\n if (!declared.ok) { this.failLoad(generation, declared.error.message); return }\n const mirrored = this.describeFace.getSnapshot()\n if (mirrored.view === undefined) {\n this.failLoad(generation, mirrored.error ?? 'settings are unavailable in this browser')\n return\n }\n const providers = joinProviderDirectory(registered.value, declared.value)\n const writable = mirrored.view.writable\n const views: readonly SettingsNamespaceView[] = mirrored.view.namespaces\n const namespaces = new Map(views.map(view => [view.ns, view]))\n const rows: ProviderRow[] = providers.map((entry) => {\n const namespace = namespaces.get(entry.settingsNs)\n const configured = namespace !== undefined\n && (entry.settingsPath.length === 0 || this.schema.getPath(namespace.value, entry.settingsPath) !== undefined)\n const removable = namespace !== undefined\n && entry.settingsPath.length > 0\n && this.schema.hasPath(namespace.user, entry.settingsPath)\n && !this.schema.hasPath(namespace.base, entry.settingsPath)\n return {\n entry,\n configured,\n removable,\n apiKeyEnv: entry.provider === 'deepseek-account' ? undefined : apiKeyEnvOf(namespace, entry.settingsPath, this.schema),\n credential: undefined,\n }\n })\n if (rows.some(row => row.entry.provider === 'deepseek-account')) {\n const catalog = await this.ctx.remote.session.modelCatalog()\n for (const row of rows) {\n if (row.entry.provider === 'deepseek-account') row.accountAvailable = catalog.ok\n && catalog.value.groups.some(group => group.id === 'deepseek-account' && group.models.length > 0)\n }\n }\n const refs = [...new Set(rows.filter(row => row.entry.provider !== 'deepseek-account').map(row => row.apiKeyEnv ?? deriveKeyRef(row.entry.provider)))]\n let credentials: Record<string, CredentialInfo> = {}\n let credentialError: string | null = null\n if (refs.length > 0) {\n const response = await this.ctx.remote.credentials.describe(refs)\n // Credential state is an enrichment for the Models page: a failure\n // degrades the badge instead of failing the load. The onboarding\n // projection below retains the failure distinction.\n if (response.ok) credentials = response.value\n else credentialError = response.error.message\n }\n if (generation !== this.generation) return\n this.store.update((s) => {\n s.status = 'ready'\n s.error = null\n s.credentialError = credentialError\n s.writable = writable\n s.rows = rows.filter(row => row.entry.provider !== 'deepseek-account' || row.accountAvailable === true).map((row) => {\n if (row.entry.provider === 'deepseek-account') return row\n const named = row.apiKeyEnv === undefined ? undefined : credentials[row.apiKeyEnv]\n const derived = row.apiKeyEnv !== undefined ? undefined : credentials[deriveKeyRef(row.entry.provider)]\n return {\n ...row,\n ...named === undefined ? {} : { credential: named },\n ...derived === undefined ? {} : { derivedCredential: derived },\n }\n })\n s.namespaces = namespaces\n })\n }\n\n /** Publish one load's failure text, unless a newer load already took over. */\n private failLoad(generation: number, message: string): void {\n if (generation !== this.generation) return\n this.store.update((s) => {\n s.status = 'error'\n s.error = message\n })\n }\n}\n\n/**\n * Whether a joined row can serve model requests as it stands: the route is\n * registered with the adapter registry, and whatever credential its resolved\n * profile names is stored. A profile naming no reference authenticates through\n * the provider's own path (the Bedrock chain, Vertex ADC, a gateway that needs\n * nothing), as does a live route with no settings address at all, so neither\n * owes this page a key.\n * @param row - one joined provider row.\n * @returns whether the user already has this provider to talk to.\n */\nexport function providerUsable(row: ProviderRow): boolean {\n if (!row.entry.active) return false\n if (row.entry.provider === 'deepseek-account') return row.accountAvailable === true\n if (row.apiKeyEnv === undefined) return true\n return row.credential?.configured === true\n}\n\n/** First-run onboarding readiness derived only from the shared Models join. */\nexport type OnboardingReadiness =\n | { kind: 'loading' }\n | { kind: 'adapter-absent' }\n | { kind: 'provider-ready' }\n | { kind: 'credential-missing' }\n | {\n kind: 'unavailable'\n reason:\n | 'load-failed'\n | 'provider-inactive'\n | 'credentials-unavailable'\n | 'settings-read-only'\n | 'credential-read-only'\n }\n\n/**\n * Project first-run readiness from the provider/settings/credential join used\n * by the Models page. The step exists to leave the user with a model to talk\n * to, so ANY usable provider ends it; only when none exists does the official\n * DeepSeek route — the one route the prompt can offer a key field for — decide\n * whether prompting can help. A missing official configurable-provider\n * declaration means the adapter is not repairable by navigating to Models.\n * @param state - current shared Models join snapshot.\n * @returns the onboarding state without reading a parallel fact source.\n */\nexport function onboardingReadiness(state: ModelsSettingsState): OnboardingReadiness {\n if ((state.status === 'idle' || state.status === 'loading') && state.rows.length === 0) {\n return { kind: 'loading' }\n }\n if (state.status === 'error') {\n return {\n kind: 'unavailable',\n reason: 'load-failed',\n }\n }\n if (state.rows.some(providerUsable)) return { kind: 'provider-ready' }\n const row = state.rows.find(candidate =>\n candidate.entry.provider === 'deepseek-official'\n && candidate.entry.settingsNs === 'llm-deepseek'\n && candidate.entry.settingsPath.length === 0)\n if (row === undefined) return { kind: 'adapter-absent' }\n if (!row.entry.active) {\n return {\n kind: 'unavailable',\n reason: 'provider-inactive',\n }\n }\n // Past the usable gate an active route names a reference it has no stored\n // credential for, so the remaining questions are all about that credential.\n if (state.credentialError !== null || row.credential === undefined) {\n return {\n kind: 'unavailable',\n reason: 'credentials-unavailable',\n }\n }\n if (!state.writable) {\n return {\n kind: 'unavailable',\n reason: 'settings-read-only',\n }\n }\n if (!row.credential.writable) {\n return {\n kind: 'unavailable',\n reason: 'credential-read-only',\n }\n }\n return { kind: 'credential-missing' }\n}\n","/**\n * Client access to the prefill index.\n *\n * Two sources, one search surface:\n *\n * - **pi-ai** — the installed `@earendil-works/pi-ai` catalog, served by this\n * plugin's own route straight from the package the host adapter loads. It is\n * the source carrying the reasoning and compat surface models.dev has no\n * concept of, and it costs no network call.\n * - **models.dev** — a flat metadata file, fetched ONLY when the user clicks\n * the title-row button and cached next to settings.yaml under DSH home.\n *\n * pi-ai candidates lead (richer, and faithful to what the host will actually\n * do); models.dev follows as the fallback for routes pi-ai ships nothing\n * about. An unavailable pi-ai source is not an error — the index simply\n * carries an empty pi-ai list and the search degrades to models.dev alone.\n */\n\n/** Which source a prefill candidate came from. */\nexport type PrefillSource = 'pi-ai' | 'models.dev'\n\n/** One prefill candidate, normalized across both sources. */\nexport interface PrefillEntry {\n readonly source: PrefillSource\n /** Unique within the fetched index (source, provider and id combined). */\n readonly key: string\n /** The source's own model id — also what the candidate list renders. */\n readonly id: string\n /**\n * Owning provider: pi-ai's provider id (the route key a catalog route is\n * named after), or the leading segment of a models.dev directory path.\n * Absent when the source does not name one.\n */\n readonly provider?: string\n /** Display name, when the source carries one. */\n readonly name?: string\n /** Maximum combined request and response context in tokens. */\n readonly context: number | undefined\n /** Maximum output tokens. */\n readonly output: number | undefined\n /** Accepted request modalities, already narrowed to what this UI offers. */\n readonly input: readonly string[]\n /** Whether the model reasons at all. */\n readonly reasoning: boolean\n /**\n * pi-ai only: its own level→wire-spelling map. Semantically our\n * `reasoningEfforts`, except that `null` means *unsupported* here while our\n * dict reads it as *supported, send nothing* — the panel maps it, never\n * copies it across.\n */\n readonly thinkingLevelMap?: Readonly<Record<string, string | null>>\n /** pi-ai only: the wire protocol the model speaks, which picks its compat set. */\n readonly api?: string\n /** pi-ai only: the wire-compatibility switches the catalog records. */\n readonly compat?: Readonly<Record<string, unknown>>\n}\n\n/** The fetched prefill index: pi-ai leads, models.dev follows. */\nexport interface PrefillIndex {\n /** Candidates from the installed pi-ai catalog; empty when unavailable. */\n readonly piAi: readonly PrefillEntry[]\n /** Candidates from the cached models.dev file; empty when not downloaded. */\n readonly modelsDev: readonly PrefillEntry[]\n /** Installed pi-ai version, for the source note in the UI. */\n readonly piAiVersion?: string\n /** Generation timestamp of the pi-ai catalog snapshot. */\n readonly piAiGeneratedAt?: string\n /**\n * Drift findings reported alongside the catalog: a pi-ai version outside the\n * verified set, a resolution path that had to be guessed, several pi-ai\n * copies on the host, or records that did not project cleanly.\n *\n * Surfaced verbatim and unconditionally — a warning nobody sees is a silent\n * failure with extra steps, which is exactly the state this field exists to\n * rule out.\n */\n readonly piAiWarnings: readonly string[]\n /**\n * Why the pi-ai source is empty, when it was *refused* rather than simply\n * absent. The server names the concrete cause (no package found, the catalog\n * API unreachable), which is the difference between a diagnosis and a shrug.\n */\n readonly piAiFailure?: string\n}\n\n/** Same-origin routes served by the server half. */\nconst INDEX_URL = '/plugins/dsh-model-extension/models-index'\nconst DOWNLOAD_URL = '/plugins/dsh-model-extension/models-download'\nconst PI_AI_URL = '/plugins/dsh-model-extension/pi-ai-catalog'\n\n/** Precise entry the models.dev route returns (a subset of the raw record). */\nexport interface MetadataEntry {\n readonly id: string\n readonly context: number | undefined\n readonly output: number | undefined\n readonly input: readonly string[]\n readonly reasoning: boolean\n}\n\n/** Module-level cache: one page load fetches each source at most once. */\nlet cachedIndex: PrefillIndex | undefined\n\n/** Normalize the models.dev route payload. */\nfunction normalize(raw: unknown): readonly MetadataEntry[] {\n if (!Array.isArray(raw)) return []\n const entries: MetadataEntry[] = []\n for (const item of raw) {\n if (typeof item !== 'object' || item === null) continue\n const row = item as Record<string, unknown>\n if (typeof row['id'] !== 'string' || row['id'].length === 0) continue\n const modalities = Array.isArray(row['input'])\n ? row['input'].filter((m): m is string => typeof m === 'string')\n : []\n entries.push({\n id: row['id'],\n context: typeof row['context'] === 'number' ? row['context'] : undefined,\n output: typeof row['output'] === 'number' ? row['output'] : undefined,\n input: modalities,\n reasoning: row['reasoning'] === true,\n })\n }\n return entries\n}\n\n/** Narrow a modality list to what this UI offers. */\nfunction supportedInput(value: unknown): string[] {\n if (!Array.isArray(value)) return []\n return value.filter((m): m is string => typeof m === 'string' && (m === 'text' || m === 'image'))\n}\n\n/** Read one object-valued field off a raw record. */\nfunction objectField(source: Record<string, unknown>, key: string): Record<string, unknown> | undefined {\n const value = source[key]\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? value as Record<string, unknown>\n : undefined\n}\n\n/**\n * The provider a models.dev id belongs to.\n *\n * models.dev ids are directory paths (`zhipuai/glm-5.3-flash`), so the leading\n * segment names the provider. Reading it here gives the picker the same\n * provider-first navigation that pi-ai's per-provider catalog has for free —\n * and it is what lets a user narrow by vendor instead of guessing between\n * same-named ids.\n * @param id - the models.dev directory id.\n * @returns the provider segment, or undefined when the id carries none.\n */\nfunction modelsDevProvider(id: string): string | undefined {\n const slash = id.indexOf('/')\n return slash > 0 ? id.slice(0, slash) : undefined\n}\n\n/** Turn models.dev rows into prefill candidates. */\nfunction toModelsDevEntries(rows: readonly MetadataEntry[]): readonly PrefillEntry[] {\n return rows.map((row): PrefillEntry => ({\n source: 'models.dev',\n key: `models.dev\\u0000${row.id}`,\n id: row.id,\n provider: modelsDevProvider(row.id),\n context: row.context,\n output: row.output,\n input: row.input,\n reasoning: row.reasoning,\n }))\n}\n\n/** Read the diagnostics warnings the server attaches to a catalog payload. */\nfunction diagnosticsWarnings(payload: unknown): readonly string[] {\n if (typeof payload !== 'object' || payload === null) return []\n const diagnostics = (payload as Record<string, unknown>)['diagnostics']\n if (typeof diagnostics !== 'object' || diagnostics === null) return []\n const warnings = (diagnostics as Record<string, unknown>)['warnings']\n if (!Array.isArray(warnings)) return []\n return warnings.filter((warning): warning is string => typeof warning === 'string')\n}\n\n/** Turn a pi-ai route payload into prefill candidates, keeping both ids' provenance. */\nfunction toPiAiEntries(payload: unknown): {\n entries: readonly PrefillEntry[]\n version?: string\n generatedAt?: string\n warnings: readonly string[]\n} {\n const warnings = diagnosticsWarnings(payload)\n if (typeof payload !== 'object' || payload === null) return { entries: [], warnings }\n const body = payload as Record<string, unknown>\n if (!Array.isArray(body['models'])) return { entries: [], warnings }\n\n // One id can live in several providers (zai, opencode and two gateways all\n // ship `glm-5.3-flash`), so ownership travels per entry instead of being\n // disambiguated inside a display string — the picker filters by provider\n // rather than asking the user to decode a suffix.\n const entries: PrefillEntry[] = []\n for (const item of body['models']) {\n if (typeof item !== 'object' || item === null) continue\n const row = item as Record<string, unknown>\n const id = row['id']\n const provider = row['provider']\n if (typeof id !== 'string' || id.length === 0) continue\n if (typeof provider !== 'string' || provider.length === 0) continue\n entries.push({\n source: 'pi-ai',\n key: `pi-ai\\u0000${provider}\\u0000${id}`,\n id,\n provider,\n name: typeof row['name'] === 'string' && row['name'].length > 0 ? row['name'] : undefined,\n context: typeof row['contextWindow'] === 'number' ? row['contextWindow'] : undefined,\n output: typeof row['maxTokens'] === 'number' ? row['maxTokens'] : undefined,\n input: supportedInput(row['input']),\n reasoning: row['reasoning'] === true,\n api: typeof row['api'] === 'string' ? row['api'] : undefined,\n thinkingLevelMap: objectField(row, 'thinkingLevelMap') as Record<string, string | null> | undefined,\n compat: objectField(row, 'compat'),\n })\n }\n\n return {\n entries,\n warnings,\n version: typeof body['piAiVersion'] === 'string' ? body['piAiVersion'] : undefined,\n generatedAt: typeof body['generatedAt'] === 'string' ? body['generatedAt'] : undefined,\n }\n}\n\n/**\n * Fetch one JSON route, keeping a refusal distinguishable from an empty source.\n *\n * The distinction matters for the pi-ai half: \"the host ships no catalog\" and\n * \"the host's catalog could not be called\" both leave the list empty, but only\n * the second one has a fix, and the server names it in the refusal body.\n * @param url - the same-origin route.\n * @returns the parsed payload, or the reason it is missing.\n */\nasync function fetchJson(url: string): Promise<{ payload?: unknown; failure?: string }> {\n try {\n const response = await fetch(url)\n const payload: unknown = await response.json().catch(() => undefined)\n if (response.ok) return { payload }\n const message = typeof payload === 'object' && payload !== null\n ? (payload as Record<string, unknown>)['message']\n : undefined\n return { failure: typeof message === 'string' ? message : `HTTP ${String(response.status)}` }\n } catch (error) {\n return { failure: error instanceof Error ? error.message : String(error) }\n }\n}\n\n/**\n * The prefill index, fetched once per page load. Both sources are requested\n * together and either may come back empty; an entirely empty index is a\n * legitimate answer the caller renders as \"nothing to load yet\".\n * @returns the merged index.\n */\nexport async function getPrefillIndex(): Promise<PrefillIndex> {\n if (cachedIndex !== undefined) return cachedIndex\n\n const [piAiResult, modelsDevResult] = await Promise.all([fetchJson(PI_AI_URL), fetchJson(INDEX_URL)])\n const piAi = toPiAiEntries(piAiResult.payload)\n\n cachedIndex = {\n piAi: piAi.entries,\n modelsDev: toModelsDevEntries(normalize(modelsDevResult.payload)),\n piAiVersion: piAi.version,\n piAiGeneratedAt: piAi.generatedAt,\n piAiWarnings: piAi.warnings,\n ...(piAiResult.failure !== undefined ? { piAiFailure: piAiResult.failure } : {}),\n }\n return cachedIndex\n}\n\n/**\n * The one wire protocol one catalog provider's entries agree on.\n *\n * This mirrors the host's own `sharedCatalogApi`: a route whose installed\n * entries all speak the same protocol needs no `api` in configuration, because\n * the host resolves every model — including ones the catalog does not describe\n * — to that shared protocol. Reading it here is what lets the panel judge a\n * row's compat switches the way the adapter will. A provider whose entries\n * disagree (an OpenAI-style catalog spanning Responses and Chat Completions)\n * has no such answer, and neither does an index that has not loaded yet.\n * @param index - the fetched index, or undefined while the page still loads.\n * @param provider - the route key to inspect.\n * @returns the shared protocol, or undefined when none settles it.\n */\nexport function sharedCatalogApi(index: PrefillIndex | undefined, provider: string | undefined): string | undefined {\n if (index === undefined || provider === undefined || provider.length === 0) return undefined\n const apis = new Set<string>()\n for (const entry of index.piAi) {\n if (entry.provider !== provider || entry.api === undefined) continue\n apis.add(entry.api)\n }\n return apis.size === 1 ? [...apis][0] : undefined\n}\n\n/** The outcome of an explicit user-triggered download. */\nexport type MetadataDownload = { readonly ok: true } | { readonly ok: false; readonly message: string }\n\n/**\n * Download/refresh the models.dev file through the server half (user-triggered\n * from the title-row button). A success also refreshes the local cache.\n */\nexport async function downloadMetadata(): Promise<MetadataDownload> {\n try {\n const response = await fetch(DOWNLOAD_URL, { method: 'POST' })\n const body = await response.json().catch(() => undefined) as\n | { ok?: boolean; message?: string }\n | undefined\n if (!response.ok || body?.ok !== true) {\n return { ok: false, message: body?.message ?? `HTTP ${String(response.status)}` }\n }\n cachedIndex = undefined\n return { ok: true }\n } catch (error) {\n return { ok: false, message: error instanceof Error ? error.message : String(error) }\n }\n}\n\n/**\n * How many candidates the picker renders before it stops and reports the rest.\n *\n * Ten was too few once one id could arrive from a dozen providers; fifty shows\n * a vendor's catalog without pouring a 1354-row index into the DOM.\n */\nconst DEFAULT_PREFILL_LIMIT = 50\n\n/** How one prefill lookup is narrowed. */\nexport interface PrefillQuery {\n /** Which source to search; the picker always names exactly one. */\n readonly source: PrefillSource\n /** Restrict to one provider; blank means every provider in the source. */\n readonly provider?: string\n /** Model-id substring, case-insensitive; blank means every model. */\n readonly text?: string\n /** Maximum candidates to return; the caller reports the remainder. */\n readonly limit?: number\n}\n\n/** The candidates a lookup produced, plus how many matched in total. */\nexport interface PrefillHits {\n /** The candidates to render, capped at the query's limit. */\n readonly hits: readonly PrefillEntry[]\n /** Every match, so a capped list can say what it is hiding. */\n readonly total: number\n}\n\n/**\n * The providers a source offers, alphabetically.\n *\n * This is what turns \"which `glm-5.3-flash` did you mean?\" into a choice the\n * user can actually make: the same id ships under several providers, and each\n * provider's copy can carry different capacities and compat switches.\n * @param index - the fetched index, or undefined while the page still loads.\n * @param source - the source to enumerate.\n * @returns the provider names; empty when the source has none.\n */\nexport function providersOf(index: PrefillIndex | undefined, source: PrefillSource): readonly string[] {\n if (index === undefined) return []\n const entries = source === 'pi-ai' ? index.piAi : index.modelsDev\n const providers = new Set<string>()\n for (const entry of entries) {\n if (entry.provider !== undefined && entry.provider.length > 0) providers.add(entry.provider)\n }\n return [...providers].sort((a, b) => a.localeCompare(b))\n}\n\n/**\n * Candidates matching one source, one provider and one id substring.\n *\n * Either filter may be blank, and a blank one *widens* rather than matching\n * nothing: a provider with no id typed lists that provider's whole catalog,\n * which is how a user browses a vendor whose model names they have not\n * memorized. Both blank lists the source's first page.\n * @param index - the fetched index, or undefined while the page still loads.\n * @param query - the source, provider, id substring and cap.\n * @returns the capped candidates and the total match count.\n */\nexport function searchPrefill(\n index: PrefillIndex | undefined,\n query: PrefillQuery,\n): PrefillHits {\n if (index === undefined) return { hits: [], total: 0 }\n const entries = query.source === 'pi-ai' ? index.piAi : index.modelsDev\n const provider = query.provider?.trim() ?? ''\n const needle = query.text?.trim().toLowerCase() ?? ''\n const limit = query.limit ?? DEFAULT_PREFILL_LIMIT\n\n const hits: PrefillEntry[] = []\n let total = 0\n for (const entry of entries) {\n if (provider.length > 0 && entry.provider !== provider) continue\n if (needle.length > 0 && !entry.id.toLowerCase().includes(needle)) continue\n total += 1\n if (hits.length < limit) hits.push(entry)\n }\n return { hits, total }\n}\n","/**\n * Shared extension metadata: enums pinned to the host release this extension\n * was last verified against, and the extra locale keys the extension adds on\n * top of the official Models page dictionaries.\n */\n\n/** Thinking levels offered by llm-pi-ai (THINKING_LEVEL_GATE @ 0.1.2-alpha.4). Only `off` may carry an empty wire value. */\nexport const THINKING_LEVELS = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'] as const\nexport type ThinkingLevel = (typeof THINKING_LEVELS)[number]\n\n/** Input modalities accepted by llm-pi-ai (MODALITY_GATE @ 0.1.2-alpha.4). */\nexport const MODALITIES = ['text', 'image'] as const\nexport type Modality = (typeof MODALITIES)[number]\n\n/** Reasoning wire formats understood by llm-pi-ai (SUPPORTED_THINKING_FORMATS @ 0.1.2-alpha.4). */\nexport const THINKING_FORMATS = [\n 'openai',\n 'deepseek',\n 'openrouter',\n 'together',\n 'baseten',\n 'zai',\n 'qwen',\n 'chat-template',\n 'qwen-chat-template',\n 'string-thinking',\n 'ant-ling',\n] as const\nexport type ThinkingFormat = (typeof THINKING_FORMATS)[number]\n\n/**\n * The compatibility switches llm-pi-ai *offers*, by wire protocol (the `offer`\n * set of its COMPAT_GATES @ 0.1.5-rc.2). Only these may reach a model row: the\n * adapter refuses a switch no protocol offers rather than ignoring it, so\n * copying pi-ai's catalog `compat` across verbatim would fail resolution on\n * the withheld fields it also records (routing preferences, session affinity,\n * deferred tools, grammar tools). Re-check against the host's COMPAT_GATES on\n * every host upgrade — the same drift gate the host keeps for itself.\n */\nexport const COMPAT_FIELDS: Readonly<Record<string, readonly string[]>> = {\n 'openai-completions': [\n 'supportsStore',\n 'supportsDeveloperRole',\n 'supportsReasoningEffort',\n 'supportsUsageInStreaming',\n 'supportsFinishReason',\n 'maxTokensField',\n 'requiresToolResultName',\n 'requiresAssistantAfterToolResult',\n 'requiresThinkingAsText',\n 'requiresReasoningContentOnAssistantMessages',\n 'thinkingFormat',\n 'chatTemplateKwargs',\n 'chatTemplateArgs',\n 'supportsThinkingTokenBudget',\n 'thinkingTokenBudgetField',\n 'vllmPriority',\n 'supportsStrictMode',\n 'cacheControlFormat',\n 'supportsLongCacheRetention',\n ],\n 'openai-responses': [\n 'supportsDeveloperRole',\n 'supportsMaxOutputTokens',\n 'supportsStrictMode',\n 'supportsLongCacheRetention',\n ],\n 'azure-openai-responses': [\n 'supportsDeveloperRole',\n 'supportsMaxOutputTokens',\n 'supportsStrictMode',\n 'supportsLongCacheRetention',\n ],\n 'openai-codex-responses': [\n 'supportsDeveloperRole',\n 'supportsMaxOutputTokens',\n 'supportsStrictMode',\n 'supportsLongCacheRetention',\n ],\n 'anthropic-messages': [\n 'supportsEagerToolInputStreaming',\n 'supportsLongCacheRetention',\n 'supportsCacheControlOnTools',\n 'supportsTemperature',\n 'forceAdaptiveThinking',\n 'allowEmptySignature',\n 'supportsStrictTools',\n ],\n 'bedrock-converse-stream': ['supportsStrictMode'],\n}\n\n/**\n * Switches the base panel already renders a dedicated control for; the\n * \"other compatibility switches\" block lists everything else.\n */\nexport const COMPAT_BASE_FIELDS: readonly string[] = [\n 'supportsDeveloperRole',\n 'supportsReasoningEffort',\n 'thinkingFormat',\n]\n\n/**\n * The offered compat field names for one wire protocol.\n * @param api - the model's protocol, when known.\n * @returns the field names; empty for an unknown or absent protocol.\n */\nexport function offeredCompatFields(api: string | undefined): readonly string[] {\n if (api === undefined) return []\n const fields = COMPAT_FIELDS[api]\n return fields === undefined ? [] : fields\n}\n\n/**\n * Whether one protocol takes one compat switch.\n *\n * The adapter *refuses* a switch its protocol does not declare rather than\n * ignoring it, so this is the difference between a control that can be offered\n * and one that would fail the save. An unknown protocol takes nothing: its\n * field set cannot be read, and the adapter resolves it to the same refusal.\n * @param api - the model's wire protocol, when known.\n * @param field - the compat field name.\n * @returns true when the protocol offers the field.\n */\nexport function protocolOffers(api: string | undefined, field: string): boolean {\n return offeredCompatFields(api).includes(field)\n}\n\n/** Extra copy for the extension, keyed like the official dictionaries (en is authoritative). */\nexport const en = {\n // --- official Models-page keys the forked components still render -------\n nav: 'Models+',\n deepSeekAccount: 'DeepSeek Account',\n title: 'Models+',\n intro: 'Enter your API keys to use models from the following providers.',\n edit: 'Edit',\n editProvider: 'Edit {provider}',\n remove: 'Delete',\n removeProvider: 'Delete {provider}',\n deleteTitle: 'Delete {provider}?',\n deleteDescription: 'Deleting {provider} removes its configuration. Any credential it uses is managed elsewhere and will be kept.',\n deleteDescriptionWithCredential: 'Deleting {provider} removes its configuration and stored API key.',\n deleteConfirm: 'Delete {provider}',\n deleting: 'Deleting {provider}…',\n add: 'Add provider',\n provider: 'Provider',\n close: 'Close',\n cancel: 'Cancel',\n apply: 'Apply',\n applying: 'Applying…',\n savedProvider: 'Saved {provider}.',\n credentialConfigured: 'API key configured',\n credentialMissing: 'API key missing',\n readOnly: 'The settings document is read-only in this deployment.',\n loadFailed: 'Loading the provider directory failed',\n conflict: 'Someone else changed these settings while this card was open. Close it and reopen to edit the current values.',\n retry: 'Retry',\n keyInput: 'API key',\n keyPlaceholder: 'Enter your API key',\n keyPlaceholderNative: 'Enter an API key, or leave blank to use environment authentication',\n keyStored: 'Configured — enter a new value to replace',\n keyEnvLocked: 'Provided by the launch environment (read-only)',\n customized: 'Customized settings',\n baseUrl: 'Base URL',\n baseUrlDefault: 'Provider default',\n models: 'Models',\n modelsInherited: 'Using the adapter defaults',\n modelsCustomized: 'Customized model catalog',\n resetModels: 'Restore defaults',\n model: 'Model',\n modelId: 'Model ID',\n modelName: 'Display name',\n modelNamePlaceholder: 'Uses the model ID when empty',\n contextWindow: 'Context window',\n contextWindowPlaceholder: 'Uses the provider default',\n maxTokens: 'Max output tokens',\n maxTokensPlaceholder: 'Uses the provider default',\n modelAdvanced: 'Capacities',\n addModel: 'Add model',\n removeModel: 'Delete model',\n modelsEmpty: 'No models will be shown in the selector. Unlisted IDs can still be sent directly.',\n keyBlank: 'Enter the API key, or leave the field empty to keep the stored one.',\n keyBlankNew: 'Enter the API key, or leave the field empty if this provider authenticates another way.',\n keyIllegalCharacters: 'This API key is not in a valid format. Please check it.',\n modelIdRequired: 'Model ID is required.',\n modelIdDuplicate: 'Model ID must be unique.',\n modelNameInvalid: 'Display name cannot be empty.',\n modelContextInvalid: 'Context window must be a positive count, like 131072, 256K, or 1M.',\n modelMaxTokensInvalid: 'Max output tokens must be a positive count, like 8192, 64K, or 1M.',\n advancedHint: 'Other fields live in settings.yaml; edit that section directly.',\n modelCapacityInvalid: 'A capacity must be a number, optionally suffixed K or M.',\n modelDuplicate: 'Each model ID may appear once.',\n modelContextWindow: 'Context window',\n modelMaxTokens: 'Max output tokens',\n fetchModels: 'Fetch available models',\n fetching: 'Asking the provider…',\n fetchNeedsBaseUrl: 'Enter the base URL first, then fetch.',\n fetchEmpty: 'The provider listed no models. Add them by hand.',\n fetchTitle: 'Choose models to add',\n fetchDescription: 'These are the models this provider has available. Choose the ones to add.',\n fetchSelectAll: 'Select all',\n fetchDeselectAll: 'Deselect all',\n fetchAdopt: 'Add selected',\n customAdd: 'Add a custom provider',\n customTitle: 'Custom provider',\n customTag: 'Custom',\n customRoute: 'Provider ID',\n customRouteHint: 'Lowercase identifier, starting with a letter, that uniquely names this provider in requests and as its credential name.',\n customRouteInvalid: 'Start with a lowercase letter; then lowercase letters, digits, and dashes.',\n customRouteTaken: 'A provider already uses this ID.',\n customDisplayName: 'Display name',\n customApi: 'API protocol',\n customApiUnset: 'Not selected',\n customNeedsBaseUrl: 'A custom provider needs a base URL.',\n customBaseUrlInvalid: 'Enter a valid HTTP or HTTPS URL.',\n customNeedsModels: 'A custom provider needs at least one model.',\n customBaseUrlPlaceholder: 'https://gateway.example/v1',\n settingsPathUnresolvable: 'unresolvable settings path',\n create: 'Create provider',\n creating: 'Creating…',\n onboardingTitle: 'Add an API key to get started',\n onboardingDescription: 'Configure the official DeepSeek provider to start building.',\n onboardingLater: 'Configure later',\n onboardingSave: 'Save and continue',\n onboardingSaving: 'Saving…',\n keyRequired: 'Enter an API key to continue.',\n\n // --- extension-only keys ------------------------------------------------\n extDeclare: 'Declared',\n extSection: 'Model extensions',\n extSectionHint: 'Extra per-model fields that live in settings.yaml.',\n supportsReasoningEffort: 'Endpoint accepts reasoning effort',\n supportsDeveloperRole: 'System prompt may use the developer role',\n supportsDeveloperRoleHint: 'Reasoning-model system prompts go out as \"developer\"; uncheck to keep \"system\" for gateways that reject it.',\n reasoningEfforts: 'Reasoning efforts',\n reasoningEffortLevel: 'Level',\n reasoningEffortWire: 'Wire value',\n reasoningEffortOffHint: '\"off\" takes no wire value.',\n reasoningEffortEmptyWire: 'A checked level other than \"off\" needs a wire value.',\n reasoningEffortsNeedNonOff: 'Declare at least one level beyond \"off\".',\n inputModalities: 'Input modalities',\n inputNeedOne: 'Keep at least one modality checked.',\n thinkingFormat: 'Thinking format',\n} as const\n\nexport type ExtensionKey = keyof typeof en\n\n/** Chinese strings — same key set as {@link en}. */\nexport const zh: { [K in ExtensionKey]: string } = {\n // --- official Models-page keys (upstream zh values) ----------------------\n nav: '模型+',\n deepSeekAccount: 'DeepSeek 账号',\n title: '模型+',\n intro: '填入各提供方的 API 密钥即可使用其模型。',\n edit: '编辑',\n editProvider: '编辑 {provider}',\n remove: '删除',\n removeProvider: '删除 {provider}',\n deleteTitle: '删除 {provider}?',\n deleteDescription: '删除 {provider} 会移除其配置;其使用的凭证(如有)由其他位置管理,将会保留。',\n deleteDescriptionWithCredential: '删除 {provider} 会移除其配置和存储的 API 密钥。',\n deleteConfirm: '删除 {provider}',\n deleting: '正在删除 {provider}…',\n add: '添加提供方',\n provider: '提供方',\n close: '关闭',\n cancel: '取消',\n apply: '保存',\n applying: '保存中…',\n savedProvider: '已保存 {provider}。',\n credentialConfigured: 'API 密钥已配置',\n credentialMissing: 'API 密钥缺失',\n readOnly: '当前部署的设置文档为只读。',\n loadFailed: '加载提供方目录失败',\n conflict: '这张卡片打开期间,这些设置已被其他地方改动。请关闭后重新打开,在当前值上编辑。',\n retry: '重试',\n keyInput: 'API 密钥',\n keyPlaceholder: '输入 API 密钥',\n keyPlaceholderNative: '输入 API 密钥,或留空使用环境认证',\n keyStored: '已配置——输入新值可替换',\n keyEnvLocked: '由启动环境提供(只读)',\n customized: '自定义设置',\n baseUrl: 'API 地址',\n baseUrlDefault: '提供方默认',\n models: '模型目录',\n modelsInherited: '正在使用适配器默认模型',\n modelsCustomized: '已自定义模型目录',\n resetModels: '恢复默认模型',\n model: '模型',\n modelId: '模型 ID',\n modelName: '显示名称',\n modelNamePlaceholder: '留空时使用模型 ID',\n contextWindow: '上下文窗口',\n contextWindowPlaceholder: '使用提供方默认值',\n maxTokens: '最大输出 token 数',\n maxTokensPlaceholder: '使用提供方默认值',\n modelAdvanced: '容量',\n addModel: '添加模型',\n removeModel: '删除模型',\n modelsEmpty: '模型选择器中将不显示任何模型;目录外 ID 仍可直接发送。',\n keyBlank: '请输入 API 密钥;留空则保持已存储的密钥。',\n keyBlankNew: '请输入 API 密钥;若该提供方以其他方式鉴权,可以留空。',\n keyIllegalCharacters: '此 API 密钥格式无效,请检查。',\n modelIdRequired: '模型 ID 必填。',\n modelIdDuplicate: '模型 ID 不能重复。',\n modelNameInvalid: '显示名称不能为空。',\n modelContextInvalid: '上下文窗口须为正数,如 131072、256K、1M。',\n modelMaxTokensInvalid: '最大输出 token 数须为正数,如 8192、64K、1M。',\n advancedHint: '其余字段存于 settings.yaml;请直接编辑该节。',\n modelCapacityInvalid: '容量须为数字,可带 K 或 M 后缀。',\n modelDuplicate: '每个模型 ID 只能出现一次。',\n modelContextWindow: '上下文窗口',\n modelMaxTokens: '最大输出 token 数',\n fetchModels: '获取可用模型',\n fetching: '正在询问提供方…',\n fetchNeedsBaseUrl: '请先填写 API 地址再获取。',\n fetchEmpty: '该提供方未列出任何模型,请手动添加。',\n fetchTitle: '选择要添加的模型',\n fetchDescription: '这些是该提供方可用的模型,选择要添加的项。',\n fetchSelectAll: '全选',\n fetchDeselectAll: '取消全选',\n fetchAdopt: '添加所选',\n customAdd: '添加自定义提供方',\n customTitle: '自定义提供方',\n customTag: '自定义',\n customRoute: '提供方 ID',\n customRouteHint: '小写字母开头的唯一标识符,用于请求与凭证命名。',\n customRouteInvalid: '以小写字母开头;其后为小写字母、数字和短横线。',\n customRouteTaken: '已有提供方使用此 ID。',\n customDisplayName: '显示名称',\n customApi: 'API 协议',\n customApiUnset: '未选择',\n customNeedsBaseUrl: '自定义提供方需要 API 地址。',\n customBaseUrlInvalid: '请输入有效的 HTTP 或 HTTPS 地址。',\n customNeedsModels: '自定义提供方至少需要一个模型。',\n customBaseUrlPlaceholder: 'https://gateway.example/v1',\n settingsPathUnresolvable: '无法解析设置路径',\n create: '创建提供方',\n creating: '创建中…',\n onboardingTitle: '先添加一个 API 密钥即可开始',\n onboardingDescription: '配置官方 DeepSeek 提供方以开始构建。',\n onboardingLater: '稍后配置',\n onboardingSave: '保存并继续',\n onboardingSaving: '保存中…',\n keyRequired: '请输入 API 密钥以继续。',\n\n // --- extension-only keys ------------------------------------------------\n extDeclare: '声明',\n extSection: '模型扩展',\n extSectionHint: 'settings.yaml 中按模型生效的扩展字段。',\n supportsReasoningEffort: '端点接受推理挡位参数(reasoning_effort)',\n supportsDeveloperRole: '允许以 developer 角色发送系统提示',\n supportsDeveloperRoleHint: '推理模型的系统提示将以 developer 角色发出;网关拒绝该角色时取消勾选,改用 system。',\n reasoningEfforts: '推理挡位',\n reasoningEffortLevel: '挡位',\n reasoningEffortWire: '线上取值',\n reasoningEffortOffHint: '“off”不需要线上取值。',\n reasoningEffortEmptyWire: '除 off 外勾选的挡位必须填写线上取值。',\n reasoningEffortsNeedNonOff: '至少声明一个 off 以外的挡位。',\n inputModalities: '输入模态',\n inputNeedOne: '至少保留一个模态。',\n thinkingFormat: '思考格式',\n}\n","/**\n * Pure helpers copied from the host's ui-settings-models UI component files\n * (they live inside components there, so they cannot be inlined as standalone\n * modules like operations/store/schema-operations are).\n *\n * ⚠️ Fork-copy risk: these must be re-checked against the pinned host sources\n * (packages/client/ui-settings-models/src/client/{ProviderEditor,DeepSeekModelsEditor}.tsx\n * — last verified unchanged @ 0.1.7-rc.2) on every host upgrade.\n */\n\n/** One model entry kept structurally open so hidden or future fields survive an edit. */\nexport type ModelDraft = Record<string, unknown>\n\n// ---------------------------------------------------------------------------\n// pathOps — copied from ProviderEditor.tsx @ 0.1.5-rc.1\n// ---------------------------------------------------------------------------\n\nimport type { JsonValue } from '@deepseek-ai/dsh-util-values'\nimport type { SettingsPathOpView } from '@deepseek-ai/dsh-api-remotes/client'\nimport { offeredCompatFields, protocolOffers } from '../extension-meta.ts'\n\n/**\n * The minimal path ops carrying `after` over `before`, both as the card sees\n * them. Only keys the card observed are named; fields absent from both sides\n * produce no op, which is why edits are path-addressed rather than a rebuilt\n * section.\n * @param base - path of the edited subtree inside the user section.\n * @param before - the subtree as loaded, or undefined when it is new.\n * @param after - the subtree as edited.\n * @returns ordered set/unset ops; empty when nothing changed.\n */\nexport function pathOps(\n base: readonly string[],\n before: unknown,\n after: Record<string, unknown>,\n): SettingsPathOpView[] {\n const previous = typeof before === 'object' && before !== null && !Array.isArray(before)\n ? before as Record<string, unknown>\n : {}\n const ops: SettingsPathOpView[] = []\n for (const [key, value] of Object.entries(after)) {\n if (JSON.stringify(previous[key]) === JSON.stringify(value)) continue\n ops.push({ op: 'set', path: [...base, key], value: value as JsonValue })\n }\n for (const key of Object.keys(previous)) {\n if (!(key in after)) ops.push({ op: 'unset', path: [...base, key] })\n }\n return ops\n}\n\n// ---------------------------------------------------------------------------\n// capacity parsing/formatting — copied from DeepSeekModelsEditor.tsx @ 0.1.5-rc.1\n// ---------------------------------------------------------------------------\n\n/** Accepted capacity spellings: a decimal count with an optional K/M suffix. */\nconst CAPACITY_PATTERN = /^(\\d+(?:\\.\\d+)?)([km])?$/i\n\n/** Decimal suffix scales — `1M` is 1000K, matching how model capacities are quoted. */\nconst CAPACITY_SCALE = { k: 1_000, m: 1_000_000 } as const\n\n/**\n * Read a typed capacity, so a user can write `256K` or `1M` instead of counting\n * zeroes. The stored value stays a plain token count.\n * @param text - raw field text.\n * @returns the count; `undefined` when blank (inherit), `NaN` when unreadable\n * (rejected by {@link validateModelRows} before any write).\n */\nexport function parseCapacity(text: string): number | undefined {\n const trimmed = text.trim()\n if (trimmed.length === 0) return undefined\n const match = CAPACITY_PATTERN.exec(trimmed)\n if (match === null) return Number.NaN\n const suffix = match[2]?.toLowerCase()\n const scale = suffix === 'k' || suffix === 'm' ? CAPACITY_SCALE[suffix] : 1\n const scaled = Number(match[1]) * scale\n // A decimal multiple is exact in intent but not in binary floating point\n // (2.3 * 1e6 lands a few ULPs high), so an integral intent snaps back.\n const rounded = Math.round(scaled)\n return Math.abs(scaled - rounded) < 1e-6 ? rounded : scaled\n}\n\n/**\n * Spell a stored count back in the shortest form that survives a round trip\n * through {@link parseCapacity}; a count that is not a whole number of\n * thousands stays written out.\n * @param value - stored capacity.\n * @returns the field text.\n */\nexport function formatCapacity(value: number): string {\n if (!Number.isInteger(value) || value <= 0) return String(value)\n if (value % CAPACITY_SCALE.m === 0) return `${String(value / CAPACITY_SCALE.m)}M`\n if (value % CAPACITY_SCALE.k === 0) return `${String(value / CAPACITY_SCALE.k)}K`\n return String(value)\n}\n\n// ---------------------------------------------------------------------------\n// model-row validation — copied from DeepSeekModelsEditor.tsx @ 0.1.5-rc.1\n// ---------------------------------------------------------------------------\n\n/** A localized validation failure for one user-owned model array. */\nexport interface ModelRowsValidationFailure {\n /** Zero-based model position. */\n index: number\n /** Message key owned by the Models+ dictionary. */\n key: 'modelIdRequired' | 'modelIdDuplicate' | 'modelNameInvalid' | 'modelContextInvalid'\n | 'modelMaxTokensInvalid' | 'modelCompatNotOffered'\n /** For `modelCompatNotOffered`: the switch the protocol refuses. */\n field?: string\n /** For `modelCompatNotOffered`: the protocol the row resolves to. */\n api?: string\n /** For `modelCompatNotOffered`: the switches that protocol does take. */\n offered?: readonly string[]\n}\n\n/** Convert a schema-validated catalog value into records without dropping hidden fields. */\nexport function modelDrafts(value: unknown): ModelDraft[] {\n if (!Array.isArray(value)) return []\n return value.map(entry =>\n typeof entry === 'object' && entry !== null && !Array.isArray(entry)\n ? entry as ModelDraft\n : {})\n}\n\n// ---------------------------------------------------------------------------\n// row key-order normalization (plugin addition, v1.0.0: stable YAML key order)\n// ---------------------------------------------------------------------------\n\n/** Canonical key order for one models[] row (plugin-known fields first). */\nconst ROW_KEY_ORDER = ['id', 'name', 'contextWindow', 'maxTokens', 'input', 'reasoningEfforts', 'compat']\n\n/** Canonical key order for the row's compat sub-object. */\nconst COMPAT_KEY_ORDER = ['supportsDeveloperRole', 'supportsReasoningEffort', 'thinkingFormat']\n\n/**\n * Re-key one model row into the canonical order (plugin-known fields in\n * order, unknown/future fields kept at the tail so nothing is dropped).\n * YAML emits keys in object insertion order, and interactive edits append\n * keys at the tail — without this, rows saved after quick-load or gated-key\n * removals come out with scrambled key orders (purely cosmetic, but noisy\n * in settings.yaml diffs).\n * @param row - the drafted row.\n * @returns the re-keyed row (shallow copy).\n */\nexport function normalizeModelRow(row: ModelDraft): ModelDraft {\n const next: ModelDraft = {}\n for (const key of ROW_KEY_ORDER) {\n if (key in row) next[key] = row[key]\n }\n for (const key of Object.keys(row)) {\n if (!ROW_KEY_ORDER.includes(key)) next[key] = row[key]\n }\n const compat = next['compat']\n if (typeof compat === 'object' && compat !== null && !Array.isArray(compat)) {\n const source = compat as Record<string, unknown>\n const normalized: Record<string, unknown> = {}\n for (const key of COMPAT_KEY_ORDER) {\n if (key in source) normalized[key] = source[key]\n }\n for (const key of Object.keys(source)) {\n if (!COMPAT_KEY_ORDER.includes(key)) normalized[key] = source[key]\n }\n next['compat'] = normalized\n }\n return next\n}\n\n/**\n * The message for a refused compat switch, shared by both provider cards so the\n * same failure reads the same way wherever it is hit.\n * @param failure - a `modelCompatNotOffered` failure from {@link validateModelRows}.\n * @returns the localised sentence.\n */\nexport function compatFailureMessage(failure: ModelRowsValidationFailure): string {\n const offered = failure.offered ?? []\n const available = offered.length === 0\n ? ',该协议不接受任何可配置开关'\n : `,该协议可用:${offered.join('、')}`\n return `模型 ${String(failure.index + 1)}:compat 开关 ${String(failure.field)} 不适用于当前协议`\n + `(${String(failure.api)})${available}。请在展开的「其他兼容开关」中清空该项以移除,`\n + '或回到供应商页把协议改成端点真正使用的协议。'\n}\n\n/**\n * Validate adapter constraints that the serialized schema cannot express.\n *\n * The compat half of the check exists because the adapter *refuses* a switch a\n * model's protocol does not declare rather than ignoring it — and the protocol\n * a row resolves to is `route.api` first, the installed catalog entry second.\n * A row can therefore hold switches that were legal when it was written (a\n * protocol change on the route, or a prefill taken from another protocol's\n * catalog entry) and only fail at save time, in English, from the host. This\n * turns that into a positioned, named, localised refusal.\n *\n * An unknown protocol is skipped on purpose: the route's protocol could not be\n * resolved, so the row's real one is unknowable here, and a guess would refuse\n * a configuration the host accepts. The host's own diagnostic still covers it.\n * @param value - user-owned `models` value, or undefined while inherited.\n * @param api - the protocol every row resolves to, when the route settles one.\n * @returns the first invalid row, or undefined when the adapter will accept it.\n */\nexport function validateModelRows(value: unknown, api?: string): ModelRowsValidationFailure | undefined {\n if (value === undefined) return undefined\n const models = modelDrafts(value)\n const seen = new Set<string>()\n for (const [index, model] of models.entries()) {\n // Compared trimmed: surrounding whitespace is a paste artifact the adapter\n // would never match, and an untrimmed compare lets `model ` slip past the\n // duplicate check against its own twin.\n const id = model['id']\n const trimmed = typeof id === 'string' ? id.trim() : undefined\n if (trimmed === undefined || trimmed.length === 0) return { index, key: 'modelIdRequired' }\n if (seen.has(trimmed)) return { index, key: 'modelIdDuplicate' }\n seen.add(trimmed)\n const name = model['name']\n if (name !== undefined && (typeof name !== 'string' || name.length === 0)) {\n return { index, key: 'modelNameInvalid' }\n }\n const contextWindow = model['contextWindow']\n if (contextWindow !== undefined\n && (typeof contextWindow !== 'number' || !Number.isInteger(contextWindow) || contextWindow <= 0)) {\n return { index, key: 'modelContextInvalid' }\n }\n const maxTokens = model['maxTokens']\n if (maxTokens !== undefined\n && (typeof maxTokens !== 'number' || !Number.isInteger(maxTokens) || maxTokens <= 0)) {\n return { index, key: 'modelMaxTokensInvalid' }\n }\n const compat = model['compat']\n if (api !== undefined && typeof compat === 'object' && compat !== null && !Array.isArray(compat)) {\n for (const field of Object.keys(compat)) {\n if (protocolOffers(api, field)) continue\n return { index, key: 'modelCompatNotOffered', field, api, offered: offeredCompatFields(api) }\n }\n }\n }\n return undefined\n}\n","/**\n * Draft defaults for a NEW model row (added by hand or adopted from a fetch),\n * per the v1.0.0 plan: reasoning effort ON with every level declared, thinking\n * format `openai`, both input modalities checked. These are draft seeds that\n * land in settings.yaml when the row is saved — they are not inherited-state\n * sentinels, except `supportsDeveloperRole`, which stays UNWRITTEN (its\n * tri-state reads an absent key as checked, so only an explicit user uncheck\n * ever writes `false`).\n *\n * The compat half of the seed is PROTOCOL-DEPENDENT, and that is load-bearing:\n * `supportsReasoningEffort` and `thinkingFormat` belong to `openai-completions`\n * alone, and the adapter refuses a switch its protocol does not declare rather\n * than ignoring it. Seeding them onto an `anthropic-messages` route — which is\n * what a fixed vocabulary here did — made every hand-added model on such a\n * route fail the save over a switch the user never wrote. So the seed asks\n * {@link protocolOffers} first and writes nothing its protocol would refuse.\n * `reasoningEfforts` is unaffected: the levels travel through each protocol's\n * own thinking parameter, so every protocol takes them.\n */\n\nimport { protocolOffers } from '../extension-meta.ts'\nimport type { ModelDraft } from './compat.ts'\n\n/** The tri-state `compat.supportsDeveloperRole` seed: absent (reads checked). */\nconst DEVELOPER_ROLE_SEED: Record<string, unknown> = {}\n\n/**\n * Draft seed for one new model row.\n *\n * An UNKNOWN protocol (no route-level `api`, and the installed catalog does not\n * describe the route) seeds no compat at all: nothing can say which switches\n * its endpoint would take, and a guessed `supportsReasoningEffort` on an\n * Anthropic-shaped route is refused rather than dropped. The levels stay seeded\n * — they are protocol-independent — so the row still opens with its effort\n * table populated.\n * @param api - the wire protocol this row will resolve to, when known.\n * @returns the draft row.\n */\nexport function newModelDraft(api?: string): ModelDraft {\n const compat: Record<string, unknown> = { ...DEVELOPER_ROLE_SEED }\n if (protocolOffers(api, 'supportsReasoningEffort')) compat['supportsReasoningEffort'] = true\n if (protocolOffers(api, 'thinkingFormat')) compat['thinkingFormat'] = 'openai'\n return {\n id: '',\n input: ['text', 'image'],\n reasoningEfforts: {\n off: null,\n minimal: 'minimal',\n low: 'low',\n medium: 'medium',\n high: 'high',\n xhigh: 'xhigh',\n max: 'max',\n },\n ...Object.keys(compat).length === 0 ? {} : { compat },\n }\n}\n","/**\n * Mapping pi-ai catalog values onto a Models+ row.\n *\n * The two sides describe the same thing, but two conventions differ in a way\n * that makes a straight copy wrong:\n *\n * 1. **`null` means the opposite in each.** pi-ai's `thinkingLevelMap[level]`\n * is *unsupported* when null; our `reasoningEfforts[level]` is *supported,\n * send nothing* when null (the adapter then drops the key entirely, and\n * pi-ai reads an absent `off` key as \"supported but send no parameter\").\n * Copying one across would invert the meaning for 338 of the catalog's\n * models, so values are mapped rather than copied: a pi-ai `null` becomes\n * \"omit our key\", and an absent pi-ai key becomes an explicit entry.\n * 2. **An absent base level has a protocol-specific default.** pi-ai resolves\n * an absent `off`/`minimal`/`low`/`medium`/`high` by falling back to the\n * level name — except on the Anthropic protocols, where `minimal` collapses\n * onto `low`, and on Mistral, where every level resolves to `high`. Writing\n * the level name there would send a spelling those providers never see.\n *\n * `xhigh` and `max` are the one pair pi-ai treats as unsupported when absent,\n * so they are only written when the catalog declares them.\n *\n * @module dsh-model-extension/prefill\n */\n\nimport { offeredCompatFields } from '../extension-meta.ts'\n\n/** The seven levels, in pi-ai's escalation order. */\nconst LEVELS: readonly string[] = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max']\n\n/**\n * The wire spelling pi-ai falls back to for one absent base level, per\n * protocol. This mirrors the fallbacks inside pi-ai's own dispatch branches.\n * @param api - the model's wire protocol.\n * @param level - the level whose key was absent.\n * @returns the spelling pi-ai would send for that level.\n */\nexport function defaultWireSpelling(api: string | undefined, level: string): string {\n // anthropic-messages: mapThinkingLevelToEffort collapses minimal onto low and\n // passes the rest through. bedrock shares the mapper.\n if (api === 'anthropic-messages' || api === 'bedrock-converse-stream') {\n return level === 'minimal' ? 'low' : level\n }\n // mistral-conversations: mapReasoningEffort ends in `?? \"high\"`.\n if (api === 'mistral-conversations') return 'high'\n return level\n}\n\n/**\n * Convert a catalog `thinkingLevelMap` into our `reasoningEfforts` dict.\n *\n * A model that does not reason gets `false`. An outcome that offers nothing\n * beyond `off` also becomes `false`, because the adapter rejects a dict whose\n * only level is `off` — and the two describe the same request anyway.\n * @param levelMap - the catalog's map, when it carries one.\n * @param api - the model's wire protocol, which picks the fallback spellings.\n * @param reasoning - whether the model reasons at all.\n * @returns the dict to write into the row, or `false` for a non-reasoning model.\n */\nexport function reasoningEffortsFrom(\n levelMap: Readonly<Record<string, string | null>> | undefined,\n api: string | undefined,\n reasoning: boolean,\n): Record<string, string | null> | false {\n if (!reasoning) return false\n\n const map = levelMap ?? {}\n const efforts: Record<string, string | null> = {}\n for (const level of LEVELS) {\n if (!(level in map)) {\n if (level === 'off') {\n // Absent `off` is pi-ai's \"supported, send nothing\"; our spelling of\n // that is an explicit null, which the adapter drops before handing the\n // map over.\n efforts[level] = null\n continue\n }\n if (level === 'xhigh' || level === 'max') continue\n efforts[level] = defaultWireSpelling(api, level)\n continue\n }\n const wire = map[level]\n // pi-ai's null means unsupported, so the key is simply left out.\n if (wire === null) continue\n efforts[level] = wire\n }\n\n const beyondOff = Object.keys(efforts).some(level => level !== 'off')\n return beyondOff ? efforts : false\n}\n\n/**\n * Project a catalog `compat` block onto the switches the host offers for one\n * protocol.\n *\n * The filter is load-bearing twice over. It drops pi-ai's withheld switches\n * (routing preferences, session affinity, deferred tools, grammar tools), which\n * the adapter *refuses* rather than ignores — a verbatim copy would make the\n * route fail to resolve. And it filters by the protocol the row will be JUDGED\n * by, which is not always the catalog entry's own: a hand-declared route states\n * its `api`, that value overrides the catalog for every model on the route, and\n * a block taken from another protocol's entry (`supportsStore` on a gateway\n * that speaks `anthropic-messages`) is refused at save time.\n * @param compat - the catalog's compat record, when it carries one.\n * @param api - the protocol the row resolves to, as the adapter resolves it.\n * @returns the writable subset; empty when nothing survives.\n */\nexport function compatFrom(\n compat: Readonly<Record<string, unknown>> | undefined,\n api: string | undefined,\n): Record<string, unknown> {\n const offered = offeredCompatFields(api)\n if (offered.length === 0 || compat === undefined) return {}\n const next: Record<string, unknown> = {}\n for (const field of offered) {\n if (field in compat) next[field] = compat[field]\n }\n return next\n}\n","/* models-plus styles — the official ModelsSection.module.css classes (as\n * transcribed and verified in docs/models-settings-demo.html) plus the\n * extension-block styles, all on --dsw-alias tokens. */\n\n.section { display: flex; flex-direction: column; gap: 12px; max-width: 720px; color: var(--dsw-alias-label-primary); }\n.titleRow { display: flex; align-items: center; gap: 10px; }\n.title { margin: 0; font-size: 16px; line-height: 24px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n.intro { margin: 0; font-size: 14px; line-height: 22px; color: var(--dsw-alias-label-tertiary); }\n.savedNotice { margin: 0; font-size: 12px; line-height: 18px; color: var(--dsw-alias-state-success-primary); }\n.error { margin: 0; font-size: 12px; line-height: 18px; color: var(--dsw-alias-state-error-primary); }\n\n.rows { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }\n.rowCard { border: 0.5px solid var(--dsw-alias-border-l4); border-radius: 16px; padding: 12px 14px; display: flex; flex-direction: column; gap: 12px; }\n.rowHead { display: flex; align-items: center; gap: 10px; }\n.rowIdentity { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }\n.rowName { font-size: 14px; line-height: 22px; font-weight: 500; color: var(--dsw-alias-label-primary); }\n.rowTag { flex: none; padding: 1px 6px; border: 0.5px solid var(--dsw-alias-border-l3); border-radius: 4px; font-size: 11px; line-height: 16px; color: var(--dsw-alias-label-secondary); }\n.credentialDot { box-sizing: border-box; display: inline-block; flex: none; width: 8px; height: 8px; border-radius: 50%; }\n.credentialDotConfigured { background: var(--dsw-alias-state-success-primary); }\n.credentialDotMissing { background: var(--dsw-alias-state-error-primary); }\n.rowActions { display: inline-flex; align-items: center; gap: 4px; margin-left: auto; }\n\n.primaryButton, .secondaryButton, .addButton { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; gap: 4px; height: 36px; padding: 0 14px; border: none; border-radius: 18px; font: inherit; font-size: 14px; line-height: 22px; cursor: pointer; }\n.primaryButton { background: var(--dsw-alias-button-primary-fill); color: var(--dsw-alias-label-primary-foreground); }\n.primaryButton:hover:not(:disabled) { background: var(--dsw-alias-button-primary-hover); }\n.secondaryButton, .addButton { border: 0.5px solid var(--dsw-alias-border-l3); background: transparent; color: var(--dsw-alias-label-primary); }\n.secondaryButton:hover:not(:disabled), .addButton:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }\n.secondaryButton:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover-solid); }\n.dangerButton { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; height: 36px; padding: 0 14px; border: none; border-radius: 18px; background: transparent; color: var(--dsw-alias-state-error-primary); font: inherit; font-size: 14px; line-height: 22px; cursor: pointer; }\n.dangerButton:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover-danger); }\n.rowActions .secondaryButton, .rowActions .dangerButton { height: 28px; padding: 0 10px; border-radius: 14px; font-size: 12px; line-height: 18px; }\n.primaryButton:disabled, .secondaryButton:disabled, .dangerButton:disabled, .addButton:disabled, .linkButton:disabled, .addModelButton:disabled { opacity: 0.4; cursor: default; }\n.primaryButton:focus-visible, .secondaryButton:focus-visible, .dangerButton:focus-visible, .addButton:focus-visible, .linkButton:focus-visible, .addModelButton:focus-visible, .iconButton:focus-visible, .customizedSummary:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--dsw-alias-border-l3); }\n\n.editor { border-radius: 12px; background: var(--dsw-alias-bg-module-platform); padding: 14px 16px; display: flex; flex-direction: column; gap: 14px; }\n.field { display: flex; flex-direction: column; gap: 6px; }\n.fieldLabel { display: inline-flex; align-items: center; gap: 10px; font-size: 12px; line-height: 18px; font-weight: 500; color: var(--dsw-alias-label-secondary); }\n.linkButton { box-sizing: border-box; display: inline-flex; align-items: center; height: 28px; padding: 0 10px; border: none; border-radius: 14px; background: transparent; color: var(--dsw-alias-label-tertiary); font: inherit; font-size: 12px; line-height: 18px; cursor: pointer; }\n.linkButton:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); color: var(--dsw-alias-label-secondary); }\n.advancedHint { margin: 0; font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n.editorActions { display: flex; justify-content: flex-end; gap: 8px; }\n\n.addBlock { display: flex; flex-direction: column; gap: 12px; }\n.addActions { display: flex; flex-wrap: wrap; gap: 10px; }\n.addButton { flex: 1 1 0; min-width: 180px; gap: 6px; height: 44px; border: 1px dashed var(--dsw-alias-border-l3); border-radius: 16px; }\n.addCard { border-radius: 12px; background: var(--dsw-alias-bg-module-platform); padding: 14px 16px; display: flex; flex-direction: column; gap: 14px; list-style: none; }\n.addCard .editor, .setupCard .editor { background: none; padding: 0; }\n\n\n.tabs { display: flex; flex-direction: column; gap: 12px; }\n.tabBar { display: flex; gap: 4px; border-bottom: 0.5px solid var(--dsw-alias-border-l2); }\n.tabButton { appearance: none; border: none; background: transparent; padding: 6px 12px 8px; font: inherit; font-size: 13px; line-height: 20px; color: var(--dsw-alias-label-tertiary); cursor: pointer; position: relative; }\n.tabButton:hover { color: var(--dsw-alias-label-primary); }\n.tabButton:disabled { opacity: 0.4; cursor: default; }\n.tabButtonActive { color: var(--dsw-alias-label-primary); font-weight: 500; }\n.tabButtonActive::after { content: ''; position: absolute; left: 10px; right: 10px; bottom: -1px; height: 2px; border-radius: 2px; background: var(--dsw-alias-brand-primary); }\n.tabPanel { display: flex; flex-direction: column; gap: 12px; }\n.modelCatalog { display: flex; flex-direction: column; gap: 10px; }\n.modelCatalogHeading { display: flex; flex-direction: column; gap: 2px; }\n.modelCatalogTitle { font-size: 12px; line-height: 18px; font-weight: 500; color: var(--dsw-alias-label-secondary); }\n.modelCatalogMeta, .modelEmpty { margin: 0; color: var(--dsw-alias-label-tertiary); font-size: 12px; line-height: 18px; }\n.modelList { display: flex; flex-direction: column; gap: 8px; }\n.modelListHead { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }\n.modelEntry { border: 0.5px solid var(--dsw-alias-border-l4); border-radius: 10px; padding: 6px; }\n.modelRow { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) auto auto; align-items: center; gap: 6px; }\n.iconButton { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-tertiary); cursor: pointer; }\n.iconButton:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); color: var(--dsw-alias-label-primary); }\n.iconButton:disabled { cursor: default; opacity: 0.4; }\n.iconButtonDanger:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover-danger); color: var(--dsw-alias-state-error-primary); }\n.modelAdvanced { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 8px; padding: 8px 4px 2px; }\n.modelField { display: flex; flex-direction: column; gap: 4px; }\n.modelFieldLabel { color: var(--dsw-alias-label-tertiary); font-size: 12px; line-height: 18px; }\n.modelEmpty { padding: 12px; border: 1px dashed var(--dsw-alias-border-l3); border-radius: 8px; text-align: center; }\n.addModelButton { box-sizing: border-box; align-self: flex-start; display: inline-flex; align-items: center; gap: 4px; height: 28px; padding: 0 10px; border: 0.5px solid var(--dsw-alias-border-l3); border-radius: 14px; background: transparent; color: var(--dsw-alias-label-primary); font: inherit; font-size: 12px; line-height: 18px; cursor: pointer; }\n.addModelButton:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }\n\n.input { box-sizing: border-box; width: 100%; height: 32px; padding: 0 10px; border: 0.5px solid var(--dsw-alias-border-l4); border-radius: 8px; font: inherit; font-size: 14px; line-height: 22px; background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); }\nselect.input { max-width: 240px; cursor: pointer; }\n.input:focus { outline: none; border-color: var(--dsw-alias-brand-primary); }\n.input::placeholder { color: var(--dsw-alias-label-dimmed); }\n.input:disabled { opacity: 0.6; cursor: default; }\n.selectInput { appearance: none; padding-right: 32px; background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\"); background-repeat: no-repeat; background-position: right 12px center; background-size: 12px 12px; }\n\n.deleteDialog { width: min(480px, 100%); }\n.deleteConfirm:not(:disabled) { border-color: var(--dsw-alias-state-error-primary); color: var(--dsw-alias-state-error-primary); }\n.deleteConfirm:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover-danger); }\n\n.fetchDialog { max-width: 520px; }\n.candidateToolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }\n.candidateSearch { min-width: 0; flex: 1 1 240px; }\n.candidateList { display: flex; flex-direction: column; gap: 2px; max-height: 320px; margin: 0; overflow-y: auto; padding: 0; list-style: none; }\n.candidate { border-radius: 6px; }\n.candidateLabel { display: flex; align-items: center; gap: 8px; padding: 6px 8px; cursor: pointer; }\n.candidateId { flex: 1 1 auto; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; overflow-wrap: anywhere; }\n.candidateEmpty { margin: 24px 0; color: var(--dsw-alias-label-secondary); font-size: 13px; line-height: 20px; text-align: center; }\n\n/* ---- extension block (plugin-owned; official token palette) ---- */\n[hidden] { display: none !important; }\n.extBlock { border: 0.5px solid var(--dsw-alias-border-l3); border-radius: 10px; padding: 10px; margin: 8px 4px 2px; background: var(--dsw-alias-bg-layer-1); display: flex; flex-direction: column; gap: 10px; }\n.extGroup { border-top: 0.5px solid var(--dsw-alias-border-l2); padding-top: 12px; }\n.extGroupFirst { border-top: none; padding-top: 0; }\n.extCheck { display: flex; align-items: flex-start; gap: 8px; cursor: pointer; }\n.extCheckLabel { font-size: 14px; line-height: 22px; color: var(--dsw-alias-label-primary); }\n.extHint { font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n.extGated { display: flex; flex-direction: column; gap: 12px; padding-left: 2px; }\n.extField { display: flex; flex-direction: column; gap: 6px; }\n.extLabel { font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n.extTable { border: 0.5px solid var(--dsw-alias-border-l4); border-radius: 8px; overflow: hidden; }\n.extTHead { display: grid; grid-template-columns: 64px minmax(0,1fr) minmax(0,1.2fr); font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); background: var(--dsw-alias-bg-module-platform); }\n.extTHead > div { padding: 6px 10px; }\n.extTHead > div + div { border-left: 0.5px solid var(--dsw-alias-border-l2); }\n.extTRow { display: grid; grid-template-columns: 64px minmax(0,1fr) minmax(0,1.2fr); align-items: center; border-top: 0.5px solid var(--dsw-alias-border-l2); }\n.extTRow > div { padding: 6px 10px; font-size: 14px; }\n.extTRow > div + div { border-left: 0.5px solid var(--dsw-alias-border-l2); }\n.extTRow input[type=\"text\"] { box-sizing: border-box; width: 100%; height: 32px; padding: 0 10px; border: 0.5px solid var(--dsw-alias-border-l4); border-radius: 8px; font: inherit; font-size: 14px; background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-label-primary); }\n.extTRow input[type=\"text\"]:disabled { opacity: 0.6; cursor: default; }\n.extCheckbox { accent-color: var(--dsw-alias-brand-primary); width: 15px; height: 15px; flex: none; }\n.switchRow { display: flex; align-items: center; gap: 8px; font-size: 14px; line-height: 22px; cursor: pointer; }\n.extTag { flex: none; padding: 1px 6px; border: 0.5px solid rgba(65,118,230,0.35); border-radius: 4px; background: var(--dsw-static-deepseek-100); color: var(--dsw-static-deepseek-600); font-size: 11px; line-height: 16px; font-weight: 500; }\n\n/* ---- modal (matches the ui-primitives look closely enough for these two dialogs) ---- */\n.modalMask { position: fixed; inset: 0; background: var(--dsw-alias-bg-mask-1); display: flex; align-items: center; justify-content: center; z-index: 100; padding: 24px; }\n.modal { background: var(--dsw-specific-menu); border-radius: 16px; padding: 20px; width: 100%; box-shadow: 0 12px 40px rgba(0,0,0,0.18); }\n.modalTitle { font-size: 16px; line-height: 24px; font-weight: 500; margin-bottom: 8px; color: var(--dsw-alias-label-primary); }\n.modalDesc { font-size: 14px; line-height: 22px; color: var(--dsw-alias-label-secondary); margin-bottom: 16px; }\n.modalFoot { display: flex; justify-content: flex-end; gap: 8px; }\n\n/* ---- quick-load dropdown (filtered and capped, plugin-rendered for both the\n provider and the model list — never a native datalist, whose popup position\n and styling the page cannot control) ---- */\n.quickWrap { position: relative; display: flex; flex-direction: column; gap: 6px; }\n/* The candidate panel is an elevated surface over page content, so it takes the\n theme's own menu material plus the same filter the host pairs with it\n (docs/web-styling.md @ 0.1.7-rc.2: `--dsw-specific-menu` is a 58%-opaque fill\n and only reads as a surface when it blurs what is behind it). The hairline is\n the elevation shadow's first layer, not a border: the theme spec rejects a\n `--dsw-alias-border-*` border paired with an elevation shadow. */\n.quickList { position: absolute; top: 100%; left: 0; right: 0; z-index: 20; margin-top: 2px; padding: 4px; border: 0; border-radius: 8px; background: var(--dsw-specific-menu); backdrop-filter: var(--dsw-menu-backdrop-filter); --dsw-elevation-stroke-color: var(--dsw-alias-border-l1); box-shadow: var(--dsw-elevation-prominent); max-height: 264px; overflow-y: auto; }\n.quickItem { display: flex; flex-direction: column; gap: 1px; width: 100%; padding: 6px 8px; border: none; border-radius: 6px; background: transparent; color: var(--dsw-alias-label-primary); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; text-align: left; cursor: pointer; }\n.quickItemId { overflow-wrap: anywhere; }\n.quickItemApi { font-size: 11px; line-height: 14px; color: var(--dsw-alias-label-tertiary); letter-spacing: 0.2px; }\n.quickItem:hover { background: var(--dsw-alias-interactive-bg-hover); }\n.quickEmpty { padding: 6px 8px; font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }\n\n@media (prefers-reduced-motion: reduce) {\n .customizedSummary::before { transition: none; }\n}\n","/**\n * Quick-load: source → provider → model id, three narrowing steps.\n *\n * The single search box could not answer the question it raised. One model id\n * ships under a dozen providers (`glm-5.3-flash` exists in zai, opencode,\n * opencode-go, baseten, together, huggingface and two gateways), and each\n * provider's copy can carry different capacities and compat switches — so a\n * flat list of ten same-looking ids left the user to pick blind, or to decode\n * a suffix the plugin had appended for want of a better idea.\n *\n * Splitting the axis fixes it at the source: the user states *which catalog*\n * and *whose copy* first, and the id search then runs inside that slice.\n *\n * Both drop-downs are plugin-rendered rather than native. A `<datalist>` was\n * tried for the provider field and abandoned: the browser positions its popup\n * itself (it opened across unrelated fields) and none of it is themeable, so\n * it could not look like the list beside it. One `quickList` now serves both,\n * which also keeps only one popup on screen at a time.\n */\n\nimport { useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport { getPrefillIndex, providersOf, searchPrefill } from './models-index.ts'\nimport type { PrefillEntry, PrefillIndex, PrefillSource } from './models-index.ts'\nimport styles from './models-plus.module.css'\n\n/** Props of {@link QuickLoad}. */\nexport interface QuickLoadProps {\n /** Apply one prefill candidate to the current model draft. */\n onPick: (entry: PrefillEntry) => void\n /** Disable while a write is in flight. */\n disabled: boolean\n}\n\n/** The two sources, in the order the picker offers them; pi-ai leads by default. */\nconst SOURCES: readonly { readonly id: PrefillSource; readonly label: string }[] = [\n { id: 'pi-ai', label: 'llm-pi-ai' },\n { id: 'models.dev', label: 'models.dev' },\n]\n\n/** Which drop-down is showing; at most one at a time. */\ntype OpenPanel = 'provider' | 'model' | null\n\n/**\n * One line describing what the selected source currently offers, shown while\n * nothing is typed. The pi-ai version and snapshot date matter here: a DSH home\n * can hold more than one pi-ai copy, and knowing which one answered is the\n * difference between a diagnosis and a mystery.\n * @param index - the fetched index.\n * @param source - the selected source.\n * @returns the summary line.\n */\nfunction sourceSummary(index: PrefillIndex, source: PrefillSource): string {\n if (source === 'pi-ai') {\n if (index.piAi.length === 0) {\n return index.piAiFailure === undefined\n ? 'pi-ai 目录不可用'\n : `pi-ai 目录不可用:${index.piAiFailure}`\n }\n const version = index.piAiVersion === undefined ? '' : ` v${index.piAiVersion}`\n const when = index.piAiGeneratedAt === undefined ? '' : ` · ${index.piAiGeneratedAt.slice(0, 10)}`\n return `pi-ai 目录${version},${String(index.piAi.length)} 个模型${when};选择提供方或输入 model id`\n }\n if (index.modelsDev.length === 0) {\n return 'models.dev 元数据未下载——点击页首「下载/更新元数据」'\n }\n return `models.dev,${String(index.modelsDev.length)} 条;选择提供方或输入 model id`\n}\n\n/**\n * Render the three-step quick-load picker and its candidate list.\n * @param props - the pick handler and disabled flag.\n * @returns the quick-load block.\n */\nexport function QuickLoad(props: QuickLoadProps): ReactNode {\n const [source, setSource] = useState<PrefillSource>('pi-ai')\n const [provider, setProvider] = useState('')\n const [text, setText] = useState('')\n const [panel, setPanel] = useState<OpenPanel>(null)\n const [index, setIndex] = useState<PrefillIndex | undefined>(undefined)\n const textField = useRef<HTMLInputElement>(null)\n\n // Re-asked on every focus: getPrefillIndex() memoizes per page load, so a\n // warm index costs nothing, while a download that just invalidated the cache\n // is picked up without a reload. (Keeping the first result forever would\n // leave the picker stuck on \"未下载\" right after the user clicked download.)\n const ensureIndex = (): void => {\n void getPrefillIndex().then((loaded) => { setIndex(loaded) })\n }\n\n const providers = providersOf(index, source)\n // The provider field doubles as the filter for its own candidate list, so a\n // half-typed name must not narrow the model list yet — only a name that\n // actually is a provider does. Typing the full name counts, which is what\n // makes the field usable both ways.\n const chosenProvider = providers.includes(provider) ? provider : ''\n const { hits, total } = searchPrefill(index, { source, provider: chosenProvider, text })\n\n const pick = (entry: PrefillEntry): void => {\n setPanel(null)\n // Keep the chosen id on screen rather than clearing the field: an emptied\n // box right after a pick leaves no trace of what was just loaded, and the\n // id is also the natural starting point for narrowing to a sibling model.\n setText(entry.id)\n props.onPick(entry)\n }\n\n const switchSource = (next: PrefillSource): void => {\n setSource(next)\n // The provider list belongs to the source, so a stale pick would filter\n // every candidate away and read as \"the source is empty\".\n setProvider('')\n setText('')\n setPanel(null)\n }\n\n /**\n * Commit one provider choice and move straight on to the id field, so the\n * flow is pick → type rather than pick → click → type.\n * @param name - the provider to select; blank means \"every provider\".\n */\n const chooseProvider = (name: string): void => {\n setProvider(name)\n setText('')\n textField.current?.focus()\n }\n\n const providerBody = (): ReactNode => {\n if (index === undefined) return <span className={styles['quickEmpty']}>正在载入预填数据…</span>\n const needle = provider.trim().toLowerCase()\n const matches = needle.length === 0\n ? providers\n : providers.filter(name => name.toLowerCase().includes(needle))\n if (providers.length === 0) {\n return <span className={styles['quickEmpty']}>该数据源没有提供方信息</span>\n }\n return (\n <>\n <button\n type=\"button\"\n className={styles['quickItem']}\n onMouseDown={(event) => { event.preventDefault(); chooseProvider('') }}\n >\n 全部(不限提供方)\n </button>\n {matches.map(name => (\n <button\n type=\"button\"\n key={name}\n className={styles['quickItem']}\n onMouseDown={(event) => { event.preventDefault(); chooseProvider(name) }}\n >\n {name}\n </button>\n ))}\n {matches.length === 0\n ? <span className={styles['quickEmpty']}>没有匹配的提供方</span>\n : null}\n </>\n )\n }\n\n const modelBody = (): ReactNode => {\n if (index === undefined) return <span className={styles['quickEmpty']}>正在载入预填数据…</span>\n\n const nothingNarrowed = chosenProvider.length === 0 && text.trim().length === 0\n if (nothingNarrowed) {\n return (\n <>\n <span className={styles['quickEmpty']}>{sourceSummary(index, source)}</span>\n {source === 'pi-ai' && index.piAiWarnings.length > 0\n ? <span className={styles['error']}>{index.piAiWarnings.join(';')}</span>\n : null}\n </>\n )\n }\n\n if (hits.length === 0) {\n return <span className={styles['quickEmpty']}>没有匹配的模型</span>\n }\n\n return (\n <>\n {hits.map(entry => (\n <button\n type=\"button\"\n key={entry.key}\n className={styles['quickItem']}\n onMouseDown={(event) => {\n // mousedown beats the input's blur handler.\n event.preventDefault()\n pick(entry)\n }}\n >\n <span className={styles['quickItemId']}>{entry.id}</span>\n {/* The protocol of each candidate, because the SAME id ships under\n several of them (`claude-fable-5` exists in anthropic,\n github-copilot and openrouter — one speaks anthropic-messages,\n two speak openai-completions). Which one a row gets decides its\n whole compat surface, so it belongs beside the id and not in a\n later surprise. models.dev candidates carry no protocol, which\n is why the line is conditional rather than a placeholder. */}\n {entry.api === undefined\n ? null\n : <span className={styles['quickItemApi']}>{entry.api}</span>}\n </button>\n ))}\n {total > hits.length\n ? (\n <span className={styles['quickEmpty']}>\n 另有 {total - hits.length} 项匹配——继续输入或选定提供方以缩小范围\n </span>\n )\n : null}\n </>\n )\n }\n\n return (\n <div className={styles['quickWrap']}>\n <span className={styles['extLabel']}>快速装入</span>\n <div style={{ display: 'flex', gap: 6, alignItems: 'center' }}>\n <select\n className={`${styles['input']} ${styles['selectInput']}`}\n style={{ flex: '0 0 108px', minWidth: 0 }}\n value={source}\n disabled={props.disabled}\n aria-label=\"数据源\"\n onChange={(event) => { switchSource(event.target.value as PrefillSource) }}\n >\n {SOURCES.map(option => <option key={option.id} value={option.id}>{option.label}</option>)}\n </select>\n\n <input\n className={styles['input']}\n style={{ flex: '0 0 132px', minWidth: 0 }}\n type=\"text\"\n value={provider}\n placeholder=\"提供方:全部\"\n aria-label=\"提供方\"\n autoComplete=\"off\"\n disabled={props.disabled}\n onFocus={() => { ensureIndex(); setPanel('provider') }}\n onBlur={() => { setPanel(null) }}\n onChange={(event) => { setProvider(event.target.value); setPanel('provider') }}\n />\n\n <input\n className={styles['input']}\n style={{ flex: '1 1 auto', minWidth: 0 }}\n type=\"text\"\n ref={textField}\n value={text}\n placeholder=\"model id(如 glm)…\"\n aria-label=\"model id\"\n autoComplete=\"off\"\n disabled={props.disabled}\n onFocus={() => { ensureIndex(); setPanel('model') }}\n onBlur={() => { setPanel(null) }}\n onChange={(event) => { setText(event.target.value); setPanel('model') }}\n />\n </div>\n\n {panel === 'provider' ? <div className={styles['quickList']}>{providerBody()}</div> : null}\n {panel === 'model' ? <div className={styles['quickList']}>{modelBody()}</div> : null}\n </div>\n )\n}\n","/**\n * One model entry's expanded panel: quick-load, capacities (the official\n * modelAdvanced fields, merged into this block per the v1.0.0 design), input\n * modalities, the developer-role tri-state, the reasoning-effort gate and its\n * gated area (thinking format, then the seven-level effort table).\n *\n * Every edit patches the row's draft object through `onChange` — persistence\n * rides the card's existing path-ops save with no extra wire calls. Clearing\n * the effort gate drops `reasoningEfforts` AND `compat.thinkingFormat` in ONE\n * commit so partial updates never overwrite each other (no orphan settings).\n *\n * Which compat switches this panel may write at all is decided by `api` (see\n * {@link ModelEntryPanelProps.api}): the adapter refuses a switch the model's\n * protocol does not declare instead of ignoring it, so a control offered on the\n * wrong protocol is a save that cannot succeed. An UNKNOWN protocol hides\n * nothing — nothing can be judged — and the host's own diagnostic still covers\n * that case.\n */\n\nimport { useState } from 'react'\nimport type { ReactNode } from 'react'\nimport { COMPAT_BASE_FIELDS, THINKING_FORMATS, THINKING_LEVELS, offeredCompatFields } from '../extension-meta.ts'\nimport type { ModelDraft } from './compat.ts'\nimport { formatCapacity, parseCapacity } from './compat.ts'\nimport { compatFrom, reasoningEffortsFrom } from './prefill.ts'\nimport { QuickLoad } from './QuickLoad.tsx'\nimport type { PrefillEntry } from './models-index.ts'\nimport styles from './models-plus.module.css'\n\n/**\n * Whether a draft field is absent or whitespace-only.\n * @param value - the field's current value.\n * @returns true when the field carries nothing worth keeping.\n */\nfunction isBlank(value: unknown): boolean {\n if (value === undefined || value === null) return true\n return typeof value === 'string' && value.trim().length === 0\n}\n\n/** The row's compat sub-object as a plain record (absent → empty). */\nfunction compatOf(model: ModelDraft): Record<string, unknown> {\n const value = model['compat']\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? value as Record<string, unknown>\n : {}\n}\n\n/** The row's reasoningEfforts dict (absent/invalid → undefined = not declared). */\nfunction effortsOf(model: ModelDraft): Record<string, string | null> | undefined {\n const value = model['reasoningEfforts']\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined\n return value as Record<string, string | null>\n}\n\n/** The row's input modality list (absent → empty, matching the host reader). */\nfunction inputsOf(model: ModelDraft): readonly string[] {\n const value = model['input']\n return Array.isArray(value) ? value.filter((m): m is string => typeof m === 'string') : []\n}\n\n/** Props of {@link ModelEntryPanel}. */\nexport interface ModelEntryPanelProps {\n /** The row's current draft (read). */\n model: ModelDraft\n /** Replace the row with this next draft; `undefined`-valued keys clear them. */\n onChange: (next: ModelDraft) => void\n /** Disable every control (read-only deployment or a pending write). */\n disabled: boolean\n /**\n * The wire protocol this row resolves to, when the route settles one — the\n * route's own `api` for a hand-declared route, the installed catalog's shared\n * api for a catalog route, `undefined` when neither settles it.\n *\n * This is the protocol the ADAPTER will judge the row by (`route.api` wins\n * over the catalog entry), which is why it — and not the catalog entry's own\n * api — decides which compat switches may be written here.\n */\n api?: string\n}\n\n/**\n * Render one model entry's expanded panel.\n * @param props - the row draft, its writer, and the disabled flag.\n * @returns the expanded panel.\n */\nexport function ModelEntryPanel(props: ModelEntryPanelProps): ReactNode {\n const { model, onChange, disabled, api } = props\n\n /**\n * Whether this panel may OFFER a control for one compat switch.\n *\n * Not the same question as `protocolOffers`, and deliberately so: an\n * unresolvable protocol answers `true` throughout, because with no protocol to\n * read nothing can be judged — hiding a control on a guess would remove a\n * switch the route may well take, while the host still names anything it\n * refuses. A resolved protocol that offers nothing (one pi-ai gives no compat\n * type) answers `false` throughout, which is exactly what the adapter says.\n */\n const mayOffer = (field: string): boolean => api === undefined || offeredCompatFields(api).includes(field)\n\n // Capacities are text-edited, so keystrokes live in this buffer rather than\n // being re-derived from the parsed count (which would rewrite `1000` to\n // `1K` mid-word). Unreadable text stays on screen for the save-time check.\n const [capacityText, setCapacityText] = useState<ReadonlyMap<string, string>>(() => new Map())\n\n /** Patch one key onto the row; `undefined` clears it. */\n const setKey = (key: string, value: unknown): void => {\n const next = { ...model }\n if (value === undefined) Reflect.deleteProperty(next, key)\n else next[key] = value\n onChange(next)\n }\n\n /** Patch one key inside `compat`; an emptied compat leaves no trace. */\n const setCompatKey = (key: string, value: unknown): void => {\n const compat = { ...compatOf(model) }\n if (value === undefined) Reflect.deleteProperty(compat, key)\n else compat[key] = value\n setKey('compat', Object.keys(compat).length === 0 ? undefined : compat)\n }\n\n const setEfforts = (efforts: Record<string, string | null> | undefined): void => {\n setKey('reasoningEfforts', efforts)\n }\n\n const setInput = (modalities: readonly string[]): void => {\n setKey('input', modalities.length === 0 ? undefined : [...modalities])\n }\n\n // --- quick load ----------------------------------------------------------\n /**\n * Apply one prefill candidate.\n *\n * Every value is *restated* from the picked source rather than merged into\n * whatever was already there: capacities, modalities, reasoning levels and\n * compat are replaced wholesale. A prefill answers \"what does this catalog\n * say about the model\", so an absent field clears — leaving another source's\n * value behind would describe a model neither catalog claims, and switching\n * sources then re-picking is meant to be a clean rewrite.\n *\n * Two things do not follow that rule. `id` and `name` are filled only into a\n * blank row, because a catalog id is the request id for the vendor's *own*\n * endpoint while behind a gateway the string on the wire is often different.\n * And pi-ai's level map is *mapped* rather than copied, because `null` means\n * the opposite on each side.\n * @param entry - the picked candidate.\n */\n const applyMetadata = (entry: PrefillEntry): void => {\n const next = { ...model }\n // The protocol the row will be judged by, which is the route's when the\n // route states one. A catalog entry taken from another protocol's provider\n // (`deepseek-v4-pro` picked while the route speaks Anthropic) carries that\n // other protocol's compat block, and filtering it with the ENTRY's api is\n // what wrote `supportsStore` onto an `anthropic-messages` route.\n const judgedBy = props.api ?? entry.api\n if (entry.context === undefined) Reflect.deleteProperty(next, 'contextWindow')\n else next['contextWindow'] = entry.context\n if (entry.output === undefined) Reflect.deleteProperty(next, 'maxTokens')\n else next['maxTokens'] = entry.output\n // A prefill states what *this* source knows, so an absent value clears\n // rather than merges — leaving the other catalog's modality list behind\n // would describe a model neither source claims.\n const modality = entry.input.filter(m => m === 'text' || m === 'image')\n if (modality.length > 0) next['input'] = modality\n else Reflect.deleteProperty(next, 'input')\n\n if (entry.source === 'pi-ai') {\n // The id and name are filled into an *empty* row and never written over a\n // typed one. A catalog id is the request id for the vendor's own\n // endpoint; behind a gateway the string that actually reaches the wire is\n // often different (`v2.5-pro` vs `mimo-v2.5-pro`), so overwriting a typed\n // id would silently repoint the row at a model the endpoint does not\n // serve — the failure would surface later, as a 404 from the provider.\n if (isBlank(next['id'])) next['id'] = entry.id\n if (isBlank(next['name']) && entry.name !== undefined) next['name'] = entry.name\n\n next['reasoningEfforts'] = reasoningEffortsFrom(entry.thinkingLevelMap, judgedBy, entry.reasoning)\n\n // Catalog values only. `supportsReasoningEffort` is deliberately NOT\n // inferred from `reasoning`: the two answer different questions (does\n // the endpoint accept the field, vs. does the model think), and an\n // absent key is pi-ai's way of saying \"auto-detect from the endpoint\".\n // Writing our guess there would replace a detection with a claim we\n // cannot check, and a wrong `true` makes the adapter send a parameter\n // the endpoint may refuse.\n const compat = compatFrom(entry.compat, judgedBy)\n if (Object.keys(compat).length === 0) Reflect.deleteProperty(next, 'compat')\n else next['compat'] = compat\n } else {\n // models.dev: its ids are directory paths (`zhipuai/glm-5.3-flash`) and\n // the file carries no reasoning or compat surface at all — so the whole\n // block is REPLACED by the one fact this source can support.\n //\n // Merging here (as an earlier revision did) leaves a previous pi-ai\n // prefill's switches in place, and the row goes on claiming a thinking\n // format — or a reasoning-content requirement — that the source you just\n // switched to says nothing about. Switching sources is asking for the\n // other catalog's answer, not for a blend of the two.\n Reflect.deleteProperty(next, 'reasoningEfforts')\n // This one fact is itself protocol-bound: `supportsReasoningEffort`\n // exists on `openai-completions` alone, so claiming it for a models.dev\n // candidate on any other route is a save the adapter refuses.\n if (entry.reasoning && mayOffer('supportsReasoningEffort')) next['compat'] = { supportsReasoningEffort: true }\n else Reflect.deleteProperty(next, 'compat')\n }\n\n onChange(next)\n setCapacityText(new Map())\n }\n\n // --- capacities ----------------------------------------------------------\n const capacityField = (field: 'contextWindow' | 'maxTokens', label: string): ReactNode => {\n const stored = model[field]\n const typed = capacityText.get(field)\n const text = typed ?? (typeof stored === 'number' ? formatCapacity(stored) : '')\n return (\n <label className={styles['modelField']}>\n <span className={styles['modelFieldLabel']}>{label}</span>\n <input\n className={styles['input']}\n type=\"text\"\n inputMode=\"numeric\"\n value={text}\n placeholder=\"使用提供方默认值\"\n aria-label={label}\n disabled={disabled}\n onChange={(event) => {\n setCapacityText(current => new Map(current).set(field, event.target.value))\n setKey(field, parseCapacity(event.target.value))\n }}\n onBlur={() => {\n const raw = capacityText.get(field)\n if (raw === undefined) return\n const parsed = parseCapacity(raw)\n // Unreadable text stays on screen; the save-time check names it.\n if (parsed !== undefined && Number.isNaN(parsed)) return\n setCapacityText(current => {\n const next = new Map(current)\n next.delete(field)\n return next\n })\n }}\n />\n </label>\n )\n }\n\n // --- developer role (tri-state, NOT gated) -------------------------------\n const compat = compatOf(model)\n const developerRole = compat['supportsDeveloperRole'] !== false\n\n // --- compat switches with no dedicated control ---------------------------\n /**\n * Switches a prefill wrote that no control above stands for. Listing them\n * keeps a prefilled value from becoming invisible state: the pi-ai catalog\n * records far more of the compat surface than this panel models explicitly,\n * and that API refuses an unknown switch rather than ignoring it — so a value\n * the user cannot see is a value the user cannot fix.\n *\n * The set is the panel's base list narrowed to what this protocol takes. A\n * switch the protocol refuses keeps NO control — writing it would fail the\n * save — so it lands here instead, where it is named as refused and can be\n * cleared. That is the only way out of a row written before a protocol change\n * on the route, which no amount of hiding would repair.\n */\n const dedicated = COMPAT_BASE_FIELDS.filter(field => mayOffer(field))\n const extraCompat = Object.entries(compat)\n .filter(([key]) => !dedicated.includes(key))\n .sort(([a], [b]) => a.localeCompare(b))\n\n /**\n * Read an edited switch back as the type it already had.\n * @param previous - the value the switch carried when rendered.\n * @param raw - the field text.\n * @returns the coerced value, or the previous one when the text is unreadable.\n */\n const readCompatValue = (previous: unknown, raw: string): unknown => {\n if (typeof previous === 'boolean') return raw === 'true'\n if (typeof previous === 'number') {\n const parsed = Number(raw)\n return Number.isNaN(parsed) ? previous : parsed\n }\n if (typeof previous === 'string') return raw\n try {\n return JSON.parse(raw) as unknown\n } catch {\n return previous\n }\n }\n\n // --- effort gate ----------------------------------------------------------\n /**\n * The switch as a wire field: whether the endpoint takes `reasoning_effort`.\n *\n * Gated on the protocol as well as on the stored value: on a protocol that\n * does not take the switch a leftover `true` describes nothing this route can\n * act on, and the field's real home is the refused-switch list below.\n */\n const gateOn = mayOffer('supportsReasoningEffort') && compat['supportsReasoningEffort'] === true\n const efforts = effortsOf(model)\n /**\n * Whether the reasoning area is worth showing.\n *\n * The switch and the area answer different questions: the switch tells the\n * adapter the endpoint accepts `reasoning_effort`, while the area edits what\n * *this model* offers. A pi-ai prefill can leave the switch unset on purpose\n * — an absent key lets the adapter auto-detect from the endpoint — while\n * still carrying levels worth editing, and those levels reach the provider\n * through the protocol's own thinking parameter either way. So the area keys\n * off either signal, not the switch alone.\n */\n const reasoningAreaShown = gateOn || efforts !== undefined\n || (mayOffer('thinkingFormat') && compat['thinkingFormat'] !== undefined)\n\n const toggleGate = (checked: boolean): void => {\n if (checked) {\n setCompatKey('supportsReasoningEffort', true)\n return\n }\n // One commit clears the flag AND every gated node — no orphan settings.\n const nextCompat = { ...compat }\n Reflect.deleteProperty(nextCompat, 'supportsReasoningEffort')\n Reflect.deleteProperty(nextCompat, 'thinkingFormat')\n const next = { ...model, compat: Object.keys(nextCompat).length === 0 ? undefined : nextCompat }\n Reflect.deleteProperty(next, 'reasoningEfforts')\n onChange(next)\n }\n\n const toggleLevel = (level: string, checked: boolean): void => {\n const current = { ...(efforts ?? {}) }\n if (checked) current[level] = level === 'off' ? null : level\n else Reflect.deleteProperty(current, level)\n setEfforts(Object.keys(current).length === 0 ? undefined : current)\n }\n\n const setWireValue = (level: string, text: string): void => {\n if (efforts === undefined || !(level in efforts)) return\n const current = { ...efforts }\n current[level] = text.trim().length === 0 ? null : text.trim()\n setEfforts(current)\n }\n\n // --- validation (mirrors the host checks) --------------------------------\n const declaredLevels = efforts === undefined ? [] : THINKING_LEVELS.filter(level => level in efforts)\n const hasEmptyWire = declaredLevels.some(level =>\n level !== 'off' && String(efforts?.[level] ?? '').trim().length === 0)\n const onlyOffDeclared = efforts !== undefined\n && declaredLevels.length > 0\n && !declaredLevels.some(level => level !== 'off')\n\n // --- input modalities ------------------------------------------------------\n const inputList = inputsOf(model)\n const toggleModality = (modality: string, checked: boolean): void => {\n // Reading defaults to text-bearing rows; an explicit list wins.\n const base = inputList.length === 0 && model['input'] === undefined ? ['text'] : [...inputList]\n setInput(checked ? [...new Set([...base, modality])] : base.filter(m => m !== modality))\n }\n\n return (\n <div className={styles['extBlock']}>\n <div className={`${styles['extGroup']} ${styles['extGroupFirst']}`}>\n <QuickLoad onPick={applyMetadata} disabled={disabled} />\n </div>\n\n <div className={styles['extGroup']}>\n <div className={styles['modelField']} style={{ padding: '0 4px' }}>\n {capacityField('contextWindow', '上下文窗口')}\n {capacityField('maxTokens', '最大输出 token')}\n </div>\n </div>\n\n <div className={styles['extGroup']}>\n <span className={styles['extLabel']} style={{ marginBottom: 6 }}>输入模态</span>\n <div style={{ display: 'flex', gap: 18 }}>\n {['text', 'image'].map(modality => (\n <label key={modality} className={styles['switchRow']}>\n <input\n type=\"checkbox\"\n className={styles['extCheckbox']}\n checked={inputList.includes(modality)}\n disabled={disabled}\n onChange={(event) => { toggleModality(modality, event.target.checked) }}\n />\n {modality === 'text' ? '文本' : '图像'}\n </label>\n ))}\n </div>\n </div>\n\n {mayOffer('supportsDeveloperRole')\n ? (\n <div className={styles['extGroup']}>\n <label className={styles['extCheck']}>\n <input\n type=\"checkbox\"\n className={styles['extCheckbox']}\n style={{ marginTop: 3 }}\n checked={developerRole}\n disabled={disabled}\n onChange={(event) => {\n // Checked is the natural default, so a check REMOVES the key;\n // only an explicit uncheck writes `false`.\n setCompatKey('supportsDeveloperRole', event.target.checked ? undefined : false)\n }}\n />\n <span style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <span className={styles['extCheckLabel']}>允许以 developer 角色发送系统提示</span>\n <span className={styles['extHint']}>\n 推理模型的系统提示将以 developer 角色发出;网关拒绝该角色时取消勾选,改用 system。\n </span>\n </span>\n </label>\n </div>\n )\n : null}\n\n <div className={styles['extGroup']}>\n {mayOffer('supportsReasoningEffort')\n ? (\n <label className={styles['switchRow']}>\n <input\n type=\"checkbox\"\n className={styles['extCheckbox']}\n checked={gateOn}\n disabled={disabled}\n onChange={(event) => { toggleGate(event.target.checked) }}\n />\n 端点接受推理挡位参数(reasoning_effort)\n </label>\n )\n : (\n <p className={styles['extHint']}>\n 当前协议({String(api)})不接受 reasoning_effort 开关,故此处不提供;下面的挡位仍通过该协议自身的\n thinking 参数生效。\n </p>\n )}\n {mayOffer('supportsReasoningEffort') && !gateOn && reasoningAreaShown\n ? (\n <p className={styles['extHint']} style={{ marginTop: 6 }}>\n 此项未设置:由 llm-pi-ai 按其 baseURL 检测结果决定是否发送 reasoning_effort;\n 下面的挡位不受影响,仍通过各协议自己的 thinking 参数生效。\n </p>\n )\n : null}\n </div>\n\n {/* Gated area: HIDDEN (not dimmed) while the gate is off. */}\n <div className={styles['extGated']} hidden={!reasoningAreaShown}>\n {mayOffer('thinkingFormat')\n ? (\n <div className={styles['extField']}>\n <span className={styles['extLabel']}>思考格式</span>\n <select\n className={`${styles['input']} ${styles['selectInput']}`}\n value={typeof compat['thinkingFormat'] === 'string' ? compat['thinkingFormat'] : ''}\n disabled={disabled}\n onChange={(event) => { setCompatKey('thinkingFormat', event.target.value === '' ? undefined : event.target.value) }}\n >\n <option value=\"\">—</option>\n {THINKING_FORMATS.map(format => <option key={format} value={format}>{format}</option>)}\n </select>\n </div>\n )\n : null}\n\n <div className={styles['extField']}>\n <span className={styles['extLabel']}>推理挡位</span>\n <div className={styles['extTable']}>\n <div className={styles['extTHead']}>\n <div>声明</div><div>挡位</div><div>线上取值</div>\n </div>\n {THINKING_LEVELS.map((level) => {\n const declared = efforts !== undefined && level in efforts\n const isOff = level === 'off'\n const wire = declared ? String(efforts?.[level] ?? '') : ''\n return (\n <div key={level} className={styles['extTRow']}>\n <div style={{ display: 'flex', justifyContent: 'center' }}>\n <input\n type=\"checkbox\"\n className={styles['extCheckbox']}\n checked={declared}\n disabled={disabled}\n aria-label={`声明 ${level}`}\n onChange={(event) => { toggleLevel(level, event.target.checked) }}\n />\n </div>\n <div style={{ opacity: declared ? 1 : 0.5 }}>{level}</div>\n <div style={{ opacity: declared ? 1 : 0.4 }}>\n {declared && !isOff\n ? (\n <input\n type=\"text\"\n value={wire}\n placeholder={level}\n aria-label={`${level} 线上取值`}\n disabled={disabled}\n onChange={(event) => { setWireValue(level, event.target.value) }}\n />\n )\n : <span style={{ fontSize: 12, color: 'var(--dsw-alias-label-tertiary)' }}>—</span>}\n </div>\n </div>\n )\n })}\n </div>\n {hasEmptyWire || onlyOffDeclared\n ? (\n <p className={styles['error']} style={{ marginTop: 6 }}>\n {hasEmptyWire ? '除 off 外勾选的挡位必须填写线上取值。' : '至少声明一个 off 以外的挡位。'}\n </p>\n )\n : null}\n </div>\n </div>\n\n {extraCompat.length > 0\n ? (\n <div className={styles['extGroup']}>\n <span className={styles['extLabel']} style={{ marginBottom: 6 }}>其他兼容开关</span>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n {extraCompat.map(([key, value]) => {\n // A switch this protocol refuses is the one state the panel\n // cannot leave implicit: the save fails until the key is\n // gone, and this field is the only place it can go.\n const refused = !mayOffer(key)\n return (\n <label key={key} style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n <span className={refused ? styles['error'] : styles['extHint']}>\n {refused\n ? `${key} —— 当前协议(${String(api)})不接受此开关,请清空输入框以移除`\n : key}\n </span>\n <input\n className={styles['input']}\n type=\"text\"\n defaultValue={typeof value === 'string' ? value : JSON.stringify(value) ?? ''}\n aria-label={key}\n disabled={disabled}\n onBlur={(event) => {\n const raw = event.target.value.trim()\n // An emptied field drops the switch, handing the\n // decision back to the installed catalog.\n setCompatKey(key, raw.length === 0 ? undefined : readCompatValue(value, raw))\n }}\n />\n </label>\n )\n })}\n </div>\n <p className={styles['extHint']} style={{ marginTop: 6 }}>\n 这些开关由 pi-ai 目录预填;清空输入框即移除该开关,回到目录默认。\n </p>\n </div>\n )\n : null}\n </div>\n )\n}\n\n","/**\n * One provider profile's model catalog: rows joined from the draft's `models`\n * array, the fetch action (interrogating the endpoint the form currently\n * shows), and the candidate-picker modal. Each row's expanded panel is the\n * plugin's ModelEntryPanel — capacities and extension fields in one block.\n */\n\nimport { useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { LlmDiscoveredModel } from '@deepseek-ai/dsh-api-remotes/client'\nimport { Modal } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { ModelDraft } from './compat.ts'\nimport { newModelDraft } from './presets.ts'\nimport { ModelEntryPanel } from './ModelEntryPanel.tsx'\nimport type { ModelsOperations } from '../vendor/operations.ts'\nimport styles from './models-plus.module.css'\n\n/** Endpoint facts for the fetch action, taken from the live form. */\nexport interface ProbeTarget {\n readonly settingsNs: string\n readonly provider?: string\n readonly baseURL?: string\n readonly api?: string\n readonly apiKey?: string\n}\n\n/** Props of {@link ModelCatalog}. */\nexport interface ModelCatalogProps {\n /** The drafted rows (inherited rows until the first edit materializes an override). */\n models: readonly ModelDraft[]\n /** Whether the user layer owns the whole array. */\n overridden: boolean\n /** DeepSeek-family route-level fallbacks (undefined on the pi-ai family). */\n defaultContextWindow: number | undefined\n defaultMaxTokens: number | undefined\n /** Endpoint facts for the fetch action. */\n probe: ProbeTarget\n /**\n * The wire protocol every row of this route resolves to, when the route\n * settles one (a hand-declared route's own `api`, or the api its installed\n * catalog entries agree on). Rows seed and validate their compat against it;\n * see {@link ModelEntryPanelProps.api}.\n */\n routeApi?: string\n /** Why the fetch action is unavailable, or undefined when it is. */\n probeBlocked?: string\n /**\n * Hide the fetch action entirely. The host registers model discovery only\n * for `llm-pi-ai` (the sole `registerModelDiscovery` caller across the host\n * tree), so a deepseek-family card would otherwise offer an action that can\n * only ever fail with `NO_DISCOVERY` — mirroring the official page, whose\n * DeepSeekModelsEditor has no fetch button at all.\n */\n hideFetch?: boolean\n /** The Host operations whose interrogation answers the fetch action. */\n operations: ModelsOperations\n /** Disable every control (read-only deployment or a pending write). */\n disabled: boolean\n /** Replace the drafted rows. */\n onChange: (models: ModelDraft[]) => void\n /** Remove the user-owned array and return to inheritance. */\n onReset?: () => void\n}\n\n/** A row's text field, or the empty string when unset or not a string. */\nfunction textOf(model: ModelDraft, key: string): string {\n const value = model[key]\n return typeof value === 'string' ? value : ''\n}\n\n/** Adopt one candidate, v1.0.0 defaults + the endpoint's disclosed capacities. */\nfunction adopt(candidate: LlmDiscoveredModel, routeApi: string | undefined): ModelDraft {\n const row = newModelDraft(routeApi)\n row['id'] = candidate.id\n row['name'] = candidate.name ?? candidate.id\n if (candidate.contextWindow !== undefined) row['contextWindow'] = candidate.contextWindow\n if (candidate.maxTokens !== undefined) row['maxTokens'] = candidate.maxTokens\n return row\n}\n\n/**\n * Render the model catalog with its fetch action.\n * @param props - the drafted rows, probe target, wire face, and mutators.\n * @returns the catalog editor.\n */\nexport function ModelCatalog(props: ModelCatalogProps): ReactNode {\n const { models, onChange, probe, operations, disabled } = props\n\n const [busy, setBusy] = useState(false)\n const [failure, setFailure] = useState<string | undefined>(undefined)\n const [candidates, setCandidates] = useState<readonly LlmDiscoveredModel[] | undefined>(undefined)\n const [picked, setPicked] = useState<ReadonlySet<string>>(() => new Set())\n const [query, setQuery] = useState('')\n const [expanded, setExpanded] = useState<ReadonlySet<number>>(() => new Set())\n\n const patch = (index: number, next: Record<string, string | number | undefined>): void => {\n onChange(models.map((model, at) => {\n if (at !== index) return model\n const cleared = new Set(\n Object.entries(next).filter(([, value]) => value === undefined || value === '').map(([key]) => key),\n )\n return Object.fromEntries(\n Object.entries({ ...model, ...next }).filter(([key]) => !cleared.has(key)),\n )\n }))\n }\n\n const toggleExpanded = (index: number): void => {\n setExpanded((current) => {\n const next = new Set(current)\n if (!next.delete(index)) next.add(index)\n return next\n })\n }\n\n const removeRow = (index: number): void => {\n onChange(models.filter((_model, at) => at !== index))\n // Both stores are keyed by position; shift the rows after this one down.\n setExpanded((current) => {\n const next = new Set<number>()\n for (const at of current) {\n if (at < index) next.add(at)\n else if (at > index) next.add(at - 1)\n }\n return next\n })\n }\n\n const fetchModels = async (): Promise<void> => {\n setBusy(true)\n setFailure(undefined)\n try {\n const answer = await operations.discoverModels(probe.settingsNs, {\n ...probe.provider === undefined ? {} : { provider: probe.provider },\n ...probe.baseURL === undefined || probe.baseURL.length === 0 ? {} : { baseURL: probe.baseURL },\n ...probe.api === undefined ? {} : { api: probe.api },\n ...probe.apiKey === undefined ? {} : { apiKey: probe.apiKey },\n })\n if (answer.kind === 'refused') {\n setFailure(answer.message)\n return\n }\n const found = answer.models\n if (found.length === 0) {\n setFailure('该提供方没有列出任何模型,请手动添加。')\n return\n }\n const known = new Set(models.map(model => textOf(model, 'id')))\n setQuery('')\n setCandidates(found)\n setPicked(new Set(found.filter(model => !known.has(model.id)).map(model => model.id)))\n } finally {\n setBusy(false)\n }\n }\n\n const closePicker = (): void => {\n setCandidates(undefined)\n setPicked(new Set())\n setQuery('')\n }\n\n const adoptPicked = (): void => {\n if (candidates === undefined) return\n const byId = new Map(models.map(model => [textOf(model, 'id'), model]))\n for (const candidate of candidates) {\n if (!picked.has(candidate.id)) continue\n // A row the user already tuned wins over the provider's own numbers.\n byId.set(candidate.id, byId.get(candidate.id) ?? adopt(candidate, props.routeApi))\n }\n onChange([...byId.values()])\n closePicker()\n }\n\n const toggle = (id: string): void => {\n setPicked((current) => {\n const next = new Set(current)\n if (!next.delete(id)) next.add(id)\n return next\n })\n }\n\n const activeCandidates = candidates ?? []\n const needle = query.trim().toLowerCase()\n const visible = needle.length === 0\n ? activeCandidates\n : activeCandidates.filter(candidate => candidate.id.toLowerCase().includes(needle))\n const allPicked = visible.length > 0 && visible.every(candidate => picked.has(candidate.id))\n\n // A route the adapter already describes answers without an endpoint.\n const askable = probe.provider !== undefined || (probe.baseURL !== undefined && probe.baseURL.length > 0)\n\n return (\n <section className={styles['modelCatalog']} aria-label=\"模型目录\">\n <div className={styles['modelListHead']}>\n <div className={styles['modelCatalogHeading']}>\n <span className={styles['modelCatalogTitle']}>模型目录</span>\n <span className={styles['modelCatalogMeta']}>\n {props.overridden ? '已自定义模型目录' : '正在使用适配器默认模型'}\n </span>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>\n {props.overridden && props.onReset !== undefined\n ? (\n <button\n type=\"button\"\n className={styles['linkButton']}\n disabled={disabled}\n onClick={props.onReset}\n >\n 恢复默认模型\n </button>\n )\n : null}\n {props.hideFetch === true\n ? null\n : (\n <button\n type=\"button\"\n className={styles['linkButton']}\n disabled={disabled || busy || !askable || props.probeBlocked !== undefined}\n title={props.probeBlocked !== undefined\n ? props.probeBlocked\n : askable ? undefined : '请先填写 API 地址,再获取。'}\n onClick={() => { void fetchModels() }}\n >\n {busy ? '正在询问提供方…' : '获取可用模型'}\n </button>\n )}\n </div>\n </div>\n\n {models.length === 0\n ? <p className={styles['modelEmpty']}>模型选择器中将不显示任何模型;目录外 ID 仍可直接发送。</p>\n : (\n <div className={styles['modelList']}>\n {models.map((model, index) => (\n // Keyed by position alone. A key derived from the row's content\n // — the id especially — changes on every keystroke, so React\n // unmounts and remounts the row and the field being typed into\n // loses focus after each character. Nothing in this subtree\n // needs resetting when the id changes, so position is correct.\n <div\n key={String(index)}\n className={styles['modelEntry']}\n >\n <div className={styles['modelRow']}>\n <input\n className={styles['input']}\n type=\"text\"\n value={textOf(model, 'id')}\n placeholder=\"模型 ID\"\n aria-label={`模型 ID ${String(index + 1)}`}\n disabled={disabled}\n onChange={(event) => { patch(index, { id: event.target.value }) }}\n />\n <input\n className={styles['input']}\n type=\"text\"\n value={textOf(model, 'name')}\n placeholder=\"显示名称\"\n aria-label={`显示名称 ${String(index + 1)}`}\n disabled={disabled}\n onChange={(event) => { patch(index, { name: event.target.value === '' ? undefined : event.target.value }) }}\n />\n <button\n type=\"button\"\n className={styles['iconButton']}\n aria-label={`容量 ${String(index + 1)}`}\n aria-expanded={expanded.has(index)}\n title=\"容量\"\n onClick={() => { toggleExpanded(index) }}\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\" style={{ transform: expanded.has(index) ? 'rotate(90deg)' : undefined, transition: 'transform 120ms ease' }}>\n <path d=\"M6 3.5L10.5 8L6 12.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </button>\n <button\n type=\"button\"\n className={`${styles['iconButton']} ${styles['iconButtonDanger']}`}\n aria-label={`删除模型 ${String(index + 1)}`}\n title=\"删除模型\"\n disabled={disabled}\n onClick={() => { removeRow(index) }}\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M2.5 4h11M6.5 4V2.5h3V4M4 4l.7 9a1 1 0 001 .9h4.6a1 1 0 001-.9L12 4M6.5 6.8v4.4M9.5 6.8v4.4\" stroke=\"currentColor\" strokeWidth=\"1.3\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </button>\n </div>\n {expanded.has(index)\n ? (\n <ModelEntryPanel\n model={model}\n api={props.routeApi}\n disabled={disabled}\n onChange={(next) => {\n onChange(models.map((row, at) => (at === index ? next : row)))\n }}\n />\n )\n : null}\n </div>\n ))}\n </div>\n )}\n\n <button\n type=\"button\"\n className={styles['addModelButton']}\n disabled={disabled}\n onClick={() => { onChange([...models, newModelDraft(props.routeApi)]) }}\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M8 3.5v9M3.5 8h9\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n 添加模型\n </button>\n\n {failure !== undefined ? <p className={styles['error']}>{failure}</p> : null}\n\n <Modal\n open={candidates !== undefined}\n onClose={closePicker}\n title=\"选择要添加的模型\"\n closeLabel=\"关闭\"\n description=\"以下是模型提供方的可用模型,勾选要添加的模型。\"\n className={styles['fetchDialog'] as string}\n footer={(\n <>\n <button type=\"button\" className={styles['secondaryButton']} onClick={closePicker}>取消</button>\n <button type=\"button\" className={styles['primaryButton']} onClick={adoptPicked}>添加所选</button>\n </>\n )}\n >\n <div className={styles['candidateToolbar']}>\n <input\n className={`${styles['input']} ${styles['candidateSearch']}`}\n type=\"search\"\n value={query}\n placeholder=\"搜索模型\"\n aria-label=\"搜索模型\"\n onChange={(event) => { setQuery(event.target.value) }}\n />\n <button\n type=\"button\"\n className={styles['linkButton']}\n disabled={visible.length === 0}\n onClick={() => {\n setPicked(current => {\n if (visible.every(candidate => current.has(candidate.id))) {\n return new Set([...current].filter(id => !visible.some(candidate => candidate.id === id)))\n }\n return new Set([...current, ...visible.map(candidate => candidate.id)])\n })\n }}\n >\n {allPicked ? '取消全选' : '全选'}\n </button>\n </div>\n {visible.length === 0\n ? <p className={styles['candidateEmpty']} role=\"status\">没有匹配的模型。</p>\n : (\n <ul className={styles['candidateList']}>\n {visible.map(candidate => (\n <li key={candidate.id} className={styles['candidate']}>\n <label className={styles['candidateLabel']}>\n <input\n type=\"checkbox\"\n checked={picked.has(candidate.id)}\n onChange={() => { toggle(candidate.id) }}\n />\n <span className={styles['candidateId']}>{candidate.id}</span>\n </label>\n </li>\n ))}\n </ul>\n )}\n </Modal>\n </section>\n )\n}\n\n","/**\n * One existing provider's editor card, fully plugin-owned (v1.0.0 rewrite).\n * Primary field: a single write-only API key input; the collapsed\n * 「供应商」 section carries baseURL (plus displayName/protocol for a\n * hand-declared route), the 「模型」 section the model catalog with the\n * extension panel. Save semantics mirror the host card: minimal path ops\n * against the stored section with a revision fence, then the credential\n * write — the draft comes from the user layer, so a wholesale replace can\n * never delete fields outside the card.\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { CredentialInfo, SettingsNamespaceView } from '@deepseek-ai/dsh-api-remotes/client'\nimport { deriveKeyRef, protocolChoices } from '../vendor/store.ts'\nimport type { ModelsOperations } from '../vendor/operations.ts'\nimport type { SettingsSchemaOperations } from '../vendor/schema-operations.ts'\nimport type { ModelDraft } from './compat.ts'\nimport { compatFailureMessage, modelDrafts, normalizeModelRow, pathOps, validateModelRows } from './compat.ts'\nimport { getPrefillIndex, sharedCatalogApi } from './models-index.ts'\nimport type { PrefillIndex } from './models-index.ts'\nimport { ModelCatalog } from './ModelCatalog.tsx'\nimport styles from './models-plus.module.css'\n\n/**\n * The official DeepSeek endpoint root, and the only one left to prefill: the\n * route is Messages-only. The host dropped the `protocol` field in\n * 0.1.7-alpha.1 and its resolver now refuses a configuration that still carries\n * one, so a chat-completions variant is neither offered nor reachable — reading\n * that old field only ever produced the bare root, which the adapter refuses\n * (host @ 0.1.7-rc.2, `PUBLIC_BASE_URL`).\n */\nconst DEEPSEEK_BASE_URL = 'https://api.deepseek.com/anthropic'\n\n/** Per-adapter-family curated field sets (unknown namespaces get the hint alone). */\nexport type EditorLayout = 'deepseek' | 'pi-ai' | 'unknown'\n\n/**\n * The official signed-in account route. It carries no API key and no base URL\n * of its own — the host renders the model catalog alone for it, under the\n * DeepSeek family's curated field set (host @ 0.1.7-rc.2).\n */\nexport const ACCOUNT_PROVIDER = 'deepseek-account'\n\n/** The editor layout the owning namespace selects. */\nexport function layoutOf(ns: string): EditorLayout {\n if (ns === 'llm-deepseek') return 'deepseek'\n if (ns === 'llm-pi-ai') return 'pi-ai'\n return 'unknown'\n}\n\n/** A user-section subtree as a plain draft object (absent → empty). */\nexport function draftAt(\n schema: SettingsSchemaOperations,\n namespace: SettingsNamespaceView,\n path: readonly string[],\n): Record<string, unknown> {\n const subtree = schema.getPath(namespace.user, path)\n if (typeof subtree !== 'object' || subtree === null || Array.isArray(subtree)) return {}\n return structuredClone(subtree) as Record<string, unknown>\n}\n\n/** The credential reference this profile resolves keys through. */\nfunction refFor(\n schema: SettingsSchemaOperations,\n namespace: SettingsNamespaceView,\n path: readonly string[],\n provider: string,\n): string {\n const profile = schema.getPath(namespace.value, path)\n const named = typeof profile === 'object' && profile !== null\n ? (profile as { apiKeyEnv?: unknown }).apiKeyEnv\n : undefined\n return typeof named === 'string' && named.length > 0 ? named : deriveKeyRef(provider)\n}\n\n/** Props of {@link ProviderEditor}. */\nexport interface ProviderEditorProps {\n /** Provider route id. */\n provider: string\n /** Display name for the card title. */\n displayName: string\n /** Whether the adapter reports this route as hand-declared. */\n declared?: boolean\n /** The owning namespace view (schema, layers, secrets). */\n namespace: SettingsNamespaceView\n /** Settings-owned synchronous schema and immutable path operations. */\n schema: SettingsSchemaOperations\n /** Path from the section root to this provider's profile. */\n settingsPath: readonly string[]\n /** The Host operations this card writes and interrogates through. */\n operations: ModelsOperations\n /** Disable writes (read-only settings provider). */\n readOnly: boolean\n /** Close the editor; `changed` reports whether an Apply committed. */\n onClose: (changed: boolean) => void\n}\n\n/**\n * Render one existing provider's editing card.\n * @param props - the addressed profile plus wire faces.\n * @returns the editor card.\n */\nexport function ProviderEditor(props: ProviderEditorProps): ReactNode {\n const { namespace, schema, settingsPath, operations } = props\n const [draft, setDraft] = useState<Record<string, unknown>>(() => draftAt(schema, namespace, settingsPath))\n const [tab, setTab] = useState<'provider' | 'models'>('provider')\n const [keyDraft, setKeyDraft] = useState('')\n const [keyState, setKeyState] = useState<CredentialInfo | undefined>(undefined)\n const [busy, setBusy] = useState(false)\n const [failure, setFailure] = useState<string | undefined>(undefined)\n const [committedOriginal, setCommittedOriginal] = useState<unknown>(\n () => schema.getPath(namespace.user, settingsPath),\n )\n const [expectedRevision, setExpectedRevision] = useState(() => namespace.revision)\n const root = useMemo(() => schema.rehydrate(namespace.schema), [namespace.schema, schema])\n const node = useMemo(() => schema.nodeAtPath(root, settingsPath), [root, schema, settingsPath])\n const fallback = schema.getPath(namespace.value, settingsPath)\n const disabled = props.readOnly || busy\n const accountProvider = props.provider === ACCOUNT_PROVIDER\n // The account route is modelled on the DeepSeek family although its namespace\n // is the adapter's own, so the curated field set applies to it (host @ 0.1.7-rc.2).\n const layout = accountProvider ? 'deepseek' : layoutOf(namespace.ns)\n const keyRef = refFor(schema, namespace, settingsPath, props.provider)\n const protocols = useMemo(\n () => layout === 'pi-ai' ? protocolChoices(namespace, schema) : [],\n [layout, namespace, schema],\n )\n /**\n * The pi-ai catalog, loaded only on the family that needs it: it answers the\n * protocol of a route that states none (a catalog route), which is what the\n * model panel judges compat switches by.\n */\n const [prefillIndex, setPrefillIndex] = useState<PrefillIndex | undefined>(undefined)\n useEffect(() => {\n if (layout !== 'pi-ai') return\n let stale = false\n void getPrefillIndex().then((loaded) => {\n if (!stale) setPrefillIndex(loaded)\n })\n return () => { stale = true }\n }, [layout])\n\n useEffect(() => {\n // The account route has no page-managed credential to describe.\n if (accountProvider) return\n let stale = false\n setKeyState(undefined)\n void operations.describeCredential(keyRef).then((described) => {\n if (stale) return\n setKeyState(described)\n })\n return () => { stale = true }\n }, [operations, keyRef, accountProvider])\n\n const stringAt = (source: unknown, key: string): string | undefined => {\n const value = schema.getPath(source, [key])\n return typeof value === 'string' && value.trim().length > 0 ? value : undefined\n }\n const setField = (key: string, next: string | undefined): void => {\n const value = next === undefined || next.trim().length === 0 ? undefined : next\n setDraft((current) => value === undefined\n ? schema.deletePath(current, [key])\n : schema.setPath(current, [key], value))\n }\n\n /**\n * The protocol every row of this route resolves to, resolved the way the\n * adapter resolves it: a hand-declared route's own `api` first — it overrides\n * the catalog for every model on the route — then the protocol the installed\n * catalog's entries for this route agree on, then nothing.\n *\n * The model panel needs it because the adapter judges each row's compat\n * switches by THIS protocol, not by the catalog entry the row was prefilled\n * from; without it a row can carry switches the route will refuse.\n */\n const routeApi = layout === 'pi-ai'\n ? (props.declared === true ? stringAt(draft, 'api') ?? stringAt(fallback, 'api') : undefined)\n ?? sharedCatalogApi(prefillIndex, props.provider)\n : undefined\n\n const modelFailure = validateModelRows(schema.getPath(draft, ['models']), routeApi)\n const keyFailure = ((): 'keyBlank' | 'keyIllegalCharacters' | undefined => {\n if (keyDraft.length === 0) return undefined\n const value = keyDraft.trim()\n if (value.length === 0) return 'keyBlank'\n // Mirrors the host's apiKeyFailure heuristics (env line / quoted / charset).\n if (/^[A-Z][A-Z0-9_]*=[^=]/.test(value)) return 'keyIllegalCharacters'\n const first = value[0]\n if ((first === '\"' || first === '\\'' || first === '`') && value.length > 1 && value.endsWith(first)) {\n return 'keyIllegalCharacters'\n }\n return /^[\\x21-\\x7E]+$/.test(value) ? undefined : 'keyIllegalCharacters'\n })()\n const keyValue = keyDraft.trim()\n\n const probe = {\n settingsNs: namespace.ns,\n provider: props.provider,\n ...(() => {\n const baseURL = stringAt(draft, 'baseURL') ?? stringAt(fallback, 'baseURL')\n return baseURL === undefined ? {} : { baseURL }\n })(),\n ...(() => {\n const api = layout === 'pi-ai' && props.declared === true\n ? stringAt(draft, 'api') ?? stringAt(fallback, 'api')\n : undefined\n return api === undefined ? {} : { api }\n })(),\n ...keyValue.length === 0 ? {} : { apiKey: keyValue },\n }\n\n /** The write for this card, or a failure message. */\n const applyOnce = async (): Promise<string | undefined> => {\n const ns = namespace.ns\n let next = layout === 'pi-ai' && stringAt(draft, 'apiKeyEnv') === undefined\n && stringAt(fallback, 'apiKeyEnv') === undefined && keyValue.length > 0\n ? schema.setPath(draft, ['apiKeyEnv'], keyRef)\n : draft\n const rowFailure = validateModelRows(schema.getPath(next, ['models']), routeApi)\n if (rowFailure !== undefined) {\n return rowFailure.key === 'modelCompatNotOffered'\n ? compatFailureMessage(rowFailure)\n : `模型 ${String(rowFailure.index + 1)}:${{\n modelIdRequired: '模型 ID 不能为空。',\n modelIdDuplicate: '模型 ID 不能重复。',\n modelNameInvalid: '显示名称不能为空。',\n modelContextInvalid: '上下文窗口须为正数,如 131072、256K、1M。',\n modelMaxTokensInvalid: '最大输出 token 数须为正数,如 8192、64K、1M。',\n }[rowFailure.key]}`\n }\n if (node !== undefined && settingsPath.length === 0) {\n const sectionError = schema.validate(node, next)\n if (sectionError !== undefined) return sectionError\n }\n // Stable YAML key order: normalize every drafted row before diffing.\n if (schema.hasPath(next, ['models'])) {\n next = schema.setPath(\n next,\n ['models'],\n modelDrafts(schema.getPath(next, ['models'])).map(normalizeModelRow),\n )\n }\n // Official semantic: a pi-ai route whose only act is activating the route\n // (no fields the card can see, no key yet) still writes an empty profile\n // so the route exists in the directory at all.\n const materializesNativeProfile = layout === 'pi-ai'\n && fallback === undefined\n && committedOriginal === undefined\n && Object.keys(next).length === 0\n const ops = materializesNativeProfile\n ? [{ op: 'set', path: [...settingsPath], value: {} }]\n : pathOps(settingsPath, committedOriginal, next)\n if (ops.length > 0) {\n const written = await operations.writeSettings(ns, ops, expectedRevision)\n if (written.kind !== 'written') return written.kind === 'conflict'\n ? '这张卡片打开期间,这些设置已被其他地方改动。请关闭后重新打开,在当前值上编辑。'\n : written.message\n setCommittedOriginal(schema.getPath(written.view.user, settingsPath))\n setExpectedRevision(written.view.revision)\n setDraft(next)\n }\n if (keyValue.length > 0) {\n const stored = await operations.storeCredential(keyRef, keyValue)\n if (stored !== undefined) return stored\n }\n setKeyDraft('')\n return undefined\n }\n\n const apply = async (): Promise<void> => {\n setBusy(true)\n setFailure(undefined)\n try {\n const applyFailure = await applyOnce()\n if (applyFailure !== undefined) {\n setFailure(applyFailure)\n return\n }\n props.onClose(true)\n } finally {\n setBusy(false)\n }\n }\n\n if (node === undefined) {\n return <p className={styles['error']}>{props.provider}: 无法解析设置路径</p>\n }\n\n /**\n * The catalog beneath the user layer: the composition entry's pin, or the\n * schema default — reading the effective value would echo the stored\n * override back the moment reset drops it.\n */\n const inheritedModels = (): unknown => {\n const pinned = schema.getPath(namespace.base, [...settingsPath, 'models'])\n return pinned ?? schema.nodeAtPath(root, [...settingsPath, 'models'])?.meta.default\n }\n const customModels = schema.getPath(draft, ['models'])\n const modelsOverridden = schema.hasPath(draft, ['models'])\n const models = modelDrafts(modelsOverridden ? customModels : inheritedModels())\n const defaultContextWindow = schema.getPath(fallback, ['defaultContextWindow'])\n const defaultMaxTokens = schema.getPath(fallback, ['maxTokens'])\n\n const keyPlaceholder = keyState?.writable === false\n ? '由启动环境提供(只读)'\n : keyState?.configured === true\n ? '已配置——输入新值可替换'\n : layout === 'pi-ai' && props.declared === true\n ? '输入 API 密钥,或留空使用环境认证'\n : '输入 API 密钥'\n const keyLocked = keyState?.writable === false\n\n return (\n <div className={styles['editor']}>\n {layout === 'unknown'\n ? <p className={styles['advancedHint']}>其余字段存于 settings.yaml;请直接编辑对应段。({namespace.ns})</p>\n : accountProvider\n ? (\n /* No API key and no base URL: the platform's own model catalog is\n the whole card, and its list is never fetched (host @ 0.1.7-rc.2). */\n <ModelCatalog\n models={models}\n overridden={modelsOverridden}\n routeApi={routeApi}\n defaultContextWindow={typeof defaultContextWindow === 'number' ? defaultContextWindow : undefined}\n defaultMaxTokens={typeof defaultMaxTokens === 'number' ? defaultMaxTokens : undefined}\n probe={probe}\n probeBlocked={keyFailure}\n hideFetch\n operations={operations}\n disabled={disabled}\n onChange={(rows: ModelDraft[]) => {\n setDraft(current => schema.setPath(current, ['models'], rows))\n }}\n onReset={() => { setDraft(current => schema.deletePath(current, ['models'])) }}\n />\n )\n : (\n <>\n <div className={styles['tabs']}>\n <div className={styles['tabBar']} role=\"tablist\">\n <button type=\"button\" role=\"tab\" aria-selected={tab === 'provider'} className={tab === 'provider' ? `${styles['tabButton']} ${styles['tabButtonActive']}` : styles['tabButton']} onClick={() => { setTab('provider') }}>供应商</button>\n <button type=\"button\" role=\"tab\" aria-selected={tab === 'models'} className={tab === 'models' ? `${styles['tabButton']} ${styles['tabButtonActive']}` : styles['tabButton']} onClick={() => { setTab('models') }}>模型</button>\n </div> <div className={styles['tabPanel']} role=\"tabpanel\" hidden={tab !== 'provider'}>\n {/* Offered for every pi-ai route, not only hand-declared ones.\n The display name is a provider-level field the adapter\n defaults to the route key and honours as an override, and\n for a catalog route it is the only way to relabel: the key\n itself cannot change without breaking the catalog match\n and every credential ref derived from it. */}\n {layout === 'pi-ai'\n ? (\n <div className={styles['field']}>\n <label className={styles['fieldLabel']}>显示名称</label>\n <input\n className={styles['input']}\n type=\"text\"\n value={stringAt(draft, 'displayName') ?? ''}\n placeholder={stringAt(schema.getPath(namespace.base, settingsPath), 'displayName')\n ?? props.provider}\n aria-label=\"显示名称\"\n disabled={disabled}\n onChange={(event) => { setField('displayName', event.target.value) }}\n />\n </div>\n )\n : null}\n <div className={styles['field']}>\n <label className={styles['fieldLabel']}>API 密钥</label>\n <input\n className={styles['input']}\n type=\"password\"\n autoComplete=\"off\"\n value={keyDraft}\n placeholder={keyPlaceholder}\n aria-label=\"API 密钥\"\n disabled={disabled || keyLocked}\n onChange={(event) => { setKeyDraft(event.target.value) }}\n />\n {keyFailure === undefined\n ? null\n : <p className={styles['error']}>{keyFailure === 'keyBlank' ? '请输入 API 密钥;留空则保持已存储的密钥。' : '此 API 密钥格式无效,请检查。'}</p>}\n </div>\n <div className={styles['field']}>\n <label className={styles['fieldLabel']}>API 地址</label>\n <input\n className={styles['input']}\n type=\"text\"\n value={stringAt(draft, 'baseURL') ?? ''}\n placeholder={layout === 'deepseek'\n ? DEEPSEEK_BASE_URL\n : stringAt(fallback, 'baseURL') ?? '提供方默认'}\n aria-label=\"API 地址\"\n disabled={disabled}\n onChange={(event) => { setField('baseURL', event.target.value === '' ? undefined : event.target.value) }}\n />\n {layout === 'deepseek'\n ? <span className={styles['advancedHint']}>该路由固定使用 Messages 协议,地址须指向兼容该协议的端点。</span>\n : null}\n </div>\n {layout === 'pi-ai' && props.declared === true\n ? (\n <div className={styles['field']}>\n <label className={styles['fieldLabel']}>API 协议</label>\n <select\n className={`${styles['input']} ${styles['selectInput']}`}\n value={stringAt(draft, 'api') ?? stringAt(fallback, 'api') ?? ''}\n aria-label=\"API 协议\"\n disabled={disabled}\n onChange={(event) => { setField('api', event.target.value) }}\n >\n {(stringAt(draft, 'api') ?? stringAt(fallback, 'api')) === undefined\n ? <option value=\"\">未选择</option>\n : null}\n {protocols.map(choice => <option key={choice} value={choice}>{choice}</option>)}\n </select>\n </div>\n )\n : null}\n </div>\n <div className={styles['tabPanel']} role=\"tabpanel\" hidden={tab !== 'models'}>\n <ModelCatalog\n models={models}\n overridden={modelsOverridden}\n routeApi={routeApi}\n defaultContextWindow={typeof defaultContextWindow === 'number' ? defaultContextWindow : undefined}\n defaultMaxTokens={typeof defaultMaxTokens === 'number' ? defaultMaxTokens : undefined}\n probe={probe}\n probeBlocked={keyFailure}\n hideFetch={layout === 'deepseek'}\n operations={operations}\n disabled={disabled}\n onChange={(rows: ModelDraft[]) => {\n setDraft(current => schema.setPath(current, ['models'], rows))\n }}\n onReset={() => { setDraft(current => schema.deletePath(current, ['models'])) }}\n />\n </div>\n </div>\n </>\n )}\n\n {failure !== undefined ? <p className={styles['error']}>{failure}</p> : null}\n {modelFailure === undefined\n ? null\n : (\n <p className={styles['advancedHint']}>\n {modelFailure.key === 'modelCompatNotOffered'\n ? compatFailureMessage(modelFailure)\n : `模型 ${String(modelFailure.index + 1)}:${modelFailure.key}`}\n </p>\n )}\n\n <div className={styles['editorActions']}>\n <button\n type=\"button\"\n className={styles['secondaryButton']}\n disabled={busy}\n onClick={() => { props.onClose(false) }}\n >\n 取消\n </button>\n <button\n type=\"button\"\n className={styles['primaryButton']}\n disabled={disabled || layout === 'unknown' || modelFailure !== undefined\n || keyFailure !== undefined}\n onClick={() => { void apply() }}\n >\n {busy ? '保存中…' : '保存'}\n </button>\n </div>\n </div>\n )\n}\n","/**\n * The card that declares a provider pi-ai does not ship — an OpenAI-compatible\n * gateway, a self-hosted server, or a provider newer than the installed\n * catalog. One `settings.mutate` sets the whole profile at `providers.<route>`;\n * the key travels separately through `credentials/set` under the reference\n * the profile records. The three fields a hand-declared route cannot default\n * (endpoint, protocol, at least one model) are required here.\n */\n\nimport { useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { JsonValue } from '@deepseek-ai/dsh-util-values'\nimport { deriveKeyRef } from '../vendor/store.ts'\nimport type { ModelsOperations } from '../vendor/operations.ts'\nimport type { ModelDraft } from './compat.ts'\nimport { compatFailureMessage, normalizeModelRow, validateModelRows } from './compat.ts'\nimport { ModelCatalog } from './ModelCatalog.tsx'\nimport styles from './models-plus.module.css'\n\n/** The settings namespace a hand-declared provider is written into. */\nconst NS = 'llm-pi-ai'\n\n/**\n * A route id usable as a settings key AND as the stem of a credential name.\n */\nconst ROUTE_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/\n\n/** Props of {@link CreateProviderCard}. */\nexport interface CreateProviderCardProps {\n /** Route ids already declared, so the card refuses to shadow one. */\n taken: readonly string[]\n /** Wire protocols the adapter can serve, in the order it reports them. */\n protocols: readonly string[]\n /** Revision of the `llm-pi-ai` user section this card opened at. */\n revision: number\n /** The Host operations this card writes and interrogates through. */\n operations: ModelsOperations\n /** Disable writes (read-only settings provider). */\n readOnly: boolean\n /** Close the card; `changed` reports whether a provider was created. */\n onClose: (changed: boolean) => void\n}\n\n/**\n * Render the custom-provider creation card.\n * @param props - existing routes, protocol choices, wire faces.\n * @returns the creation card.\n */\nexport function CreateProviderCard(props: CreateProviderCardProps): ReactNode {\n const { taken, protocols, operations } = props\n const [openedAt] = useState(() => props.revision)\n const [route, setRoute] = useState('')\n const [displayName, setDisplayName] = useState('')\n const [baseURL, setBaseURL] = useState('')\n const [protocol, setProtocol] = useState(protocols[0] ?? '')\n const [tab, setTab] = useState<'provider' | 'models'>('provider')\n const [keyDraft, setKeyDraft] = useState('')\n const [models, setModels] = useState<readonly ModelDraft[]>([])\n const [busy, setBusy] = useState(false)\n const [failure, setFailure] = useState<string | undefined>(undefined)\n /** The profile write landed; only the key write can still be outstanding. */\n const [committed, setCommitted] = useState(false)\n const disabled = props.readOnly || busy\n const profileDisabled = disabled || committed\n\n const routeInvalid = route.length > 0 && !ROUTE_PATTERN.test(route)\n const routeTaken = taken.includes(route)\n // The card states the protocol itself, so every row it drafts is judged by it\n // — the same protocol the adapter will resolve the route to.\n const modelFailure = validateModelRows(models, protocol)\n const keyFailure = ((): 'keyBlank' | 'keyIllegalCharacters' | undefined => {\n if (keyDraft.length === 0) return undefined\n const value = keyDraft.trim()\n if (value.length === 0) return 'keyBlank'\n if (/^[A-Z][A-Z0-9_]*=[^=]/.test(value)) return 'keyIllegalCharacters'\n const first = value[0]\n if ((first === '\"' || first === '\\'' || first === '`') && value.length > 1 && value.endsWith(first)) {\n return 'keyIllegalCharacters'\n }\n return /^[\\x21-\\x7E]+$/.test(value) ? undefined : 'keyIllegalCharacters'\n })()\n const keyValue = keyDraft.trim()\n const ready = route.length > 0 && !routeInvalid && !routeTaken\n && baseURL.length > 0 && models.length > 0 && modelFailure === undefined\n && keyFailure === undefined\n const hint = failure !== undefined || ready || keyFailure !== undefined\n || route.length === 0 || routeInvalid || routeTaken\n ? undefined\n : baseURL.length === 0\n ? '自定义提供方需要填写 API 地址。'\n : modelFailure !== undefined\n ? modelFailure.key === 'modelCompatNotOffered'\n ? compatFailureMessage(modelFailure)\n : `模型 ${String(modelFailure.index + 1)}:${modelFailure.key}`\n : '自定义提供方至少需要一个模型。'\n\n /** Perform the create, returning a failure message or undefined. */\n const createOnce = async (): Promise<string | undefined> => {\n const keyRef = deriveKeyRef(route)\n const storesKey = keyValue.length > 0\n if (!committed) {\n const profile = {\n ...displayName.length === 0 ? {} : { displayName },\n ...storesKey ? { apiKeyEnv: keyRef } : {},\n api: protocol,\n baseURL,\n models: models.map(normalizeModelRow),\n }\n const written = await operations.writeSettings(\n NS,\n [{ op: 'set', path: ['providers', route], value: profile as JsonValue }],\n openedAt,\n )\n if (written.kind !== 'written') {\n return written.kind === 'conflict'\n ? '这张卡片打开期间,这些设置已被其他地方改动。请关闭后重新打开,在当前值上编辑。'\n : written.message\n }\n // A retry after a failed key write must not re-run this mutate.\n setCommitted(true)\n }\n if (storesKey) {\n const stored = await operations.storeCredential(keyRef, keyValue)\n if (stored !== undefined) return stored\n }\n return undefined\n }\n\n const create = async (): Promise<void> => {\n setBusy(true)\n setFailure(undefined)\n try {\n const outcome = await createOnce()\n if (outcome !== undefined) {\n setFailure(outcome)\n return\n }\n props.onClose(true)\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <div className={styles['editor']}>\n <div className={styles['field']} style={{ paddingTop: 12, borderTop: '0.5px solid var(--dsw-alias-border-l2)' }}>\n <label className={styles['fieldLabel']}>Provider ID</label>\n <input\n className={styles['input']}\n type=\"text\"\n value={route}\n placeholder=\"acme-gateway\"\n aria-label=\"Provider ID\"\n disabled={profileDisabled}\n onChange={(event) => { setRoute(event.target.value) }}\n />\n {routeInvalid || routeTaken\n ? <p className={styles['error']}>{routeInvalid ? '需以小写字母开头,之后可用小写字母、数字和短横线。' : '已有提供方使用了这个 ID。'}</p>\n : <p className={styles['advancedHint']}>以小写字母开头的标识,在请求中唯一标识该提供方,并用于派生凭据名。</p>}\n </div>\n\n <div className={styles['tabs']}>\n <div className={styles['tabBar']} role=\"tablist\">\n <button type=\"button\" role=\"tab\" aria-selected={tab === 'provider'} className={tab === 'provider' ? `${styles['tabButton']} ${styles['tabButtonActive']}` : styles['tabButton']} onClick={() => { setTab('provider') }}>供应商</button>\n <button type=\"button\" role=\"tab\" aria-selected={tab === 'models'} className={tab === 'models' ? `${styles['tabButton']} ${styles['tabButtonActive']}` : styles['tabButton']} onClick={() => { setTab('models') }}>模型</button>\n </div>\n <div className={styles['tabPanel']} role=\"tabpanel\" hidden={tab !== 'provider'}>\n <div className={styles['field']}>\n <label className={styles['fieldLabel']}>显示名称</label>\n <input\n className={styles['input']}\n type=\"text\"\n value={displayName}\n placeholder={route.length === 0 ? '显示名称' : route}\n aria-label=\"显示名称\"\n disabled={profileDisabled}\n onChange={(event) => { setDisplayName(event.target.value) }}\n />\n </div>\n <div className={styles['field']}>\n <label className={styles['fieldLabel']}>API 地址</label>\n <input\n className={styles['input']}\n type=\"text\"\n value={baseURL}\n placeholder=\"https://gateway.example/v1\"\n aria-label=\"API 地址\"\n disabled={profileDisabled}\n onChange={(event) => { setBaseURL(event.target.value) }}\n />\n </div>\n <div className={styles['field']}>\n <label className={styles['fieldLabel']}>API 协议</label>\n <select\n className={`${styles['input']} ${styles['selectInput']}`}\n value={protocol}\n aria-label=\"API 协议\"\n disabled={profileDisabled}\n onChange={(event) => { setProtocol(event.target.value) }}\n >\n {protocols.map(choice => <option key={choice} value={choice}>{choice}</option>)}\n </select>\n </div>\n <div className={styles['field']}>\n <label className={styles['fieldLabel']}>API 密钥</label>\n <input\n className={styles['input']}\n type=\"password\"\n autoComplete=\"off\"\n value={keyDraft}\n placeholder=\"输入 API 密钥,或留空使用环境认证\"\n aria-label=\"API 密钥\"\n disabled={disabled}\n onChange={(event) => { setKeyDraft(event.target.value) }}\n />\n {keyFailure === undefined\n ? null\n : <p className={styles['error']}>{keyFailure === 'keyBlank' ? '请输入 API 密钥;若该提供方以其他方式鉴权,可以留空。' : '此 API 密钥格式无效,请检查。'}</p>}\n </div>\n </div>\n <div className={styles['tabPanel']} role=\"tabpanel\" hidden={tab !== 'models'}>\n <ModelCatalog\n models={models}\n overridden={true}\n routeApi={protocol}\n defaultContextWindow={undefined}\n defaultMaxTokens={undefined}\n probe={{\n settingsNs: NS,\n baseURL,\n api: protocol,\n ...keyValue.length === 0 ? {} : { apiKey: keyValue },\n }}\n probeBlocked={keyFailure === 'keyBlank' ? '请输入 API 密钥;若该提供方以其他方式鉴权,可以留空。' : keyFailure}\n operations={operations}\n disabled={profileDisabled}\n onChange={setModels}\n />\n </div>\n </div>\n\n {failure !== undefined ? <p className={styles['error']}>{failure}</p> : null}\n {hint === undefined ? null : <p className={styles['advancedHint']}>{hint}</p>}\n\n <div className={styles['editorActions']}>\n <button\n type=\"button\"\n className={styles['secondaryButton']}\n disabled={busy}\n onClick={() => { props.onClose(committed) }}\n >\n 取消\n </button>\n <button\n type=\"button\"\n className={styles['primaryButton']}\n disabled={disabled || !ready}\n onClick={() => { void create() }}\n >\n {busy ? '创建中…' : '创建提供方'}\n </button>\n </div>\n </div>\n )\n}\n\n","/**\n * The Models+ settings section (v1.0.0, fully plugin-owned UI): provider rows\n * joined from the configurable directory, settings namespaces, and credential\n * states, one editor card at a time. The title row carries the adapter badge\n * and the metadata download button — the only place models.dev data is ever\n * fetched, on an explicit user click.\n */\n\nimport { useState } from 'react'\nimport type { ReactNode } from 'react'\nimport { Modal } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { ModelsSettingsStore, ProviderRow } from '../vendor/store.ts'\nimport { deriveKeyRef, protocolChoices, providerUsable } from '../vendor/store.ts'\nimport type { ModelsOperations } from './operations.ts'\nimport type { SettingsSchemaOperations } from './schema-operations.ts'\nimport { downloadMetadata } from './models-index.ts'\nimport { ProviderEditor } from './ProviderEditor.tsx'\nimport { CreateProviderCard } from './CreateProviderCard.tsx'\nimport styles from './models-plus.module.css'\n\n/** One existing row or dormant directory entry addressed by an editor action. */\nexport interface EditorTarget {\n readonly provider: string\n readonly displayName: string\n readonly settingsNs: string\n readonly settingsPath: readonly string[]\n /** Writable credential identified under this page's conventional reference. */\n credentialRef?: string\n readonly declared?: boolean\n}\n\n/** Injected dependencies of {@link ModelsPlusSection} (slot `inject`). */\nexport interface ModelsPlusInjected {\n controller: ModelsSettingsStore\n hooks: {\n snapshot: ModelsSettingsStore['store']\n }\n operations: ModelsOperations\n schema: SettingsSchemaOperations\n t: (key: string) => string\n}\n\n/** One fact decides the first-run posture: whether any provider is usable. */\nfunction needsSetup(row: ProviderRow, anyUsable: boolean): boolean {\n if (anyUsable || row.entry.provider === 'deepseek-account') return false\n if (row.entry.settingsPath.length > 0) return false\n return row.credential?.configured !== true\n}\n\n/** The credential reference a row resolves keys through, confirmed configured. */\nfunction keyConfiguredOf(row: ProviderRow): boolean {\n return row.apiKeyEnv !== undefined\n ? row.credential?.configured === true\n : row.derivedCredential?.configured === true\n}\n\nfunction targetOf(row: ProviderRow): EditorTarget {\n const managedRef = deriveKeyRef(row.entry.provider)\n const credentialRef = row.apiKeyEnv === managedRef\n && row.credential?.configured === true\n && row.credential.writable\n ? managedRef\n : undefined\n return {\n provider: row.entry.provider,\n displayName: row.entry.displayName,\n settingsNs: row.entry.settingsNs,\n settingsPath: row.entry.settingsPath,\n ...credentialRef === undefined ? {} : { credentialRef },\n ...row.entry.declared === true ? { declared: true } : {},\n }\n}\n\n/**\n * Remove one user-added provider and its page-managed credential. Credential\n * removal comes first so a second-step failure leaves the row retryable.\n */\nasync function removeProviderProfile(\n operations: ModelsOperations,\n controller: ModelsSettingsStore,\n target: { settingsNs: string; settingsPath: readonly string[]; credentialRef?: string },\n): Promise<string | undefined> {\n if (target.credentialRef !== undefined) {\n const credential = await operations.removeCredential(target.credentialRef)\n if (credential !== undefined) return credential\n }\n const written = await operations.writeSettings(\n target.settingsNs,\n [{ op: 'unset', path: [...target.settingsPath] }],\n undefined,\n )\n if (written.kind !== 'written') return written.message\n await controller.load()\n return undefined\n}\n\n/** Replace the one provider placeholder in localized destructive copy. */\nfunction providerCopy(template: string, target: { displayName: string; provider: string }): string {\n const label = target.provider === target.displayName\n ? target.provider\n : `${target.displayName} (${target.provider})`\n return template.replace('{provider}', () => label)\n}\n\n/**\n * Render the Models+ section content column.\n * @param props - slot-delivered injected dependencies.\n * @returns the section, or null while the shell has not injected yet.\n */\nexport function ModelsPlusSection(props: {\n controller?: ModelsPlusInjected['controller']\n useSnapshot?: ModelsPlusInjected['hooks']['snapshot']\n operations?: ModelsPlusInjected['operations']\n schema?: ModelsPlusInjected['schema']\n t?: ModelsPlusInjected['t']\n}): ReactNode {\n const { controller, useSnapshot, operations, schema, t } = props\n if (\n controller === undefined || useSnapshot === undefined || operations === undefined\n || schema === undefined || t === undefined\n ) return null\n // Hooks live in the Loaded child (mirrors the host section): the null check\n // above must not change this component's hook count between renders.\n return <Loaded injected={{ controller, useSnapshot, operations, schema, t }} />\n}\n\nfunction Loaded({ injected }: { injected: ModelsPlusInjected }): ReactNode {\n const { controller, operations, schema, t } = injected\n const useSnapshot = injected.useSnapshot\n\n const snapshot = useSnapshot(value => value)\n // The account route takes the extension dictionary's name instead of the\n // adapter's own; the store already sinks it to the top of the list and drops\n // it entirely while it has no usable model (host @ 0.1.7-rc.2).\n const state = { ...snapshot, rows: snapshot.rows.map(row => row.entry.provider === 'deepseek-account'\n ? { ...row, entry: { ...row.entry, displayName: t('deepSeekAccount') } } : row) }\n const [editing, setEditing] = useState<EditorTarget | undefined>(undefined)\n const [adding, setAdding] = useState(false)\n const [declaring, setDeclaring] = useState(false)\n const [deleteTarget, setDeleteTarget] = useState<EditorTarget | undefined>(undefined)\n const [deleting, setDeleting] = useState(false)\n const [deleteFailure, setDeleteFailure] = useState<string | undefined>(undefined)\n const [savedTarget, setSavedTarget] = useState<{ displayName: string; provider: string } | undefined>(undefined)\n const [dismissedSetup, setDismissedSetup] = useState<ReadonlySet<string>>(() => new Set())\n const [metaBusy, setMetaBusy] = useState(false)\n const [metaMessage, setMetaMessage] = useState<{ ok: boolean; text: string } | undefined>(undefined)\n\n const announceSaved = (target: { displayName: string; provider: string }): void => {\n void controller.load().then(() => { setSavedTarget(target) })\n }\n\n const closeEditor = (changed: boolean, target: { displayName: string; provider: string }): void => {\n setEditing(undefined)\n setAdding(false)\n setDeclaring(false)\n if (changed) announceSaved(target)\n }\n\n const closeSetup = (changed: boolean, target: { displayName: string; provider: string }): void => {\n setDismissedSetup(previous => new Set([...previous, target.provider]))\n if (changed) announceSaved(target)\n }\n\n const downloadMeta = async (): Promise<void> => {\n setMetaBusy(true)\n setMetaMessage(undefined)\n try {\n const outcome = await downloadMetadata()\n setMetaMessage(outcome.ok\n ? { ok: true, text: 'models.dev 元数据已下载并就绪。' }\n : { ok: false, text: `元数据下载失败:${outcome.message}` })\n } finally {\n setMetaBusy(false)\n }\n }\n\n if (state.status === 'idle') void controller.load()\n if (state.status === 'error') {\n const errorText = state.error ?? ''\n return (\n <div className={styles['section']}>\n <p className={styles['error']}>{`加载提供方目录失败: ${errorText}`}</p>\n <button type=\"button\" className={styles['secondaryButton']} onClick={() => { void controller.load() }}>\n 重试\n </button>\n </div>\n )\n }\n\n const savedRow = savedTarget === undefined\n ? undefined\n : state.rows.find(row => row.entry.provider === savedTarget.provider)\n const savedIdentity = savedRow === undefined\n ? savedTarget\n : { displayName: savedRow.entry.displayName, provider: savedRow.entry.provider }\n\n const anyUsable = state.rows.some(providerUsable)\n const configured = state.rows.filter(row => row.configured)\n // Mirrors the host page @ 0.1.7-rc.2: a row is addable only when its\n // settings namespace actually resolved — a namespace name the settings\n // document does not carry would open a card that can never save.\n const configurable = state.rows.filter(row => state.namespaces.has(row.entry.settingsNs))\n const addable = configurable.filter(row => !row.configured)\n const addTarget = adding ? editing : undefined\n const addNamespace = addTarget === undefined ? undefined : state.namespaces.get(addTarget.settingsNs)\n const protocols = (() => {\n // The protocol choices a hand-declared route may name (schema read).\n return protocolChoices(state.namespaces.get('llm-pi-ai'), schema)\n })()\n\n const renderEditor = (\n target: EditorTarget,\n namespace: Parameters<typeof ProviderEditor>[0]['namespace'] | undefined,\n onClose: (changed: boolean) => void,\n ): ReactNode => {\n if (namespace === undefined) return null\n return (\n <ProviderEditor\n provider={target.provider}\n displayName={target.displayName}\n settingsPath={target.settingsPath}\n {...target.declared === true ? { declared: true } : {}}\n namespace={namespace}\n schema={schema}\n operations={operations}\n readOnly={!state.writable}\n onClose={onClose}\n />\n )\n }\n\n return (\n <div className={styles['section']}>\n {/* Title row: heading + metadata download button */}\n <div className={styles['titleRow']}>\n <h2 className={styles['title']}>{t('nav')}</h2>\n <span className={styles['rowActions']}>\n <button\n type=\"button\"\n className={styles['linkButton']}\n disabled={metaBusy}\n title=\"下载/更新 models.dev 元数据(供快速装入预填)\"\n onClick={() => { void downloadMeta() }}\n >\n {metaBusy ? '正在下载元数据…' : '下载/更新元数据'}\n </button>\n </span>\n </div>\n {metaMessage === undefined\n ? null\n : <p className={metaMessage.ok ? styles['savedNotice'] : styles['error']}>{metaMessage.text}</p>}\n\n <p className={styles['intro']}>{t('intro')}</p>\n\n {savedIdentity === undefined\n ? null\n : (\n <p className={styles['savedNotice']} role=\"status\" aria-live=\"polite\">\n {providerCopy('已保存 {provider}。', savedIdentity)}\n </p>\n )}\n\n <ul className={styles['rows']}>\n {configured.map((row) => {\n const target = targetOf(row)\n const namespace = state.namespaces.get(target.settingsNs)\n if (namespace === undefined) return null\n // Adapter-reported configuration diagnostic (@ 0.1.7-rc.2): shown\n // above the card so a route that cannot be served still explains why.\n const error = row.entry.error === undefined\n ? null\n : <p role=\"alert\" className={styles['error']}>{row.entry.error}</p>\n if (needsSetup(row, anyUsable) && !dismissedSetup.has(row.entry.provider)) {\n return (\n <li key={row.entry.provider} className={styles['rowCard']}>\n {error}\n {renderEditor(target, namespace, (changed) => { closeSetup(changed, target) })}\n </li>\n )\n }\n const open = !adding && !declaring && editing?.provider === row.entry.provider\n const credentialConfigured = row.credential?.configured === true\n const credentialMissing = !credentialConfigured\n && row.apiKeyEnv !== undefined\n && row.credential?.configured === false\n return (\n <li key={row.entry.provider} className={styles['rowCard']}>\n {error}\n <div className={styles['rowHead']}>\n <span className={styles['rowIdentity']}>\n <span className={styles['rowName']}>{row.entry.displayName}</span>\n {row.entry.declared === true\n ? <span className={styles['rowTag']}>自定义</span>\n : null}\n {credentialConfigured\n ? (\n <span\n className={`${styles['credentialDot']} ${styles['credentialDotConfigured']}`}\n role=\"img\"\n aria-label=\"API 密钥已配置\"\n title=\"API 密钥已配置\"\n />\n )\n : credentialMissing\n ? (\n <span\n className={`${styles['credentialDot']} ${styles['credentialDotMissing']}`}\n role=\"img\"\n aria-label=\"API 密钥缺失\"\n title=\"API 密钥缺失\"\n />\n )\n : null}\n </span>\n <span className={styles['rowActions']}>\n <button\n type=\"button\"\n className={styles['secondaryButton']}\n aria-label={providerCopy('编辑 {provider}', target)}\n onClick={() => {\n setSavedTarget(undefined)\n setDeclaring(false)\n setAdding(false)\n setEditing(open ? undefined : target)\n }}\n >\n 编辑\n </button>\n {row.removable\n ? (\n <button\n type=\"button\"\n className={styles['dangerButton']}\n aria-label={providerCopy('删除 {provider}', target)}\n disabled={!state.writable}\n onClick={() => {\n setSavedTarget(undefined)\n setDeleteFailure(undefined)\n setDeleteTarget(target)\n }}\n >\n 删除\n </button>\n )\n : null}\n </span>\n </div>\n {open\n ? renderEditor(target, namespace, (changed) => { closeEditor(changed, target) })\n : null}\n </li>\n )\n })}\n </ul>\n\n <div className={styles['addBlock']}>\n {addTarget !== undefined && addNamespace !== undefined\n ? (\n <div className={styles['addCard']}>\n <div className={styles['field']}>\n <label className={styles['fieldLabel']}>提供方</label>\n <select\n className={`${styles['input']} ${styles['selectInput']}`}\n value={addTarget.provider}\n aria-label=\"提供方\"\n onChange={(event) => {\n const row = addable.find(candidate => candidate.entry.provider === event.target.value)\n if (row === undefined) return\n setEditing(targetOf(row))\n }}\n >\n {addable.map(row => (\n <option key={row.entry.provider} value={row.entry.provider}>\n {row.entry.displayName}\n </option>\n ))}\n </select>\n </div>\n <ProviderEditor\n key={addTarget.provider}\n provider={addTarget.provider}\n displayName={addTarget.displayName}\n namespace={addNamespace}\n schema={schema}\n settingsPath={addTarget.settingsPath}\n operations={operations}\n readOnly={!state.writable}\n onClose={(changed) => { closeEditor(changed, addTarget) }}\n />\n </div>\n )\n : declaring\n ? (\n <div className={styles['addCard']}>\n <CreateProviderCard\n taken={state.rows.map(row => row.entry.provider)}\n protocols={protocols}\n revision={state.namespaces.get('llm-pi-ai')?.revision ?? 0}\n operations={operations}\n readOnly={!state.writable}\n onClose={(changed) => {\n setDeclaring(false)\n if (changed) void controller.load()\n }}\n />\n </div>\n )\n : (\n <div className={styles['addActions']}>\n {configurable.length > 0 && (\n <button\n type=\"button\"\n className={styles['addButton']}\n disabled={addable.length === 0 || !state.writable}\n onClick={() => {\n const first = addable[0]\n if (first === undefined) return\n setSavedTarget(undefined)\n setDeclaring(false)\n setAdding(true)\n setEditing(targetOf(first))\n }}\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M8 3.5v9M3.5 8h9\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n 添加提供方\n </button>\n )}\n {state.namespaces.has('llm-pi-ai') && (\n <button\n type=\"button\"\n className={styles['addButton']}\n disabled={protocols.length === 0 || !state.writable}\n onClick={() => {\n setSavedTarget(undefined)\n setAdding(false)\n setEditing(undefined)\n setDeclaring(true)\n }}\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M8 3.5v9M3.5 8h9\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n 添加自定义提供方\n </button>\n )}\n </div>\n )}\n </div>\n\n <Modal\n open={deleteTarget !== undefined}\n onClose={() => {\n if (deleting) return\n setDeleteTarget(undefined)\n setDeleteFailure(undefined)\n }}\n title={deleteTarget === undefined ? '' : providerCopy('删除 {provider}?', deleteTarget)}\n closeLabel=\"关闭\"\n description={deleteTarget === undefined\n ? ''\n : providerCopy(\n deleteTarget.credentialRef === undefined\n ? '删除 {provider} 会移除其配置;其使用的凭证(如有)由其他位置管理,将会保留。'\n : '删除 {provider} 会移除其配置和存储的 API 密钥。',\n deleteTarget,\n )}\n className={styles['deleteDialog'] as string}\n footer={(\n <>\n <button\n type=\"button\"\n className={styles['secondaryButton']}\n disabled={deleting}\n onClick={() => {\n setDeleteTarget(undefined)\n setDeleteFailure(undefined)\n }}\n >\n 取消\n </button>\n <button\n type=\"button\"\n className={`${styles['secondaryButton']} ${styles['deleteConfirm']}`}\n disabled={deleting}\n onClick={() => {\n if (deleteTarget === undefined || deleting) return\n setDeleting(true)\n setDeleteFailure(undefined)\n void removeProviderProfile(operations, controller, deleteTarget)\n .then((removeFailure) => {\n if (removeFailure !== undefined) {\n setDeleteFailure(removeFailure)\n return\n }\n setDeleteTarget(undefined)\n })\n .finally(() => { setDeleting(false) })\n }}\n >\n {deleteTarget === undefined ? '' : providerCopy(deleting ? '正在删除 {provider}…' : '删除 {provider}', deleteTarget)}\n </button>\n </>\n )}\n >\n {deleteFailure === undefined ? null : <p className={styles['error']}>{deleteFailure}</p>}\n </Modal>\n </div>\n )\n}\n\n","/**\n * VENDORED from @deepseek-ai/dsh-client-ui-settings-models @ 0.1.5-rc.1\n * (host tree packages/client/ui-settings-models/src/client/operations.ts) — copied\n * VERBATIM so the build is self-contained (no host checkout required).\n * Re-diff against the host source on every host upgrade (last verified\n * byte-identical @ 0.1.7-rc.2).\n */\n/**\n * The Host reads and writes the Models cards perform, as callbacks built in the\n * plugin body. Cards receive these instead of a context: the outcomes name what\n * a card renders — a stored view, a stale revision, a refusal message — so the\n * failure codes and Remote namespaces stay in the apply world.\n */\n\nimport type { Context as ClientContext } from '@deepseek-ai/cordis'\nimport type {\n CredentialInfo, LlmDiscoveredModel, LlmModelDiscoveryRequest,\n SettingsNamespaceView, SettingsPathOpView,\n} from '@deepseek-ai/dsh-api-remotes/client'\n\n/** What one namespace write answered. */\nexport type SettingsWriteOutcome =\n /** Committed; the view carries the stored user subtree and the new revision. */\n | { readonly kind: 'written'; readonly view: SettingsNamespaceView }\n /**\n * The stored revision moved after the card read it, so the draft is stale.\n * The message stays for callers that report the Host diagnostic as it is.\n */\n | { readonly kind: 'conflict'; readonly message: string }\n /** Any other refusal, with the Host's own diagnostic. */\n | { readonly kind: 'refused'; readonly message: string }\n\n/** What one endpoint interrogation answered. */\nexport type ModelDiscoveryOutcome =\n /** The candidates the provider disclosed, in its own order. */\n | { readonly kind: 'found'; readonly models: readonly LlmDiscoveredModel[] }\n /** The interrogation was refused, with the Host's own diagnostic. */\n | { readonly kind: 'refused'; readonly message: string }\n\n/** The Host operations the Models page and its cards invoke. */\nexport interface ModelsOperations {\n /**\n * Read one credential reference's state.\n * @param ref - credential reference name.\n * @returns the state, or undefined when the reference is unknown or the read was refused.\n */\n describeCredential(ref: string): Promise<CredentialInfo | undefined>\n /**\n * Store one credential literal under its reference.\n * @param ref - credential reference name.\n * @param value - the literal to store.\n * @returns the refusal message, or undefined once stored.\n */\n storeCredential(ref: string, value: string): Promise<string | undefined>\n /**\n * Remove one credential reference (idempotent).\n * @param ref - credential reference name.\n * @returns the refusal message, or undefined once removed.\n */\n removeCredential(ref: string): Promise<string | undefined>\n /**\n * Apply path operations to one settings namespace.\n * @param ns - settings namespace identity.\n * @param ops - ordered path operations against the stored section, as the\n * wire takes them (the Remote signature owns the array).\n * @param expectedRevision - revision the draft was opened at, or undefined to write unfenced.\n * @returns the write outcome the card renders from.\n */\n writeSettings(\n ns: string,\n ops: SettingsPathOpView[],\n expectedRevision: number | undefined,\n ): Promise<SettingsWriteOutcome>\n /**\n * Ask a provider endpoint what models it serves.\n * @param settingsNs - namespace whose adapter family answers.\n * @param request - endpoint facts as the form currently shows them.\n * @returns the candidates, or the refusal.\n */\n discoverModels(settingsNs: string, request: LlmModelDiscoveryRequest): Promise<ModelDiscoveryOutcome>\n}\n\n/**\n * Bind the page's Host operations to the plugin's own Remote namespaces.\n * @param ctx - the page plugin's context, which declares `remote.credentials`,\n * `remote.llm`, and `remote.settings` in its own `inject`.\n * @returns the callbacks the section and its cards are injected with.\n */\nexport function createModelsOperations(ctx: ClientContext): ModelsOperations {\n return {\n describeCredential: async (ref) => {\n const response = await ctx.remote.credentials.describe([ref])\n return response.ok ? response.value[ref] : undefined\n },\n storeCredential: async (ref, value) => {\n const response = await ctx.remote.credentials.set(ref, value)\n return response.ok ? undefined : response.error.message\n },\n removeCredential: async (ref) => {\n const response = await ctx.remote.credentials.unset(ref)\n return response.ok ? undefined : response.error.message\n },\n writeSettings: async (ns, ops, expectedRevision) => {\n const response = await ctx.remote.settings.mutate(ns, ops, expectedRevision)\n if (response.ok) return { kind: 'written', view: response.value }\n const { code, message } = response.error\n return code === 'settings/conflict' ? { kind: 'conflict', message } : { kind: 'refused', message }\n },\n discoverModels: async (settingsNs, request) => {\n const response = await ctx.remote.llm.discoverModels(settingsNs, request)\n return response.ok\n ? { kind: 'found', models: response.value }\n : { kind: 'refused', message: response.error.message }\n },\n }\n}\n","/**\n * VENDORED from @deepseek-ai/dsh-client-ui-settings-models @ 0.1.5-rc.1\n * (host tree packages/client/ui-settings-models/src/client/schema-operations.ts) — copied\n * VERBATIM so the build is self-contained (no host checkout required).\n * Re-diff against the host source on every host upgrade (last verified\n * byte-identical @ 0.1.7-rc.2).\n */\nimport type {\n SettingsSchemaService,\n} from '@deepseek-ai/dsh-client-ui-settings/client'\n\n/** Plain schema callbacks exposed to Models stores and presentation components. */\nexport type SettingsSchemaOperations = Pick<\n SettingsSchemaService,\n 'rehydrate' | 'validate' | 'nodeAtPath' | 'getPath' | 'hasPath' | 'setPath' | 'deletePath'\n>\n\n/**\n * Hide the Cordis service identity behind bound schema callbacks.\n * @param service - settings-owned schema service available in the apply context.\n * @returns callbacks that cannot expose the service context to React components.\n */\nexport function createSettingsSchemaOperations(service: SettingsSchemaService): SettingsSchemaOperations {\n return {\n rehydrate: serialized => service.rehydrate(serialized),\n validate: (schema, draft) => service.validate(schema, draft),\n nodeAtPath: (root, path) => service.nodeAtPath(root, path),\n getPath: (value, path) => service.getPath(value, path),\n hasPath: (value, path) => service.hasPath(value, path),\n setPath: (root, path, value) => service.setPath(root, path, value),\n deletePath: (root, path) => service.deletePath(root, path),\n }\n}\n","/**\n * dsh-model-extension — client entry (v1.0.0).\n *\n * Registers the Models+ settings section rendering the fully plugin-owned\n * models-plus component tree (no host component code is bundled). The store,\n * schema operations, Host operations, dictionaries, and invalidation wiring\n * keep the upstream ui-settings-models contracts @ 0.1.7-rc.2 — the logic\n * modules (store/operations/schema-operations) are still inlined from the\n * host tree at build time, only the presentation is ours.\n */\nimport type { Context as ClientContext } from '@deepseek-ai/cordis'\n// Type-only: pulls the shell's SlotMap merge ('settings.section') into this program.\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\n// Type-only: pulls the locale plugin's Context merge (ctx.locale).\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\n// Type-only: pulls the ui renderer's Context merge (useSnapshot and friends on inject faces).\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\n// Type-only: pulls the ctx.remote merge and forwarded-event key face.\nimport type {} from '@deepseek-ai/dsh-api-remotes/client'\nimport { ModelsPlusSection } from './models-plus/ModelsPlusSection.tsx'\nimport type { ModelsPlusInjected } from './models-plus/ModelsPlusSection.tsx'\nimport { ModelsSettingsStore } from './vendor/store.ts'\nimport { createModelsOperations } from './vendor/operations.ts'\nimport { createSettingsSchemaOperations } from './vendor/schema-operations.ts'\nimport { en as extensionEn, zh as extensionZh } from './extension-meta.ts'\n\n/** Cordis service name (distinct from the npm package name). */\nexport const name = 'model-extension-client'\n\n/** Required services — mirrors the upstream Models section registration @ 0.1.7-rc.2. */\nexport const inject = [\n 'slots', 'locale', 'remote', 'remote.credentials', 'remote.llm', 'remote.settings', 'remote.session',\n 'configForms', 'settingsSchema',\n]\n\n/** Refetch the page snapshot only after its first load (upstream helper, inlined). */\nfunction refreshIfLoaded(controller: ModelsSettingsStore): void {\n if (controller.store.getSnapshot().status === 'idle') return\n void controller.load()\n}\n\n/**\n * Apply: register the Models+ section once slot/locale services are up.\n * @param ctx - client root context.\n */\nexport function apply(ctx: ClientContext): void {\n const NS = 'settings.models-extension'\n ctx.effect(() => ctx.locale.register(NS, {\n zh: { ...extensionZh },\n en: { ...extensionEn },\n }), 'dsh-model-extension: copy dictionaries')\n\n const schema = createSettingsSchemaOperations(ctx.settingsSchema)\n const operations = createModelsOperations(ctx)\n const controller = new ModelsSettingsStore(ctx, schema, ctx.configForms.describe())\n const t = ctx.locale.bind(NS) as ModelsPlusInjected['t']\n const injected = (): ModelsPlusInjected => ({\n controller,\n hooks: { snapshot: controller.store },\n operations,\n schema,\n t,\n })\n\n // Pushed invalidations converge every open surface without polling.\n ctx.effect(() => {\n const refreshModels = (): void => { refreshIfLoaded(controller) }\n return () => [\n ctx.remote.$on('settings/document-updated', () => { refreshModels() }),\n // The account route's availability follows its credential record, which\n // the reference-updated event does not cover (host @ 0.1.7-rc.2).\n ctx.remote.$on('credentials/record-updated', refreshModels),\n ctx.remote.$on('credentials/reference-updated', refreshModels),\n ctx.remote.$on('llm/adapters-updated', refreshModels),\n ctx.on('connection/reset', refreshModels),\n ]\n }, 'dsh-model-extension: pushed invalidations')\n\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: 'models-extension',\n order: 11,\n label: () => t('nav'),\n inject: injected,\n }, ModelsPlusSection))\n}\n"],"mappings":"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"}
|