@deepseek-ai/dsh-client-ui-settings-models 0.1.7-rc.1 → 0.2.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -1,6 +1,61 @@
1
- # Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
2
- # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
- # after editing either side, bring the other along and re-record with:
1
+ # Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
2
+ # section, a hash of its English and Chinese blocks outside code blocks and generated regions.
3
+ # After editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/client/ui-settings-models/README.md
5
- README.md: 52a8e91c158db912a5c7a4f84ff2892de2bd4a7d
6
- README.zh.md: 9470c9c0f1e80136e31e6e656b09c5fd17f7c691
5
+ /:
6
+ en: d1bc4d9ef67bfb19
7
+ zh: d095e4dc76f1c5e0
8
+ /deepseek-ai-dsh-client-ui-settings-models:
9
+ en: 0db6fa836e1ff511
10
+ zh: 0e2968763e1fb7a5
11
+ /deepseek-ai-dsh-client-ui-settings-models/summary:
12
+ en: 51252c1e9fa6da0a
13
+ zh: 227b54d7898417fa
14
+ /deepseek-ai-dsh-client-ui-settings-models/table-of-contents:
15
+ en: d152484eb41ac6b4
16
+ zh: 09388d293f9be9cb
17
+ /deepseek-ai-dsh-client-ui-settings-models/use-this-package:
18
+ en: 9ad8f5243c87c5b9
19
+ zh: f3b01e25c28ebba2
20
+ /deepseek-ai-dsh-client-ui-settings-models/use-this-package/api-keys:
21
+ en: c2f2a5c06ef20d5b
22
+ zh: 49a7eb0b66b4ed53
23
+ /deepseek-ai-dsh-client-ui-settings-models/use-this-package/editing-a-provider:
24
+ en: ec0ba62a4e7185b4
25
+ zh: 37d1e1e7a3817d12
26
+ /deepseek-ai-dsh-client-ui-settings-models/use-this-package/adding-and-deleting-providers:
27
+ en: 9d533c65c82cd4a4
28
+ zh: 0a5da334e127c035
29
+ /deepseek-ai-dsh-client-ui-settings-models/use-this-package/first-run-dialogs:
30
+ en: 589397a35f82244e
31
+ zh: 342fbceee2c173a2
32
+ /deepseek-ai-dsh-client-ui-settings-models/use-this-package/extension-slots:
33
+ en: 65e9d8822b67b6c2
34
+ zh: 7e83be9defda28ee
35
+ /deepseek-ai-dsh-client-ui-settings-models/understand-the-implementation:
36
+ en: a87afbec5e339b36
37
+ zh: 6348c81af7e650e1
38
+ /deepseek-ai-dsh-client-ui-settings-models/understand-the-implementation/validation:
39
+ en: 74948a88fe1f9aac
40
+ zh: 8ad2200fa74c12c9
41
+ /deepseek-ai-dsh-client-ui-settings-models/understand-the-implementation/concurrency-and-credentials:
42
+ en: 670b8c066aed9b7a
43
+ zh: 2bedba9a2e0e3fee
44
+ /deepseek-ai-dsh-client-ui-settings-models/understand-the-implementation/onboarding-coordinator:
45
+ en: 46dea666dffe8813
46
+ zh: 6f56fdc365fa3642
47
+ /deepseek-ai-dsh-client-ui-settings-models/further-exploration:
48
+ en: 20abd8b98b6c20e2
49
+ zh: 6dfda7955ce5f33f
50
+ /deepseek-ai-dsh-client-ui-settings-models/model-experience:
51
+ en: 3120df665299c634
52
+ zh: 1d9f365d091d0d2a
53
+ /deepseek-ai-dsh-client-ui-settings-models/model-experience/kv-cache-effect:
54
+ en: ca75c51c89c2c9b0
55
+ zh: 9779c98fff4c949a
56
+ /deepseek-ai-dsh-client-ui-settings-models/known-limitations-and-deferred-work:
57
+ en: cc69c9934bf22302
58
+ zh: 4ea896f4b54aa203
59
+ /deepseek-ai-dsh-client-ui-settings-models/known-limitations-and-deferred-work/dev-note:
60
+ en: 4f6749870e661a48
61
+ zh: 4953f3ea814546a4
package/README.md CHANGED
@@ -7,9 +7,11 @@ kind: "package-reference"
7
7
 
8
8
  English | [中文](README.zh.md)
9
9
 
10
+ Desktop product events use the optional [product analytics service](../product-analytics/README.md); ordinary Web interactions are excluded.
11
+
10
12
  ## Summary
11
13
 
