dsh-llm-providers-ui
Manifest validMounted owner of the LLM Providers Settings page: provider cards, drag-reorder card order, and picker sort.
dsh-llm-providers-ui
English | 中文
Mounted owner of the LLM Providers Settings page for DeepSeek Harness.
Compatibility
Host @deepseek-ai/dsh-* packages are not version-locked: peers are * and optional. devDependencies pin the compile target (0.1.5-rc.1). Cordis stays >=4.0.2 <5.0.0.
Verified Hosts in package.json#dsh.compatibility.dshReleases are evidence, not an allowlist. Unknown newer Hosts warn once and keep the normal mount path. Only a reproduced failure is blocklisted.
Ownership
- Host owns the
llm-providerssettings namespace{ order: string[] }(sole writer). Unloading the owner drops the namespace; reloading recreates it. Providers continue to work Host-side when the owner is absent because theirllmroutes are independent. - Web (client) owns
settings.sectionid: providers(order 12) with childsettings.provider.item(keyed, root), localesettings.providers, and the nav-icon. The section and child declaration mount only while the Host-ownedllm-providersscope is ready; provider plugins contribute only their keyed card viasettings.provider.item.
Load order does not matter. Unloading a provider removes only its card. Unloading/reloading the owner does not corrupt provider Host services; cards reappear via the public slot lifecycle when the owner returns.
Missing owner
- Headless/Host without the owner: model routing still works.
- Web without the owner: the Providers page and its cards are omitted; provider Host routes stay live. During development, the browser console emits one owner-unavailable warning; after the owner is ready, a separate
settings.sectionwarning identifies a missing Web settings shell.
Navigation icon
The 14px globe glyph on the nav row is an isolated temporary adapter (src/client/nav-icon.ts). DSH's settings.section has no icon field, so this file patches the DOM via MutationObserver + rAF. It is idempotent and owned only here — do not duplicate it into provider plugins. When DSH exposes a public icon seam, replace this file.
Exports
dsh-llm-providers-ui(Host):applySavedOrder,decodeProviderOrder,sortCatalogGroups,PROVIDER_ITEM_ORDER, etc. Built artifact:lib/index.js+lib/types.dsh-llm-providers-ui/order(pure, ESM): same order helpers, stable built utility fordsh-model-switchand provider pickers. Built artifact:lib/order.js+lib/types/order.d.ts. Provider pluginsalwaysBundlethis built export; do not import fromsrc.dsh-llm-providers-ui/sortable(client utility, ESM):SortableListdrag-reorder implementation. Built artifact:lib/sortable.js+lib/types/sortable.d.ts. Single implementation lives insrc/client/SortableList.tsxand is re-exported here; provider pluginsalwaysBundlethe built file. Do not import fromsrc/client/SortableList.tsx.dsh-llm-providers-ui/provider-ui(client utility, ESM): sharedProviderCardHeader,ProviderQuotaMeter,ProviderMark,normalizeQuotaRemaining,providerUiCss, and the header's binding to the shared usage cache,useProviderQuotaCache(with itsProviderAuthStateverdict). Built artifact:lib/provider-ui.js+lib/types/provider-ui.d.ts. Single implementation lives insrc/client/provider-ui.tsxand is re-exported here; provider pluginsalwaysBundlethe built file. Do not import fromsrc/client/provider-ui.tsx.dsh-llm-providers-ui/provider-detail(client utility, ESM): the sharedProviderDetailtemplate every provider card renders in detail mode, itsproviderDetailCopylocale bundle, theProviderDetailProps/ProviderDetailModels/ProviderDetailCopycontracts, and theProviderItemSlotContextthe settings page hands to each card (mode,usage,accountState,onRefresh,copy,template). Built artifact:lib/provider-detail.js+lib/types/provider-detail.d.ts. The single implementation lives insrc/client/provider-detail.tsx; provider pluginsalwaysBundlethe built file and render the component the page passes through the slot context. Do not import fromsrc/client/provider-detail.tsx.dsh-llm-providers-ui/client(Web): owner plugin wiring and theproviderDirectoryCordis service declaration. Built artifact:lib/client.js(ModuleLoader CJS) +lib/types/client; it exports only the plugin entrypoints. Do not import./src/*.dsh-llm-providers-ui/model-catalog(client utility, ESM):ModelCatalogEditor,ModelPickerDialog,applyCatalogPatch, and catalog layout helpers. Built artifact:lib/model-catalog.js+lib/types/model-catalog.d.ts. Provider pluginsalwaysBundlethis built export; do not import fromsrc/client.dsh-llm-providers-ui/usage-readers(pure, ESM):ProviderUsageReadertypes and vendorcreate*UsageReaderfactories for provider client bundles. Built artifact:lib/usage-readers.js+lib/types/usage-readers.d.ts. Provider pluginsalwaysBundlethis export. It also owns the browser last-good usage cache (readUsageCache,writeUsageCache,dropPersistedUsageKeys,peekCachedUsage,rememberCachedUsage,rememberHeadlineQuota,headerQuotaFromCache,clearProviderUsageCache): readable storage is authoritative (including empty after invalidation) with memory only as an unavailable-storage fallback; stale status persists honestly; collapsed-header headlines never replace a full multi-window summary and record no fetch time; invalidation flows throughctx.providerDirectory.invalidateUsage(key).
The package exposes only the built lib/ entrypoints listed above; consumers should import those package exports rather than source paths.
Installation
This package is a bundle and must be listed in the profile. Until DSH mounts transitive bundles, install it alongside every provider card:
dsh plugin --profile web add --force \
https://github.com/NOirBRight/dsh-llm-providers-ui/releases/latest/download/dsh-llm-providers-ui-0.2.8.tgz
No strict load order with providers is required. See cordis.patch.yml.
Consumer contract
Provider plugins register their card under settings.provider.item with their settingsNs key and register { key, role, header, usage } on ctx.providerDirectory inside an effect. The returned disposer owns the registration. Usage-enabled providers import their reader factory from dsh-llm-providers-ui/usage-readers. Unregistered cards keep the LLM badge and do not receive a Provider Usage tile. The sidebar usage stage sizes to its rendered tiles (natural grid height up to the three-row cap, then scrolls), so hiding providers shrinks the panel instead of leaving blank rows. Quota and unavailable-status headlines stay on one line with ellipsis, keeping tiles equal-height and three rows fully visible at narrow sidebar widths.
Migrated cards render the shared header from dsh-llm-providers-ui/provider-ui (ProviderCardHeader with role, caller status, and headline quota; title/mark/summary/open/unsaved keep the legacy codex layout), mark their root li[data-provider-card][data-provider-role], their header button data-provider-card-header, and their body data-provider-body, include one <style>{providerUiCss}</style>, and declare header: 'shared' so the shell drops its fallback badge. Cards start their existing cached quota read when account readiness is known, independent of expansion; opening an already-loaded card does not refetch. Missing quota renders no meter, never a zero bar; normalizeQuotaRemaining keeps precision and reports NaN/Infinity/out-of-range as unavailable.
The settings fallback preserves ancestor overflow clipping and the native settings title. Mobile layouts keep ownership of offscreen panels and dialog header spacing.
Provider plugins import directory and slot types from dsh-llm-providers-ui/client with import type {} and must not duplicate the module augmentations locally. After sign-out or account switch, providers call ctx.providerDirectory.invalidateUsage(key) so the sidebar drops the cached quota and refetches; a Settings card reports the same event through useProviderQuotaCache's signedOut verdict, which purges the stored entry. Transient read errors still show the last good windows as stale in the sidebar, while a card keeps its truthful unavailable dash.
dsh-model-switch reuses sortCatalogGroups via the built dsh-llm-providers-ui/order export.
Until this package is published to npm, lab checkouts may use link:../dsh-llm-providers-ui in dev, but workspace package.json must not commit link: specs.
Release installation (Latest)
Shared LLM Providers settings page, navigation, card order, and picker sort owner. The published pack contains built Host/Client files only; it has no sibling-repository source, workstation path, link:, or workspace: dependency. Pack-check fixtures and compile-target devDependencies are 0.1.5-rc.1.
Latest installation (asset name matches the current latest tarball):
dsh plugin --profile web add --force \
https://github.com/NOirBRight/dsh-llm-providers-ui/releases/latest/download/dsh-llm-providers-ui-0.2.8.tgz
Fixed-version installation (v0.2.8):
dsh plugin --profile web add --force \
https://github.com/NOirBRight/dsh-llm-providers-ui/releases/download/v0.2.8/dsh-llm-providers-ui-0.2.8.tgz
Update, uninstall, and verify:
# Update to Latest
dsh plugin --profile web add --force \
https://github.com/NOirBRight/dsh-llm-providers-ui/releases/latest/download/dsh-llm-providers-ui-0.2.8.tgz
# Verify the loaded version
dsh plugin --profile web list
dsh plugin --profile web doctor
# Uninstall only this plugin
dsh plugin --profile web remove dsh-llm-providers-ui
Configuration: use the plugin section in Settings for Web UI plugins, or the profile dsh.profile.bundles entry for Host-only plugins. Start with this README's minimal YAML/JSON example and provide credentials/backend addresses explicitly.
Rollback: reinstall the previously recorded immutable tarball, verify the profile list, then restart the Web service once. Inspect journalctl --user -u dsh-web.service; never put a source checkout in the production profile.
Verify release assets against the SHA-256 manifest attached to the selected release.
Codex quota reads explicitly refresh the backend; the UI store controls caching for both manual refresh and expired-cache polling.
Live lab UI check
With an isolated Chrome exposing CDP on port 9229 and authenticated to the existing 3082 lab, run node scripts/check-lab-settings.mjs. The check covers seven real Provider cards and their brand/role icons at 1280, 390 and 320 pixels in light/dark themes, including expanded Antigravity. It restores the prior theme, does not edit Provider credentials or configuration, and writes screenshots to /tmp/lab-*.png. The script does not start a replacement application server.
Similar plugins
Adds a configurable dsh-ui status card before each DSH agent reply, with bilingual templates and a live settings preview. Requires @omdsh-dev/dsh-genui from dsh-market; without it, the card markup is
★ 0
dsh plugin --profile web add dsh-status-cardProvider-tabbed model picker for the dsh web composer: left provider column and right model list, both independently scrollable, with cross-provider search.
★ 0
dsh plugin --profile web add dsh-model-pickerProvider-first three-level model selector for the DSH Web model seat: pick a provider, then a model from that provider, with inline search on both levels, failed-provider retry rows, and a Model · Pro
★ 0
dsh plugin --profile web add dsh-model-providerRate-limits LLM requests per provider and per model using a reservation-based token bucket, with queue or reject modes, plus gateway identity rules that rewrite user-agent and inject custom headers.
★ 0
dsh plugin --profile web add dsh-provider-rate-limitCard-style plugin manager in Settings: enable/disable each plugin through the profile patch layer, install-source details, npm update check with one-click update, uninstall, search, and load-error bad
★ 0
↓ 221/wk
dsh plugin --profile web add dsh-plugin-mgrProvider-folded model selector for the DSH Web composer with catalog-driven reasoning effort choices.
★ 0
↓ 370/wk
dsh plugin --profile web add dsh-model-accordion