dsh-llm-fallbacks 0.1.3 → 0.1.5
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 +4 -2
- package/README.zh-CN.md +4 -2
- package/dist/client/fallbacks-store.d.ts +34 -2
- package/dist/client/index.js +464 -335
- package/dist/client/locales.d.ts +14 -4
- package/dist/gateway.d.ts +75 -23
- package/dist/index.d.ts +13 -3
- package/dist/index.js +243 -5
- package/dist/seeds.d.ts +141 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|

|
|
7
7
|

|
|
8
8
|

|
|
9
|
+
[](https://dshfind.com/zh/plugins/omdsh-dev/dsh-llm-fallbacks?ref=badge)
|
|
9
10
|
|
|
10
11
|
Automatic provider/model fallback chains for dsh (DeepSeek Harness): when an agent's LLM requests keep failing — retries exhausted, auth errors, quota exceeded, rate limiting (429) — the plugin switches provider/model along the fallback chain for the current role, and the current step/turn continues on the target model: tasks are not interrupted by model problems.
|
|
11
12
|
|
|
@@ -35,7 +36,7 @@ dsh plugin --profile web add dsh-llm-fallbacks # pin a version with @<version>
|
|
|
35
36
|
|
|
36
37
|
A registry install fetches the **built package** (`dist/`) — nothing is built on the target machine. The plugin is **mount-only**: it never modifies the dsh source tree, and no patch / postinstall step exists — dsh upgrades never require re-patching. Versioning follows npm dist-tags (`latest` by default); pin an exact version with `dsh plugin --profile web add dsh-llm-fallbacks@<version>`.
|
|
37
38
|
|
|
38
|
-
> **Release status**: published as `dsh-llm-fallbacks@0.1.
|
|
39
|
+
> **Release status**: published as `dsh-llm-fallbacks@0.1.3` (latest). The first publish used a one-time `NODE_AUTH_TOKEN` bootstrap secret; Trusted Publishing is configured afterwards for tokenless releases.
|
|
39
40
|
|
|
40
41
|
### Registry package (npm / pnpm)
|
|
41
42
|
|
|
@@ -133,7 +134,8 @@ The plugin installs as a **pure mount** — it never modifies the dsh source tre
|
|
|
133
134
|
Beyond the dsh plugin mount, `dsh-llm-fallbacks` exposes a programmable consumer surface — both faces share the same function implementations (single point of truth, no copied logic):
|
|
134
135
|
|
|
135
136
|
- **Library API**: import the runtime functions and types from the package root — `import { resolveRole, resolveChain, validateFallbacksConfig } from 'dsh-llm-fallbacks'`.
|
|
136
|
-
- **Named cordis service**: while the plugin is applied, `ctx.get('llm-fallbacks')` returns a pure-function service (`{ name, version, resolveRole, resolveChain, validateFallbacksConfig, detectLegacyKeys }`); after the plugin is disposed it is `undefined`. Runtime state stays observable via `fallbacks/switch` events, not through the service.
|
|
137
|
+
- **Named cordis service**: while the plugin is applied, `ctx.get('llm-fallbacks')` returns a pure-function service (`{ name, version, resolveRole, resolveChain, validateFallbacksConfig, detectLegacyKeys, declareSeeds, getEffectiveRoles, revertSeededPersona }`); after the plugin is disposed it is `undefined`. Runtime state stays observable via `fallbacks/switch` events, not through the service.
|
|
138
|
+
- **Role seeds**: companion plugins auto-provision role rows with zero operator hand-edit — `declareSeeds([{ id, persona }])` declares the full current seed set (re-declaring is a no-op; ids failing `/^[a-z0-9-]{1,32}$/` or equal to `inherit` are skipped per-id with a warn, never coerced), `getEffectiveRoles()` reads back which roles are seeded and whether the persona is overridden, and `revertSeededPersona(id)` restores the **currently declared** seed default. The settings card shows a seed-default / override badge with a revert button; seeds never write `chain` / `fallback`.
|
|
137
139
|
|
|
138
140
|
Full contract (export inventory, minimal examples, lifecycle, typing) → [docs/consumer-api.md](docs/consumer-api.md).
|
|
139
141
|
|
package/README.zh-CN.md
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|

|
|
7
7
|

|
|
8
8
|

|
|
9
|
+
[](https://dshfind.com/zh/plugins/omdsh-dev/dsh-llm-fallbacks?ref=badge)
|
|
9
10
|
|
|
10
11
|
dsh(DeepSeek Harness)的自动模型降级插件:当 root agent 或 subagent 的模型请求持续失败(重试耗尽、权限、配额超限、限流 429)时,按角色/模型 fallback 链自动切换 provider/model,当前 step/turn 在目标模型上继续完成——任务不因模型问题中断。
|
|
11
12
|
|
|
@@ -35,7 +36,7 @@ dsh plugin --profile web add dsh-llm-fallbacks # 钉版本:加 @<version>
|
|
|
35
36
|
|
|
36
37
|
registry 安装拉取的是**已构建产物**(`dist/`),目标机无需构建。插件为**纯挂载**:对 dsh 源码树零修改,无任何补丁 / postinstall 步骤——dsh 升级无需重打。版本跟随 npm dist-tag(默认 `latest`);钉精确版本:`dsh plugin --profile web add dsh-llm-fallbacks@<version>`。
|
|
37
38
|
|
|
38
|
-
> **发布状态**:已发布 `dsh-llm-fallbacks@0.1.
|
|
39
|
+
> **发布状态**:已发布 `dsh-llm-fallbacks@0.1.3`(latest)。首次发布用一次性 `NODE_AUTH_TOKEN` bootstrap;Trusted Publishing 后续配置为无 token 发布。
|
|
39
40
|
|
|
40
41
|
### registry 包安装(npm / pnpm)
|
|
41
42
|
|
|
@@ -128,7 +129,8 @@ fallbacks:
|
|
|
128
129
|
除插件挂载外,`dsh-llm-fallbacks` 还暴露可编程消费面——两个入口共享同一函数实现(单点真相,无复制逻辑):
|
|
129
130
|
|
|
130
131
|
- **库 API**:从包根直接 import 运行时函数与类型——`import { resolveRole, resolveChain, validateFallbacksConfig } from 'dsh-llm-fallbacks'`。
|
|
131
|
-
- **具名 cordis service**:插件 apply 期间 `ctx.get('llm-fallbacks')` 返回纯函数服务(`{ name, version, resolveRole, resolveChain, validateFallbacksConfig, detectLegacyKeys }`),插件 dispose 后为 `undefined`。运行态(冷却、最近切换)请读 `fallbacks/switch` 事件,不走服务对象。
|
|
132
|
+
- **具名 cordis service**:插件 apply 期间 `ctx.get('llm-fallbacks')` 返回纯函数服务(`{ name, version, resolveRole, resolveChain, validateFallbacksConfig, detectLegacyKeys, declareSeeds, getEffectiveRoles, revertSeededPersona }`),插件 dispose 后为 `undefined`。运行态(冷却、最近切换)请读 `fallbacks/switch` 事件,不走服务对象。
|
|
133
|
+
- **角色 seeds(种子角色)**:伴随插件可**零手工配置**自动补全角色行——`declareSeeds([{ id, persona }])` 声明完整当前种子集(重复声明为 no-op;不匹配 `/^[a-z0-9-]{1,32}$/` 或等于保留字 `inherit` 的 id 按条跳过并告警,绝不改写),`getEffectiveRoles()` 回读哪些角色为 seeded、persona 是否被覆盖,`revertSeededPersona(id)` 恢复**当前声明**的 seed 默认 persona。设置卡显示 seed 默认 / override 徽标并带 revert 按钮;seeds 永不写 `chain` / `fallback`。
|
|
132
134
|
|
|
133
135
|
完整契约(导出清单、最小示例、生命周期、类型说明)见 [docs/consumer-api.md](docs/consumer-api.md)。
|
|
134
136
|
|
|
@@ -28,6 +28,7 @@ import type { ClientConnectionRpc, ConfigurableProviderView, HistoryEntry, IApiC
|
|
|
28
28
|
import { type SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client';
|
|
29
29
|
import { type FallbackStrategy, type FallbacksConfig, type FallbacksRole, type FallbacksRoleRule, type FallbacksRoles } from '../config.ts';
|
|
30
30
|
import type { FallbacksSwitchEventData } from '../events.ts';
|
|
31
|
+
import type { SeedsWireStatus } from '../seeds.ts';
|
|
31
32
|
/** The plugin's settings namespace on the host wire (settings/document-updated ns filter). */
|
|
32
33
|
export declare const FALLBACKS_SETTINGS_NS = "fallbacks";
|
|
33
34
|
/** Single-page history read for the status block (spec §2.5 D-5: `HISTORY_PAGE_MESSAGES`-sized). */
|
|
@@ -92,6 +93,13 @@ export interface FallbacksSettingsState {
|
|
|
92
93
|
* over the user layer, so it cannot delete legacy keys).
|
|
93
94
|
*/
|
|
94
95
|
legacyKeys: string[];
|
|
96
|
+
/**
|
|
97
|
+
* Seeded-role badge state (spec §9.4): one entry per live seed, with the
|
|
98
|
+
* gateway's override verdict. The wire field is authoritative — absent on
|
|
99
|
+
* an old response it keeps the last accepted value (the `legacyKeys`
|
|
100
|
+
* honest rule: only a `get` may settle seed truth).
|
|
101
|
+
*/
|
|
102
|
+
seeds: SeedsWireStatus[];
|
|
95
103
|
/** Provider/model directory snapshot (spec §2.5 D-4). */
|
|
96
104
|
catalogStatus: 'idle' | 'loading' | 'ready' | 'error';
|
|
97
105
|
/** Catalog read diagnostic: whole-load failure or per-provider lookups. */
|
|
@@ -262,7 +270,14 @@ export declare class FallbacksSettingsController {
|
|
|
262
270
|
private readonly rpc;
|
|
263
271
|
/** Snapshot consumed by the section through `useSyncExternalStore`. */
|
|
264
272
|
readonly store: SnapshotStore<FallbacksSettingsState>;
|
|
265
|
-
|
|
273
|
+
/** Read guard: a newer load() supersedes an older one's publish. */
|
|
274
|
+
private readGeneration;
|
|
275
|
+
/**
|
|
276
|
+
* Write guard: save()/resetToDefaults() completions ALWAYS publish unless
|
|
277
|
+
* dispose() invalidated them — an overlapping read must never discard a
|
|
278
|
+
* successful write's accept() (audit F1).
|
|
279
|
+
*/
|
|
280
|
+
private writeGeneration;
|
|
266
281
|
private catalogGeneration;
|
|
267
282
|
private switchesGeneration;
|
|
268
283
|
/** Every settings namespace from the last describe, keyed by ns — the configured-provider join's other input. */
|
|
@@ -338,6 +353,20 @@ export declare class FallbacksSettingsController {
|
|
|
338
353
|
* merge cannot express). Same error handling as {@link save} (KD-G3).
|
|
339
354
|
*/
|
|
340
355
|
resetToDefaults(): Promise<void>;
|
|
356
|
+
/**
|
|
357
|
+
* Revert one seeded role to its CURRENT declared seed default (spec §9.4,
|
|
358
|
+
* AC-3) through the gateway channel (`/api/fallbacks/revert-seed`). Same
|
|
359
|
+
* write guards as {@link save} — writable / saving / write-generation —
|
|
360
|
+
* and the same KD-G3 error handling: any business rejection or transport
|
|
361
|
+
* failure surfaces its message in `state.error` for the error banner and
|
|
362
|
+
* the form stays editable for retry. A business `{ reverted: false,
|
|
363
|
+
* reason }` outcome is still a successful RPC — the post-write read
|
|
364
|
+
* result (config / legacyKeys / seeds) lands either way, and the revert
|
|
365
|
+
* button stays disabled while the write is in flight.
|
|
366
|
+
* @param id - the seeded role id; the host matches it by trimmed id
|
|
367
|
+
* against the seed registry (spec §9.3).
|
|
368
|
+
*/
|
|
369
|
+
revertSeed(id: string): Promise<void>;
|
|
341
370
|
/** Stop in-flight responses from publishing after plugin disposal. */
|
|
342
371
|
dispose(): void;
|
|
343
372
|
/**
|
|
@@ -351,7 +380,10 @@ export declare class FallbacksSettingsController {
|
|
|
351
380
|
* same publish: the wire field drives the migration banner. save/reset
|
|
352
381
|
* pass the POST-WRITE value (W-1/F-1) — or the previous value when the
|
|
353
382
|
* response omits the field, so a write can never clear the banner
|
|
354
|
-
* against server truth; only a real `get` may.
|
|
383
|
+
* against server truth; only a real `get` may. `seeds` (spec §9.4)
|
|
384
|
+
* follows the same honest rule: the wire badge field is authoritative
|
|
385
|
+
* only when a real config resolved — a transient channel-down keeps the
|
|
386
|
+
* last accepted badge state.
|
|
355
387
|
*/
|
|
356
388
|
private accept;
|
|
357
389
|
private fail;
|