12
- `dsh-client-ui-settings-models` is the Models settings page of the dsh web client: users configure API keys (stored write-only under the profile's credential reference), edit each provider's model list, and hand-declare custom pi-ai routes, with provider rows and one editor card at a time. The page joins the provider directory, the settings document, and the credential descriptions into one shared snapshot, so a row's state stays consistent across all three. It also walks first-run users through two ordered dialogs — a versioned internal-testing notice and the conditional official-DeepSeek credential step.
14
+ `dsh-client-ui-settings-models` is the Models settings page of the dsh web client: users configure API keys (stored write-only under the profile's credential reference), edit each provider's model list, and hand-declare custom pi-ai routes, with provider rows and one editor card at a time. The page joins the provider directory, the settings document, and the credential descriptions into one shared snapshot, so a row's state stays consistent across all three. It also walks first-run users through two ordered dialogs — a versioned preview notice and the conditional official-DeepSeek credential step.
13
15
 
14
16
  ## Table of Contents
15
17
 
@@ -25,14 +27,20 @@ English | [中文](README.zh.md)
25
27
  <a id="use-this-package"></a>
26
28
  ## Use this package
27
29
 
28
- Open the Models page from the Settings navigation to see every configured provider as a row. The official DeepSeek provider (`deepseek-official`) always appears first; other providers retain their directory order. A whole-section provider whose key is not configured anywhere renders as its open setup card instead, but only in the first-run posture and only until the user closes that card. Each card kind owns its own open state, so closing one never discards a draft in another.
30
+ Saving credentials or a custom provider preserves the selected model. The user can select an available model from the composer.
31
+
32
+ DeepSeek Account appears first and DeepSeek second in the provider list; third-party providers retain their directory order.
33
+
34
+ Open the Models page from the Settings navigation to see every configured provider as a row. A whole-section provider whose key is not configured anywhere renders as its open setup card instead, but only in the first-run posture and only until the user closes that card. Each card kind owns its own open state, so closing one never discards a draft in another.
29
35
 
30
36
  A provider with a stored catalog error remains visible with its diagnostic and edit/delete actions. Add actions are offered only for registered settings namespaces, so an unavailable namespace cannot leave a button that opens no editor. A rejected save leaves the editor open and displays the Host diagnostic.
31
37
 
32
- Host configuration `credentialOnboarding` defaults to `true`. Electron’s preload marker suppresses the credential step automatically; other native shells can set it to `false` in the plugin row; the Models settings page and welcome notice remain available. The Host publishes this public boolean through `webserver/index-inject`, and the Client validates it before registering its dialogs. It is page initialization data, not a persisted completion flag.
38
+ Host configuration `credentialOnboarding` defaults to `true`. The Electron preload marker suppresses automatic credential onboarding and the Web welcome notice; Models settings and explicit API-key editing remain available. The [account plugin](../ui-settings-account/README.md#desktop-onboarding) owns the Desktop introduction. Other native shells can disable only the credential step with `credentialOnboarding: false`. Host publishes this public boolean through `webserver/index-inject`, and Client validates it before registering dialogs. It is page initialization data, not a durable completion marker.
33
39
 
34
40
  ### API keys
35
41
 
42
+ API-key inputs start empty and use `autocomplete="new-password"` to ask browsers not to autofill saved login passwords.
43
+
36
44
  The primary field on an editor card is a single **API key** input — the page never asks for an environment-variable name. A typed key stores write-only through `credentials.set` under the profile's reference, deriving `<ROUTE>_API_KEY` when the profile has none, and the pi-ai profile records that derivation as `apiKeyEnv`, so `cordis.patch.yml` never carries a key value. Leaving a new pi-ai provider's key blank saves a reference-free profile and preserves provider-native authentication (for example the Bedrock credential chain or Vertex ADC). A row labels API-key state with a green solid dot only when a referenced credential is confirmed configured, and with a red solid dot only when a named reference is confirmed missing. A successful Apply emits a local accessible status message without echoing secret material.
37
45
 
38
46
  ### Editing a provider
@@ -55,6 +63,8 @@ After the versioned notice step completes, the DeepSeek step projects first-run
55
63
 
56
64
  The section declares two seats for plugins distributed outside this repository, typed in [`src/client/slot-contract.ts`](src/client/slot-contract.ts) and exported from `./client`. `settings.models.provider-card` (keyed) renders inside every card that shows a directory row — a saved row's card, its first-run setup posture, and the add-provider draft — dispatched with `entryKey = settingsNs` and owner props carrying the row's `ConfigurableProviderView`, its configured state, and its confirmed api-key credential state, so one registration under an adapter family's namespace receives every card of that family, hand-declared routes included; the hand-declared draft card has no directory row yet and dispatches nothing until saved. `settings.models.footer` (list) renders after the rows and the add controls. A registrant activates through `ctx.slots.inject` with a type-only import of this package's `/client` entry; without registrants both seats render nothing.
57
65
 
66
+ The Models page includes **DeepSeek Account** (`deepseek-account`, **DeepSeek 账号** in Chinese). Its editor exposes the shared DeepSeek model catalog without API-key or base-URL inputs, and saves that catalog under the account route's own settings section (`llm-deepseek-account` by default), so an account edit never rewrites the `llm-deepseek` section the official route reads. The account row is hidden when its available model catalog is empty, including before sign-in and after sign-out; it returns when account models become available.
67
+
58
68
  -----
59
69
 
60
70
  <a id="understand-the-implementation"></a>
@@ -75,7 +85,7 @@ Each settings write carries the card's current `revision`, so a concurrent write
75
85
 
76
86
  ### Onboarding coordinator
77
87
 
78
- The notice step owns its exact copy in `src/client/locales.ts` and its acknowledgement version in `src/onboarding-copy.ts`; on loopback it compares and writes `ui-settings-general.welcomeNoticeVersion` through the shared configuration form, and only an explicit Continue records the current version. A non-loopback browser cannot use that Host-only namespace, so acknowledgement is process-local and the notice returns after reload. The DeepSeek step targets `deepseek-official` in `llm-deepseek` and renders the existing `ProviderEditor` in credential-only mode inside the shared onboarding modal; `credentials.set` stays the only secret write, and no provider settings are changed.
88
+ The notice step owns its exact copy in `src/client/locales.ts` and its acknowledgement version in `src/onboarding-copy.ts`; on loopback it compares and writes `ui-settings-general.welcomeNoticeVersion` through the shared configuration form, and only an explicit Continue records the current version. Users who acknowledged an earlier version see the current notice again. A non-loopback browser cannot use that Host-only namespace, so acknowledgement is process-local and the notice returns after reload. The DeepSeek step targets `deepseek-official` in `llm-deepseek` and renders the existing `ProviderEditor` in credential-only mode inside the shared onboarding modal; `credentials.set` stays the only secret write, and no provider settings are changed.
79
89
 
80
90
  </details>
81
91
 
package/README.zh.md CHANGED
@@ -7,9 +7,11 @@ kind: "package-reference"
7
7
 
8
8
  [English](README.md) | 中文
9
9
 
10
+ 桌面端产品事件使用可选的[产品埋点服务](../product-analytics/README.zh.md),不包含普通 Web 交互。
11
+
10
12
  ## 概述
11
13
 
12
- `dsh-client-ui-settings-models` 是 dsh Web 客户端的 Models 设置页面:用户可以配置 API 密钥(以只写方式存入 profile 的凭据引用之下)、编辑每个提供商的模型列表,并手工声明自定义 pi-ai 路由;页面以提供商行展示,一次只展开一张编辑卡片。该页面把提供商目录、设置文档与凭据描述合并为一个共享快照,因此行的状态在三个方面始终一致。它还会带首次运行的用户走两个有序弹窗——版本化内测声明,以及按条件显示的官方 DeepSeek 凭据步骤。
14
+ `dsh-client-ui-settings-models` 是 dsh Web 客户端的 Models 设置页面:用户可以配置 API 密钥(以只写方式存入 profile 的凭据引用之下)、编辑每个提供商的模型列表,并手工声明自定义 pi-ai 路由;页面以提供商行展示,一次只展开一张编辑卡片。该页面把提供商目录、设置文档与凭据描述合并为一个共享快照,因此行的状态在三个方面始终一致。它还会带首次运行的用户走两个有序弹窗——版本化预览版说明,以及按条件显示的官方 DeepSeek 凭据步骤。
13
15
 
14
16
  ## 目录
15
17
 
@@ -25,14 +27,20 @@ kind: "package-reference"
25
27
  <a id="use-this-package"></a>
26
28
  ## 使用本包
27
29
 
28
- 从设置导航打开 Models 页面,即可看到每个已配置的提供商都有一行。官方 DeepSeek 提供商(`deepseek-official`)始终排在第一位,其他提供商保持目录中的原有顺序。其配置键未在任何位置配置的整分节提供商会渲染为其展开的设置卡片而非一行,但仅限首次运行姿态,且仅持续到用户关闭该卡片为止。每一类卡片各自持有自己的展开状态,因此关掉其中一张绝不会丢弃另一张里的草稿。
30
+ 保存凭据或自定义提供方时保留已选模型。用户可在 composer 中选择可用模型。
31
+
32
+ 提供方列表中 DeepSeek 账号排第一,DeepSeek 排第二;第三方提供方保留目录中的相对顺序。
33
+
34
+ 从设置导航打开 Models 页面,即可看到每个已配置的提供方都有一行。其配置键未在任何位置配置的整分节提供方会渲染为其展开的设置卡片而非一行,但仅限首次运行姿态,且仅持续到用户关闭该卡片为止。每一类卡片各自持有自己的展开状态,因此关掉其中一张绝不会丢弃另一张里的草稿。
29
35
 
30
36
  存在已存储目录错误的提供商仍显示诊断以及编辑、删除入口。添加操作只面向已注册的 settings 命名空间,因此不可用的命名空间不会留下无法打开编辑器的按钮。保存被拒绝时,编辑器保持打开并展示 Host 诊断。
31
37
 
32
- Host 配置 `credentialOnboarding` 默认为 `true`。Electron preload 标记会自动抑制凭证步骤;其他原生壳可以在插件行中把它设为 `false`;模型设置页和欢迎须知仍然可用。Host 通过 `webserver/index-inject` 发布这个公开的布尔值,Client 在注册弹窗前校验它。它是页面初始化数据,不是持久化的完成标记。
38
+ Host 配置 `credentialOnboarding` 默认为 `true`。Electron preload 标记会抑制自动凭证引导和 Web 欢迎须知;模型设置页与显式 API Key 编辑仍然可用。[账号插件](../ui-settings-account/README.zh.md#desktop-onboarding)负责 Desktop 引导。其他原生壳可以通过 `credentialOnboarding: false` 仅禁用凭证步骤。Host 通过 `webserver/index-inject` 发布这个公开的布尔值,Client 在注册弹窗前校验它。它是页面初始化数据,不是持久化的完成标记。
33
39
 
34
40
  ### API 密钥
35
41
 
42
+ API 密钥输入框初始为空,并通过 `autocomplete="new-password"` 请求浏览器不要自动填入已保存的登录密码。
43
+
36
44
  编辑卡片上的主字段是单独一个 **API 密钥**输入框——页面从不询问环境变量名。键入的密钥经 `credentials.set` 以**只写**方式存入 profile 的引用之下,profile 没有引用时便派生 `<ROUTE>_API_KEY`,pi-ai profile 会把这次派生记录为 `apiKeyEnv`,因此 `cordis.patch.yml` 从不携带密钥值。为新的 pi-ai 提供商留空密钥会保存一个不带引用的 profile,从而保留提供商原生认证(例如 Bedrock 凭据链或 Vertex ADC)。只有确认引用的凭据已配置时,行才会以绿色实心点标示 API 密钥状态;只有确认具名引用缺失时,才会以红色实心点标示。「应用」成功后会发出本地无障碍状态消息,且绝不回显任何机密内容。
37
45
 
38
46
  ### 编辑提供商
@@ -55,6 +63,8 @@ Host 配置 `credentialOnboarding` 默认为 `true`。Electron preload 标记会
55
63
 
56
64
  本分区为仓库外分发的插件声明两个席位,类型定义在 [`src/client/slot-contract.ts`](src/client/slot-contract.ts) 并从 `./client` 导出。`settings.models.provider-card`(keyed)渲染在每张展示目录行的卡片内部——已保存行的卡片、其首次运行 setup 形态、以及「添加提供商」草稿卡——以 `entryKey = settingsNs` 分发,owner props 携带该行的 `ConfigurableProviderView`、其 configured 状态与已确认的 api-key 凭据状态,因此以某适配器家族的 namespace 注册一次即可收到该家族的全部卡片,含手工声明的路由;手工声明的草稿卡尚无目录行,保存之前不分发。`settings.models.footer`(list)渲染在行列表与新增控件之后。注册方通过 `ctx.slots.inject` 激活,并以 type-only import 引入本包 `/client` 入口;没有注册方时两个席位均不渲染任何内容。
57
65
 
66
+ Models 页面包含 **DeepSeek 账号**(`deepseek-account`,英文为 **DeepSeek Account**)。其编辑器展示共享的 DeepSeek 模型目录,不提供 API Key 或 Base URL 输入框;目录保存到账号路由自己的设置段(默认为 `llm-deepseek-account`),因此账号侧的编辑不会改写 official 路由读取的 `llm-deepseek` 段。账号可用模型目录为空时隐藏账号行,包括登录前和退登后;账号模型恢复可用时重新显示。
67
+
58
68
  -----
59
69
 
60
70
  <a id="understand-the-implementation"></a>
@@ -75,7 +85,7 @@ Host 配置 `credentialOnboarding` 默认为 `true`。Electron preload 标记会
75
85
 
76
86
  ### 引导协调器
77
87
 
78
- 声明步骤在 `src/client/locales.ts` 中持有精确文案,并在 `src/onboarding-copy.ts` 中持有确认版本;回环时它通过既有 settings API 比较并写入 `ui-settings-general.welcomeNoticeVersion`,且只有显式点击「继续」才会记录当前版本。非回环浏览器无法使用这个仅限宿主的 namespace,因此确认只保留在进程内,刷新后声明会再次出现。DeepSeek 步骤面向 `llm-deepseek` 中的 `deepseek-official`,在共享引导模态框内以仅凭据模式渲染既有 `ProviderEditor`;`credentials.set` 仍是唯一的机密写入,且不改变任何提供商设置。
88
+ 预览版说明在 `src/client/locales.ts` 中持有精确文案,并在 `src/onboarding-copy.ts` 中持有确认版本;回环时它通过既有 settings API 比较并写入 `ui-settings-general.welcomeNoticeVersion`,且只有显式点击「继续」才会记录当前版本。已确认旧版的用户会再次看到当前说明。非回环浏览器无法使用这个仅限宿主的 namespace,因此确认只保留在进程内,刷新后说明会再次出现。DeepSeek 步骤面向 `llm-deepseek` 中的 `deepseek-official`,在共享引导模态框内以仅凭据模式渲染既有 `ProviderEditor`;`credentials.set` 仍是唯一的机密写入,且不改变任何提供商设置。
79
89
 
80
90
  </details>
81
91
 
package/lib/client.js CHANGED
@@ -55,7 +55,7 @@ window.__ModuleLoader__.load({
55
55
  }
56
56
  //#endregion
57
57
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-models/src/client/ModelsSection.module.css.mjs
58
- const css$3 = ".zGbnIq_section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}.zGbnIq_title{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}.zGbnIq_intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}.zGbnIq_notice{color:var(--dsw-alias-state-warn-label);margin:0;font-size:12px;line-height:18px}.zGbnIq_savedNotice{color:var(--dsw-alias-state-success-primary);margin:0;font-size:12px;line-height:18px}.zGbnIq_rows{flex-direction:column;gap:8px;margin:12px 0 0;padding:0;list-style:none;display:flex}.zGbnIq_rowCard{border:.5px solid var(--dsw-alias-border-l4);border-radius:16px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.zGbnIq_rowHead{align-items:center;gap:10px;display:flex}.zGbnIq_rowIdentity{align-items:center;gap:6px;min-width:0;display:inline-flex}.zGbnIq_rowName{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.zGbnIq_rowTag{border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;padding:1px 6px;font-size:11px;line-height:16px}.zGbnIq_credentialDot{box-sizing:border-box;corner-shape:round;border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.zGbnIq_credentialDotConfigured{background:var(--dsw-alias-state-success-primary)}.zGbnIq_credentialDotMissing{background:var(--dsw-alias-state-error-primary)}.zGbnIq_rowActions{align-items:center;gap:4px;margin-left:auto;display:inline-flex}.zGbnIq_primaryButton,.zGbnIq_secondaryButton,.zGbnIq_addButton{box-sizing:border-box;height:36px;font:inherit;cursor:pointer;border:none;border-radius:18px;justify-content:center;align-items:center;gap:4px;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.zGbnIq_primaryButton{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.zGbnIq_primaryButton:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.zGbnIq_secondaryButton,.zGbnIq_addButton{border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-primary);background:0 0}.zGbnIq_secondaryButton:hover:not(:disabled),.zGbnIq_addButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.zGbnIq_secondaryButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.zGbnIq_dangerButton{box-sizing:border-box;height:36px;color:var(--dsw-alias-state-error-primary);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:18px;justify-content:center;align-items:center;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.zGbnIq_dangerButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.zGbnIq_rowActions .zGbnIq_secondaryButton,.zGbnIq_rowActions .zGbnIq_dangerButton{border-radius:14px;height:28px;padding:0 10px;font-size:12px;line-height:18px}.zGbnIq_primaryButton:disabled,.zGbnIq_secondaryButton:disabled,.zGbnIq_dangerButton:disabled,.zGbnIq_addButton:disabled,.zGbnIq_linkButton:disabled,.zGbnIq_addModelButton:disabled{opacity:.4;cursor:default}.zGbnIq_primaryButton:focus-visible,.zGbnIq_secondaryButton:focus-visible,.zGbnIq_dangerButton:focus-visible,.zGbnIq_addButton:focus-visible,.zGbnIq_linkButton:focus-visible,.zGbnIq_addModelButton:focus-visible,.zGbnIq_iconButton:focus-visible,.zGbnIq_customizedSummary:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3);outline:none}.zGbnIq_editor{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;display:flex}.zGbnIq_editorHeader{align-items:baseline;gap:8px;display:flex}.zGbnIq_editorTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.zGbnIq_editorRoute{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.zGbnIq_field{flex-direction:column;gap:6px;display:flex}.zGbnIq_fieldLabel{color:var(--dsw-alias-label-secondary);align-items:center;gap:10px;font-size:12px;font-weight:500;line-height:18px;display:inline-flex}.zGbnIq_linkButton{box-sizing:border-box;height:28px;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:14px;align-items:center;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.zGbnIq_linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.zGbnIq_advancedHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.zGbnIq_editorActions{justify-content:flex-end;gap:8px;display:flex}.zGbnIq_addBlock{flex-direction:column;gap:12px;display:flex}.zGbnIq_addActions{display:flex}.zGbnIq_addButton{border:1px dashed var(--dsw-alias-border-l3);border-radius:16px;flex:1 1 0;gap:6px;min-width:180px;height:44px}.zGbnIq_addModes{flex-direction:column;align-items:flex-start;gap:8px;display:flex}.zGbnIq_addPanel{flex-direction:column;gap:14px;display:flex}.zGbnIq_addPanel[hidden]{display:none}.zGbnIq_addCard,.zGbnIq_setupCard{background:var(--dsw-alias-bg-module-platform);border-radius:12px;flex-direction:column;gap:14px;padding:14px 16px;list-style:none;display:flex}.zGbnIq_addCard .zGbnIq_editor,.zGbnIq_setupCard .zGbnIq_editor{background:0 0;padding:0}.zGbnIq_customized{border-top:.5px solid var(--dsw-alias-border-l2);padding-top:10px}.zGbnIq_customizedSummary{cursor:pointer;width:fit-content;color:var(--dsw-alias-label-secondary);border-radius:6px;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;list-style:none;display:flex}.zGbnIq_customizedSummary::-webkit-details-marker{display:none}.zGbnIq_customizedSummary:before{content:\"\";border-bottom:1.5px solid;border-right:1.5px solid;width:5px;height:5px;transition:transform .12s;transform:rotate(-45deg)translate(-1px,-1px)}.zGbnIq_customized[open]>.zGbnIq_customizedSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.zGbnIq_customizedSummary:hover{color:var(--dsw-alias-label-primary)}.zGbnIq_customizedBody{flex-direction:column;gap:12px;padding-top:12px;display:flex}.zGbnIq_modelCatalog{border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:10px;padding-top:12px;display:flex}.zGbnIq_modelCatalogHeading{flex-direction:column;gap:2px;display:flex}.zGbnIq_modelCatalogTitle{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.zGbnIq_modelCatalogMeta,.zGbnIq_modelEmpty{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.zGbnIq_modelList{flex-direction:column;gap:8px;display:flex}.zGbnIq_modelListHead{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.zGbnIq_modelEntry{border:.5px solid var(--dsw-alias-border-l4);border-radius:10px;padding:6px}.zGbnIq_modelRow{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) auto auto;align-items:center;gap:6px;display:grid}.zGbnIq_iconButton{box-sizing:border-box;width:28px;height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;display:inline-flex}.zGbnIq_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.zGbnIq_iconButton:disabled{cursor:default;opacity:.4}.zGbnIq_iconButtonDanger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary)}.zGbnIq_modelAdvanced{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;padding:8px 4px 2px;display:grid}.zGbnIq_modelField{flex-direction:column;gap:4px;min-width:0;display:flex}.zGbnIq_modelInputTypes{border:none;grid-column:1/-1;min-width:0;margin:0;padding:0}.zGbnIq_modelInputTypes legend{margin-bottom:4px;padding:0}.zGbnIq_modelInputChoices{flex-wrap:wrap;align-items:center;gap:16px;min-height:32px;display:flex}.zGbnIq_modelFieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.zGbnIq_modelEmpty{border:1px dashed var(--dsw-alias-border-l3);text-align:center;border-radius:8px;padding:12px}.zGbnIq_addModelButton{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);height:28px;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;background:0 0;border-radius:14px;align-self:flex-start;align-items:center;gap:4px;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.zGbnIq_addModelButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.zGbnIq_input{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);width:100%;height:32px;font:inherit;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 10px;font-size:14px;line-height:22px}select.zGbnIq_input{cursor:pointer;max-width:240px}.zGbnIq_input:focus{border-color:var(--dsw-alias-brand-primary);outline:none}.zGbnIq_input::placeholder{color:var(--dsw-alias-label-dimmed)}.zGbnIq_input:disabled{opacity:.6;cursor:default}.zGbnIq_selectInput{appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 12px center;background-repeat:no-repeat;background-size:12px 12px;padding-right:32px}.zGbnIq_error{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:18px}.zGbnIq_deleteDialog{width:min(480px,100%)}.zGbnIq_deleteConfirm:not(:disabled){border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.zGbnIq_deleteConfirm:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.zGbnIq_hiddenLabel{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}@media (prefers-reduced-motion:reduce){.zGbnIq_customizedSummary:before,.zGbnIq_switchThumb{transition:none}}.zGbnIq_fetchDialog{--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);max-width:520px}.zGbnIq_candidateToolbar{align-items:center;gap:8px;margin-bottom:6px;display:flex}.zGbnIq_candidateSearch{flex:240px;min-width:0}.zGbnIq_candidateList{flex-direction:column;gap:2px;max-height:320px;margin:0;padding:0;list-style:none;display:flex;overflow-y:auto}.zGbnIq_candidate{border-radius:6px}.zGbnIq_candidateLabel{cursor:pointer;align-items:center;gap:8px;padding:6px 8px;display:flex}.zGbnIq_candidateId{min-width:0;font-family:var(--ds-font-family-code);text-overflow:ellipsis;white-space:nowrap;flex:auto;font-size:13px;overflow:hidden}.zGbnIq_candidateEmpty{color:var(--dsw-alias-label-secondary);text-align:center;margin:24px 0;font-size:13px;line-height:20px}";
58
+ const css$3 = ".zGbnIq_section{max-width:720px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:12px;display:flex}.zGbnIq_title{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}.zGbnIq_intro{color:var(--dsw-alias-label-tertiary);margin:0;font-size:14px;line-height:22px}.zGbnIq_notice{color:var(--dsw-alias-state-warn-label);margin:0;font-size:12px;line-height:18px}.zGbnIq_savedNotice{color:var(--dsw-alias-state-success-primary);margin:0;font-size:12px;line-height:18px}.zGbnIq_rows{flex-direction:column;gap:8px;margin:12px 0 0;padding:0;list-style:none;display:flex}.zGbnIq_rowCard{border:.5px solid var(--dsw-alias-settings-card-stroke);background:var(--dsw-alias-settings-card-fill);border-radius:var(--dsw-radius-xl);flex-direction:column;gap:12px;padding:12px 14px;display:flex}.zGbnIq_rowHead{align-items:center;gap:10px;display:flex}.zGbnIq_rowIdentity{align-items:center;gap:6px;min-width:0;display:inline-flex}.zGbnIq_rowName{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.zGbnIq_rowTag{border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-xs);color:var(--dsw-alias-label-secondary);flex:none;padding:1px 6px;font-size:11px;line-height:16px}.zGbnIq_credentialDot{box-sizing:border-box;corner-shape:round;border-radius:50%;flex:none;width:8px;height:8px;display:inline-block}.zGbnIq_credentialDotConfigured{background:var(--dsw-alias-state-success-primary)}.zGbnIq_credentialDotMissing{background:var(--dsw-alias-state-error-primary)}.zGbnIq_rowActions{align-items:center;gap:4px;margin-left:auto;display:inline-flex}.zGbnIq_primaryButton,.zGbnIq_secondaryButton,.zGbnIq_addButton{box-sizing:border-box;border-radius:var(--dsw-radius-md);height:36px;font:inherit;cursor:pointer;border:none;justify-content:center;align-items:center;gap:4px;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.zGbnIq_primaryButton{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.zGbnIq_primaryButton:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.zGbnIq_secondaryButton,.zGbnIq_addButton{border:.5px solid var(--dsw-alias-border-l3);color:var(--dsw-alias-label-primary);background:0 0}.zGbnIq_secondaryButton:hover:not(:disabled),.zGbnIq_addButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.zGbnIq_secondaryButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.zGbnIq_dangerButton{box-sizing:border-box;border-radius:var(--dsw-radius-md);height:36px;color:var(--dsw-alias-state-error-primary);font:inherit;cursor:pointer;background:0 0;border:none;justify-content:center;align-items:center;padding:0 14px;font-size:14px;line-height:22px;display:inline-flex}.zGbnIq_dangerButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.zGbnIq_rowActions .zGbnIq_secondaryButton,.zGbnIq_rowActions .zGbnIq_dangerButton{border-radius:var(--dsw-radius-sm);height:28px;padding:0 10px;font-size:12px;line-height:18px}.zGbnIq_primaryButton:disabled,.zGbnIq_secondaryButton:disabled,.zGbnIq_dangerButton:disabled,.zGbnIq_addButton:disabled,.zGbnIq_linkButton:disabled,.zGbnIq_addModelButton:disabled{opacity:.4;cursor:default}.zGbnIq_primaryButton:focus-visible,.zGbnIq_secondaryButton:focus-visible,.zGbnIq_dangerButton:focus-visible,.zGbnIq_addButton:focus-visible,.zGbnIq_linkButton:focus-visible,.zGbnIq_addModelButton:focus-visible,.zGbnIq_iconButton:focus-visible,.zGbnIq_customizedSummary:focus-visible{box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline:none}.zGbnIq_editor{border-radius:var(--dsw-radius-lg);background:var(--dsw-alias-bg-module-platform);flex-direction:column;gap:14px;padding:14px 16px;display:flex}.zGbnIq_editorHeader{align-items:baseline;gap:8px;display:flex}.zGbnIq_editorTitle{color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:22px}.zGbnIq_editorRoute{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.zGbnIq_field{flex-direction:column;gap:6px;display:flex}.zGbnIq_fieldLabel{color:var(--dsw-alias-label-secondary);align-items:center;gap:10px;font-size:12px;font-weight:500;line-height:18px;display:inline-flex}.zGbnIq_linkButton{box-sizing:border-box;border-radius:var(--dsw-radius-sm);height:28px;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:none;align-items:center;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.zGbnIq_linkButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary)}.zGbnIq_advancedHint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.zGbnIq_editorActions{justify-content:flex-end;gap:8px;display:flex}.zGbnIq_addBlock{flex-direction:column;gap:12px;display:flex}.zGbnIq_addActions{display:flex}.zGbnIq_addButton{border:1px dashed var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-lg);flex:1 1 0;gap:6px;min-width:180px;height:44px}.zGbnIq_addModes{flex-direction:column;align-items:flex-start;gap:8px;display:flex}.zGbnIq_addPanel{flex-direction:column;gap:14px;display:flex}.zGbnIq_addPanel[hidden]{display:none}.zGbnIq_addCard,.zGbnIq_setupCard{border-radius:var(--dsw-radius-lg);background:var(--dsw-alias-bg-module-platform);flex-direction:column;gap:14px;padding:14px 16px;list-style:none;display:flex}.zGbnIq_addCard .zGbnIq_editor,.zGbnIq_setupCard .zGbnIq_editor{background:0 0;padding:0}.zGbnIq_customized{border-top:.5px solid var(--dsw-alias-border-l2);padding-top:10px}.zGbnIq_customizedSummary{border-radius:var(--dsw-radius-sm);cursor:pointer;width:fit-content;color:var(--dsw-alias-label-secondary);align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;list-style:none;display:flex}.zGbnIq_customizedSummary::-webkit-details-marker{display:none}.zGbnIq_customizedSummary:before{content:\"\";border-bottom:1.5px solid;border-right:1.5px solid;width:5px;height:5px;transition:transform .12s;transform:rotate(-45deg)translate(-1px,-1px)}.zGbnIq_customized[open]>.zGbnIq_customizedSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.zGbnIq_customizedSummary:hover{color:var(--dsw-alias-label-primary)}.zGbnIq_customizedBody{flex-direction:column;gap:12px;padding-top:12px;display:flex}.zGbnIq_modelCatalog{border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:10px;padding-top:12px;display:flex}.zGbnIq_modelCatalogHeading{flex-direction:column;gap:2px;display:flex}.zGbnIq_modelCatalogTitle{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:500;line-height:18px}.zGbnIq_modelCatalogMeta,.zGbnIq_modelEmpty{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:18px}.zGbnIq_modelList{flex-direction:column;gap:8px;display:flex}.zGbnIq_modelListHead{justify-content:space-between;align-items:flex-start;gap:12px;display:flex}.zGbnIq_modelEntry{border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-lg);padding:6px}.zGbnIq_modelRow{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) auto auto;align-items:center;gap:6px;display:grid}.zGbnIq_iconButton{box-sizing:border-box;border-radius:var(--dsw-radius-sm);width:28px;height:28px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;justify-content:center;align-items:center;display:inline-flex}.zGbnIq_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.zGbnIq_iconButton:disabled{cursor:default;opacity:.4}.zGbnIq_iconButtonDanger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary)}.zGbnIq_modelAdvanced{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;padding:8px 4px 2px;display:grid}.zGbnIq_modelField{flex-direction:column;gap:4px;min-width:0;display:flex}.zGbnIq_modelInputTypes{border:none;grid-column:1/-1;min-width:0;margin:0;padding:0}.zGbnIq_modelInputTypes legend{margin-bottom:4px;padding:0}.zGbnIq_modelInputChoices{flex-wrap:wrap;align-items:center;gap:16px;min-height:32px;display:flex}.zGbnIq_modelFieldLabel{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.zGbnIq_modelEmpty{border:1px dashed var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-lg);text-align:center;padding:12px}.zGbnIq_addModelButton{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-sm);height:28px;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;background:0 0;align-self:flex-start;align-items:center;gap:4px;padding:0 10px;font-size:12px;line-height:18px;display:inline-flex}.zGbnIq_addModelButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.zGbnIq_input{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md);width:100%;height:32px;font:inherit;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);padding:0 10px;font-size:14px;line-height:22px}select.zGbnIq_input{cursor:pointer;max-width:240px}.zGbnIq_input:focus{border-color:var(--dsw-alias-state-business-primary);outline:none}.zGbnIq_input::placeholder{color:var(--dsw-alias-label-dimmed)}.zGbnIq_input:disabled{opacity:.6;cursor:default}.zGbnIq_selectInput{appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 12px center;background-repeat:no-repeat;background-size:12px 12px;padding-right:32px}.zGbnIq_error{color:var(--dsw-alias-state-error-primary);margin:0;font-size:12px;line-height:18px}.zGbnIq_deleteDialog{width:min(480px,100%)}.zGbnIq_deleteConfirm:not(:disabled){border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.zGbnIq_deleteConfirm:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.zGbnIq_hiddenLabel{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}@media (prefers-reduced-motion:reduce){.zGbnIq_customizedSummary:before,.zGbnIq_switchThumb{transition:none}}.zGbnIq_fetchDialog{--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);max-width:520px}.zGbnIq_candidateToolbar{align-items:center;gap:8px;margin-bottom:6px;display:flex}.zGbnIq_candidateSearch{flex:240px;min-width:0}.zGbnIq_candidateList{flex-direction:column;gap:2px;max-height:320px;margin:0;padding:0;list-style:none;display:flex;overflow-y:auto}.zGbnIq_candidate{border-radius:var(--dsw-radius-md)}.zGbnIq_candidateLabel{cursor:pointer;align-items:center;gap:8px;padding:6px 8px;display:flex}.zGbnIq_candidateId{min-width:0;font-family:var(--ds-font-family-code);text-overflow:ellipsis;white-space:nowrap;flex:auto;font-size:13px;overflow:hidden}.zGbnIq_candidateEmpty{color:var(--dsw-alias-label-secondary);text-align:center;margin:24px 0;font-size:13px;line-height:20px}";
59
59
  const tagId$3 = "@deepseek-ai/dsh-client-ui-settings-models/ModelsSection.module.css";
60
60
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
61
61
  const tag = document.createElement("style");
@@ -902,7 +902,7 @@ window.__ModuleLoader__.load({
902
902
  * Join declared configurable providers with the currently registered routes.
903
903
  * @param registered - live provider routes in registration order.
904
904
  * @param directory - declared configurable providers in declaration order.
905
- * @returns declared rows followed by live routes with no declaration.
905
+ * @returns account and official routes first, then other routes in their original order.
906
906
  */
907
907
  function joinProviderDirectory(registered, directory) {
908
908
  const active = new Set(registered.map((provider) => provider.id));
@@ -926,7 +926,7 @@ window.__ModuleLoader__.load({
926
926
  active: true
927
927
  });
928
928
  }
929
- return rows;
929
+ return rows.toSorted((left, right) => (left.provider === "deepseek-account" ? 0 : left.provider === "deepseek-official" ? 1 : 2) - (right.provider === "deepseek-account" ? 0 : right.provider === "deepseek-official" ? 1 : 2));
930
930
  }
931
931
  /**
932
932
  * Derive the conventional credential reference for a provider route: the v1
@@ -1034,11 +1034,15 @@ window.__ModuleLoader__.load({
1034
1034
  entry,
1035
1035
  configured: namespace !== void 0 && (entry.settingsPath.length === 0 || this.schema.getPath(namespace.value, entry.settingsPath) !== void 0),
1036
1036
  removable: namespace !== void 0 && entry.settingsPath.length > 0 && this.schema.hasPath(namespace.user, entry.settingsPath) && !this.schema.hasPath(namespace.base, entry.settingsPath),
1037
- apiKeyEnv: apiKeyEnvOf(namespace, entry.settingsPath, this.schema),
1037
+ apiKeyEnv: entry.provider === "deepseek-account" ? void 0 : apiKeyEnvOf(namespace, entry.settingsPath, this.schema),
1038
1038
  credential: void 0
1039
1039
  };
1040
1040
  });
1041
- const refs = [...new Set(rows.map((row) => row.apiKeyEnv ?? deriveKeyRef(row.entry.provider)))];
1041
+ if (rows.some((row) => row.entry.provider === "deepseek-account")) {
1042
+ const catalog = await this.ctx.remote.session.modelCatalog();
1043
+ for (const row of rows) if (row.entry.provider === "deepseek-account") row.accountAvailable = catalog.ok && catalog.value.groups.some((group) => group.id === "deepseek-account" && group.models.length > 0);
1044
+ }
1045
+ const refs = [...new Set(rows.filter((row) => row.entry.provider !== "deepseek-account").map((row) => row.apiKeyEnv ?? deriveKeyRef(row.entry.provider)))];
1042
1046
  let credentials = {};
1043
1047
  let credentialError = null;
1044
1048
  if (refs.length > 0) {
@@ -1052,7 +1056,8 @@ window.__ModuleLoader__.load({
1052
1056
  s.error = null;
1053
1057
  s.credentialError = credentialError;
1054
1058
  s.writable = writable;
1055
- s.rows = rows.map((row) => {
1059
+ s.rows = rows.filter((row) => row.entry.provider !== "deepseek-account" || row.accountAvailable === true).map((row) => {
1060
+ if (row.entry.provider === "deepseek-account") return row;
1056
1061
  const named = row.apiKeyEnv === void 0 ? void 0 : credentials[row.apiKeyEnv];
1057
1062
  const derived = row.apiKeyEnv !== void 0 ? void 0 : credentials[deriveKeyRef(row.entry.provider)];
1058
1063
  return {
@@ -1085,6 +1090,7 @@ window.__ModuleLoader__.load({
1085
1090
  */
1086
1091
  function providerUsable(row) {
1087
1092
  if (!row.entry.active) return false;
1093
+ if (row.entry.provider === "deepseek-account") return row.accountAvailable === true;
1088
1094
  if (row.apiKeyEnv === void 0) return true;
1089
1095
  return row.credential?.configured === true;
1090
1096
  }
@@ -1372,7 +1378,7 @@ window.__ModuleLoader__.load({
1372
1378
  (0, react_jsx_runtime.jsx)("input", {
1373
1379
  className: ModelsSection_module_css_default["input"],
1374
1380
  type: "password",
1375
- autoComplete: "off",
1381
+ autoComplete: "new-password",
1376
1382
  value: keyDraft,
1377
1383
  placeholder: t("keyPlaceholder"),
1378
1384
  "aria-label": t("keyInput"),
@@ -1526,7 +1532,8 @@ window.__ModuleLoader__.load({
1526
1532
  ]);
1527
1533
  const fallback = schema.getPath(namespace.value, settingsPath);
1528
1534
  const disabled = props.readOnly || busy;
1529
- const layout = layoutOf(namespace.ns);
1535
+ const accountProvider = props.provider === "deepseek-account";
1536
+ const layout = accountProvider ? "deepseek" : layoutOf(namespace.ns);
1530
1537
  const keyRef = refFor(schema, namespace, settingsPath, props.provider);
1531
1538
  const protocols = (0, react.useMemo)(() => layout === "pi-ai" ? protocolChoices(namespace, schema) : [], [
1532
1539
  layout,
@@ -1534,6 +1541,7 @@ window.__ModuleLoader__.load({
1534
1541
  schema
1535
1542
  ]);
1536
1543
  (0, react.useEffect)(() => {
1544
+ if (accountProvider) return;
1537
1545
  let stale = false;
1538
1546
  setKeyState(void 0);
1539
1547
  operations.describeCredential(keyRef).then((described) => {
@@ -1543,7 +1551,11 @@ window.__ModuleLoader__.load({
1543
1551
  return () => {
1544
1552
  stale = true;
1545
1553
  };
1546
- }, [operations, keyRef]);
1554
+ }, [
1555
+ operations,
1556
+ keyRef,
1557
+ accountProvider
1558
+ ]);
1547
1559
  const stringAt = (source, key) => {
1548
1560
  const value = schema.getPath(source, [key]);
1549
1561
  return typeof value === "string" && value.trim().length > 0 ? value : void 0;
@@ -1663,6 +1675,11 @@ window.__ModuleLoader__.load({
1663
1675
  setDraft((current) => schema.deletePath(current, ["models"]));
1664
1676
  }
1665
1677
  };
1678
+ if (accountProvider) return (0, react_jsx_runtime.jsx)(DeepSeekModelsEditor, {
1679
+ ...catalogProps,
1680
+ defaultContextWindow: typeof defaultContextWindow === "number" ? defaultContextWindow : void 0,
1681
+ defaultMaxTokens: typeof defaultMaxTokens === "number" ? defaultMaxTokens : void 0
1682
+ });
1666
1683
  return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
1667
1684
  className: ModelsSection_module_css_default["field"],
1668
1685
  children: [
@@ -1673,7 +1690,7 @@ window.__ModuleLoader__.load({
1673
1690
  (0, react_jsx_runtime.jsx)("input", {
1674
1691
  className: ModelsSection_module_css_default["input"],
1675
1692
  type: "password",
1676
- autoComplete: "off",
1693
+ autoComplete: "new-password",
1677
1694
  value: keyDraft,
1678
1695
  placeholder: keyPlaceholder,
1679
1696
  "aria-label": t("keyInput"),
@@ -1816,6 +1833,7 @@ window.__ModuleLoader__.load({
1816
1833
  props.onClose(false);
1817
1834
  },
1818
1835
  onSubmit: () => {
1836
+ props.onSubmitCredential?.();
1819
1837
  apply();
1820
1838
  }
1821
1839
  })
@@ -1827,8 +1845,8 @@ window.__ModuleLoader__.load({
1827
1845
  /**
1828
1846
  * Models settings section: the provider rows joined from the configurable
1829
1847
  * directory, settings namespaces, and credential states, with one editor
1830
- * card at a time. The official DeepSeek provider appears first; other rows
1831
- * retain directory order. Rows expose only confirmed API-key state through accessible
1848
+ * card at a time. Rows retain the account-first order supplied by the store
1849
+ * and expose only confirmed API-key state through accessible
1832
1850
  * solid configured or missing dots. A whole-section provider without a
1833
1851
  * configured key renders as its open setup card instead of a row, but only in
1834
1852
  * the first-run posture — no provider on the page can serve requests yet — and
@@ -1889,7 +1907,7 @@ window.__ModuleLoader__.load({
1889
1907
  * @returns whether to render the setup card.
1890
1908
  */
1891
1909
  function needsSetup(row, anyUsable) {
1892
- if (anyUsable) return false;
1910
+ if (anyUsable || row.entry.provider === "deepseek-account") return false;
1893
1911
  if (row.entry.settingsPath.length > 0) return false;
1894
1912
  return row.credential?.configured !== true;
1895
1913
  }
@@ -1944,7 +1962,17 @@ window.__ModuleLoader__.load({
1944
1962
  }
1945
1963
  function Loaded({ injected, renderSlot }) {
1946
1964
  const { controller, operations, schema, t } = injected;
1947
- const state = injected.useSnapshot((snapshot) => snapshot);
1965
+ const snapshot = injected.useSnapshot((value) => value);
1966
+ const state = {
1967
+ ...snapshot,
1968
+ rows: snapshot.rows.map((row) => row.entry.provider === "deepseek-account" ? {
1969
+ ...row,
1970
+ entry: {
1971
+ ...row.entry,
1972
+ displayName: t("deepSeekAccount")
1973
+ }
1974
+ } : row)
1975
+ };
1948
1976
  const [editing, setEditing] = (0, react.useState)(void 0);
1949
1977
  const [addOpen, setAddOpen] = (0, react.useState)(false);
1950
1978
  const [addMode, setAddMode] = (0, react.useState)("catalog");
@@ -2038,7 +2066,7 @@ window.__ModuleLoader__.load({
2038
2066
  displayName: savedRow.entry.displayName
2039
2067
  };
2040
2068
  const anyUsable = state.rows.some(providerUsable);
2041
- const configured = state.rows.filter((row) => row.configured).sort((left, right) => Number(right.entry.provider === "deepseek-official") - Number(left.entry.provider === "deepseek-official"));
2069
+ const configured = state.rows.filter((row) => row.configured);
2042
2070
  const configurable = state.rows.filter((row) => state.namespaces.has(row.entry.settingsNs));
2043
2071
  const addable = state.rows.flatMap((row) => {
2044
2072
  const namespace = state.namespaces.get(row.entry.settingsNs);
@@ -2347,7 +2375,7 @@ window.__ModuleLoader__.load({
2347
2375
  className: ModelsSection_module_css_default["deleteDialog"],
2348
2376
  footer: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2349
2377
  variant: "outline",
2350
- autoFocus: true,
2378
+ "data-modal-autofocus": true,
2351
2379
  disabled: deleting,
2352
2380
  onClick: closeDelete,
2353
2381
  children: t("cancel")
@@ -2445,13 +2473,6 @@ window.__ModuleLoader__.load({
2445
2473
  };
2446
2474
  //#endregion
2447
2475
  //#region lib/types/client/DeepSeekOnboardingDialog.js
2448
- /**
2449
- * Official-DeepSeek first-run step. Readiness comes from the same
2450
- * provider/settings/credential join as the Models page: any provider the user
2451
- * can already talk to ends the step, and only a user with none is offered the
2452
- * official DeepSeek route. The step reuses that page's credential editor in
2453
- * the onboarding plugin's shared modal, so the key is entered once.
2454
- */
2455
2476
  /* v8 ignore next 3 -- closed-union defaults only defend future source widening */
2456
2477
  function assertNever$1(_value) {
2457
2478
  throw new Error("unexpected DeepSeek onboarding state");
@@ -2524,6 +2545,9 @@ window.__ModuleLoader__.load({
2524
2545
  readOnly: false,
2525
2546
  hideTitle: true,
2526
2547
  credentialOnly: true,
2548
+ onSubmitCredential: () => {
2549
+ props.track?.("api_key_save_click", {});
2550
+ },
2527
2551
  credentialRequired: true,
2528
2552
  autoFocusCredential: true,
2529
2553
  cancelLabelKey: "onboardingLater",
@@ -2559,7 +2583,7 @@ window.__ModuleLoader__.load({
2559
2583
  };
2560
2584
  //#endregion
2561
2585
  //#region lib/types/client/WelcomeNotice.js
2562
- /** Product-wide, versioned internal-testing notice. */
2586
+ /** Product-wide, versioned preview notice. */
2563
2587
  /**
2564
2588
  * Render the current notice until its exact copy version is acknowledged.
2565
2589
  * @param props - settings-shell owner state and welcome dependencies.
@@ -2623,7 +2647,7 @@ window.__ModuleLoader__.load({
2623
2647
  * Bump only when the notice changes materially and every user should see it
2624
2648
  * again. The acknowledgement is compared for exact equality.
2625
2649
  */
2626
- const WELCOME_NOTICE_VERSION = "2026-08-13.1";
2650
+ const WELCOME_NOTICE_VERSION = "2026-09-28.1";
2627
2651
  //#endregion
2628
2652
  //#region lib/types/client/welcome-store.js
2629
2653
  /**
@@ -2819,6 +2843,7 @@ window.__ModuleLoader__.load({
2819
2843
  /** English strings (the key-set source of truth for this pair). */
2820
2844
  const en = {
2821
2845
  nav: "Models",
2846
+ deepSeekAccount: "DeepSeek Account",
2822
2847
  title: "Models",
2823
2848
  intro: "Enter your API keys to use models from the following providers.",
2824
2849
  edit: "Edit",
@@ -2920,8 +2945,8 @@ window.__ModuleLoader__.load({
2920
2945
  settingsPathUnresolvable: "unresolvable settings path",
2921
2946
  create: "Create provider",
2922
2947
  creating: "Creating…",
2923
- welcomeTitle: "Internal Testing Notice",
2924
- welcomeBody: "DeepSeek Harness 0.1 remains in testing for Harness developers. Many areas need further improvement, and we welcome feedback from the developer community. DeepSeek Harness's core plugins and foundational APIs will continue to evolve rapidly over the coming months.\n\nWe look forward to exploring the limits of intelligence with developers around the world, building on open-source, open, reusable, and composable infrastructure. We welcome Harness developers everywhere to join the DSH plugin ecosystem.",
2948
+ welcomeTitle: "Preview Notice",
2949
+ welcomeBody: "DeepSeek Harness 0.2 is still in preview, and many areas need continued improvement and refinement. We welcome feedback and suggestions from all developers and users. The new desktop app now targets a broad range of users, while developer-related advanced features can be enabled in the settings. DeepSeek Harness’s product features and plugin APIs are expected to continue rapid iteration and evolution, and will gradually stabilize over time.\n\nWe look forward to exploring the limits of intelligence together with users and developers around the world, building on open-source, reusable, and composable infrastructure. We welcome everyone to bring their ideas to life with DeepSeek Harness and participate in the community to enrich the plugin ecosystem.",
2925
2950
  welcomeContinue: "Continue",
2926
2951
  welcomeError: "The acknowledgement could not be saved. Please try again.",
2927
2952
  onboardingTitle: "Add an API key to get started",
@@ -2934,6 +2959,7 @@ window.__ModuleLoader__.load({
2934
2959
  /** Chinese strings (same keys as {@link en}). */
2935
2960
  const zh = {
2936
2961
  nav: "模型",
2962
+ deepSeekAccount: "DeepSeek 账号",
2937
2963
  title: "模型",
2938
2964
  intro: "填入各提供商的 API 密钥即可使用其模型。",
2939
2965
  edit: "编辑",
@@ -3035,8 +3061,8 @@ window.__ModuleLoader__.load({
3035
3061
  settingsPathUnresolvable: "无法解析设置路径",
3036
3062
  create: "创建提供商",
3037
3063
  creating: "创建中…",
3038
- welcomeTitle: "内测声明",
3039
- welcomeBody: "DeepSeek Harness 目前的 0.1 版本仍处在面向 Harness 开发者进行测试的阶段,还有许多地方需要持续改进和打磨,希望听取广大开发者的反馈建议。预计 DeepSeek Harness 的核心插件以及基础 API 都会在接下来的一段时间内快速迭代、持续演化。\n\n我们期待与全球开发者一起,在开源、开放、可复用、可组合的基础设施之上,共同探索智能上限。欢迎全球 Harness 开发者加入 DSH 插件生态。",
3064
+ welcomeTitle: "预览版说明",
3065
+ welcomeBody: "DeepSeek Harness 目前的 0.2 版本仍处于预览阶段,还有许多地方需要持续改进和打磨,希望听取广大开发者和用户的反馈建议。现在,新的桌面端面向广泛用户,开发者相关的进阶功能可在配置中开启使用。预计 DeepSeek Harness 的产品功能以及插件 API 都会继续快速迭代、持续演化,并逐渐趋于稳定。\n\n我们期待与全球用户和开发者一起,在开源、可复用、可组合的基础设施之上,共同探索智能上限。欢迎大家用 DeepSeek Harness 将想法变成现实,与社区一起丰富插件生态。",
3040
3066
  welcomeContinue: "继续",
3041
3067
  welcomeError: "暂时无法保存确认状态,请重试。",
3042
3068
  onboardingTitle: "添加一个 API Key 开始使用",
@@ -3969,6 +3995,7 @@ window.__ModuleLoader__.load({
3969
3995
  "remote.credentials",
3970
3996
  "remote.llm",
3971
3997
  "remote.settings",
3998
+ "remote.session",
3972
3999
  "configForms",
3973
4000
  "settingsSchema"
3974
4001
  ];
@@ -3998,6 +4025,7 @@ window.__ModuleLoader__.load({
3998
4025
  });
3999
4026
  const deepSeekOnboardingInjected = () => ({
4000
4027
  automatic: credentialOnboarding,
4028
+ track: (name, attributes) => ctx.get("productAnalytics")?.track(name, attributes),
4001
4029
  controller,
4002
4030
  hooks: { models: controller.store },
4003
4031
  operations,
@@ -4018,6 +4046,7 @@ window.__ModuleLoader__.load({
4018
4046
  ctx.remote.$on("settings/document-updated", () => {
4019
4047
  refreshModels();
4020
4048
  }),
4049
+ ctx.remote.$on("credentials/record-updated", refreshModels),
4021
4050
  ctx.remote.$on("credentials/reference-updated", refreshModels),
4022
4051
  ctx.remote.$on("llm/adapters-updated", refreshModels),
4023
4052
  ctx.on("connection/reset", refreshModels)
@@ -4044,7 +4073,7 @@ window.__ModuleLoader__.load({
4044
4073
  }
4045
4074
  }
4046
4075
  }, ModelsSection));
4047
- ctx.slots.inject("settings.onboarding", () => ctx.slots.register({
4076
+ if (!("dshDesktop" in globalThis)) ctx.slots.inject("settings.onboarding", () => ctx.slots.register({
4048
4077
  name: "settings.onboarding",
4049
4078
  id: "welcome-notice",
4050
4079
  order: -100,
@@ -5,6 +5,7 @@
5
5
  * official DeepSeek route. The step reuses that page's credential editor in
6
6
  * the onboarding plugin's shared modal, so the key is entered once.
7
7
  */
8
+ import type { TrackProductEvent } from '@deepseek-ai/dsh-client-product-analytics/client';
8
9
  import type { ReactNode } from 'react';
9
10
  import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
10
11
  import type { InjectFace, PropsRuntime, PropsRenderSlots } from '@deepseek-ai/dsh-client-ui-slots';
@@ -14,6 +15,8 @@ import type { SettingsSchemaOperations } from './schema-operations.ts';
14
15
  import type { en } from './locales.ts';
15
16
  /** Registration-side dependencies of {@link DeepSeekOnboardingDialog}. */
16
17
  export interface DeepSeekOnboardingInjected {
18
+ /** Desktop-only event collection. */
19
+ track?: TrackProductEvent;
17
20
  /** Whether first-run setup should show automatically. Explicit requests remain available. */
18
21
  automatic: boolean;
19
22
  hooks: {
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Models settings section: the provider rows joined from the configurable
3
3
  * directory, settings namespaces, and credential states, with one editor
4
- * card at a time. The official DeepSeek provider appears first; other rows
5
- * retain directory order. Rows expose only confirmed API-key state through accessible
4
+ * card at a time. Rows retain the account-first order supplied by the store
5
+ * and expose only confirmed API-key state through accessible
6
6
  * solid configured or missing dots. A whole-section provider without a
7
7
  * configured key renders as its open setup card instead of a row, but only in
8
8
  * the first-run posture — no provider on the page can serve requests yet — and
@@ -67,6 +67,8 @@ export interface ProviderEditorProps {
67
67
  submitBusyLabelKey?: keyof typeof en;
68
68
  /** Close the editor; `changed` reports whether an Apply committed. */
69
69
  onClose: (changed: boolean) => void;
70
+ /** Called on a credential form submission before the save starts. */
71
+ onSubmitCredential?: () => void;
70
72
  /**
71
73
  * Called once per change with whether the apply or the model list's
72
74
  * endpoint interrogation is in flight, so the owner can hold its surface
@@ -1,4 +1,4 @@
1
- /** Product-wide, versioned internal-testing notice. */
1
+ /** Product-wide, versioned preview notice. */
2
2
  import type { ReactNode } from 'react';
3
3
  import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
4
4
  import type { InjectFace, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
@@ -1,11 +1,3 @@
1
- /**
2
- * Models settings and product-onboarding plugin, browser half. It registers
3
- * the Models page plus the ordered internal-testing and official-DeepSeek
4
- * onboarding dialogs, whose UI shares this package's modal wrapper. The Host
5
- * settings and credential contracts stay behind their existing wire APIs.
6
- * Export discipline:
7
- * packages/client/AGENTS.md.
8
- */
9
1
  import type { Context as ClientContext } from '@deepseek-ai/cordis';
10
2
  import { ModelsSettingsStore } from './store.ts';
11
3
  import { type ModelsKey } from './locales.ts';
@@ -2,6 +2,7 @@
2
2
  /** English strings (the key-set source of truth for this pair). */
3
3
  export declare const en: {
4
4
  nav: string;
5
+ deepSeekAccount: string;
5
6
  title: string;
6
7
  intro: string;
7
8
  edit: string;
@@ -25,11 +25,13 @@ export interface ProviderDirectoryEntry {
25
25
  * Join declared configurable providers with the currently registered routes.
26
26
  * @param registered - live provider routes in registration order.
27
27
  * @param directory - declared configurable providers in declaration order.
28
- * @returns declared rows followed by live routes with no declaration.
28
+ * @returns account and official routes first, then other routes in their original order.
29
29
  */
30
30
  export declare function joinProviderDirectory(registered: readonly LlmProviderInfo[], directory: readonly LlmConfigurableProvider[]): ProviderDirectoryEntry[];
31
31
  /** One provider row the page renders. */
32
32
  export interface ProviderRow {
33
+ /** Account route has usable credentials for the configured inference origin. */
34
+ accountAvailable?: boolean;
33
35
  /** The directory entry (route id, display name, settings address, live state). */
34
36
  entry: ProviderDirectoryEntry;
35
37
  /** Whether any layer configures this provider (its profile resolves). */
@@ -6,5 +6,5 @@ export declare const WELCOME_NOTICE_ACK_FIELD = "welcomeNoticeVersion";
6
6
  * Bump only when the notice changes materially and every user should see it
7
7
  * again. The acknowledgement is compared for exact equality.
8
8
  */
9
- export declare const WELCOME_NOTICE_VERSION = "2026-08-13.1";
9
+ export declare const WELCOME_NOTICE_VERSION = "2026-09-28.1";
10
10
  //# sourceMappingURL=onboarding-copy.d.ts.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-client-ui-settings-models",
3
3
  "description": "Models settings and shared product-onboarding dialogs over existing settings and credential joins",
4
- "version": "0.1.7-rc.1",
4
+ "version": "0.2.0-rc.1",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -42,18 +42,19 @@
42
42
  "devDependencies": {
43
43
  "@types/react": "~18.3.1",
44
44
  "react": "^18.2.0",
45
- "@deepseek-ai/dsh-host-webserver": "0.1.7-rc.1",
46
- "@deepseek-ai/dsh-api-remotes": "0.1.7-rc.1",
47
- "@deepseek-ai/dsh-client-locale": "0.1.7-rc.1",
48
- "@deepseek-ai/dsh-client-store": "0.1.7-rc.1",
49
- "@deepseek-ai/dsh-client-test-runtime": "0.1.7-rc.1",
50
- "@deepseek-ai/dsh-client-ui-primitives": "0.1.7-rc.1",
51
- "@deepseek-ai/dsh-client-ui-settings": "0.1.7-rc.1",
45
+ "@deepseek-ai/dsh-host-webserver": "0.2.0-rc.1",
46
+ "@deepseek-ai/dsh-api-remotes": "0.2.0-rc.1",
47
+ "@deepseek-ai/dsh-client-locale": "0.2.0-rc.1",
48
+ "@deepseek-ai/dsh-client-test-runtime": "0.2.0-rc.1",
49
+ "@deepseek-ai/dsh-client-ui-settings": "0.2.0-rc.1",
50
+ "@deepseek-ai/dsh-client-ui-primitives": "0.2.0-rc.1",
51
+ "@deepseek-ai/dsh-client-store": "0.2.0-rc.1",
52
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.0-rc.1",
52
53
  "@deepseek-ai/cordis": "~4.0.4",
53
- "@deepseek-ai/dsh-client-ui-renderer": "0.1.7-rc.1",
54
- "@deepseek-ai/dsh-util-values": "0.1.7-rc.1",
55
- "@deepseek-ai/dsh-remote-mock": "0.1.7-rc.1",
56
- "@deepseek-ai/dsh-client-ui-slots": "0.1.7-rc.1"
54
+ "@deepseek-ai/dsh-client-ui-renderer": "0.2.0-rc.1",
55
+ "@deepseek-ai/dsh-util-values": "0.2.0-rc.1",
56
+ "@deepseek-ai/dsh-remote-mock": "0.2.0-rc.1",
57
+ "@deepseek-ai/dsh-client-product-analytics": "0.2.0-rc.1"
57
58
  },
58
59
  "dependencies": {
59
60
  "@deepseek-ai/schemastery": "~3.18.4"