@omdp/dsh-key-fallback 3.2.0 → 3.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -3
- package/README.zh-CN.md +29 -2
- package/lib/index.js +40 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -4,13 +4,44 @@
|
|
|
4
4
|
|
|
5
5
|
**Multi-key API key pool with automatic rotation for [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness)** — sits between the LLM adapter and the credential store. Before each request the plugin picks a key from the per-provider pool and pre-writes it into the provider's credential reference; when a configured trigger error occurs it marks the failed key cooling (fixed `cooldownMs`, no exponential backoff) and advances to the next key. **Re-sending is left entirely to DSH's own `dsh-llm-retry`** — this plugin never re-sends on its own; it only switches the key and lets the retry policy decide.
|
|
6
6
|
|
|
7
|
-
Current version: **v3.2.
|
|
7
|
+
Current version: **v3.2.2** (`v7` UI generation).
|
|
8
|
+
|
|
9
|
+
## What v3.2.2 offers
|
|
10
|
+
|
|
11
|
+
- **Declares its DSH version support** (2026-09-24): a new `@deepseek-ai/dsh` peer entry
|
|
12
|
+
(`0.1.7-rc.1`, enumerated per version) so the supported runtime is explicit. DSH's own
|
|
13
|
+
`evaluatePluginCompatibility()` (`dsh-app-boot`) enforces it at install time and on boot — an untested
|
|
14
|
+
newer runtime has the bundle **gracefully skipped** (`skipping profile bundle` on stderr, DSH still
|
|
15
|
+
boots) instead of failing in some undefined way. The gate only exists from DSH `0.1.7`, so runtimes
|
|
16
|
+
`≤0.1.6` merely see an unrecognized peer and are unaffected (this plugin already worked there through
|
|
17
|
+
the file backend). Only tested versions are named — no open ranges (repo rule 3).
|
|
18
|
+
|
|
19
|
+
## What v3.2.1 offers
|
|
20
|
+
|
|
21
|
+
- **Rescues pools stranded in `settings.yaml.imported`** (2026-09-24). `0.1.7`'s one-shot importer
|
|
22
|
+
**renames `settings.yaml` to `settings.yaml.imported` before it writes anything**, so if a section fails to
|
|
23
|
+
import (e.g. the target entry declares no volatile field) it never retries and the pools sit in
|
|
24
|
+
`.imported` forever. The symptom is exactly: badge shows **"尚未启用"** and the page shows
|
|
25
|
+
**"还没有任何池,点上方「启用新 provider 池」开始。"** even though the pools are on disk.
|
|
26
|
+
Note the file fallback was *already* there in v3.2.0 (`readSettingsFromFile()` falls back to
|
|
27
|
+
`settings.yaml.imported`) — but on `0.1.7` it is **never reached**, because `readSettings()` returns from the
|
|
28
|
+
live-ref branch first whenever `_liveRef` is set, and the ref holds `{}`. What was missing was a **bridge
|
|
29
|
+
between the two backends**, not another read fallback.
|
|
30
|
+
`v3.2.1` performs a **one-time explicit migration** on the first HTTP request (not in `apply()` — see below):
|
|
31
|
+
when the live config has zero providers *and* the legacy file has some, it writes them into the profile entry via
|
|
32
|
+
`settings.replace()`. A marker file (`<DSH_HOME>/.key-fallback-migrated`) makes it genuinely once-only, so
|
|
33
|
+
deliberately deleting every pool does not resurrect them on the next boot.
|
|
34
|
+
- **Why not in `apply()`:** `settings.replace()` goes through `configEditor.edit()` and requires the entry's fiber
|
|
35
|
+
to be **ACTIVE** — `describe()` skips entries whose `fiber.state !== 2`, and during `apply()` the fiber is still
|
|
36
|
+
being created, so the call throws `No configurable plugin entry`. The first UI request (`/pools`) is the
|
|
37
|
+
earliest safe moment.
|
|
38
|
+
- The marker is written **only after** the persist succeeds, so a failed write is retried on the next boot.
|
|
8
39
|
|
|
9
40
|
## Requirements
|
|
10
41
|
|
|
11
42
|
- DeepSeek Harness with a `web`-profile GUI (`npx @deepseek-ai/dsh web`)
|
|
12
43
|
- Node.js `^22.19` or `>=24`
|
|
13
|
-
- Peer ranges strictly enumerate **only compatibility-tested versions** — `@deepseek-ai/dsh-credentials` `0.1.0-rc.6 || 0.1.1-rc.2 || 0.1.2-alpha.1 || 0.1.2-alpha.2 || 0.1.2-alpha.3 || 0.1.2-alpha.4 || 0.1.2-alpha.5 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.7-rc.1`, `@deepseek-ai/dsh-llm` / `@deepseek-ai/dsh-settings` `0.1.1-rc.2 || 0.1.2-alpha.1 || 0.1.2-alpha.2 || 0.1.2-alpha.3 || 0.1.2-alpha.4 || 0.1.2-alpha.5 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.7-rc.1`, `@deepseek-ai/cordis` `4.0.1 || 4.0.2 || 4.0.4`, `@deepseek-ai/schemastery` `3.18.1 || 3.18.2 || 3.18.4`. No open-ended ranges (`<0.2.0`, caret): untested versions are deliberately excluded until verified. The plugin only uses the credential-reference half (`resolve`/`describe`/`set`/`unset`/`credentialRef` — stable since `0.1.0-rc.6`) and the `agent/request` + `agent/request-error` waterfall (payload unchanged across the enumerated versions); `isCredentialRefName` (added `rc.8`) is implemented locally for compatibility. The `0.1.2-alpha.2 → alpha.5 → 0.1.2-rc.1` companion packages are byte-identical (2026-09-03 verified), so DSH `0.1.2-rc.1` (`next`) needs no plugin change.
|
|
44
|
+
- Peer ranges strictly enumerate **only compatibility-tested versions** — `@deepseek-ai/dsh` `0.1.7-rc.1` (the plugin's claimed DSH runtime; the gate that enforces it only exists from 0.1.7, so older runtimes just see an unrecognized peer), `@deepseek-ai/dsh-credentials` `0.1.0-rc.6 || 0.1.1-rc.2 || 0.1.2-alpha.1 || 0.1.2-alpha.2 || 0.1.2-alpha.3 || 0.1.2-alpha.4 || 0.1.2-alpha.5 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.7-rc.1`, `@deepseek-ai/dsh-llm` / `@deepseek-ai/dsh-settings` `0.1.1-rc.2 || 0.1.2-alpha.1 || 0.1.2-alpha.2 || 0.1.2-alpha.3 || 0.1.2-alpha.4 || 0.1.2-alpha.5 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.7-rc.1`, `@deepseek-ai/cordis` `4.0.1 || 4.0.2 || 4.0.4`, `@deepseek-ai/schemastery` `3.18.1 || 3.18.2 || 3.18.4`. No open-ended ranges (`<0.2.0`, caret): untested versions are deliberately excluded until verified. The plugin only uses the credential-reference half (`resolve`/`describe`/`set`/`unset`/`credentialRef` — stable since `0.1.0-rc.6`) and the `agent/request` + `agent/request-error` waterfall (payload unchanged across the enumerated versions); `isCredentialRefName` (added `rc.8`) is implemented locally for compatibility. The `0.1.2-alpha.2 → alpha.5 → 0.1.2-rc.1` companion packages are byte-identical (2026-09-03 verified), so DSH `0.1.2-rc.1` (`next`) needs no plugin change.
|
|
14
45
|
|
|
15
46
|
## What v3.2.0 offers
|
|
16
47
|
|
|
@@ -103,7 +134,12 @@ dsh plugin --profile web add link:D:/WorkSpace/omdp/dsh-key-fallback
|
|
|
103
134
|
# restart DSH, then open Settings → API Key 回退
|
|
104
135
|
```
|
|
105
136
|
|
|
106
|
-
>
|
|
137
|
+
> **To upgrade, move the profile pin — do not copy files into `node_modules`.** A hand-copied
|
|
138
|
+
> `lib/index.js` looks like it works until something re-runs `pnpm install` (DSH does this on boot), at
|
|
139
|
+
> which point pnpm restores the version recorded in `pnpm-lock.yaml` and the "fix" silently disappears.
|
|
140
|
+
> Edit the version in `~/.dsh/profiles/web/package.json`, then run `pnpm install` in that directory and
|
|
141
|
+
> restart DSH. The package declares a `dsh.bundle.patch`, so it activates automatically — no manual
|
|
142
|
+
> `cordis.patch.yml` editing.
|
|
107
143
|
|
|
108
144
|
## HTTP API (host)
|
|
109
145
|
|
package/README.zh-CN.md
CHANGED
|
@@ -4,13 +4,40 @@
|
|
|
4
4
|
|
|
5
5
|
**为 [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness) 提供多 key 池 + 自动轮换**——插件位于 LLM 适配器与凭证存储之间:每次请求前从按 provider 分组的 key 池里选一把,预写入该 provider 的凭证引用;遇到配置的触发错误时,把失败 key 标记为冷却(固定 `cooldownMs`,无指数退避)并前进到下一把。**重发完全交给 DSH 自带的 `dsh-llm-retry`**——本插件从不自行重发,只负责换 key,重试策略由 retry policy 决定。
|
|
6
6
|
|
|
7
|
-
当前版本:**v3.2.
|
|
7
|
+
当前版本:**v3.2.2**(v7 UI 代)。
|
|
8
8
|
|
|
9
9
|
## 环境要求
|
|
10
10
|
|
|
11
11
|
- DeepSeek Harness 带 `web` profile GUI(`npx @deepseek-ai/dsh web`)
|
|
12
12
|
- Node.js `^22.19` 或 `>=24`
|
|
13
|
-
- peer 范围**只枚举已实际进行过兼容测试的版本**——`@deepseek-ai/dsh-credentials` `0.1.0-rc.6 || 0.1.1-rc.2 || 0.1.2-alpha.1 || 0.1.2-alpha.2 || 0.1.2-alpha.3 || 0.1.2-alpha.4 || 0.1.2-alpha.5 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.7-rc.1`、`@deepseek-ai/dsh-llm` / `@deepseek-ai/dsh-settings` `0.1.1-rc.2 || 0.1.2-alpha.1 || 0.1.2-alpha.2 || 0.1.2-alpha.3 || 0.1.2-alpha.4 || 0.1.2-alpha.5 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.7-rc.1`、`@deepseek-ai/cordis` `4.0.1 || 4.0.2 || 4.0.4`、`@deepseek-ai/schemastery` `3.18.1 || 3.18.2 || 3.18.4`。不使用 `<0.2.0`、caret 之类的开放范围:未测试版本在核查通过前刻意排除。插件只使用 credential-reference 半边(`resolve`/`describe`/`set`/`unset`/`credentialRef`,自 `0.1.0-rc.6` 起稳定)与 `agent/request` + `agent/request-error` waterfall(载荷跨上述枚举版本未变);`isCredentialRefName`(rc.8 新增)本地实现兜底。`0.1.2-alpha.2 → alpha.5 → 0.1.2-rc.1` 配套包逐字节一致(2026-09-03 复核),故 DSH `0.1.2-rc.1`(`next`)无需改动插件。
|
|
13
|
+
- peer 范围**只枚举已实际进行过兼容测试的版本**——`@deepseek-ai/dsh` `0.1.7-rc.1`(本插件声明的 DSH 运行时;**执行该声明的门禁本身只有 0.1.7 才有**,更旧的运行时只是看到一条不认识的 peer 而已,不受影响)、`@deepseek-ai/dsh-credentials` `0.1.0-rc.6 || 0.1.1-rc.2 || 0.1.2-alpha.1 || 0.1.2-alpha.2 || 0.1.2-alpha.3 || 0.1.2-alpha.4 || 0.1.2-alpha.5 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.7-rc.1`、`@deepseek-ai/dsh-llm` / `@deepseek-ai/dsh-settings` `0.1.1-rc.2 || 0.1.2-alpha.1 || 0.1.2-alpha.2 || 0.1.2-alpha.3 || 0.1.2-alpha.4 || 0.1.2-alpha.5 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.7-rc.1`、`@deepseek-ai/cordis` `4.0.1 || 4.0.2 || 4.0.4`、`@deepseek-ai/schemastery` `3.18.1 || 3.18.2 || 3.18.4`。不使用 `<0.2.0`、caret 之类的开放范围:未测试版本在核查通过前刻意排除。插件只使用 credential-reference 半边(`resolve`/`describe`/`set`/`unset`/`credentialRef`,自 `0.1.0-rc.6` 起稳定)与 `agent/request` + `agent/request-error` waterfall(载荷跨上述枚举版本未变);`isCredentialRefName`(rc.8 新增)本地实现兜底。`0.1.2-alpha.2 → alpha.5 → 0.1.2-rc.1` 配套包逐字节一致(2026-09-03 复核),故 DSH `0.1.2-rc.1`(`next`)无需改动插件。
|
|
14
|
+
|
|
15
|
+
## v3.2.2 新增
|
|
16
|
+
|
|
17
|
+
- **声明 DSH 版本支持**(2026-09-24):新增 `@deepseek-ai/dsh` peer 条目(`0.1.7-rc.1`,逐版本枚举),
|
|
18
|
+
把「支持的运行时」写成显式契约。该声明由 DSH 自己的 `evaluatePluginCompatibility()`(`dsh-app-boot` 的
|
|
19
|
+
公开导出)在**安装时**与**每次启动时**校验:命中未实测的新运行时,bundle 会被**优雅跳过**
|
|
20
|
+
(stderr 打 `skipping profile bundle`,DSH 照常启动),而不是以某种未定义方式崩掉。这个门禁
|
|
21
|
+
**只有 DSH 0.1.7 起才存在**,所以 `≤0.1.6` 的运行时只是看到一条不认识的 peer,不受影响
|
|
22
|
+
(本插件在那些版本上本来就走 `settings.yaml` 文件后端,一直可用)。只列实测版本,不用开放范围(仓库规范 3)。
|
|
23
|
+
|
|
24
|
+
## v3.2.1 新增
|
|
25
|
+
|
|
26
|
+
- **救回滞留在 `settings.yaml.imported` 里的池**(2026-09-24)。`0.1.7` 的一次性导入器会在写入任何东西**之前**
|
|
27
|
+
先把 `settings.yaml` 改名为 `settings.yaml.imported`——所以某段导入失败时(典型:目标条目没声明 volatile 字段)
|
|
28
|
+
它永远不会重试,池子会永久留在 `.imported` 里。表现恰是:徽标显示 **「尚未启用」**、页面显示
|
|
29
|
+
**「还没有任何池,点上方「启用新 provider 池」开始。」**,尽管池子就在磁盘上。
|
|
30
|
+
注意**文件回退在 v3.2.0 里本来就写了**(`readSettingsFromFile()` 会在 `settings.yaml` 缺失时退读
|
|
31
|
+
`settings.yaml.imported`)——但在 `0.1.7` 上它**永远轮不到**:只要 `_liveRef` 非空,
|
|
32
|
+
`readSettings()` 第一行就从 live-ref 分支返回,而 ref 里是 `{}`。**真正缺的不是又一个读回退,
|
|
33
|
+
而是两个后端之间的一座桥。**
|
|
34
|
+
`v3.2.1` 在**首个 HTTP 请求**时做一次性显式搬运(不在 `apply()` 里——原因见下):
|
|
35
|
+
当 live 配置里 provider 数为 0 *且* 旧文件里有池时,经 `settings.replace()` 写进 profile 条目。
|
|
36
|
+
标记文件(`<DSH_HOME>/.key-fallback-migrated`)保证「真正只做一次」,因此有意删光所有池后不会在下次启动被复活。
|
|
37
|
+
- **为什么不能放在 `apply()`:** `settings.replace()` 走 `configEditor.edit()`,要求本 entry 的 fiber 已
|
|
38
|
+
**ACTIVE**——`describe()` 会跳过 `fiber.state !== 2` 的条目,而 `apply()` 执行时 fiber 还在创建中,
|
|
39
|
+
调用必抛 `No configurable plugin entry`。首个 UI 请求(`/pools`)才是最早的安全时机。
|
|
40
|
+
- 标记**只在落盘成功之后**才写,因此写失败会在下次启动重试。
|
|
14
41
|
|
|
15
42
|
## v3.2.0 新增
|
|
16
43
|
|
package/lib/index.js
CHANGED
|
@@ -42,6 +42,8 @@ const SETTINGS_FILE = join(DSH_HOME, 'settings.yaml')
|
|
|
42
42
|
const SETTINGS_FILE_IMPORTED = SETTINGS_FILE + '.imported'
|
|
43
43
|
const CRED_FILE = join(DSH_HOME, '.credentials.yaml')
|
|
44
44
|
const BACKUP_DIR = join(DSH_HOME, 'backups')
|
|
45
|
+
// 一次性 legacy→profile 迁移的标记(见 apply() 里的迁移块)。
|
|
46
|
+
const MIGRATED_MARKER = join(DSH_HOME, '.key-fallback-migrated')
|
|
45
47
|
if (!existsSync(BACKUP_DIR)) try { mkdirSync(BACKUP_DIR, { recursive: true }) } catch (e) {}
|
|
46
48
|
let _backupCounter = 0
|
|
47
49
|
function tsName(prefix) {
|
|
@@ -254,6 +256,39 @@ export function apply(ctx, config) {
|
|
|
254
256
|
diag('settings', 'backend = settings.yaml file (rc.x)')
|
|
255
257
|
}
|
|
256
258
|
} catch (e) { diag('settings', 'probe failed: ' + ((e && e.message) || e)) }
|
|
259
|
+
|
|
260
|
+
// ── 一次性迁移:老 settings.yaml(.imported) 里的池 → settings 托管的 entry config ──
|
|
261
|
+
// 0.1.7 的 importLegacyDocument() 在首次写入前就把 settings.yaml 改名成
|
|
262
|
+
// settings.yaml.imported,而本机的池恰好躺在 .imported 里 —— 迁移入口已永久失活,
|
|
263
|
+
// 池不会自己回到 UI(表现为徽标「尚未启用」+「还没有任何池」)。
|
|
264
|
+
//
|
|
265
|
+
// 必须在首个 HTTP 请求时做,不能在这里(apply 期间)做:settings.replace() 走
|
|
266
|
+
// configEditor.edit(),要求本 entry 的 fiber 已 ACTIVE(describe() 会跳过
|
|
267
|
+
// state !== 2 的 entry),apply() 执行时 fiber 尚在创建中,必然抛
|
|
268
|
+
// "No configurable plugin entry"。UI 打开设置页就会请求 /pools,时机正好。
|
|
269
|
+
// 标记文件保证「真正只做一次」:否则用户有意清空所有池后,下次启动又会灌回来。
|
|
270
|
+
let _migrationAttempted = false
|
|
271
|
+
async function ensureLegacyMigration() {
|
|
272
|
+
if (_migrationAttempted) return
|
|
273
|
+
_migrationAttempted = true
|
|
274
|
+
try {
|
|
275
|
+
if (!_liveRef || existsSync(MIGRATED_MARKER)) return
|
|
276
|
+
if (Object.keys((_cache && _cache.providers) || {}).length > 0) return
|
|
277
|
+
const migrated = (readSettingsFromFile() || {}).providers || {}
|
|
278
|
+
const names = Object.keys(migrated)
|
|
279
|
+
if (names.length === 0) {
|
|
280
|
+
// 无可搬运内容:也落标记(空文件算「已处理过」),避免每次启动重复探测。
|
|
281
|
+
try { writeFileSync(MIGRATED_MARKER, new Date().toISOString() + '\n', 'utf8') } catch (e) {}
|
|
282
|
+
return
|
|
283
|
+
}
|
|
284
|
+
// 直接 await 真正的 replace:只有落盘成功才写标记,否则下次启动还能重试。
|
|
285
|
+
if (!_settingsSvc || typeof _settingsSvc.replace !== 'function') return
|
|
286
|
+
_cache = { providers: cloneJson(migrated) }
|
|
287
|
+
await _settingsSvc.replace(ENTRY_ID, { providers: cloneJson(migrated) })
|
|
288
|
+
try { writeFileSync(MIGRATED_MARKER, new Date().toISOString() + '\n', 'utf8') } catch (e) {}
|
|
289
|
+
diag('migrate', 'imported ' + names.length + ' provider(s) from settings.yaml(.imported): ' + names.join(','))
|
|
290
|
+
} catch (e) { diag('migrate', 'failed: ' + ((e && e.message) || e)) }
|
|
291
|
+
}
|
|
257
292
|
// ── 包装 credentials.resolve:ref 命中池 env 时返回池当前 key(llm-pi-ai 唯一读取入口)──
|
|
258
293
|
const poolsByEnv = new Map()
|
|
259
294
|
const credSvc = ctx.credentials
|
|
@@ -541,6 +576,11 @@ export function apply(ctx, config) {
|
|
|
541
576
|
if (webServer) {
|
|
542
577
|
const route = async (req, res) => {
|
|
543
578
|
try {
|
|
579
|
+
// 首次请求时补做 legacy 池迁移(此时 fiber 已 ACTIVE,settings.replace 可用)。
|
|
580
|
+
// 放在所有分支之前,保证无论 UI 先请求哪个端点,池都已被搬进 live 配置。
|
|
581
|
+
// 首次请求时补做 legacy 池迁移(此时 fiber 已 ACTIVE,settings.replace 可用)。
|
|
582
|
+
// 放在所有分支之前,保证无论 UI 先请求哪个端点,池都已被搬进 live 配置。
|
|
583
|
+
await ensureLegacyMigration()
|
|
544
584
|
const url = new URL(req.url, 'http://127.0.0.1')
|
|
545
585
|
const path = url.pathname.replace(new RegExp('^' + API_BASE + '/?'), '').replace(/\/$/, '')
|
|
546
586
|
const readBody = () => new Promise((resolve, reject) => {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@omdp/dsh-key-fallback",
|
|
3
3
|
"description": "API Key 回退轮换插件:多 key 池 + 自动轮换(触发码可配置,含 LlmError 标准码全集)+ 环境密钥编辑 + 明文揭示 + 短 ref 迁移。同时兼容 DSH 0.1.5-rc.3(settings.yaml 后端)与 0.1.7+(profile entry config 后端)。Settings → API Key 回退 UI. v7.",
|
|
4
|
-
"version": "3.2.
|
|
4
|
+
"version": "3.2.2",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"@deepseek-ai/cordis": "4.0.1 || 4.0.2 || 4.0.4",
|
|
42
|
+
"@deepseek-ai/dsh": "0.1.7-rc.1",
|
|
42
43
|
"@deepseek-ai/dsh-credentials": "0.1.0-rc.6 || 0.1.1-rc.2 || 0.1.2-alpha.1 || 0.1.2-alpha.2 || 0.1.2-alpha.3 || 0.1.2-alpha.4 || 0.1.2-alpha.5 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.7-rc.1",
|
|
43
44
|
"@deepseek-ai/dsh-llm": "0.1.1-rc.2 || 0.1.2-alpha.1 || 0.1.2-alpha.2 || 0.1.2-alpha.3 || 0.1.2-alpha.4 || 0.1.2-alpha.5 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.7-rc.1",
|
|
44
45
|
"@deepseek-ai/dsh-settings": "0.1.1-rc.2 || 0.1.2-alpha.1 || 0.1.2-alpha.2 || 0.1.2-alpha.3 || 0.1.2-alpha.4 || 0.1.2-alpha.5 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.6-alpha.1 || 0.1.7-rc.1",
|