dsh-model-extension 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","names":["styles","useState","styles","IconChevronDownOutline14","IconChevronRightOutline14","IconTrashOutline16","IconPlusOutline16","createSnapshotStore","extensionZh","extensionEn","styles","useState","styles","Modal","Button","useState","styles","useState","useMemo","styles","useState","styles","IconPlusOutline16","Modal","Button","extensionZh","extensionEn"],"sources":["packages/client/ui-settings-models/src/client/apiKey.ts","packages/client/ui-settings-models/src/client/ModelsSection.module.css","packages/client/ui-settings-models/src/client/EditorFooter.tsx","packages/client/ui-settings-models/src/client/DeepSeekModelsEditor.tsx","packages/client/ui-settings-models/src/client/store.ts","official/src/client/ModelsSection.ext.module.css","official/src/client/extension-meta.ts","official/src/client/ModelExtensionFields.tsx","official/src/client/ModelListEditor.ext.tsx","packages/client/ui-settings-models/src/client/CustomProviderCard.tsx","packages/client/ui-settings-models/src/client/ProviderEditor.tsx","official/src/client/ModelsSection.ext.tsx","packages/client/ui-settings-models/src/client/schema-operations.ts","official/src/client/index-extension.ts"],"sourcesContent":["/**\n * Browser-side judgement of a typed API key.\n * @module @deepseek-ai/dsh-client-ui-settings-models/apiKey\n */\n\n/**\n * Twin of `normalizeApiKey` in `@deepseek-ai/dsh-llm`: printable ASCII, space\n * excluded. Client packages reference only client packages, so the charset\n * rule is mirrored here rather than imported; keep the two in step, as\n * `validateDeepSeekModels` is kept in step with the host's `catalogModel`.\n */\nconst LEGAL_API_KEY = /^[\\x21-\\x7E]+$/\n\n/**\n * A pasted `NAME=value` environment line. Two narrowings keep real keys clear\n * of it: the name must be upper-case, so `sk-` forms break at the hyphen, and\n * the `=` must be followed by something other than another `=`, so base64\n * padding on an all-upper-case key (`ABCD==`) is not mistaken for an\n * assignment. This heuristic runs only here — a resolver applying it could\n * lock a user out of a gateway whose key legitimately takes this shape, with\n * the environment refusing it too and no way through.\n */\nconst ENV_LINE = /^[A-Z][A-Z0-9_]*=[^=]/\n\n/**\n * Copy key naming why a typed key cannot be saved. A wrapped paste reports the\n * same format failure as an illegal character: the reader's next move is the\n * same either way — look at the key and paste it again — so naming the two\n * causes apart would spend the field's one line on a distinction that changes\n * nothing about what to do.\n */\nexport type ApiKeyFailureKey = 'keyBlank' | 'keyIllegalCharacters'\n\n/** Whether a value is wrapped in one matching pair of quotes. */\nfunction isQuoted(value: string): boolean {\n const first = value[0]\n if (first !== '\"' && first !== '\\'' && first !== '`') return false\n return value.length > 1 && value.endsWith(first)\n}\n\n/**\n * Judge the key input's current value.\n *\n * An empty field is not a failure: every card opens with it empty even when a\n * key is already stored, where it means keep that one. A field holding only\n * whitespace is a failure rather than an empty field, so typed input is never\n * silently discarded.\n * @param draft - the key input's current value, untrimmed.\n * @returns the copy key for a field-level failure, or `undefined` to allow submit.\n */\nexport function apiKeyFailure(draft: string): ApiKeyFailureKey | undefined {\n if (draft.length === 0) return undefined\n const value = draft.trim()\n if (value.length === 0) return 'keyBlank'\n if (ENV_LINE.test(value) || isQuoted(value)) return 'keyIllegalCharacters'\n if (!LEGAL_API_KEY.test(value)) return 'keyIllegalCharacters'\n return undefined\n}\n","/* Models settings section, in the settings-panel design language: 14/22 body,\n * 12/18 caption, capsule controls (h36 r18; h28 r14 where a row is dense),\n * 32px fields, and `border-l2` hairlines — the vocabulary GeneralSection and\n * the Button/Input primitives already use.\n *\n * Every color resolves through a `--dsw-alias-*` token. Bare `--border` /\n * `--surface` / `--text-*` names, which nothing in this app defines, would\n * render the light-mode literals written as their fallbacks and stay light\n * under the dark theme. */\n\n.section {\n display: flex;\n flex-direction: column;\n gap: 12px;\n max-width: 720px;\n color: var(--dsw-alias-label-primary);\n}\n\n.title {\n margin: 0;\n font-size: 16px;\n line-height: 24px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n.intro {\n margin: 0;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.notice {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-warn-label);\n}\n\n.savedNotice {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-success-primary);\n}\n\n.rows {\n list-style: none;\n /* Extra air between the title/intro block and the first provider card. */\n margin: 12px 0 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n/* A configured provider: outlined on the panel fill, so the filled editor\n card it expands into reads as the nested object. */\n.rowCard {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n padding: 12px 14px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.rowHead {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.rowIdentity {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n}\n\n.rowName {\n font-size: 14px;\n line-height: 22px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n/* Reads as an annotation on the name, not as a second name: caption size and\n the secondary label tone, so it never competes with the row's own title. It\n sits inside `rowIdentity` with the credential dot, which is what keeps it\n beside the name rather than drifting toward the actions. */\n.rowTag {\n flex: none;\n padding: 1px 6px;\n border: 1px solid var(--dsw-alias-border-l3);\n border-radius: 4px;\n font-size: 11px;\n line-height: 16px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.credentialDot {\n box-sizing: border-box;\n display: inline-block;\n flex: none;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n}\n\n.credentialDotConfigured {\n background: var(--dsw-alias-state-success-primary);\n}\n\n.credentialDotMissing {\n background: var(--dsw-alias-state-error-primary);\n}\n\n.rowActions {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n margin-left: auto;\n}\n\n/* `box-sizing` on every control here: the app has no global border-box reset,\n so without it the outlined variants stand 2px taller than the filled ones\n they sit beside (Cancel next to Apply, Edit next to Delete). */\n.primaryButton,\n.secondaryButton,\n.addButton {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n height: 36px;\n padding: 0 14px;\n border: none;\n border-radius: 18px;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n cursor: pointer;\n}\n\n.primaryButton {\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n.primaryButton:hover:not(:disabled) {\n background: var(--dsw-alias-button-primary-hover);\n}\n\n.secondaryButton,\n.addButton {\n border: 1px solid var(--dsw-alias-border-l2);\n background: transparent;\n color: var(--dsw-alias-label-primary);\n}\n\n.secondaryButton:hover:not(:disabled),\n.addButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.secondaryButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n}\n\n.dangerButton {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 36px;\n padding: 0 14px;\n border: none;\n border-radius: 18px;\n background: transparent;\n color: var(--dsw-alias-state-error-primary);\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n cursor: pointer;\n}\n\n.dangerButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-danger);\n}\n\n/* Provider-row controls take the dense capsule (Button `.sm`). */\n.rowActions .secondaryButton,\n.rowActions .dangerButton {\n height: 28px;\n padding: 0 10px;\n border-radius: 14px;\n font-size: 12px;\n line-height: 18px;\n}\n\n.primaryButton:disabled,\n.secondaryButton:disabled,\n.dangerButton:disabled,\n.addButton:disabled,\n.linkButton:disabled,\n.addModelButton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n.primaryButton:focus-visible,\n.secondaryButton:focus-visible,\n.dangerButton:focus-visible,\n.addButton:focus-visible,\n.linkButton:focus-visible,\n.addModelButton:focus-visible,\n.iconButton:focus-visible,\n.customizedSummary:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n/* Editing surface: a filled module on the panel, matching the settings\n selector fill rather than adding another outline inside the row. */\n.editor {\n border-radius: 12px;\n background: var(--dsw-alias-bg-module-platform);\n padding: 14px 16px;\n display: flex;\n flex-direction: column;\n gap: 14px;\n}\n\n.editorHeader {\n display: flex;\n align-items: baseline;\n gap: 8px;\n}\n\n.editorTitle {\n font-size: 14px;\n line-height: 22px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n.editorRoute {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.fieldLabel {\n display: inline-flex;\n align-items: center;\n gap: 10px;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n.linkButton {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n height: 28px;\n padding: 0 10px;\n border: none;\n border-radius: 14px;\n background: transparent;\n color: var(--dsw-alias-label-tertiary);\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n cursor: pointer;\n}\n\n.linkButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n\n.advancedHint {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.editorActions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n\n.addBlock {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n/* The two ways to gain a provider, as equal siblings spanning the same width\n as the rows above. Wraps rather than shrinking below a legible label. */\n.addActions {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n}\n\n.addButton {\n /* Overrides the shared button base above: these two are not pills sitting in\n a footer but the last slot of the provider list, so they split the row\n evenly and repeat the row cards' corner. Dashed, like every other \"nothing\n here yet\" affordance on this page, to read as a place rather than a\n command. */\n flex: 1 1 0;\n min-width: 180px;\n gap: 6px;\n height: 44px;\n border: 1px dashed var(--dsw-alias-border-l3);\n border-radius: 12px;\n}\n\n.addCard,\n.setupCard {\n border-radius: 12px;\n background: var(--dsw-alias-bg-module-platform);\n padding: 14px 16px;\n display: flex;\n flex-direction: column;\n gap: 14px;\n list-style: none;\n}\n\n/* Nested in a card that already carries the module chrome. */\n.addCard .editor,\n.setupCard .editor {\n background: none;\n padding: 0;\n}\n\n.customized {\n border-top: 1px solid var(--dsw-alias-border-l2);\n padding-top: 10px;\n}\n\n/* Native disclosure marker replaced by a rotating chevron: the built-in\n triangle differs per engine and cannot take the label color. */\n.customizedSummary {\n display: flex;\n align-items: center;\n gap: 6px;\n width: fit-content;\n padding: 2px 4px;\n margin-left: -4px;\n border-radius: 6px;\n cursor: pointer;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n list-style: none;\n}\n\n.customizedSummary::-webkit-details-marker {\n display: none;\n}\n\n.customizedSummary::before {\n content: '';\n width: 5px;\n height: 5px;\n border-right: 1.5px solid currentcolor;\n border-bottom: 1.5px solid currentcolor;\n transform: rotate(-45deg) translate(-1px, -1px);\n transition: transform 120ms ease;\n}\n\n.customized[open] > .customizedSummary::before {\n transform: rotate(45deg) translate(-1px, -1px);\n}\n\n.customizedSummary:hover {\n color: var(--dsw-alias-label-primary);\n}\n\n.customizedBody {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding-top: 12px;\n}\n\n/* Model catalog: a table, not a stack of cards. The column captions are\n written once above the rows, so a row is one line of fields plus its\n delete control; each field still carries the indexed `aria-label` that\n names it, and the caption strip is hidden from assistive tech to keep\n that name from being announced twice. */\n.modelCatalog {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding-top: 12px;\n border-top: 1px solid var(--dsw-alias-border-l2);\n}\n\n.modelCatalogHeading {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.modelCatalogTitle {\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n.modelCatalogMeta,\n.modelEmpty {\n margin: 0;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n}\n\n/* Model list, shared with the pi-ai provider form: one bordered\n entry per model, id and display name on the row, capacities behind the\n row's own disclosure. The rules use this stylesheet's token vocabulary —\n `--dsw-alias-border-subtle`, `--dsw-alias-text-tertiary`, and\n `--dsw-alias-text-primary` are undefined here and would resolve to their\n light-mode literals. */\n.modelList {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.modelListHead {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 12px;\n}\n\n.modelEntry {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n padding: 6px;\n}\n\n.modelRow {\n display: grid;\n grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) auto auto;\n align-items: center;\n gap: 6px;\n}\n\n/* Square, label-free affordances: the row's own inputs carry the meaning, so\n the actions stay glyphs and announce themselves through aria-label. */\n.iconButton {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n}\n\n.iconButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.iconButton:disabled {\n cursor: default;\n opacity: 0.4;\n}\n\n/* The delete glyph keeps the danger tint the rest of the section uses. */\n.iconButtonDanger:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-danger);\n color: var(--dsw-alias-state-error-primary);\n}\n\n.modelAdvanced {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 8px;\n padding: 8px 4px 2px;\n}\n\n.modelField {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.modelFieldLabel {\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n}\n\n.modelEmpty {\n padding: 12px;\n border: 1px dashed var(--dsw-alias-border-l3);\n border-radius: 8px;\n text-align: center;\n}\n\n.addModelButton {\n box-sizing: border-box;\n align-self: flex-start;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n height: 28px;\n padding: 0 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 14px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n cursor: pointer;\n}\n\n.addModelButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.input {\n box-sizing: border-box;\n width: 100%;\n height: 32px;\n padding: 0 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n}\n\n/* Enum pickers hold a handful of short options; a field-width dropdown reads\n as a text field the user is expected to fill. */\nselect.input {\n max-width: 240px;\n cursor: pointer;\n}\n\n.input:focus {\n outline: none;\n border-color: var(--dsw-alias-brand-primary);\n}\n\n.input::placeholder {\n color: var(--dsw-alias-label-dimmed);\n}\n\n.input:disabled {\n opacity: 0.6;\n cursor: default;\n}\n\n/* Select variant of .input: replaces the OS arrow (which sits flush against\n the right edge) with the shared 12px chevron inset like the composer's\n .select chips; the right pad reserves its cell. */\n.selectInput {\n appearance: none;\n padding-right: 32px;\n /* Data-URI SVGs cannot resolve CSS variables; #81858C is the caption gray\n shared by both themes. */\n 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\");\n background-repeat: no-repeat;\n background-position: right 12px center;\n background-size: 12px 12px;\n}\n\n.error {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-error-primary);\n}\n\n.deleteDialog {\n width: min(480px, 100%);\n}\n\n.deleteConfirm:not(:disabled) {\n border-color: var(--dsw-alias-state-error-primary);\n color: var(--dsw-alias-state-error-primary);\n}\n\n.deleteConfirm:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-danger);\n}\n\n/* Icon-button label seat: named for assistive tech and for the tests that\n query these controls by their text. */\n.hiddenLabel {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .customizedSummary::before {\n transition: none;\n }\n}\n\n.fetchDialog {\n max-width: 520px;\n\n /* The candidate list scrolls inside this dialog, an elevated surface, so the\n scrollbar indirection is rebound here rather than on the scrolling child:\n the elevation choice belongs with the surface and inherits down (see\n ui-theme styles/scrollbar.css for the contract). */\n --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);\n --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);\n}\n\n.candidateActions {\n display: flex;\n justify-content: flex-end;\n margin-bottom: 6px;\n}\n\n.candidateList {\n display: flex;\n flex-direction: column;\n gap: 2px;\n max-height: 320px;\n margin: 0;\n overflow-y: auto;\n padding: 0;\n list-style: none;\n}\n\n.candidate {\n border-radius: 6px;\n}\n\n.candidateLabel {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n cursor: pointer;\n}\n\n.candidateId {\n flex: 1 1 auto;\n font-family: var(--ds-font-family-code);\n font-size: 13px;\n overflow-wrap: anywhere;\n}\n","/**\n * The action row every provider card ends with: dismiss on the left, commit on\n * the right.\n *\n * The two cards commit different things — one creates a route, one edits an\n * existing profile — but the row itself carries no such knowledge. It renders\n * what it is handed, so the cards keep sole ownership of when a commit is\n * allowed and what the in-flight wording is.\n *\n * Cancel refuses input only while a commit is in flight, never because the card\n * is disabled: a card the deployment cannot write to must still be dismissable.\n *\n * @module dsh-client-ui-settings-models/client/EditorFooter\n */\n\nimport type { ReactNode } from 'react'\nimport type { en } from './locales.ts'\nimport styles from './ModelsSection.module.css'\n\n/** Props of {@link EditorFooter}. */\nexport interface EditorFooterProps {\n /** Localizer for the row's own labels. */\n t: (key: keyof typeof en) => string\n /** Whether a commit is in flight; holds Cancel and swaps the commit label. */\n busy: boolean\n /** Whether the commit is refused, as judged by the owning card. */\n submitDisabled: boolean\n /** Commit label while idle. */\n submitLabel: keyof typeof en\n /** Commit label while a commit is in flight. */\n submitBusyLabel: keyof typeof en\n /** Dismiss label; defaults to the settings editor copy. */\n cancelLabel?: keyof typeof en\n /** Dismiss the card without committing. */\n onCancel: () => void\n /** Run the card's commit. */\n onSubmit: () => void\n}\n\n/**\n * Render one provider card's action row.\n * @param props - the labels, commit gating, and handlers the owning card supplies.\n * @returns the cancel/commit row.\n */\nexport function EditorFooter(props: EditorFooterProps): ReactNode {\n const { t } = props\n return (\n <div className={styles['editorActions']}>\n <button\n type=\"button\"\n className={styles['secondaryButton']}\n disabled={props.busy}\n onClick={props.onCancel}\n >\n {t(props.cancelLabel ?? 'cancel')}\n </button>\n <button\n type=\"button\"\n className={styles['primaryButton']}\n disabled={props.submitDisabled}\n onClick={props.onSubmit}\n >\n {props.busy ? t(props.submitBusyLabel) : t(props.submitLabel)}\n </button>\n </div>\n )\n}\n","/**\n * Curated editor for the direct DeepSeek adapter's advisory model catalog.\n * The settings layer replaces `models` as one array, so the parent supplies\n * the effective inherited rows until the first edit materializes a user\n * override; reset removes that override instead of copying defaults into it.\n */\n\nimport { useState } from 'react'\nimport type { ReactNode } from 'react'\nimport {\n IconChevronDownOutline14, IconChevronRightOutline14, IconPlusOutline16, IconTrashOutline16,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { en } from './locales.ts'\nimport styles from './ModelsSection.module.css'\n\n/** One catalog entry kept structurally open so hidden or future fields survive an edit. */\nexport type DeepSeekModelDraft = Record<string, unknown>\n\n/** The catalog fields this editor writes. */\ntype CatalogField = 'id' | 'name' | 'contextWindow' | 'maxTokens'\n\n/** The two token counts edited as K/M-suffixed text behind a row's disclosure. */\ntype CapacityField = 'contextWindow' | 'maxTokens'\n\n/** Row index encoded in an editing-buffer key. */\nfunction rowOf(key: string): number {\n return Number(key.slice(0, key.indexOf(':')))\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 validateDeepSeekModels} 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/** A localized validation failure for one user-owned model array. */\nexport interface DeepSeekModelsValidationFailure {\n /** Zero-based model position. */\n index: number\n /** Message key owned by the Models settings section. */\n key: 'modelIdRequired' | 'modelIdDuplicate' | 'modelNameInvalid' | 'modelContextInvalid'\n | 'modelMaxTokensInvalid'\n}\n\n/** Convert a schema-validated catalog value into records without dropping hidden fields. */\nexport function modelDrafts(value: unknown): DeepSeekModelDraft[] {\n if (!Array.isArray(value)) return []\n return value.map(entry =>\n typeof entry === 'object' && entry !== null && !Array.isArray(entry)\n ? entry as DeepSeekModelDraft\n : {})\n}\n\n/**\n * Validate adapter constraints that the serialized schema cannot express.\n * @param value - user-owned `models` value, or undefined while inherited.\n * @returns the first invalid row, or undefined when the adapter will accept it.\n */\nexport function validateDeepSeekModels(value: unknown): DeepSeekModelsValidationFailure | 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 }\n return undefined\n}\n\n/** Props of {@link DeepSeekModelsEditor}. */\nexport interface DeepSeekModelsEditorProps {\n /** Effective rows: inherited until the parent materializes an override. */\n models: readonly DeepSeekModelDraft[]\n /** Whether the user layer currently owns the whole array. */\n overridden: boolean\n /** Fallback context capacity used when a row omits its exact value. */\n defaultContextWindow: number | undefined\n /** Fallback output cap used when a row omits its exact value. */\n defaultMaxTokens: number | undefined\n /** Section copy. */\n t: (key: keyof typeof en) => string\n /** Disable every mutation. */\n disabled: boolean\n /** Replace the user-owned array after one visible edit. */\n onChange: (models: DeepSeekModelDraft[]) => void\n /** Remove the user-owned array and return to inheritance. */\n onReset: () => void\n}\n\n/**\n * Render the direct DeepSeek adapter's model catalog: id and display name on\n * each row, capacities behind the row's own disclosure.\n * @param props - effective rows plus the array-level override actions.\n * @returns the catalog editor.\n */\nexport function DeepSeekModelsEditor(props: DeepSeekModelsEditorProps): ReactNode {\n // Capacities are edited as text, so a field's keystrokes are held here\n // rather than re-derived from the parsed count on every change, which would\n // rewrite `1000` to `1K` mid-word. Unreadable text is kept past blur so the\n // save-time rejection names a row the user can still see — which is why\n // this is one entry PER FIELD: a single active buffer would be displaced by\n // editing any other field, and the abandoned one would fall back to\n // rendering its stored NaN as the literal `NaN`.\n //\n // Keys carry the row index, so the two operations that move indexes maintain\n // them: `remove` re-keys around the dropped row, and reset clears them all\n // because the rows they annotated are gone.\n const [editing, setEditing] = useState<ReadonlyMap<string, string>>(() => new Map())\n const [expanded, setExpanded] = useState<ReadonlySet<number>>(() => new Set())\n\n const update = (index: number, key: CatalogField, value: unknown): void => {\n const next = props.models.map((model, at) => {\n const copy = { ...model }\n if (at !== index) return copy\n if (value === undefined) Reflect.deleteProperty(copy, key)\n else copy[key] = value\n return copy\n })\n props.onChange(next)\n }\n\n const remove = (index: number): void => {\n setEditing((current) => {\n const next = new Map<string, string>()\n for (const [key, text] of current) {\n const at = rowOf(key)\n if (at === index) continue\n // Only the row number moves; the field half of the key is untouched.\n next.set(at > index ? key.replace(/^\\d+/, String(at - 1)) : key, text)\n }\n return next\n })\n setExpanded((current) => {\n const next = new Set<number>()\n for (const at of current) {\n if (at === index) continue\n next.add(at > index ? at - 1 : at)\n }\n return next\n })\n props.onChange(props.models.filter((_model, at) => at !== index).map(model => ({ ...model })))\n }\n\n const reset = (): void => {\n setEditing(new Map())\n setExpanded(new Set())\n props.onReset()\n }\n\n const toggle = (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 /** The field's text: its live keystrokes, else the stored count spelled short. */\n const capacityText = (model: DeepSeekModelDraft, index: number, field: CapacityField): string => {\n const typed = editing.get(`${String(index)}:${field}`)\n if (typed !== undefined) return typed\n const value = model[field]\n return typeof value === 'number' ? formatCapacity(value) : ''\n }\n\n const settleCapacity = (index: number, field: CapacityField): void => {\n const key = `${String(index)}:${field}`\n const typed = editing.get(key)\n if (typed === undefined) return\n // Unreadable text stays on screen: the save-time rejection names a row the\n // user can still see and correct.\n const parsed = parseCapacity(typed)\n if (parsed !== undefined && Number.isNaN(parsed)) return\n setEditing((current) => {\n const next = new Map(current)\n next.delete(key)\n return next\n })\n }\n\n /** One capacity field of one row, rendered inside the row's disclosure. */\n const capacityField = (\n model: DeepSeekModelDraft,\n index: number,\n field: CapacityField,\n fallback: number | undefined,\n ): ReactNode => (\n <label className={styles['modelField']}>\n <span className={styles['modelFieldLabel']}>{props.t(field === 'contextWindow' ? 'contextWindow' : 'maxTokens')}</span>\n <input\n className={styles['input']}\n type=\"text\"\n inputMode=\"numeric\"\n value={capacityText(model, index, field)}\n placeholder={fallback === undefined\n ? props.t(field === 'contextWindow' ? 'contextWindowPlaceholder' : 'maxTokensPlaceholder')\n : formatCapacity(fallback)}\n aria-label={`${props.t(field === 'contextWindow' ? 'contextWindow' : 'maxTokens')} ${String(index + 1)}`}\n disabled={props.disabled}\n onChange={(event) => {\n const text = event.target.value\n setEditing(current => new Map(current).set(`${String(index)}:${field}`, text))\n update(index, field, parseCapacity(text))\n }}\n onBlur={() => { settleCapacity(index, field) }}\n />\n </label>\n )\n\n return (\n <section className={styles['modelCatalog']} aria-label={props.t('models')}>\n <div className={styles['modelListHead']}>\n <div className={styles['modelCatalogHeading']}>\n <span className={styles['modelCatalogTitle']}>{props.t('models')}</span>\n <span className={styles['modelCatalogMeta']}>\n {props.overridden ? props.t('modelsCustomized') : props.t('modelsInherited')}\n </span>\n </div>\n {props.overridden\n ? (\n <button\n type=\"button\"\n className={styles['linkButton']}\n disabled={props.disabled}\n onClick={reset}\n >\n {props.t('resetModels')}\n </button>\n )\n : null}\n </div>\n {props.models.length === 0\n ? <p className={styles['modelEmpty']}>{props.t('modelsEmpty')}</p>\n : (\n <div className={styles['modelList']}>\n {props.models.map((model, index) => (\n <div className={styles['modelEntry']} key={index}>\n <div className={styles['modelRow']}>\n <input\n className={styles['input']}\n type=\"text\"\n value={typeof model['id'] === 'string' ? model['id'] : ''}\n placeholder={props.t('modelId')}\n aria-label={`${props.t('modelId')} ${String(index + 1)}`}\n disabled={props.disabled}\n onChange={(event) => { update(index, 'id', event.target.value) }}\n onBlur={(event) => {\n // Settle a pasted id rather than trimming per keystroke,\n // which would stop the user typing an interior space.\n const trimmed = event.target.value.trim()\n if (trimmed !== event.target.value) update(index, 'id', trimmed)\n }}\n />\n <input\n className={styles['input']}\n type=\"text\"\n value={typeof model['name'] === 'string' ? model['name'] : ''}\n placeholder={props.t('modelName')}\n aria-label={`${props.t('modelName')} ${String(index + 1)}`}\n disabled={props.disabled}\n onChange={(event) => {\n update(index, 'name', event.target.value === '' ? undefined : event.target.value)\n }}\n />\n <button\n type=\"button\"\n className={styles['iconButton']}\n aria-label={`${props.t('modelAdvanced')} ${String(index + 1)}`}\n aria-expanded={expanded.has(index)}\n title={props.t('modelAdvanced')}\n onClick={() => { toggle(index) }}\n >\n {expanded.has(index) ? <IconChevronDownOutline14 /> : <IconChevronRightOutline14 />}\n </button>\n <button\n type=\"button\"\n className={`${styles['iconButton']} ${styles['iconButtonDanger']}`}\n aria-label={`${props.t('removeModel')} ${String(index + 1)}`}\n title={props.t('removeModel')}\n disabled={props.disabled}\n onClick={() => { remove(index) }}\n >\n <IconTrashOutline16 size={14} />\n </button>\n </div>\n {expanded.has(index)\n ? (\n <div className={styles['modelAdvanced']}>\n {capacityField(model, index, 'contextWindow', props.defaultContextWindow)}\n {capacityField(model, index, 'maxTokens', props.defaultMaxTokens)}\n </div>\n )\n : null}\n </div>\n ))}\n </div>\n )}\n <button\n type=\"button\"\n className={styles['addModelButton']}\n disabled={props.disabled}\n onClick={() => { props.onChange([...props.models.map(model => ({ ...model })), { id: '' }]) }}\n >\n <IconPlusOutline16 size={14} />\n {props.t('addModel')}\n </button>\n </section>\n )\n}\n","/**\n * Models settings page store: one snapshot joining the configurable-provider\n * directory (`llm.providers`), 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 {\n ConfigurableProviderView, CredentialView, IApiClient, SettingsNamespaceView,\n} from '@deepseek-ai/dsh-api-remotes/client'\nimport type { SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client'\nimport { createSnapshotStore } from '@deepseek-ai/dsh-client-runtime/client'\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 the page renders. */\nexport interface ProviderRow {\n /** The directory entry (route id, display name, settings address, live state). */\n entry: ConfigurableProviderView\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: CredentialView | undefined\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 * Human text for a rejected wire call. A transport failure rejects with an\n * Error; a host or a runtime can reject with anything, and the page still has\n * to say something.\n * @param error - the rejection value.\n * @returns the message to show.\n */\nexport function messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\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 api - the wire face (credentials/llm domains, and settings writes).\n * @param describeFace - the shared mirror's describe face (namespace views and writability).\n */\n constructor(\n private readonly api: Pick<IApiClient, 'settings' | 'credentials' | 'llm'>,\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 let providers: ConfigurableProviderView[]\n let writable: boolean\n let views: readonly SettingsNamespaceView[]\n try {\n const [providersResponse] = await Promise.all([\n this.api.llm.providers({}),\n this.describeFace.ensure(),\n ])\n if (!providersResponse.result.ok) throw new Error(providersResponse.result.error.message)\n const mirrored = this.describeFace.getSnapshot()\n if (mirrored.view === undefined) {\n throw new Error(mirrored.error ?? 'settings are unavailable in this browser')\n }\n providers = providersResponse.result.value.providers\n writable = mirrored.view.writable\n views = mirrored.view.namespaces\n } catch (error) {\n if (generation !== this.generation) return\n this.store.update((s) => {\n s.status = 'error'\n s.error = error instanceof Error ? error.message : String(error)\n })\n return\n }\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.flatMap(row => row.apiKeyEnv === undefined ? [] : [row.apiKeyEnv]))]\n let credentials: Record<string, CredentialView> = {}\n let credentialError: string | null = null\n if (refs.length > 0) {\n try {\n const response = await this.api.credentials.describe({ refs })\n // Credential state is an enrichment for the Models page: neither a\n // business rejection nor a transport failure fails the load. The\n // onboarding projection below retains the failure distinction.\n if (response.result.ok) credentials = response.result.value.credentials\n else credentialError = response.result.error.message\n } catch (error) {\n credentialError = messageOf(error)\n }\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 ...row,\n ...row.apiKeyEnv !== undefined && credentials[row.apiKeyEnv] !== undefined\n ? { credential: credentials[row.apiKeyEnv] }\n : {},\n }))\n s.namespaces = namespaces\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","/* Models settings section, in the settings-panel design language: 14/22 body,\n * 12/18 caption, capsule controls (h36 r18; h28 r14 where a row is dense),\n * 32px fields, and `border-l2` hairlines — the vocabulary GeneralSection and\n * the Button/Input primitives already use.\n *\n * Every color resolves through a `--dsw-alias-*` token. Bare `--border` /\n * `--surface` / `--text-*` names, which nothing in this app defines, would\n * render the light-mode literals written as their fallbacks and stay light\n * under the dark theme. */\n\n.section {\n display: flex;\n flex-direction: column;\n gap: 12px;\n max-width: 720px;\n color: var(--dsw-alias-label-primary);\n}\n\n.title {\n margin: 0;\n font-size: 16px;\n line-height: 24px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n.intro {\n margin: 0;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.notice {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-warn-label);\n}\n\n.savedNotice {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-success-primary);\n}\n\n.rows {\n list-style: none;\n /* Extra air between the title/intro block and the first provider card. */\n margin: 12px 0 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n/* A configured provider: outlined on the panel fill, so the filled editor\n card it expands into reads as the nested object. */\n.rowCard {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n padding: 12px 14px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.rowHead {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.rowIdentity {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n}\n\n.rowName {\n font-size: 14px;\n line-height: 22px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n/* Reads as an annotation on the name, not as a second name: caption size and\n the secondary label tone, so it never competes with the row's own title. It\n sits inside `rowIdentity` with the credential dot, which is what keeps it\n beside the name rather than drifting toward the actions. */\n.rowTag {\n flex: none;\n padding: 1px 6px;\n border: 1px solid var(--dsw-alias-border-l3);\n border-radius: 4px;\n font-size: 11px;\n line-height: 16px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.credentialDot {\n box-sizing: border-box;\n display: inline-block;\n flex: none;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n}\n\n.credentialDotConfigured {\n background: var(--dsw-alias-state-success-primary);\n}\n\n.credentialDotMissing {\n background: var(--dsw-alias-state-error-primary);\n}\n\n.rowActions {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n margin-left: auto;\n}\n\n/* `box-sizing` on every control here: the app has no global border-box reset,\n so without it the outlined variants stand 2px taller than the filled ones\n they sit beside (Cancel next to Apply, Edit next to Delete). */\n.primaryButton,\n.secondaryButton,\n.addButton {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n height: 36px;\n padding: 0 14px;\n border: none;\n border-radius: 18px;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n cursor: pointer;\n}\n\n.primaryButton {\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n.primaryButton:hover:not(:disabled) {\n background: var(--dsw-alias-button-primary-hover);\n}\n\n.secondaryButton,\n.addButton {\n border: 1px solid var(--dsw-alias-border-l2);\n background: transparent;\n color: var(--dsw-alias-label-primary);\n}\n\n.secondaryButton:hover:not(:disabled),\n.addButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.secondaryButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n}\n\n.dangerButton {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 36px;\n padding: 0 14px;\n border: none;\n border-radius: 18px;\n background: transparent;\n color: var(--dsw-alias-state-error-primary);\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n cursor: pointer;\n}\n\n.dangerButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-danger);\n}\n\n/* Provider-row controls take the dense capsule (Button `.sm`). */\n.rowActions .secondaryButton,\n.rowActions .dangerButton {\n height: 28px;\n padding: 0 10px;\n border-radius: 14px;\n font-size: 12px;\n line-height: 18px;\n}\n\n.primaryButton:disabled,\n.secondaryButton:disabled,\n.dangerButton:disabled,\n.addButton:disabled,\n.linkButton:disabled,\n.addModelButton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n.primaryButton:focus-visible,\n.secondaryButton:focus-visible,\n.dangerButton:focus-visible,\n.addButton:focus-visible,\n.linkButton:focus-visible,\n.addModelButton:focus-visible,\n.iconButton:focus-visible,\n.customizedSummary:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n/* Editing surface: a filled module on the panel, matching the settings\n selector fill rather than adding another outline inside the row. */\n.editor {\n border-radius: 12px;\n background: var(--dsw-alias-bg-module-platform);\n padding: 14px 16px;\n display: flex;\n flex-direction: column;\n gap: 14px;\n}\n\n.editorHeader {\n display: flex;\n align-items: baseline;\n gap: 8px;\n}\n\n.editorTitle {\n font-size: 14px;\n line-height: 22px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n.editorRoute {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.fieldLabel {\n display: inline-flex;\n align-items: center;\n gap: 10px;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n.linkButton {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n height: 28px;\n padding: 0 10px;\n border: none;\n border-radius: 14px;\n background: transparent;\n color: var(--dsw-alias-label-tertiary);\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n cursor: pointer;\n}\n\n.linkButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-secondary);\n}\n\n.advancedHint {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.editorActions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n}\n\n.addBlock {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n/* The two ways to gain a provider, as equal siblings spanning the same width\n as the rows above. Wraps rather than shrinking below a legible label. */\n.addActions {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n}\n\n.addButton {\n /* Overrides the shared button base above: these two are not pills sitting in\n a footer but the last slot of the provider list, so they split the row\n evenly and repeat the row cards' corner. Dashed, like every other \"nothing\n here yet\" affordance on this page, to read as a place rather than a\n command. */\n flex: 1 1 0;\n min-width: 180px;\n gap: 6px;\n height: 44px;\n border: 1px dashed var(--dsw-alias-border-l3);\n border-radius: 12px;\n}\n\n.addCard,\n.setupCard {\n border-radius: 12px;\n background: var(--dsw-alias-bg-module-platform);\n padding: 14px 16px;\n display: flex;\n flex-direction: column;\n gap: 14px;\n list-style: none;\n}\n\n/* Nested in a card that already carries the module chrome. */\n.addCard .editor,\n.setupCard .editor {\n background: none;\n padding: 0;\n}\n\n.customized {\n border-top: 1px solid var(--dsw-alias-border-l2);\n padding-top: 10px;\n}\n\n/* Native disclosure marker replaced by a rotating chevron: the built-in\n triangle differs per engine and cannot take the label color. */\n.customizedSummary {\n display: flex;\n align-items: center;\n gap: 6px;\n width: fit-content;\n padding: 2px 4px;\n margin-left: -4px;\n border-radius: 6px;\n cursor: pointer;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n list-style: none;\n}\n\n.customizedSummary::-webkit-details-marker {\n display: none;\n}\n\n.customizedSummary::before {\n content: '';\n width: 5px;\n height: 5px;\n border-right: 1.5px solid currentcolor;\n border-bottom: 1.5px solid currentcolor;\n transform: rotate(-45deg) translate(-1px, -1px);\n transition: transform 120ms ease;\n}\n\n.customized[open] > .customizedSummary::before {\n transform: rotate(45deg) translate(-1px, -1px);\n}\n\n.customizedSummary:hover {\n color: var(--dsw-alias-label-primary);\n}\n\n.customizedBody {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding-top: 12px;\n}\n\n/* Model catalog: a table, not a stack of cards. The column captions are\n written once above the rows, so a row is one line of fields plus its\n delete control; each field still carries the indexed `aria-label` that\n names it, and the caption strip is hidden from assistive tech to keep\n that name from being announced twice. */\n.modelCatalog {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding-top: 12px;\n border-top: 1px solid var(--dsw-alias-border-l2);\n}\n\n.modelCatalogHeading {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.modelCatalogTitle {\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n.modelCatalogMeta,\n.modelEmpty {\n margin: 0;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n}\n\n/* Model list, shared with the pi-ai provider form: one bordered\n entry per model, id and display name on the row, capacities behind the\n row's own disclosure. The rules use this stylesheet's token vocabulary —\n `--dsw-alias-border-subtle`, `--dsw-alias-text-tertiary`, and\n `--dsw-alias-text-primary` are undefined here and would resolve to their\n light-mode literals. */\n.modelList {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.modelListHead {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 12px;\n}\n\n.modelEntry {\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n padding: 6px;\n}\n\n.modelRow {\n display: grid;\n grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) auto auto;\n align-items: center;\n gap: 6px;\n}\n\n/* Square, label-free affordances: the row's own inputs carry the meaning, so\n the actions stay glyphs and announce themselves through aria-label. */\n.iconButton {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n}\n\n.iconButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.iconButton:disabled {\n cursor: default;\n opacity: 0.4;\n}\n\n/* The delete glyph keeps the danger tint the rest of the section uses. */\n.iconButtonDanger:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-danger);\n color: var(--dsw-alias-state-error-primary);\n}\n\n.modelAdvanced {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 8px;\n padding: 8px 4px 2px;\n}\n\n/* EXT-only: sibling of `.modelAdvanced` (NOT a child of it). Must break out\n of any grid/flex on an ancestor and span the full entry width, otherwise a\n deep grid context would squeeze this block into a narrow column. */\n.modelExtensionFields {\n display: block;\n width: 100%;\n box-sizing: border-box;\n}\n\n.modelField {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.modelFieldLabel {\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n}\n\n.modelEmpty {\n padding: 12px;\n border: 1px dashed var(--dsw-alias-border-l3);\n border-radius: 8px;\n text-align: center;\n}\n\n.addModelButton {\n box-sizing: border-box;\n align-self: flex-start;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n height: 28px;\n padding: 0 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 14px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n cursor: pointer;\n}\n\n.addModelButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.input {\n box-sizing: border-box;\n width: 100%;\n height: 32px;\n padding: 0 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n}\n\n/* Enum pickers hold a handful of short options; a field-width dropdown reads\n as a text field the user is expected to fill. */\nselect.input {\n max-width: 240px;\n cursor: pointer;\n}\n\n.input:focus {\n outline: none;\n border-color: var(--dsw-alias-brand-primary);\n}\n\n.input::placeholder {\n color: var(--dsw-alias-label-dimmed);\n}\n\n.input:disabled {\n opacity: 0.6;\n cursor: default;\n}\n\n/* Select variant of .input: replaces the OS arrow (which sits flush against\n the right edge) with the shared 12px chevron inset like the composer's\n .select chips; the right pad reserves its cell. */\n.selectInput {\n appearance: none;\n padding-right: 32px;\n /* Data-URI SVGs cannot resolve CSS variables; #81858C is the caption gray\n shared by both themes. */\n 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\");\n background-repeat: no-repeat;\n background-position: right 12px center;\n background-size: 12px 12px;\n}\n\n.error {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-error-primary);\n}\n\n.deleteDialog {\n width: min(480px, 100%);\n}\n\n.deleteConfirm:not(:disabled) {\n border-color: var(--dsw-alias-state-error-primary);\n color: var(--dsw-alias-state-error-primary);\n}\n\n.deleteConfirm:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-danger);\n}\n\n/* Icon-button label seat: named for assistive tech and for the tests that\n query these controls by their text. */\n.hiddenLabel {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .customizedSummary::before {\n transition: none;\n }\n}\n\n.fetchDialog {\n max-width: 520px;\n\n /* The candidate list scrolls inside this dialog, an elevated surface, so the\n scrollbar indirection is rebound here rather than on the scrolling child:\n the elevation choice belongs with the surface and inherits down (see\n ui-theme styles/scrollbar.css for the contract). */\n --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);\n --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);\n}\n\n.candidateActions {\n display: flex;\n justify-content: flex-end;\n margin-bottom: 6px;\n}\n\n.candidateList {\n display: flex;\n flex-direction: column;\n gap: 2px;\n max-height: 320px;\n margin: 0;\n overflow-y: auto;\n padding: 0;\n list-style: none;\n}\n\n.candidate {\n border-radius: 6px;\n}\n\n.candidateLabel {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n cursor: pointer;\n}\n\n.candidateId {\n flex: 1 1 auto;\n font-family: var(--ds-font-family-code);\n font-size: 13px;\n overflow-wrap: anywhere;\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 @ rc.2). 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 @ rc.2). */\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 @ rc.2). */\nexport const THINKING_FORMATS = [\n 'openai',\n 'deepseek',\n 'openrouter',\n 'together',\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/** 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 customNeedsModels: 'A custom provider needs at least one model.',\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 adapterVersion: 'Current adapter: {version}',\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 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 customNeedsModels: '自定义提供方至少需要一个模型。',\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 adapterVersion: '当前适配器:{version}',\n extDeclare: '声明',\n extSection: '模型扩展',\n extSectionHint: 'settings.yaml 中按模型生效的扩展字段。',\n supportsReasoningEffort: '端点接受推理挡位参数(reasoning_effort)',\n reasoningEfforts: '推理挡位',\n reasoningEffortLevel: '挡位',\n reasoningEffortWire: '线上取值',\n reasoningEffortOffHint: '“off”不需要线上取值。',\n reasoningEffortEmptyWire: '除 off 外勾选的挡位必须填写线上取值。',\n reasoningEffortsNeedNonOff: '至少声明一个 off 以外的挡位。',\n inputModalities: '输入模态',\n inputNeedOne: '至少保留一个模态。',\n thinkingFormat: '思考格式',\n}\n","/**\n * Per-model extension fields for the Models+ page (dsh-model-extension only).\n *\n * Edits one model draft object in place — the same record the official\n * ModelListEditor card holds — so persistence rides the card's existing\n * `applyOnce()` path-ops save with no extra wire calls. Fields written:\n *\n * reasoningEfforts { [level]: wire | null } declared thinking levels\n * input Modality[] accepted input modalities\n * compat.supportsReasoningEffort boolean endpoint accepts reasoning_effort\n * compat.thinkingFormat wire format how reasoning is serialised\n *\n * NOTE: there is deliberately NO \"default effort\" (model-level reasoningEffort)\n * control here. DSH's `modelFields` schema has no such key — the runtime derives\n * `model.reasoning.defaultEffort` from `reasoningEfforts` + the route-level\n * `reasoning` default, so a hand-written `reasoningEffort` is silently stripped\n * (or, if written without an `id`, fails `modelProfile.id:required` and rejects\n * the whole `llm-pi-ai` block). Default effort is observable, never persisted,\n * from this extension. See dsh-compatibility-check/llm-pi-ai-config-nodes_*.md.\n *\n * Linkage: `supportsReasoningEffort` gates the visibility (and presence in the\n * draft) of reasoningEfforts / thinkingFormat. Clearing it removes those nodes\n * from the draft IN ONE onChange commit, so partial updates never overwrite\n * each other.\n */\nimport type { ReactNode } from 'react'\nimport styles from './ModelsSection.ext.module.css'\nimport {\n MODALITIES, THINKING_FORMATS, THINKING_LEVELS, en as extensionEn, zh as extensionZh,\n} from './extension-meta.ts'\nimport type { ThinkingFormat, ThinkingLevel } from './extension-meta.ts'\n\n/** One models[] entry as the card holds it (structurally open). */\ntype ModelDraft = Record<string, unknown>\n\n/** Row-level field writer: merge/clear keys on this row's draft object. */\ntype PatchModel = (next: Record<string, unknown>) => void\n\n/** Chinese display names for the thinking levels (wire value stays in parentheses). */\nconst LEVEL_LABELS: Record<ThinkingLevel, { zh: string; en: string }> = {\n off: { zh: '关闭', en: 'Off' },\n minimal: { zh: '极小', en: 'Minimal' },\n low: { zh: '低', en: 'Low' },\n medium: { zh: '中', en: 'Medium' },\n high: { zh: '高', en: 'High' },\n xhigh: { zh: '超高', en: 'Extra High' },\n max: { zh: '最大', en: 'Max' },\n}\n\n/** Chinese display names for the input modalities. */\nconst MODALITY_LABELS: Record<string, { zh: string; en: string }> = {\n text: { zh: '文本', en: 'Text' },\n image: { zh: '图像', en: 'Image' },\n}\n\n/** Shared checkbox inline style (matches the host's checkbox look). */\nconst checkboxStyle: React.CSSProperties = {\n width: '15px',\n height: '15px',\n margin: 0,\n accentColor: 'var(--dsw-alias-brand-primary)',\n flex: 'none',\n}\n\nexport interface ModelExtensionFieldsProps {\n /** The row's current draft object (read). */\n model: ModelDraft\n /** Merge these keys into the row; `undefined` values clear them. */\n onChange: PatchModel\n /** Disable every control (read-only deployment or pending write). */\n disabled?: boolean\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/false/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/**\n * Render the extension block for one model row.\n * @param props - the row draft, its writer, and the disabled flag.\n * @returns the extension fields section.\n */\nexport function ModelExtensionFields(props: ModelExtensionFieldsProps): ReactNode {\n const { model, onChange, disabled = false } = props\n // Extension copy is bilingual static (not the slot `t` seat): this block\n // renders inside the official card whose translate speaks only upstream\n // keys. Language follows the host UI via document lang, read per render.\n const isZh = typeof document !== 'undefined' && document.documentElement.lang.startsWith('zh')\n const t = (key: keyof typeof extensionEn): string =>\n (isZh ? extensionZh : extensionEn)[key]\n const levelLabel = (level: ThinkingLevel): string =>\n isZh ? `${LEVEL_LABELS[level].zh} (${level})` : `${LEVEL_LABELS[level].en} (${level})`\n const modalityLabel = (modality: string): string =>\n isZh ? MODALITY_LABELS[modality]?.zh ?? modality : MODALITY_LABELS[modality]?.en ?? modality\n\n const compat = compatOf(model)\n const supportsReasoningEffort = compat['supportsReasoningEffort'] === true\n\n /** Write one key into `compat`, merging into the row's existing compat and\n * clearing the whole `compat` node when it would become empty. Used for\n * `supportsReasoningEffort` and `thinkingFormat` ONLY — those are the only\n * model extension fields that live under `compat`. */\n const setCompatKey = (key: string, value: unknown): void => {\n const next = { ...compat }\n if (value === undefined) delete next[key]\n else next[key] = value\n // An emptied compat object leaves no trace, like any cleared optional field.\n onChange({ compat: Object.keys(next).length === 0 ? undefined : next })\n }\n\n const setEfforts = (efforts: Record<string, string | null> | undefined): void => {\n onChange({ reasoningEfforts: efforts })\n }\n\n const setInput = (modalities: string[]): void => {\n onChange({ input: modalities.length === 0 ? undefined : modalities })\n }\n\n const toggleLevel = (level: ThinkingLevel, checked: boolean): void => {\n const efforts = { ...(effortsOf(model) ?? {}) }\n if (checked) {\n // off carries no wire value; every other level defaults to its own name.\n efforts[level] = level === 'off' ? null : level\n } else {\n delete efforts[level]\n }\n const next: Record<string, unknown> = {\n reasoningEfforts: Object.keys(efforts).length === 0 ? undefined : efforts,\n }\n onChange(next)\n }\n\n const setWireValue = (level: ThinkingLevel, text: string): void => {\n const efforts = { ...(effortsOf(model) ?? {}) }\n if (!(level in efforts)) return\n efforts[level] = text.trim().length === 0 ? null : text.trim()\n setEfforts(efforts)\n }\n\n const toggleModality = (modality: string, checked: boolean): void => {\n const current = Array.isArray(model['input'])\n ? (model['input'] as string[])\n : ['text']\n setInput(checked\n ? [...new Set([...current, modality])]\n : current.filter(entry => entry !== modality))\n }\n\n const efforts = effortsOf(model)\n const declaredLevels = efforts === undefined ? [] : THINKING_LEVELS.filter(level => level in efforts)\n const inputList = Array.isArray(model['input']) ? model['input'] as string[] : []\n const thinkingFormat = typeof compat['thinkingFormat'] === 'string'\n ? compat['thinkingFormat'] as ThinkingFormat\n : undefined\n // Validation mirrors the host's own checks: only `off` may carry an empty\n // wire value, and a declaration needs at least one non-off level.\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 /** One declared level's wire-value row inside the levels table. */\n const wireRow = (level: ThinkingLevel): ReactNode => {\n const isOff = level === 'off'\n return isOff\n ? <span style={{ fontSize: 12, color: 'var(--color-text-tertiary, #999)' }}>—</span>\n : (\n <input\n className={styles['input']}\n type=\"text\"\n value={String(efforts?.[level] ?? '')}\n aria-label={`${t('reasoningEffortWire')} ${level}`}\n placeholder={level}\n disabled={disabled}\n onChange={event => { setWireValue(level, event.target.value) }}\n />\n )\n }\n\n return (\n <fieldset style={{ border: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: 14 }}>\n {/* --- compat: supportsReasoningEffort ------------------------------ */}\n <div style={{ borderTop: '0.5px solid var(--color-border-tertiary, rgba(0,0,0,0.15))', paddingTop: 12 }}>\n <label style={{ display: 'inline-flex', alignItems: 'center', gap: 8, cursor: 'pointer' }}>\n <input\n type=\"checkbox\"\n style={checkboxStyle}\n checked={supportsReasoningEffort}\n disabled={disabled}\n onChange={(event) => {\n if (event.target.checked) {\n // Turning the gate on declares the compat flag alone; the\n // levels table below appears empty for the user to fill in.\n setCompatKey('supportsReasoningEffort', true)\n } else {\n // Turning it off clears the flag AND every gated node in ONE\n // commit — two separate onChange calls would each start from\n // the same stale draft and overwrite each other. `reasoningEfforts`\n // and `thinkingFormat` are dropped together; there is no\n // model-level default-effort key to clear (DSH derives it).\n const nextCompat = { ...compat }\n delete nextCompat['supportsReasoningEffort']\n delete nextCompat['thinkingFormat']\n onChange({\n compat: Object.keys(nextCompat).length === 0 ? undefined : nextCompat,\n reasoningEfforts: undefined,\n })\n }\n }}\n />\n <span className={styles['modelFieldLabel']}>{t('supportsReasoningEffort')}</span>\n </label>\n </div>\n\n {/* --- gated by supportsReasoningEffort ------------------------------- */}\n {!supportsReasoningEffort ? null : (\n <>\n <div>\n <div className={styles['modelFieldLabel']} style={{ marginBottom: 6 }}>{t('reasoningEfforts')}</div>\n <div style={{\n border: '0.5px solid var(--color-border-tertiary, rgba(0,0,0,0.15))',\n borderRadius: 'var(--border-radius-md, 8px)',\n overflow: 'hidden',\n }}>\n {/* table header */}\n <div style={{\n display: 'grid',\n gridTemplateColumns: '56px 1fr 1fr',\n fontSize: 12,\n color: 'var(--color-text-secondary, #666)',\n background: 'var(--color-background-secondary, #f5f5f5)',\n }}>\n <div style={{ padding: '5px 10px' }}>{t('extDeclare')}</div>\n <div style={{ padding: '5px 10px', borderLeft: '0.5px solid var(--color-border-tertiary, rgba(0,0,0,0.15))' }}>{t('reasoningEffortLevel')}</div>\n <div style={{ padding: '5px 10px', borderLeft: '0.5px solid var(--color-border-tertiary, rgba(0,0,0,0.15))' }}>{t('reasoningEffortWire')}</div>\n </div>\n {/* one row per level, all levels always visible */}\n {THINKING_LEVELS.map((level, at) => (\n <div\n key={level}\n style={{\n display: 'grid',\n gridTemplateColumns: '56px 1fr 1fr',\n alignItems: 'center',\n borderTop: at === 0 ? 'none' : '0.5px solid var(--color-border-tertiary, rgba(0,0,0,0.15))',\n }}\n >\n <div style={{ padding: '5px 10px', display: 'flex', justifyContent: 'center' }}>\n <input\n type=\"checkbox\"\n style={checkboxStyle}\n checked={level in (efforts ?? {})}\n disabled={disabled}\n onChange={(event) => { toggleLevel(level, event.target.checked) }}\n />\n </div>\n <div style={{\n padding: '5px 10px',\n fontSize: 13,\n borderLeft: '0.5px solid var(--color-border-tertiary, rgba(0,0,0,0.15))',\n opacity: level in (efforts ?? {}) ? 1 : 0.5,\n }}>\n {levelLabel(level)}\n </div>\n <div style={{\n padding: '5px 10px',\n borderLeft: '0.5px solid var(--color-border-tertiary, rgba(0,0,0,0.15))',\n opacity: level in (efforts ?? {}) ? 1 : 0.4,\n }}>\n {level in (efforts ?? {}) ? wireRow(level) : <span style={{ fontSize: 12, color: 'var(--color-text-tertiary, #999)' }}>—</span>}\n </div>\n </div>\n ))}\n </div>\n {(hasEmptyWire || onlyOffDeclared)\n ? (\n <p className={styles['error']} style={{ marginTop: 6 }}>\n {hasEmptyWire ? t('reasoningEffortEmptyWire') : t('reasoningEffortsNeedNonOff')}\n </p>\n )\n : null}\n </div>\n\n <label className={styles['modelField']} style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>\n <span className={styles['modelFieldLabel']}>{t('thinkingFormat')}</span>\n <select\n className={styles['input']}\n value={thinkingFormat ?? ''}\n disabled={disabled}\n onChange={(event) => {\n const value = event.target.value\n setCompatKey('thinkingFormat', value === '' ? undefined : value)\n }}\n >\n <option value=\"\">—</option>\n {THINKING_FORMATS.map(format => <option key={format} value={format}>{format}</option>)}\n </select>\n </label>\n </>\n )}\n\n {/* --- input modalities ------------------------------------------------ */}\n <div style={{ borderTop: '0.5px solid var(--color-border-tertiary, rgba(0,0,0,0.15))', paddingTop: 12 }}>\n <div className={styles['modelFieldLabel']} style={{ marginBottom: 6 }}>{t('inputModalities')}</div>\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: 16 }}>\n {MODALITIES.map(modality => (\n <label key={modality} style={{ display: 'inline-flex', alignItems: 'center', gap: 6, cursor: 'pointer', fontSize: 13 }}>\n <input\n type=\"checkbox\"\n style={checkboxStyle}\n checked={inputList.includes(modality)}\n disabled={disabled}\n onChange={(event) => { toggleModality(modality, event.target.checked) }}\n />\n {modalityLabel(modality)}\n </label>\n ))}\n </div>\n </div>\n </fieldset>\n )\n}\n","/**\n * The model list of one pi-ai provider profile (EXT fork for dsh-model-extension).\n *\n * Forked from deepseek-harness packages/client/ui-settings-models\n * src/client/ModelListEditor.tsx @ 0.1.1-rc.2.\n * Only difference vs upstream: each row's expanded capacities area additionally\n * renders <ModelExtensionFields>, which edits the same draft object in place —\n * the extension fields ride the card's existing save path untouched.\n *\n * The list is the profile's `models` array as the card holds it: an empty list\n * means \"serve this route's built-in catalog\", and any entry replaces that\n * catalog, so a row is only ever added deliberately. Fetching asks the endpoint\n * **the form currently shows** — including a key typed but not yet saved — so\n * adding a provider is one pass instead of save-then-return; the reply is\n * candidates the user picks from, never configuration written behind them.\n *\n * A provider that cannot be interrogated (an unreachable endpoint, a protocol\n * with no readable listing) is not a dead end: the failure is shown next to the\n * rows the user can still fill in by hand.\n */\n\nimport { useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { DiscoveredModelView, IApiClient } from '@deepseek-ai/dsh-api-remotes/client'\nimport { Button, Modal } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { formatCapacity, parseCapacity } from './DeepSeekModelsEditor.tsx'\nimport type { DeepSeekModelDraft } from './DeepSeekModelsEditor.tsx'\nimport { messageOf } from './store.ts'\nimport type { en } from './locales.ts'\nimport { ModelExtensionFields } from './ModelExtensionFields.tsx'\nimport styles from './ModelsSection.ext.module.css'\n\n/**\n * One configured model row. Structurally open, exactly like the DeepSeek\n * catalog editor's rows: a profile field this card does not edit — one a future\n * schema adds, or one hand-written in `settings.yaml` — has to survive being\n * edited here rather than being dropped by a rebuild.\n */\nexport type ModelDraft = DeepSeekModelDraft\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/** A row's numeric field, or `undefined` when unset or not a number. */\nfunction numberOf(model: ModelDraft, key: string): number | undefined {\n const value = model[key]\n return typeof value === 'number' ? value : undefined\n}\n\n/** What an interrogation needs, taken from the live form. */\nexport interface ProbeTarget {\n /** Settings namespace whose adapter family answers. */\n settingsNs: string\n /**\n * Route being edited, when the card edits one. An adapter that already\n * describes it answers from its own registry, so such a card can ask without\n * an endpoint at all.\n */\n provider?: string\n /** Endpoint as the form currently shows it. */\n baseURL?: string\n /** Wire protocol the form names, when it names one. */\n api?: string\n /** Key typed into the form and not yet stored, when there is one. */\n apiKey?: string\n}\n\n/** Props of {@link ModelListEditor}. */\nexport interface ModelListEditorProps {\n /** The rows as currently drafted. */\n models: readonly ModelDraft[]\n /** Whether the user layer currently owns the whole array; absent on a create. */\n overridden?: boolean\n /** Replace the drafted rows. */\n onChange: (models: ModelDraft[]) => void\n /** Remove the user-owned array and return to inheritance; absent on a create. */\n onReset?: () => void\n /** Endpoint facts for the fetch action. */\n probe: ProbeTarget\n /**\n * Copy key naming why the fetch action is unavailable, or `undefined` when\n * it is. The card owns this because the key it would send is judged there:\n * asking with a key the form has already refused spends a round trip to be\n * told what the field already says.\n */\n probeBlocked?: keyof typeof en | undefined\n /** Wire face the fetch action calls. */\n api: Pick<IApiClient, 'llm'>\n /** Section copy. */\n t: (key: keyof typeof en) => string\n /** Disable every control (read-only deployment or a pending write). */\n disabled: boolean\n}\n\n/** Disclosure chevron; rotates to point down while its row is open. */\nfunction IconChevron({ open }: { open: boolean }): ReactNode {\n return (\n <svg\n width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden\n style={{ transform: open ? 'rotate(90deg)' : undefined, transition: 'transform 120ms ease' }}\n >\n <path d=\"M6 3.5L10.5 8L6 12.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n )\n}\n\n/** Removal glyph for one model row. */\nfunction IconTrash(): ReactNode {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden>\n <path\n 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\"\n stroke=\"currentColor\" strokeWidth=\"1.3\" strokeLinecap=\"round\" strokeLinejoin=\"round\"\n />\n </svg>\n )\n}\n\n/** The two token counts edited as K/M-suffixed text behind a row's disclosure. */\ntype CapacityField = 'contextWindow' | 'maxTokens'\n\n/**\n * What an empty capacity field is worth, shown as its placeholder so a row left\n * blank does not read as a model with no capacity at all.\n *\n * The magnitudes are the adapter's own route-level fallbacks (`llm-pi-ai`'s\n * `defaultContextWindow` and `defaultMaxTokens`), spelled the way a person\n * would say them. They are a hint, not a mirror: this page counts `K` as 1000,\n * so typing `256K` stores 256000 while leaving the field blank keeps the\n * adapter's 262144. A deployment that overrides those defaults is not\n * reflected here — nothing on this page can read them.\n */\nconst CAPACITY_HINT: Readonly<Record<CapacityField, string>> = {\n contextWindow: '256K',\n maxTokens: '32K',\n}\n\n/**\n * Spell a stored count for a field that may be unset. The spelling itself is\n * {@link formatCapacity}, shared with the DeepSeek catalog editor so both\n * surfaces read and write one K/M vocabulary.\n * @param value - stored capacity, or `undefined` for an unset field.\n * @returns the field text, empty when unset.\n */\nfunction capacitySpelling(value: number | undefined): string {\n return value === undefined ? '' : formatCapacity(value)\n}\n\n/** Adopt a candidate, keeping whatever capacities the provider disclosed. */\nfunction adopt(candidate: DiscoveredModelView): ModelDraft {\n return {\n id: candidate.id,\n ...candidate.name === undefined ? {} : { name: candidate.name },\n ...candidate.contextWindow === undefined ? {} : { contextWindow: candidate.contextWindow },\n ...candidate.maxTokens === undefined ? {} : { maxTokens: candidate.maxTokens },\n }\n}\n\n/**\n * Render the model list with its fetch action.\n * @param props - the drafted rows, probe target, wire face, and copy.\n * @returns the model-list editor.\n */\nexport function ModelListEditor(props: ModelListEditorProps): ReactNode {\n const { models, onChange, probe, api, t, disabled } = props\n const [busy, setBusy] = useState(false)\n const [failure, setFailure] = useState<string | undefined>(undefined)\n const [candidates, setCandidates] = useState<readonly DiscoveredModelView[] | undefined>(undefined)\n const [picked, setPicked] = useState<ReadonlySet<string>>(new Set())\n // Rows carry an id and a name; capacities are the exception, so they stay\n // folded until asked for rather than crowding every row with four inputs.\n const [expanded, setExpanded] = useState<ReadonlySet<number>>(new Set())\n // Capacities are edited as text, so a field's keystrokes are held here rather\n // than re-derived from the parsed count on every change — that would rewrite\n // `1000` to `1K` mid-word. Unreadable text is kept past blur so the refusal\n // names a row the user can still see, which is why this is one entry PER\n // FIELD: a single buffer would be displaced by editing any other field, and\n // the abandoned one would render its stored NaN as the literal `NaN`.\n const [editing, setEditing] = useState<ReadonlyMap<string, string>>(new Map())\n\n /** Buffer key for one capacity field; the row half moves when rows do. */\n const bufferKey = (index: number, field: CapacityField): string => `${String(index)}:${field}`\n\n const editCapacity = (index: number, field: CapacityField, text: string): void => {\n setEditing(current => new Map(current).set(bufferKey(index, field), text))\n patch(index, { [field]: parseCapacity(text) })\n }\n\n /** What a capacity field shows: the buffer while typing, else the stored count. */\n const capacityText = (model: ModelDraft, index: number, field: CapacityField): string =>\n editing.get(bufferKey(index, field)) ?? capacitySpelling(numberOf(model, field))\n\n /** Drop one row's entries and shift the rows after it down, in one pass. */\n const reindexOnRemove = (\n current: ReadonlyMap<string, string>,\n index: number,\n ): Map<string, string> => {\n const next = new Map<string, string>()\n for (const [key, value] of current) {\n const at = Number(key.slice(0, key.indexOf(':')))\n if (at === index) continue\n // Only the row number moves; the field half of the key is untouched.\n next.set(at > index ? key.replace(/^\\d+/, String(at - 1)) : key, value)\n }\n return next\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 patch = (index: number, next: Record<string, string | number | undefined>): void => {\n onChange(models.map((model, at) => {\n if (at !== index) return model\n // Rebuilt rather than spread over: an emptied optional field has to leave\n // the profile, not be stored as a value its schema would reject.\n // Spread first so a field this card does not edit survives; an emptied\n // optional field is then dropped rather than stored as a value its\n // schema would reject.\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 fetchModels = async (): Promise<void> => {\n setBusy(true)\n setFailure(undefined)\n try {\n const response = await api.llm.discoverModels({\n settingsNs: 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 (!response.result.ok) {\n setFailure(response.result.error.message)\n return\n }\n const found = response.result.value.models\n if (found.length === 0) {\n setFailure(t('fetchEmpty'))\n return\n }\n // Everything already configured starts unchecked, so adopting a\n // selection never silently rewrites a capacity the user corrected.\n const known = new Set(models.map(model => textOf(model, 'id')))\n setCandidates(found)\n setPicked(new Set(found.filter(model => !known.has(model.id)).map(model => model.id)))\n } catch (error) {\n // The transport rejected rather than answering; without this the button\n // would stay busy with nothing shown.\n setFailure(messageOf(error))\n } finally {\n setBusy(false)\n }\n }\n\n const closePicker = (): void => {\n setCandidates(undefined)\n setPicked(new Set())\n }\n\n const adoptPicked = (): void => {\n /* v8 ignore next -- the dialog only renders with candidates loaded */\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 // Keyed by id, so a half-typed row whose id is still empty is not a\n // match and the candidate joins as its own row — correct, since a row\n // without an id is not yet a model and the create/apply gates refuse it.\n byId.set(candidate.id, byId.get(candidate.id) ?? adopt(candidate))\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 allCandidatesPicked = activeCandidates.length > 0\n && activeCandidates.every(candidate => picked.has(candidate.id))\n\n const toggleAllCandidates = (): void => {\n setPicked((current) => {\n return activeCandidates.every(candidate => current.has(candidate.id))\n ? new Set()\n : new Set(activeCandidates.map(candidate => candidate.id))\n })\n }\n\n // A route the adapter already describes answers without an endpoint; only a\n // draft with neither has nothing to ask about.\n const askable = probe.provider !== undefined || (probe.baseURL !== undefined && probe.baseURL.length > 0)\n return (\n <section className={styles['modelCatalog']} aria-label={t('models')}>\n <div className={styles['modelListHead']}>\n <div className={styles['modelCatalogHeading']}>\n <span className={styles['modelCatalogTitle']}>{t('models')}</span>\n {props.overridden === undefined\n ? null\n : (\n <span className={styles['modelCatalogMeta']}>\n {props.overridden ? t('modelsCustomized') : t('modelsInherited')}\n </span>\n )}\n </div>\n {props.overridden === true && props.onReset !== undefined\n ? (\n <button\n type=\"button\"\n className={styles['linkButton']}\n disabled={disabled}\n onClick={props.onReset}\n >\n {t('resetModels')}\n </button>\n )\n : null}\n <button\n type=\"button\"\n className={styles['linkButton']}\n disabled={disabled || busy || !askable || props.probeBlocked !== undefined}\n title={props.probeBlocked !== undefined\n ? t(props.probeBlocked)\n : askable ? undefined : t('fetchNeedsBaseUrl')}\n onClick={() => { void fetchModels() }}\n >\n {busy ? t('fetching') : t('fetchModels')}\n </button>\n </div>\n {models.length === 0 ? <p className={styles['modelEmpty']}>{t('modelsEmpty')}</p> : null}\n {models.map((model, index) => (\n <div key={index} className={styles['modelEntry']}>\n <div className={styles['modelRow']}>\n <input\n className={styles['input']}\n type=\"text\"\n value={textOf(model, 'id')}\n placeholder={t('modelId')}\n aria-label={`${t('modelId')} ${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={t('modelName')}\n aria-label={`${t('modelName')} ${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={`${t('modelAdvanced')} ${index + 1}`}\n aria-expanded={expanded.has(index)}\n title={t('modelAdvanced')}\n onClick={() => { toggleExpanded(index) }}\n >\n <IconChevron open={expanded.has(index)} />\n </button>\n <button\n type=\"button\"\n className={`${styles['iconButton']} ${styles['iconButtonDanger']}`}\n aria-label={`${t('removeModel')} ${index + 1}`}\n title={t('removeModel')}\n disabled={disabled}\n onClick={() => {\n onChange(models.filter((_model, at) => at !== index))\n // Both stores are keyed by position, so every row after this\n // one shifts down and would otherwise inherit its neighbour's\n // state — a different row's capacities popping open, or its\n // half-typed text appearing in another row's field.\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 setEditing(current => reindexOnRemove(current, index))\n }}\n >\n <IconTrash />\n </button>\n </div>\n {expanded.has(index)\n ? (\n <>\n {/* Host `.modelAdvanced` is `display:grid` with\n `repeat(auto-fit, minmax(160px, 1fr))`; any child placed\n INSIDE it is squeezed into one narrow grid column. The\n extension fields need the full entry width, so they render\n as a SIBLING of `.modelAdvanced` — a direct child of the\n block-level `.modelEntry` — rather than inside its grid. */}\n <div className={styles['modelAdvanced']}>\n <label className={styles['modelField']}>\n <span className={styles['modelFieldLabel']}>{t('modelContextWindow')}</span>\n <input\n className={styles['input']}\n type=\"text\"\n inputMode=\"numeric\"\n value={capacityText(model, index, 'contextWindow')}\n placeholder={CAPACITY_HINT.contextWindow}\n aria-label={`${t('modelContextWindow')} ${index + 1}`}\n disabled={disabled}\n onChange={(event) => { editCapacity(index, 'contextWindow', event.target.value) }}\n />\n </label>\n <label className={styles['modelField']}>\n <span className={styles['modelFieldLabel']}>{t('modelMaxTokens')}</span>\n <input\n className={styles['input']}\n type=\"text\"\n inputMode=\"numeric\"\n value={capacityText(model, index, 'maxTokens')}\n placeholder={CAPACITY_HINT.maxTokens}\n aria-label={`${t('modelMaxTokens')} ${index + 1}`}\n disabled={disabled}\n onChange={(event) => { editCapacity(index, 'maxTokens', event.target.value) }}\n />\n </label>\n </div>\n {/* EXT-only: extension fields edit the same draft object in\n place; the card's own save path persists them untouched.\n patch is (index, next) — bind this row's index here. */}\n <div className={styles['modelExtensionFields']}>\n <ModelExtensionFields\n model={model}\n onChange={(next) => { patch(index, next) }}\n disabled={disabled}\n />\n </div>\n </>\n )\n : null}\n </div>\n ))}\n <button\n type=\"button\"\n className={styles['addModelButton']}\n disabled={disabled}\n onClick={() => { onChange([...models, { id: '' }]) }}\n >\n {t('addModel')}\n </button>\n {failure !== undefined ? <p className={styles['error']}>{failure}</p> : null}\n <Modal\n open={candidates !== undefined}\n onClose={closePicker}\n title={t('fetchTitle')}\n closeLabel={t('close')}\n description={t('fetchDescription')}\n className={styles['fetchDialog'] as string}\n footer={(\n <>\n <Button variant=\"outline\" onClick={closePicker}>{t('cancel')}</Button>\n <Button variant=\"outline\" onClick={adoptPicked}>{t('fetchAdopt')}</Button>\n </>\n )}\n >\n <div className={styles['candidateActions']}>\n <Button variant=\"ghost\" size=\"sm\" onClick={toggleAllCandidates}>\n {t(allCandidatesPicked ? 'fetchDeselectAll' : 'fetchSelectAll')}\n </Button>\n </div>\n <ul className={styles['candidateList']}>\n {(candidates ?? []).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 {/* The id alone: it is the string adoption writes, and the\n capacities the endpoint reported are adopted with it and\n editable in the row that appears. */}\n <span className={styles['candidateId']}>{candidate.id}</span>\n </label>\n </li>\n ))}\n </ul>\n </Modal>\n </section>\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.\n *\n * This is a create, not an edit, which is why it is its own card rather than\n * the provider editor with extra fields: the route id is being *chosen* here,\n * and the settings address does not exist until it is. One `settings.mutate`\n * sets the whole profile at `providers.<route>`; the key travels separately\n * through `credentials.set` under the reference the profile records, exactly as\n * an existing provider's key does.\n *\n * The three fields a hand-declared route cannot default — endpoint, protocol,\n * and at least one model — are required here rather than at load, so the\n * failure names the field while the user is still looking at it.\n *\n * There is deliberately no reasoning-effort control, here or on the editor\n * card: effort is a per-MODEL capability, and the models under one provider\n * disagree about it, so a provider-scoped control can only be set to a value\n * some of them reject. The composer's model picker offers each model its own\n * levels instead.\n */\n\nimport { useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { IApiClient } from '@deepseek-ai/dsh-api-remotes/client'\nimport { apiKeyFailure } from './apiKey.ts'\nimport { EditorFooter } from './EditorFooter.tsx'\nimport { validateDeepSeekModels } from './DeepSeekModelsEditor.tsx'\nimport { ModelListEditor } from './ModelListEditor.tsx'\nimport type { ModelDraft } from './ModelListEditor.tsx'\nimport { deriveKeyRef, messageOf } from './store.ts'\nimport type { en } from './locales.ts'\nimport styles from './ModelsSection.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 * The leading letter is the second half of that: `deriveKeyRef` uppercases the\n * id and replaces every non-alphanumeric run with `_`, and a credential\n * reference is a POSIX shell identifier, which cannot start with a digit. A\n * digit-leading id passes every check this card makes and then fails at the\n * credential seam with a raw regular expression the user cannot act on.\n */\nconst ROUTE_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/\n\n/** Props of {@link CustomProviderCard}. */\nexport interface CustomProviderCardProps {\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 /**\n * Revision of the `llm-pi-ai` user section this card opened at, sent with\n * the create so a route another tab declared meanwhile is a refusal rather\n * than a silent overwrite of its whole profile.\n */\n revision: number\n /** Wire faces for the write and for interrogating the endpoint. */\n api: Pick<IApiClient, 'settings' | 'credentials' | 'llm'>\n /** Section copy. */\n t: (key: keyof typeof en) => string\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, and copy.\n * @returns the creation card.\n */\nexport function CustomProviderCard(props: CustomProviderCardProps): ReactNode {\n const { taken, protocols, api, t } = props\n // Captured at mount, like the editor's: the write must be judged against the\n // section this card was drafted over, not whatever it grew into meanwhile.\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 [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 /**\n * The profile write landed. Only the key write can still be outstanding, so\n * the fields that describe the provider are settled and the retry path is\n * the credential alone.\n */\n const [committed, setCommitted] = useState(false)\n const disabled = props.readOnly || busy\n /** Everything but the key stops being editable once the provider exists. */\n const profileDisabled = disabled || committed\n\n const routeInvalid = route.length > 0 && !ROUTE_PATTERN.test(route)\n const routeTaken = taken.includes(route)\n // Rows are checked by the same per-row validator the editor cards use, so a\n // bad row is named by its position here too. Capacities have route-level\n // fallbacks; what a route cannot default is at least one model.\n const modelFailure = validateDeepSeekModels(models)\n const keyFailure = apiKeyFailure(keyDraft)\n // The typed key with paste whitespace removed. A blank field yields an empty\n // string, which the create path reads as \"no key supplied\" — a route may\n // legitimately authenticate through the provider's own ambient discovery.\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 // The one blocked gate worth a line under the form. A satisfied card says\n // nothing at all rather than printing an empty paragraph.\n const hint = failure !== undefined || ready\n // The key field prints its own failure directly beneath itself, so a card\n // blocked only by the key stays silent here rather than answering with the\n // next unmet gate — which is satisfied, and reads as a second, false fault.\n || keyFailure !== undefined\n // Same for the route id, and it must be tested rather than assumed: the\n // fallback arm below reads \"no models yet\", so an unmet route gate would\n // fall through to it and contradict the filled-in list right above.\n || route.length === 0 || routeInvalid || routeTaken\n ? undefined\n : baseURL.length === 0\n ? t('customNeedsBaseUrl')\n : modelFailure !== undefined\n ? `${t('model')} ${String(modelFailure.index + 1)}: ${t(modelFailure.key)}`\n : t('customNeedsModels')\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 // The profile names the conventional reference only when this card is\n // about to store a key, matching the editor: a route declared with the\n // key left blank keeps its provider-native auth path (a credential\n // chain, ADC) instead of resolving a reference nothing ever sets.\n ...storesKey ? { apiKeyEnv: keyRef } : {},\n api: protocol,\n baseURL,\n models: models.map(model => ({ ...model })),\n }\n const response = await api.settings.mutate({\n ns: NS,\n ops: [{ op: 'set', path: ['providers', route], value: profile }],\n // `taken` is a snapshot too, so the id check alone cannot see a route\n // declared after this card opened; the revision makes that race a\n // `settings-conflict` instead of a write over the other profile.\n expectedRevision: openedAt,\n })\n if (!response.result.ok) return response.result.error.message\n // The provider now exists. A retry after the key write below fails must\n // not re-run this mutate: the revision it holds is the one this write\n // just superseded, so the Host would answer `settings-conflict` and the\n // key could never be stored from this card at all.\n setCommitted(true)\n }\n if (storesKey) {\n const stored = await api.credentials.set({ ref: keyRef, value: keyValue })\n // The profile landed; saying the key did not is the only honest report,\n // and the retry above now goes straight back to this write.\n if (!stored.result.ok) return stored.result.error.message\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 } catch (error) {\n // A transport failure rejects rather than answering; without this the\n // card would stay busy with nothing shown.\n setFailure(messageOf(error))\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <div className={styles['editor']}>\n <div className={styles['editorHeader']}>\n <span className={styles['editorTitle']}>{t('customTitle')}</span>\n </div>\n <div className={styles['field']}>\n <span className={styles['fieldLabel']}>{t('customRoute')}</span>\n <input\n className={styles['input']}\n type=\"text\"\n value={route}\n placeholder=\"acme-gateway\"\n aria-label={t('customRoute')}\n disabled={profileDisabled}\n onChange={(event) => { setRoute(event.target.value) }}\n />\n </div>\n {/* A rejected id reads as a fault, not as guidance — the same split the\n key field below already makes between its failure and its hint. */}\n {routeInvalid || routeTaken\n ? <p className={styles['error']}>{t(routeInvalid ? 'customRouteInvalid' : 'customRouteTaken')}</p>\n : <p className={styles['advancedHint']}>{t('customRouteHint')}</p>}\n <div className={styles['field']}>\n <span className={styles['fieldLabel']}>{t('customDisplayName')}</span>\n <input\n className={styles['input']}\n type=\"text\"\n value={displayName}\n placeholder={route.length === 0 ? t('customDisplayName') : route}\n aria-label={t('customDisplayName')}\n disabled={profileDisabled}\n onChange={(event) => { setDisplayName(event.target.value) }}\n />\n </div>\n <div className={styles['field']}>\n <span className={styles['fieldLabel']}>{t('baseUrl')}</span>\n <input\n className={styles['input']}\n type=\"text\"\n value={baseURL}\n placeholder=\"https://gateway.example/v1\"\n aria-label={t('baseUrl')}\n disabled={profileDisabled}\n onChange={(event) => { setBaseURL(event.target.value) }}\n />\n </div>\n <div className={styles['field']}>\n <span className={styles['fieldLabel']}>{t('customApi')}</span>\n <select\n className={`${styles['input']} ${styles['selectInput']}`}\n value={protocol}\n aria-label={t('customApi')}\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 <span className={styles['fieldLabel']}>{t('keyInput')}</span>\n <input\n className={styles['input']}\n type=\"password\"\n autoComplete=\"off\"\n value={keyDraft}\n placeholder={t('keyPlaceholder')}\n aria-label={t('keyInput')}\n disabled={disabled}\n onChange={(event) => { setKeyDraft(event.target.value) }}\n />\n {/* A create card has no stored key to keep, so the blank case says\n what a blank field means here instead: this route may authenticate\n through the provider's own ambient discovery or OAuth. */}\n {keyFailure === undefined\n ? null\n : <p className={styles['error']}>{t(keyFailure === 'keyBlank' ? 'keyBlankNew' : keyFailure)}</p>}\n </div>\n <ModelListEditor\n models={models}\n onChange={setModels}\n probe={{\n settingsNs: NS,\n baseURL,\n api: protocol,\n ...keyValue.length === 0 ? {} : { apiKey: keyValue },\n }}\n probeBlocked={keyFailure === 'keyBlank' ? 'keyBlankNew' : keyFailure}\n api={api}\n t={t}\n disabled={profileDisabled}\n />\n {failure !== undefined ? <p className={styles['error']}>{failure}</p> : null}\n {/* Only the gates with something to say render; the route-id gate has its\n own field-level hint, so its blocked state would print an empty line. */}\n {hint === undefined ? null : <p className={styles['advancedHint']}>{hint}</p>}\n <EditorFooter\n t={t}\n busy={busy}\n submitDisabled={disabled || !ready}\n submitLabel=\"create\"\n submitBusyLabel=\"creating\"\n onCancel={() => { props.onClose(committed) }}\n onSubmit={() => { void create() }}\n />\n </div>\n )\n}\n","/**\n * One provider's editor card, hand-written per adapter family: the primary\n * field is a single write-only **API key** input (the page never asks for an\n * environment-variable name — a typed key stores through `credentials.set`\n * under the profile's reference, deriving `<ROUTE>_API_KEY` when the profile\n * has none. The pi-ai profile records that derivation as `apiKeyEnv` only when\n * a key is entered; a blank key materializes a reference-free profile for\n * provider-native authentication);\n * the collapsed 自定义设置 area carries the per-family extras (`baseURL` for\n * both families, DeepSeek's id/name/context-window model catalog, and the\n * display name and wire protocol of a pi-ai route the adapter does not ship —\n * the two fields the create card asked that route for, editable here for the\n * same reason).\n * Reasoning effort is deliberately absent: it is a per-MODEL capability, and\n * the models under one provider disagree about it, so a provider-scoped\n * control can only be set to a value some of them reject. The composer's\n * model picker offers each model its own levels; `settings.yaml` keeps the\n * profile field for a deployment that knows its route. Everything else stays\n * owned by `settings.yaml`. Profile edits land as minimal `settings.mutate`\n * path ops against the stored section — the card names only the fields it can\n * see instead of rebuilding the whole subtree from a partial descriptor.\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { CredentialView, IApiClient, SettingsNamespaceView, SettingsPathOpView } from '@deepseek-ai/dsh-api-remotes/client'\nimport {\n DeepSeekModelsEditor, modelDrafts, validateDeepSeekModels,\n} from './DeepSeekModelsEditor.tsx'\nimport { apiKeyFailure } from './apiKey.ts'\nimport { EditorFooter } from './EditorFooter.tsx'\nimport { ModelListEditor } from './ModelListEditor.tsx'\nimport { deriveKeyRef, messageOf, protocolChoices } from './store.ts'\nimport type { SettingsSchemaOperations } from './schema-operations.ts'\nimport type { en } from './locales.ts'\nimport styles from './ModelsSection.module.css'\n\n/** Per-adapter-family curated field sets (unknown namespaces get the hint alone). */\ntype EditorLayout = 'deepseek' | 'pi-ai' | 'unknown'\n\n/** The public DeepSeek endpoint shown as the deepseek base-URL placeholder. */\nconst DEEPSEEK_PUBLIC_BASE_URL = 'https://api.deepseek.com'\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 /** Hide the title row (the add card renders its own provider select). */\n hideTitle?: boolean\n /**\n * Whether the adapter reports this route as hand-declared — absent from its\n * installed catalog. Such a route carries its own wire protocol, chosen when\n * it was created and editable here for the same reason; a catalog route's\n * models each carry theirs, so a route-level protocol there could only\n * override every one of them and the card does not offer it.\n */\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 /** Wire faces for writes and for interrogating a provider endpoint. */\n api: Pick<IApiClient, 'settings' | 'credentials' | 'llm'>\n /** Section copy. */\n t: (key: keyof typeof en) => string\n /** Disable writes (read-only settings provider). */\n readOnly: boolean\n /** Render only the credential field and actions, without provider settings. */\n credentialOnly?: boolean\n /** Require a newly entered credential before this editor can submit. */\n credentialRequired?: boolean\n /** Give the credential field initial focus when this editor mounts. */\n autoFocusCredential?: boolean\n /** Override the dismiss action copy. */\n cancelLabel?: keyof typeof en\n /** Override the idle commit action copy. */\n submitLabel?: keyof typeof en\n /** Override the in-flight commit action copy. */\n submitBusyLabel?: keyof typeof en\n /** Close the editor; `changed` reports whether an Apply committed. */\n onClose: (changed: boolean) => void\n}\n\n/** A user-section subtree as a plain draft object (absent → empty). */\nfunction 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/**\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 })\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/** The editor layout the owning namespace selects. */\nfunction 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/** 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/**\n * Render one provider's editing card.\n * @param props - the addressed profile plus wire faces and copy.\n * @returns the editor card.\n */\nexport function ProviderEditor(props: ProviderEditorProps): ReactNode {\n const { namespace, schema, settingsPath, api, t } = props\n const [draft, setDraft] = useState<Record<string, unknown>>(() => draftAt(schema, namespace, settingsPath))\n const [keyDraft, setKeyDraft] = useState('')\n const [keyState, setKeyState] = useState<CredentialView | undefined>(undefined)\n const [busy, setBusy] = useState(false)\n const [failure, setFailure] = useState<string | undefined>(undefined)\n // A settings success advances both retry baselines immediately. Keeping the\n // derived fields in the draft prevents a pushed namespace refresh from\n // turning them into deletions when the following credential write is retried.\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 // The same schema read the create card makes, so the choices offered here\n // and there cannot drift apart: both come from the adapter's own `Config`.\n // Only the pi-ai layout has a per-route protocol for the read to find, and\n // it rehydrates the whole section schema, so the other layouts skip it.\n const protocols = useMemo(\n () => layout === 'pi-ai' ? protocolChoices(namespace, schema) : [],\n [layout, namespace, schema],\n )\n\n useEffect(() => {\n let stale = false\n setKeyState(undefined)\n // The key state is a placeholder hint, not a precondition for editing:\n // neither a business rejection nor a transport failure may reach the\n // browser as an unhandled rejection, so the card simply renders without\n // the \"already configured\" hint.\n void api.credentials.describe({ refs: [keyRef] }).then(\n (response) => {\n if (stale || !response.result.ok) return\n setKeyState(response.result.value.credentials[keyRef])\n },\n () => undefined,\n )\n return () => { stale = true }\n }, [api.credentials, 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 // A value of nothing but whitespace is cleared, not stored: `stringAt`\n // already reports it as absent, so the field would otherwise render empty\n // while the draft still carried the spaces into `settings.yaml`, where\n // both adapters would accept that non-empty string as a real value.\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 // The model list is validated by the same per-row checker for both families,\n // so a bad row is named by its position rather than by a blanket message.\n const modelFailure = validateDeepSeekModels(schema.getPath(draft, ['models']))\n const keyFailure = apiKeyFailure(keyDraft)\n // What a probe or a write must carry: the typed key with paste whitespace\n // removed. A blank field yields an empty string, which both call sites read\n // as \"no key supplied\" rather than as a key — that is how a card whose\n // provider already has a stored key is edited without re-entering it.\n const keyValue = keyDraft.trim()\n const credentialRequiredFailure = props.credentialRequired === true\n && keyDraft.length > 0 && keyValue.length === 0\n ? 'keyRequired' as const\n : undefined\n const shownKeyFailure = credentialRequiredFailure ?? keyFailure\n // What the form currently shows, which is what an interrogation must ask:\n // an edited-but-unsaved endpoint, and a key typed but not yet stored.\n const probeApi = stringAt(draft, 'api') ?? stringAt(fallback, 'api')\n const probeBaseURL = stringAt(draft, 'baseURL') ?? stringAt(fallback, 'baseURL')\n const probe = {\n settingsNs: namespace.ns,\n // Naming the route lets an adapter that already describes it answer from\n // its own registry — better metadata, no network call, no endpoint needed.\n provider: props.provider,\n ...probeBaseURL === undefined ? {} : { baseURL: probeBaseURL },\n ...probeApi === undefined ? {} : { api: probeApi },\n ...keyValue.length === 0 ? {} : { apiKey: keyValue },\n }\n /**\n * The write for this card, or a failure message. Every edit travels as\n * path ops against the STORED section: the draft comes from the redacted\n * descriptor, so a wholesale replace rebuilt from it could delete fields\n * outside the card. Ops name only the fields this card can see.\n */\n const applyOnce = async (): Promise<string | undefined> => {\n const ns = namespace.ns\n // A pi-ai profile names the conventional reference only when this page is\n // about to store a key. Otherwise the provider keeps its native auth path.\n const 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 if (props.credentialOnly !== true) {\n // The same checker gates the submit button, so a card cannot reach this\n // with a bad row; it stays because the schema check below would refuse\n // the write with a message naming a path instead of the row, and because\n // nothing but this function decides what is written.\n const failure = validateDeepSeekModels(schema.getPath(next, ['models']))\n /* v8 ignore next 3 -- unreachable from the card: the same failure disables submit */\n if (failure !== undefined) {\n return `${t('model')} ${String(failure.index + 1)}: ${t(failure.key)}`\n }\n }\n /* v8 ignore next -- apply is only reachable from the rendered card, which required a resolved node */\n if (props.credentialOnly !== true && node !== undefined && settingsPath.length === 0) {\n const sectionError = schema.validate(node, next)\n if (sectionError !== undefined) return sectionError\n }\n const materializesNativeProfile = layout === 'pi-ai'\n && fallback === undefined\n && committedOriginal === undefined\n && Object.keys(next).length === 0\n const ops: SettingsPathOpView[] = props.credentialOnly === true\n ? []\n : materializesNativeProfile\n ? [{ op: 'set', path: [...settingsPath], value: {} }]\n : pathOps(settingsPath, committedOriginal, next)\n if (ops.length > 0) {\n const response = await api.settings.mutate({ ns, ops, expectedRevision })\n if (!response.result.ok) {\n return response.result.error.code === 'settings-conflict'\n ? t('conflict')\n : response.result.error.message\n }\n setCommittedOriginal(schema.getPath(response.result.value.user, settingsPath))\n setExpectedRevision(response.result.value.revision)\n setDraft(next)\n }\n if (keyValue.length > 0) {\n const stored = await api.credentials.set({ ref: keyRef, value: keyValue })\n if (!stored.result.ok) return stored.result.error.message\n }\n setKeyDraft('')\n return undefined\n }\n\n const apply = async (): Promise<void> => {\n setBusy(true)\n setFailure(undefined)\n try {\n const failure = await applyOnce()\n if (failure !== undefined) {\n setFailure(failure)\n return\n }\n props.onClose(true)\n } catch (error) {\n // A transport failure (disconnect, a request the host refuses) rejects\n // rather than answering; without this the card would stay busy forever\n // with no error shown.\n setFailure(messageOf(error))\n } finally {\n setBusy(false)\n }\n }\n\n if (node === undefined) {\n // A directory entry addressing a position its schema cannot resolve is a\n // host-side inconsistency; showing it beats a blank card.\n return <p className={styles['error']}>{`${props.provider}: unresolvable settings path`}</p>\n }\n\n const keyLocked = keyState?.writable === false\n\n /**\n * The catalog beneath the user layer: what the composition entry pinned, or\n * else the schema default that `resolve` would supply. The effective value\n * cannot answer this — it still carries the stored override until the unset\n * is applied, so reading it would echo that override straight back the\n * moment reset drops it, leaving the rows unchanged until a reload.\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\n /**\n * The curated fields of one known adapter family. The family arrives\n * narrowed so the per-family branches below are total: an unknown namespace\n * renders the hint instead and never reaches this body.\n */\n const curatedFields = (family: 'deepseek' | 'pi-ai'): ReactNode => {\n // What a hand-declared route names for itself and nothing else can supply.\n // A whole-section `llm-deepseek` profile is a composition fact with no\n // per-route identity for its schema to carry, hence the family test.\n const ownsIdentity = family === 'pi-ai' && props.declared === true\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 const keyPlaceholder = keyLocked\n ? t('keyEnvLocked')\n : keyState?.configured === true && props.credentialRequired !== true\n ? t('keyStored')\n : family === 'pi-ai' ? t('keyPlaceholderNative') : t('keyPlaceholder')\n /** What both family editors take: the rows, whose layer owns them, and the two writes. */\n const catalogProps = {\n models,\n overridden: modelsOverridden,\n t,\n disabled,\n onChange: (next: Record<string, unknown>[]) => {\n setDraft(current => schema.setPath(current, ['models'], next))\n },\n onReset: () => { setDraft(current => schema.deletePath(current, ['models'])) },\n }\n return (\n <>\n <div className={styles['field']}>\n <span className={styles['fieldLabel']}>{t('keyInput')}</span>\n <input\n className={styles['input']}\n type=\"password\"\n autoComplete=\"off\"\n value={keyDraft}\n placeholder={keyPlaceholder}\n aria-label={t('keyInput')}\n aria-invalid={shownKeyFailure !== undefined}\n required={props.credentialRequired === true}\n autoFocus={props.autoFocusCredential === true}\n disabled={disabled || keyLocked}\n onChange={(event) => { setKeyDraft(event.target.value) }}\n />\n {shownKeyFailure === undefined ? null : <p className={styles['error']}>{t(shownKeyFailure)}</p>}\n </div>\n {props.credentialOnly === true ? null : <details className={styles['customized']}>\n <summary className={styles['customizedSummary']}>{t('customized')}</summary>\n <div className={styles['customizedBody']}>\n {/* The name and the protocol are the create card's two remaining\n profile fields; a route the adapter ships defaults both from\n its catalog entry and neither belongs on its card. */}\n {ownsIdentity\n ? (\n <div className={styles['field']}>\n <span className={styles['fieldLabel']}>{t('customDisplayName')}</span>\n <input\n className={styles['input']}\n type=\"text\"\n value={stringAt(draft, 'displayName') ?? ''}\n // What this route is called the moment the field is\n // cleared, which is the layer beneath the one this field\n // edits: a `cordis.yml` may pin a name for a route the\n // catalog does not ship, and only when nothing does is\n // the answer the route id. Reading the effective value\n // instead would echo the stored override back as the\n // thing clearing restores.\n placeholder={stringAt(schema.getPath(namespace.base, settingsPath), 'displayName')\n ?? props.provider}\n aria-label={t('customDisplayName')}\n disabled={disabled}\n onChange={(event) => { setField('displayName', event.target.value) }}\n />\n </div>\n )\n : null}\n <div className={styles['field']}>\n <span className={styles['fieldLabel']}>{t('baseUrl')}</span>\n <input\n className={styles['input']}\n type=\"text\"\n value={stringAt(draft, 'baseURL') ?? ''}\n placeholder={family === 'deepseek'\n ? DEEPSEEK_PUBLIC_BASE_URL\n : stringAt(fallback, 'baseURL') ?? t('baseUrlDefault')}\n aria-label={t('baseUrl')}\n disabled={disabled}\n onChange={(event) => {\n setField('baseURL', event.target.value === '' ? undefined : event.target.value)\n }}\n />\n </div>\n {/* The protocol sits beside the endpoint it describes, as it does\n on the create card. */}\n {ownsIdentity\n ? (\n <div className={styles['field']}>\n <span className={styles['fieldLabel']}>{t('customApi')}</span>\n <select\n className={`${styles['input']} ${styles['selectInput']}`}\n value={probeApi ?? ''}\n aria-label={t('customApi')}\n disabled={disabled}\n onChange={(event) => { setField('api', event.target.value) }}\n >\n {/* A profile naming no protocol — hand-written into\n settings.yaml with no model to need one — selects\n nothing rather than reading as if it had picked the\n first choice. The option is named because a screen\n reader announces it either way, and an empty one is\n announced as a choice with no identity. */}\n {probeApi === undefined ? <option value=\"\">{t('customApiUnset')}</option> : null}\n {protocols.map(choice => <option key={choice} value={choice}>{choice}</option>)}\n </select>\n </div>\n )\n : null}\n {/* Both families edit the same rows through the same contract; only\n the extras differ — DeepSeek's inherited capacities, pi-ai's\n endpoint interrogation. */}\n {family === 'deepseek'\n ? (\n <DeepSeekModelsEditor\n {...catalogProps}\n defaultContextWindow={typeof defaultContextWindow === 'number'\n ? defaultContextWindow\n : undefined}\n defaultMaxTokens={typeof defaultMaxTokens === 'number' ? defaultMaxTokens : undefined}\n />\n )\n : <ModelListEditor {...catalogProps} probe={probe} probeBlocked={keyFailure} api={api} />}\n </div>\n </details>}\n </>\n )\n }\n\n return (\n <div className={props.credentialOnly === true ? styles['addBlock'] : styles['editor']}>\n {props.hideTitle === true\n ? null\n : (\n <div className={styles['editorHeader']}>\n <span className={styles['editorTitle']}>{props.displayName}</span>\n {props.provider !== props.displayName\n ? <span className={styles['editorRoute']}>{props.provider}</span>\n : null}\n </div>\n )}\n {layout === 'unknown'\n ? <p className={styles['advancedHint']}>{`${t('advancedHint')} (${namespace.ns})`}</p>\n : curatedFields(layout)}\n {failure !== undefined ? <p className={styles['error']}>{failure}</p> : null}\n {props.credentialOnly === true || modelFailure === undefined\n ? null\n : (\n <p className={styles['advancedHint']}>\n {`${t('model')} ${String(modelFailure.index + 1)}: ${t(modelFailure.key)}`}\n </p>\n )}\n <EditorFooter\n t={t}\n busy={busy}\n submitDisabled={disabled || layout === 'unknown'\n || (props.credentialOnly !== true && modelFailure !== undefined)\n || shownKeyFailure !== undefined\n || (props.credentialRequired === true && keyValue.length === 0)}\n submitLabel={props.submitLabel ?? 'apply'}\n submitBusyLabel={props.submitBusyLabel ?? 'applying'}\n {...props.cancelLabel === undefined ? {} : { cancelLabel: props.cancelLabel }}\n onCancel={() => { props.onClose(false) }}\n onSubmit={() => { void apply() }}\n />\n </div>\n )\n}\n","/**\n * Models settings section (EXT fork for dsh-model-extension).\n *\n * Forked from deepseek-harness packages/client/ui-settings-models\n * src/client/ModelsSection.tsx @ 0.1.1-rc.2.\n * Only difference vs upstream: the h2 title row carries an adapter-version\n * badge. Everything else is upstream verbatim — keep this file minimal when\n * merging drift after a host upgrade.\n *\n * Models settings section: the provider rows joined from the configurable\n * directory, settings namespaces, and credential states, with one editor\n * card at a time. Rows expose only confirmed API-key state through accessible\n * solid configured or missing dots. A whole-section provider without a\n * configured key renders as its open setup card instead of a row, but only in\n * the first-run posture — no provider on the page can serve requests yet — and\n * only until the user closes that card; the add flow is a card carrying the\n * dormant-provider select. Each card kind owns its own open state, so closing\n * one never discards a draft in another. Every mutation writes through the\n * wire, while a provider removal first requires confirmation; the page\n * re-renders from pushed invalidations or the post-apply reload.\n */\n\nimport { useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type { IApiClient } from '@deepseek-ai/dsh-api-remotes/client'\nimport { Button, IconPlusOutline16, Modal } from '@deepseek-ai/dsh-client-ui-primitives'\nimport type { InjectFace } from '@deepseek-ai/dsh-client-ui-slots'\nimport { CustomProviderCard } from './CustomProviderCard.tsx'\nimport { deriveKeyRef, messageOf, protocolChoices, providerUsable } from './store.ts'\nimport type { ModelsSettingsStore, ProviderRow } from './store.ts'\nimport type { SettingsSchemaOperations } from './schema-operations.ts'\nimport { ProviderEditor, type ProviderEditorProps } from './ProviderEditor.tsx'\nimport type { en } from './locales.ts'\nimport { ADAPTER_VERSION } from './extension-meta.ts'\nimport styles from './ModelsSection.ext.module.css'\n\n/** Injected dependencies of {@link ModelsSection} (slot `inject`). */\nexport interface ModelsSectionInjected {\n /** The page store (loaded on mount, refreshed on pushed invalidations). */\n controller: ModelsSettingsStore\n hooks: {\n /** Page snapshot bound by the UI renderer as useSnapshot. */\n snapshot: ModelsSettingsStore['store']\n }\n /** Wire faces the editor writes through. */\n api: Pick<IApiClient, 'settings' | 'credentials' | 'llm'>\n /** Settings schema and immutable path callbacks. */\n schema: SettingsSchemaOperations\n /** Section copy. */\n t: (key: keyof typeof en) => string\n}\n\n/**\n * Props delivered by the slot outlet: the inject face spread flat (the\n * renderer erases the share boundary at the render call).\n */\nexport type ModelsSectionProps = Partial<InjectFace<ModelsSectionInjected>>\n\ntype ModelsSectionFace = InjectFace<ModelsSectionInjected>\n\n/** Provider identity shared by row actions and confirmation copy. */\nexport interface ProviderIdentity {\n /** Stable provider route id. */\n provider: string\n /** Human-facing provider name. */\n displayName: string\n}\n\n/** One existing row or dormant directory entry addressed by an editor action. */\ninterface EditorTarget extends ProviderIdentity {\n settingsNs: string\n settingsPath: readonly string[]\n /** Writable credential identified under this page's conventional reference. */\n credentialRef?: string\n /** The adapter reports this route as one it does not ship (see {@link ProviderEditorProps.declared}). */\n declared?: boolean\n}\n\n/** Values that vary around the shared provider-editor rendering. */\ninterface ProviderEditorRenderProps extends Pick<\n ProviderEditorProps,\n 'namespace' | 'schema' | 'api' | 't' | 'readOnly' | 'onClose'\n> {\n target: EditorTarget\n}\n\n/** Render an editor for either the setup posture or an expanded provider row. */\nfunction renderProviderEditor({ target, ...props }: ProviderEditorRenderProps): ReactNode {\n return (\n <ProviderEditor\n provider={target.provider}\n displayName={target.displayName}\n settingsPath={target.settingsPath}\n {...target.declared === true ? { declared: true } : {}}\n {...props}\n />\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 provider row visible\n * and the whole operation safely retryable; both unsets are idempotent.\n * The settings removal names the profile rather than rebuilding its whole\n * namespace from a partial view.\n * @param api - settings and credential wire faces.\n * @param controller - the page store to refresh.\n * @param target - the provider's settings address and optional managed credential.\n * @returns the failure message, or undefined once the write and reload landed.\n */\nexport async function removeProviderProfile(\n api: Pick<IApiClient, 'settings' | 'credentials'>,\n controller: ModelsSettingsStore,\n target: { settingsNs: string; settingsPath: readonly string[]; credentialRef?: string },\n): Promise<string | undefined> {\n try {\n if (target.credentialRef !== undefined) {\n const credential = await api.credentials.unset({ ref: target.credentialRef })\n if (!credential.result.ok) return credential.result.error.message\n }\n const response = await api.settings.mutate({\n ns: target.settingsNs,\n ops: [{ op: 'unset', path: [...target.settingsPath] }],\n })\n if (!response.result.ok) return response.result.error.message\n } catch (error) {\n // The transport rejected rather than answering; the caller must be able\n // to retry the idempotent operation instead of the row silently staying.\n return messageOf(error)\n }\n await controller.load()\n return undefined\n}\n\n/**\n * Whether a whole-section provider still needs its first key: an unconfigured\n * credential opens the setup card instead of showing a row. This is the\n * first-run posture alone — a user who can already reach some provider gets an\n * ordinary row with the missing-key dot, since nothing here is blocking them.\n * @param row - the joined provider row.\n * @param anyUsable - whether any joined row can already serve requests.\n * @returns whether to render the setup card.\n */\nexport function 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\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 // Absent is not \"shipped\": an adapter that answers nothing leaves the\n // route-level fields only a declared route owns off the card, exactly as\n // it leaves the custom tag off the row.\n ...row.entry.declared === true ? { declared: true } : {},\n }\n}\n\n/** Stable visible and accessible identity for one provider target. */\nexport function providerTargetLabel(target: ProviderIdentity): string {\n return target.provider === target.displayName\n ? target.provider\n : `${target.displayName} (${target.provider})`\n}\n\n/** Replace the one provider placeholder in localized destructive-action copy. */\nexport function providerCopy(template: string, target: ProviderIdentity): string {\n return template.replace('{provider}', () => providerTargetLabel(target))\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 ModelsSection(props: ModelsSectionProps): ReactNode {\n const { controller, useSnapshot, api, schema, t } = props\n if (\n controller === undefined || useSnapshot === undefined || api === undefined\n || schema === undefined || t === undefined\n ) return null\n return <Loaded injected={{ controller, useSnapshot, api, schema, t }} />\n}\n\nfunction Loaded({ injected }: { injected: ModelsSectionFace }): ReactNode {\n const { controller, api, schema, t } = injected\n const state = injected.useSnapshot(snapshot => snapshot)\n const [editing, setEditing] = useState<EditorTarget | undefined>(undefined)\n const [adding, setAdding] = 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<ProviderIdentity | undefined>(undefined)\n const [declaring, setDeclaring] = useState(false)\n const [dismissedSetup, setDismissedSetup] = useState<ReadonlySet<string>>(() => new Set())\n\n const announceSaved = (target: ProviderIdentity): void => {\n // Announced only once the refreshed directory is in the snapshot the\n // notice reads its name from: an apply can rename the route, and the\n // target captured when the card opened still carries the old name.\n void controller.load().then(() => { setSavedTarget(target) })\n }\n\n const closeEditor = (changed: boolean, target: ProviderIdentity): void => {\n setEditing(undefined)\n setAdding(false)\n setDeclaring(false)\n if (changed) announceSaved(target)\n }\n\n /**\n * Close a setup card, which owns none of the state above: the row-editor,\n * add, and declare cards each own one of those, so clearing them here would\n * discard a draft the user opened beside this card. Dismissal is this card's\n * own — the provider falls back to an ordinary row for the rest of the\n * session, and reopens through Edit.\n */\n const closeSetup = (changed: boolean, target: ProviderIdentity): void => {\n setDismissedSetup(previous => new Set([...previous, target.provider]))\n if (changed) announceSaved(target)\n }\n\n const closeDelete = (): void => {\n if (deleting) return\n setDeleteTarget(undefined)\n setDeleteFailure(undefined)\n }\n\n const confirmDelete = (): void => {\n /* v8 ignore next -- the action only renders with a target and is disabled while a deletion is pending */\n if (deleteTarget === undefined || deleting) return\n setDeleting(true)\n setDeleteFailure(undefined)\n void removeProviderProfile(api, controller, deleteTarget)\n .then((failure) => {\n if (failure !== undefined) {\n setDeleteFailure(failure)\n return\n }\n setDeleteTarget(undefined)\n })\n .finally(() => { setDeleting(false) })\n }\n\n if (state.status === 'idle') void controller.load()\n if (state.status === 'error') {\n /* v8 ignore next -- an error status always carries text; the fallback satisfies the nullable type */\n const errorText = state.error ?? ''\n return (\n <div className={styles['section']}>\n <p className={styles['error']}>{`${t('loadFailed')}: ${errorText}`}</p>\n <button type=\"button\" className={styles['secondaryButton']} onClick={() => { void controller.load() }}>\n {t('retry')}\n </button>\n </div>\n )\n }\n\n // The saved provider as the directory currently names it. The route id is\n // what the apply cannot change, so it is what the notice is keyed by; a row\n // the same apply removed keeps the captured identity, since nothing newer\n // exists to name it with.\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 : { provider: savedRow.entry.provider, displayName: savedRow.entry.displayName }\n\n // One fact decides both first-run postures on this page and the onboarding\n // step: whether the user already has a provider to talk to.\n const anyUsable = state.rows.some(providerUsable)\n const configured = state.rows.filter(row => row.configured)\n const addable = state.rows.filter(row => !row.configured && row.entry.settingsNs !== '')\n const addTarget = adding ? editing : undefined\n const addNamespace = addTarget === undefined ? undefined : state.namespaces.get(addTarget.settingsNs)\n // Hand-declared routes live in the pi-ai namespace, which is also the only\n // one whose schema names the protocols one may speak; without it mounted\n // there is nothing to declare and the entry point stays disabled.\n const protocols = protocolChoices(state.namespaces.get('llm-pi-ai'), schema)\n\n return (\n <div className={styles['section']}>\n <h2 className={styles['title']}>\n {t('title')}\n {/* EXT-only: adapter anchor badge (upstream has no counterpart). */}\n <span className={styles['intro']}>{` — ${t('adapterVersion').replace('{version}', ADAPTER_VERSION)}`}</span>\n </h2>\n <p className={styles['intro']}>{t('intro')}</p>\n {!state.writable && state.status === 'ready' ? <p className={styles['notice']}>{t('readOnly')}</p> : null}\n {savedIdentity === undefined\n ? null\n : (\n <p className={styles['savedNotice']} role=\"status\" aria-live=\"polite\">\n {providerCopy(t('savedProvider'), savedIdentity)}\n </p>\n )}\n <ul className={styles['rows']}>\n {configured.map((row) => {\n const target = targetOf(row)\n const namespace = state.namespaces.get(target.settingsNs)\n /* v8 ignore next -- the join marks a row configured only when its namespace resolved */\n if (namespace === undefined) return null\n if (needsSetup(row, anyUsable) && !dismissedSetup.has(row.entry.provider)) {\n // First-run posture: the provider exists but has no key — the\n // setup card IS its presence on the page, until the user closes it.\n return (\n <li key={row.entry.provider} className={styles['setupCard']}>\n {renderProviderEditor({\n target,\n namespace,\n schema,\n api,\n t,\n readOnly: !state.writable,\n onClose: (changed) => { closeSetup(changed, target) },\n })}\n </li>\n )\n }\n const open = !adding && 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 <div className={styles['rowHead']}>\n <span className={styles['rowIdentity']}>\n <span className={styles['rowName']}>{row.entry.displayName}</span>\n {/* Only the adapter can tell a hand-declared route from a\n shipped one it also has a stored profile for, so the tag\n follows its answer and stays off when it gives none. */}\n {row.entry.declared === true\n ? <span className={styles['rowTag']}>{t('customTag')}</span>\n : null}\n {credentialConfigured\n ? (\n <span\n className={`${styles['credentialDot']} ${styles['credentialDotConfigured']}`}\n role=\"img\"\n aria-label={t('credentialConfigured')}\n title={t('credentialConfigured')}\n />\n )\n : credentialMissing\n ? (\n <span\n className={`${styles['credentialDot']} ${styles['credentialDotMissing']}`}\n role=\"img\"\n aria-label={t('credentialMissing')}\n title={t('credentialMissing')}\n />\n )\n : null}\n </span>\n <span className={styles['rowActions']}>\n <button\n type=\"button\"\n className={styles['secondaryButton']}\n aria-label={providerCopy(t('editProvider'), target)}\n onClick={() => {\n setSavedTarget(undefined)\n // One card at a time: leaving `declaring` set would show\n // the create card beside this editor, and closing either\n // one discards the other's draft.\n setDeclaring(false)\n setAdding(false)\n setEditing(open ? undefined : target)\n }}\n >\n {t('edit')}\n </button>\n {row.removable\n ? (\n <button\n type=\"button\"\n className={styles['dangerButton']}\n aria-label={providerCopy(t('removeProvider'), target)}\n disabled={!state.writable}\n onClick={() => {\n setSavedTarget(undefined)\n setDeleteFailure(undefined)\n setDeleteTarget(target)\n }}\n >\n {t('remove')}\n </button>\n )\n : null}\n </span>\n </div>\n {open\n ? renderProviderEditor({\n target,\n namespace,\n schema,\n api,\n t,\n readOnly: !state.writable,\n onClose: (changed) => { closeEditor(changed, target) },\n })\n : null}\n </li>\n )\n })}\n </ul>\n <div className={styles['addBlock']}>\n {addTarget !== undefined && addNamespace !== undefined\n ? (\n <div className={styles['addCard']}>\n <div className={styles['field']}>\n <span className={styles['fieldLabel']}>{t('provider')}</span>\n <select\n className={`${styles['input']} ${styles['selectInput']}`}\n value={addTarget.provider}\n aria-label={t('provider')}\n onChange={(event) => {\n const row = addable.find(candidate => candidate.entry.provider === event.target.value)\n /* v8 ignore next -- the select only lists addable rows */\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}>{row.entry.displayName}</option>\n ))}\n </select>\n </div>\n <ProviderEditor\n key={addTarget.provider}\n provider={addTarget.provider}\n displayName={addTarget.displayName}\n hideTitle\n namespace={addNamespace}\n schema={schema}\n settingsPath={addTarget.settingsPath}\n api={api}\n t={t}\n readOnly={!state.writable}\n onClose={(changed) => { closeEditor(changed, addTarget) }}\n />\n </div>\n )\n : declaring\n ? (\n <div className={styles['addCard']}>\n <CustomProviderCard\n taken={state.rows.map(row => row.entry.provider)}\n protocols={protocols}\n /* v8 ignore next -- the card only opens from a button disabled without this namespace */\n revision={state.namespaces.get('llm-pi-ai')?.revision ?? 0}\n api={api}\n t={t}\n readOnly={!state.writable}\n onClose={(changed) => {\n setDeclaring(false)\n if (changed) void controller.load()\n }}\n />\n </div>\n )\n : (\n // One row for the two ways to gain a provider: adopt one the\n // adapter already knows, or declare one it does not. Side by side\n // and equal-width so they read as siblings and line up with the\n // rows above, rather than two pills of different lengths.\n <div className={styles['addActions']}>\n <button\n type=\"button\"\n className={styles['addButton']}\n disabled={addable.length === 0 || !state.writable}\n onClick={() => {\n const first = addable[0]\n /* v8 ignore next -- the button is disabled while nothing is addable */\n if (first === undefined) return\n setSavedTarget(undefined)\n setDeclaring(false)\n setAdding(true)\n setEditing(targetOf(first))\n }}\n >\n {/* Same glyph as the composer's attach button. */}\n <IconPlusOutline16 size={14} />\n {t('add')}\n </button>\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 <IconPlusOutline16 size={14} />\n {t('customAdd')}\n </button>\n </div>\n )}\n </div>\n <Modal\n open={deleteTarget !== undefined}\n onClose={closeDelete}\n title={deleteTarget === undefined ? '' : providerCopy(t('deleteTitle'), deleteTarget)}\n closeLabel={t('close')}\n description={deleteTarget === undefined\n ? ''\n : providerCopy(\n deleteTarget.credentialRef === undefined\n ? t('deleteDescription')\n : t('deleteDescriptionWithCredential'),\n deleteTarget,\n )}\n className={styles['deleteDialog'] as string}\n footer={(\n <>\n <Button variant=\"outline\" autoFocus disabled={deleting} onClick={closeDelete}>\n {t('cancel')}\n </Button>\n <Button\n variant=\"outline\"\n className={styles['deleteConfirm']}\n disabled={deleting}\n onClick={confirmDelete}\n >\n {deleteTarget === undefined\n ? ''\n : providerCopy(deleting ? t('deleting') : t('deleteConfirm'), deleteTarget)}\n </Button>\n </>\n )}\n >\n {deleteFailure === undefined ? null : <p className={styles['error']}>{deleteFailure}</p>}\n </Modal>\n </div>\n )\n}\n","import 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.\n *\n * Registers a \"Models+\" settings section that renders the official Models\n * page (inlined from the host's ui-settings-models sources at build time,\n * with our .ext touch-point replacements) under its own nav id. The store,\n * schema operations, dictionaries, and invalidation wiring mirror the\n * upstream ui-settings-models client/index.ts exactly — the forked components\n * run unmodified, so the wiring must too.\n */\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type { ConnectionHandle } from '@deepseek-ai/dsh-api-remotes/client'\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 ctx.remote merge and forwarded-event key face.\nimport type {} from '@deepseek-ai/dsh-api-remotes/client'\nimport { ModelsSection } from './ModelsSection.ext.tsx'\nimport type { ModelsSectionInjected } from './ModelsSection.ext.tsx'\nimport { ModelsSettingsStore } from './store.ts'\nimport { createSettingsSchemaOperations } from './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. */\nexport const inject = ['slots', 'locale', 'connection', 'remote', 'settingsScope', 'settingsSchema']\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 // Extension copy rides its own namespace; the section declares it via\n // `locale:` so the framework synthesizes the `t` seat for both the official\n // keys (resolved through our merged dictionary) and the extension keys.\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 connection = ctx.get('connection') as ConnectionHandle\n const schema = createSettingsSchemaOperations(ctx.settingsSchema)\n const controller = new ModelsSettingsStore(connection.api, schema, ctx.settingsScope.describe())\n // Registration-time text (the nav label thunk) shares one bound translate.\n const t = ctx.locale.bind(NS) as ModelsSectionInjected['t']\n const injected = (): ModelsSectionInjected => ({\n controller,\n hooks: { snapshot: controller.store },\n api: connection.api,\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 }, ModelsSection))\n}\n"],"mappings":"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"}