dsh-llm-fallbacks 0.5.2 → 0.6.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.md +5 -5
- package/README.zh-CN.md +5 -5
- package/dist/client/FallbacksCard.d.ts +10 -9
- package/dist/client/fallbacks-store.d.ts +1 -1
- package/dist/client/index.d.ts +7 -12
- package/dist/client/index.js +67 -60
- package/dist/client/locales.d.ts +0 -2
- package/dist/gateway.d.ts +49 -33
- package/dist/index.d.ts +18 -4
- package/dist/index.js +61 -32
- package/dist/role-notice.d.ts +48 -20
- package/dist/role-projection.d.ts +11 -10
- package/dist/schema.d.ts +20 -0
- package/dist/subagents-seam.d.ts +4 -4
- package/dist/time-slots.d.ts +13 -8
- package/package.json +25 -25
- package/scripts/build-client.ts +6 -5
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|

|
|
8
8
|

|
|
9
9
|

|
|
10
|
-

|
|
11
11
|
[](https://dshfind.com/zh/plugins/omdsh-dev/dsh-llm-fallbacks?ref=badge)
|
|
12
12
|
|
|
13
13
|
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.
|
|
@@ -31,7 +31,7 @@ Four frozen UTC+8 presets (windows are code constants; preset rows lock `tz` to
|
|
|
31
31
|
|
|
32
32
|
GLM Peak and GLM Valley are offered in the card picker only when `zai-coding-cn` is configured.
|
|
33
33
|
|
|
34
|
-
The first extra row whose window contains the current moment (in `fallbacks.tz`, default Asia/Shanghai) wins; no match → the all-day `rootChain`, whose tail (Default model) must be exactly one official model — `deepseek-official/deepseek-flash` or `deepseek-official/deepseek-pro` (XOR). Slot rotation is a routing seed, not a failure decision: it applies on the next root request, consumes no cooldown, and is logged as a time-slot switch — failure walks keep fallback switch. Full semantics → [Time-slot presets](#time-slot-presets) and [docs/configuration.md](docs/configuration.md).
|
|
34
|
+
The first extra row whose window contains the current moment (in `fallbacks.tz`, default Asia/Shanghai) wins; no match → the all-day `rootChain`, whose tail (Default model) must be exactly one official model — `deepseek-official/deepseek-flash` or `deepseek-official/deepseek-v4-pro` (XOR). Slot rotation is a routing seed, not a failure decision: it applies on the next root request, consumes no cooldown, and is logged as a time-slot switch — failure walks keep fallback switch. Full semantics → [Time-slot presets](#time-slot-presets) and [docs/configuration.md](docs/configuration.md).
|
|
35
35
|
|
|
36
36
|
## Quick start
|
|
37
37
|
|
|
@@ -95,7 +95,7 @@ Build the section up in four steps:
|
|
|
95
95
|
|
|
96
96
|
**2. Set the all-day `rootChain`.** Leading entries are the fallback chain, walked first when a request fails; the **last** entry is the Default model.
|
|
97
97
|
|
|
98
|
-
> **Conformance**: the last entry must be exactly one official model — `deepseek-official/deepseek-flash` or `deepseek-official/deepseek-pro` (XOR). The settings card and gateway reject any other tail on save; a legacy non-official tail warns at startup and keeps working as a fallback-only walk, but cannot be saved as-is. The retired `deepseek-v4-flash`
|
|
98
|
+
> **Conformance**: the last entry must be exactly one official model — `deepseek-official/deepseek-flash` or `deepseek-official/deepseek-v4-pro` (XOR). The settings card and gateway reject any other tail on save; a legacy non-official tail warns at startup and keeps working as a fallback-only walk, but cannot be saved as-is. The retired `deepseek-v4-flash` id is no longer a legal tail — a saved tail with it now warns, goes inert (slot rows + virtual picker), and blocks save until a legal tail is picked. The official Pro tail is catalog-served as `deepseek-official/deepseek-v4-pro` (dsh 0.1.7-rc.2; the claim re-verified against the rc.2 default catalog) and selectable in the card; a hand-written legacy `deepseek-official/deepseek-pro` tail — never catalog-served — reads back as non-conforming (no migration; re-pick the tail). The plugin does not probe catalog availability — a chain containing `deepseek-official/deepseek-v4-pro` dispatches to it like any other exact entry, and on the virtual route the `stream()` delegate serves the first dispatchable exact head of the effective chain, so a chain with a working entry before Pro still routes to that earlier entry.
|
|
99
99
|
|
|
100
100
|
**3. Add `timeSlots` (optional).** Rows rotate the effective root chain by wall-clock windows. Preset rows use frozen UTC+8 windows (only their chain is editable; while a preset row exists, `tz` locks to `Asia/Shanghai`); custom rows take `start`/`end` (may wrap midnight) and an optional `days` list. The first row whose window contains the current moment wins; no match → the all-day `rootChain`. Rotation is a routing seed — it applies on the next root request and consumes no cooldown (see [Time slots](#time-slots)).
|
|
101
101
|
|
|
@@ -120,7 +120,7 @@ A session log reaches the GUI only through the **frozen released migration chain
|
|
|
120
120
|
|
|
121
121
|
A third class — the legacy `fallbacks/switch` event type — is **not** repairable by a rewrite: see [Lossy recovery for `fallbacks/switch`](#lossy-recovery-for-fallbacksswitch-opt-in).
|
|
122
122
|
|
|
123
|
-
**If you author a plugin
|
|
123
|
+
**If you author a plugin:** through dsh 0.1.6 the persisted source vocabulary was frozen per format edge, and the sanctioned arm was `{ kind: 'plugin', plugin: '<stable-id>', form: … }`. Since dsh 0.1.7-rc.1 that vocabulary is producer-declared instead ("each producer declares its own `kind` in its own module" — dsh's own `model-selection` notice writes `{ kind: 'model-selection', form: 'notice', … }`), and the one rule a released edge enforces on a direct kind is that it is **non-empty**. Old logs written against the frozen vocabulary are exactly what this tool's `source-kind` class repairs.
|
|
124
124
|
|
|
125
125
|
### Usage
|
|
126
126
|
|
|
@@ -223,7 +223,7 @@ Notes:
|
|
|
223
223
|
|
|
224
224
|
- **Picker label**: the row's catalog `name` (what the composer trigger shows) is live — `Auto: DeepSeek Flash[Liang Peak]` / `Auto: DeepSeek Flash[all-day]` (catalog display name, not the model id); the id stays `Auto`. Bare `Auto` if the all-day tail is not conforming. Refresh by reopening the picker.
|
|
225
225
|
- **Thin delegate on every origin**: the row is served by the same `stream()` delegate for the root agent and for a subagent session that inherits the selection — subagent role resolution and injection keep their semantics apart from one deliberate widening: dispatch-time rule matching accepts **either** the recorded pair or the served head (a superset of the previous matching, so a rule keyed on the real head keeps matching), and the virtual row is never a second routing engine. A subagent that inherits the selection still routes through the chain head.
|
|
226
|
-
- **Conformance gate on the tail**: a successful delegation requires the all-day chain to be **tail-conforming** — its last entry must be exactly one official model (`deepseek-official/deepseek-flash` or `deepseek-official/deepseek-pro`, the card's Default model panel); leading entries (Default fallback chain) are walked first. Disabling the plugin hides the row again (slot-row/chain edits never churn registration).
|
|
226
|
+
- **Conformance gate on the tail**: a successful delegation requires the all-day chain to be **tail-conforming** — its last entry must be exactly one official model (`deepseek-official/deepseek-flash` or `deepseek-official/deepseek-v4-pro`, the card's Default model panel); leading entries (Default fallback chain) are walked first. Disabling the plugin hides the row again (slot-row/chain edits never churn registration).
|
|
227
227
|
- **Stale selection**: if the row disappears (plugin disabled) while `FallbacksChain / Auto` is selected, the session keeps showing it as the current model with `routable: false` — pick a real model from the catalog to continue (host-native catalog semantics).
|
|
228
228
|
- **Capabilities and retry policy follow the head**: the row's model metadata (context window, modalities, reasoning) mirrors the current effective head, and `providerRetryPolicy` returns **that head's** policy — so a user's `llm-deepseek.retryPolicy` applies on this route too, not the permissive default. The host captures the policy once at registration, so a later policy edit or a slot-driven head-provider rotation shows up only after the plugin re-registers. Retry events are keyed by the virtual provider — the route the runtime actually sees. Full semantics → [docs/configuration.md](docs/configuration.md).
|
|
229
229
|
|
package/README.zh-CN.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|

|
|
8
8
|

|
|
9
9
|

|
|
10
|
-

|
|
11
11
|
[](https://dshfind.com/zh/plugins/omdsh-dev/dsh-llm-fallbacks?ref=badge)
|
|
12
12
|
|
|
13
13
|
dsh(DeepSeek Harness)的自动模型降级插件:当 root agent 或 subagent 的模型请求持续失败(重试耗尽、权限、配额超限、限流 429)时,按角色/模型 fallback 链自动切换 provider/model,当前 step/turn 在目标模型上继续完成——任务不因模型问题中断。
|
|
@@ -31,7 +31,7 @@ dsh(DeepSeek Harness)的自动模型降级插件:当 root agent 或 subage
|
|
|
31
31
|
|
|
32
32
|
GLM 峰与 GLM 谷仅在已配置 `zai-coding-cn` 时出现在设置卡选择器中。
|
|
33
33
|
|
|
34
|
-
每个 root 请求时刻,第一条窗口包含当前时刻(按 `fallbacks.tz`,默认 Asia/Shanghai)的额外行生效;无行命中 → 全时段 `rootChain`——其链尾(默认模型)必须是恰好一个官方模型:`deepseek-official/deepseek-flash` 或 `deepseek-official/deepseek-pro`(二选一)。分时切换是路由种子而非失败决策:在下一个 root 请求生效、不消耗冷却、不计入 `maxSwitchesPerStep`,日志记为**分时切换**;失败降级保持**降级切换**。完整语义 → [分时槽预设(分时切换)](#分时槽预设分时切换) 与 [docs/configuration.md](docs/configuration.md)。
|
|
34
|
+
每个 root 请求时刻,第一条窗口包含当前时刻(按 `fallbacks.tz`,默认 Asia/Shanghai)的额外行生效;无行命中 → 全时段 `rootChain`——其链尾(默认模型)必须是恰好一个官方模型:`deepseek-official/deepseek-flash` 或 `deepseek-official/deepseek-v4-pro`(二选一)。分时切换是路由种子而非失败决策:在下一个 root 请求生效、不消耗冷却、不计入 `maxSwitchesPerStep`,日志记为**分时切换**;失败降级保持**降级切换**。完整语义 → [分时槽预设(分时切换)](#分时槽预设分时切换) 与 [docs/configuration.md](docs/configuration.md)。
|
|
35
35
|
|
|
36
36
|
## 快速开始
|
|
37
37
|
|
|
@@ -95,7 +95,7 @@ fallbacks:
|
|
|
95
95
|
|
|
96
96
|
**2. 配置全时段 `rootChain`。** 前面的条目是降级链,请求失败时先走;**最后**一项是默认模型。
|
|
97
97
|
|
|
98
|
-
> **链尾合规**:最后一项必须是恰好一个官方模型——`deepseek-official/deepseek-flash` 或 `deepseek-official/deepseek-pro`(二选一)。设置卡与 gateway 在保存时拒绝其它尾巴;遗留的非合规尾巴启动时告警并继续按 fallback-only 走原链,但无法原样保存。已退役的 `deepseek-v4-flash`
|
|
98
|
+
> **链尾合规**:最后一项必须是恰好一个官方模型——`deepseek-official/deepseek-flash` 或 `deepseek-official/deepseek-v4-pro`(二选一)。设置卡与 gateway 在保存时拒绝其它尾巴;遗留的非合规尾巴启动时告警并继续按 fallback-only 走原链,但无法原样保存。已退役的 `deepseek-v4-flash` 不再是合法链尾——已保存的该尾巴现在会告警、进入惰性(分时行 + 虚拟选择器)、并在选到合法链尾前阻止保存。官方 Pro 链尾由目录以 `deepseek-official/deepseek-v4-pro` 提供(dsh 0.1.7-rc.1),并可在设置卡中直接选择;手写的遗留 `deepseek-official/deepseek-pro` 尾巴——从未进入目录——读回为不合规(无迁移;请重选链尾)。插件不探测目录可用性——含 `deepseek-official/deepseek-v4-pro` 的链会像其它精确条目一样派发到它;在虚拟路由上由 `stream()` 委派服务生效链的第一个可派发精确链头,因此 Pro 之前有可用条目的链仍路由到更早的条目。
|
|
99
99
|
|
|
100
100
|
**3. 添加 `timeSlots`(可选)。** 各行按墙钟窗口轮换生效 root 链。预设行使用冻结的 UTC+8 窗口(仅链可编辑;存在预设行时 `tz` 锁定 `Asia/Shanghai`);自定义行使用 `start`/`end`(可跨午夜)与可选的 `days` 列表。第一个窗口包含当前时刻的行生效;无行命中 → 全时段 `rootChain`。分时切换是路由种子——在下一个 root 请求生效、不消耗冷却(见 [峰谷无忧](#峰谷无忧))。
|
|
101
101
|
|
|
@@ -120,7 +120,7 @@ fallbacks:
|
|
|
120
120
|
|
|
121
121
|
第三类——遗留 `fallbacks/switch` 事件类型——**无法**通过改写修复:见 [fallbacks/switch 的有损恢复(opt-in)](#fallbacksswitch-的有损恢复opt-in)。
|
|
122
122
|
|
|
123
|
-
|
|
123
|
+
**如果你在编写插件:** dsh 0.1.6 及之前,持久化 source 词汇表按格式边界冻结,受支持的写法是 `{ kind: 'plugin', plugin: '<stable-id>', form: … }`。自 dsh 0.1.7-rc.1 起词汇表改为由生产者自行声明(“每个生产者在自己的模块里声明自己的 `kind`”——dsh 自身的 `model-selection` notice 写的是 `{ kind: 'model-selection', form: 'notice', … }`),发行边界对直接 kind 唯一强制的规则是**非空**。按冻结词汇表写入的历史日志正是本工具 `source-kind` 类别要修复的对象。
|
|
124
124
|
|
|
125
125
|
### 用法
|
|
126
126
|
|
|
@@ -223,7 +223,7 @@ pnpm repair:session-logs -- --drop-legacy-events --apply --backup # 此处必
|
|
|
223
223
|
|
|
224
224
|
- **选择器文案**:目录行的 `name`(composer 触发器显示)是动态的——`Auto: DeepSeek Flash[Liang Peak]` / `Auto: DeepSeek Flash[all-day]`(用 catalog 显示名,不是 model id);id 仍是 `Auto`。all-day 尾巴不合规则只显示 `Auto`。重新打开选择器即可刷新。
|
|
225
225
|
- **全来源同一个薄委托**:root 代理与继承了该选择的 subagent 会话由同一个 `stream()` 薄委托服务——subagent 的角色解析与注入语义不变,只有一处刻意的放宽:派发时规则匹配接受**记录 pair 或实际服务的链头**(此前匹配的超集,因此以真实链头为键的规则仍能命中),虚拟行绝不是第二个路由引擎。继承了该选择的 subagent 仍经链头路由。
|
|
226
|
-
- **链尾合规门槛**:委托成功要求 all-day 链**尾巴合规**——最后一项必须是恰好一个官方模型(`deepseek-official/deepseek-flash` 或 `deepseek-official/deepseek-pro`,即设置卡的「默认模型」面板);前面的默认降级链先走。禁用插件后该行隐藏(slot/链编辑不会触发注册抖动)。
|
|
226
|
+
- **链尾合规门槛**:委托成功要求 all-day 链**尾巴合规**——最后一项必须是恰好一个官方模型(`deepseek-official/deepseek-flash` 或 `deepseek-official/deepseek-v4-pro`,即设置卡的「默认模型」面板);前面的默认降级链先走。禁用插件后该行隐藏(slot/链编辑不会触发注册抖动)。
|
|
227
227
|
- **过期选择**:行消失(插件禁用)而会话仍选中 `FallbacksChain / Auto` 时,会话继续把它显示为当前模型,但 `routable: false`——从目录选一个真实模型即可继续(宿主原生目录语义)。
|
|
228
228
|
- **能力与重试策略跟随链头**:该行的模型元数据(上下文窗口、模态、推理)镜像当前生效链头,`providerRetryPolicy` 返回**该链头的**策略——因此用户配置的 `llm-deepseek.retryPolicy` 在这条路由上同样生效,不再退回宽松默认。宿主在注册时一次性捕获该策略,因此之后修改策略、或分时槽导致链头 provider 轮换,都只有在插件重新注册后才会反映。重试事件按虚拟 provider 记账——即运行时实际看到的路由。完整语义 → [docs/configuration.md](docs/configuration.md)。
|
|
229
229
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Fallbacks settings card — the `fallbacks` plugin card on the web
|
|
3
|
-
*
|
|
4
|
-
* slot (key `fallbacks`, the
|
|
2
|
+
* Fallbacks settings card — the `fallbacks` plugin card on the web
|
|
3
|
+
* Plugins page (spec §4). Registered into the `plugins.bundle.config` keyed
|
|
4
|
+
* slot (key `dsh-llm-fallbacks`, the bundle package name, alongside
|
|
5
5
|
* the upstream bash/agent-loop/web-search cards and the advisor card, in
|
|
6
6
|
* registration order); owner props are empty and all data flows
|
|
7
7
|
* through {@link FallbacksSettingsController}.
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* the upstream client value face exports no reusable card): a collapsible
|
|
11
11
|
* `<li>` whose header is a button stacking the plugin name over its
|
|
12
12
|
* description, with a dirty "unsaved" pill and a rotating chevron
|
|
13
|
-
* (`
|
|
13
|
+
* (`IconChevronDownOutlineMedium` from ui-primitives — a CLIENT_EXTERNALS value
|
|
14
14
|
* import), `aria-expanded`/`aria-label` like the upstream header; a divider
|
|
15
15
|
* under the header; then the form content. PR #62 UX round 2: the card
|
|
16
16
|
* footer is gone — each big section (主代理 / 子代理 / 高级选项) carries its
|
|
@@ -79,18 +79,19 @@
|
|
|
79
79
|
* so the healthy card starts (and stays) collapsed through its first load.
|
|
80
80
|
*/
|
|
81
81
|
import type { ReactNode } from 'react';
|
|
82
|
-
import type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
83
|
-
import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';
|
|
82
|
+
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
84
83
|
import { FallbacksSettingsController, type FallbacksSettingsState } from './fallbacks-store.ts';
|
|
85
84
|
/** Injected dependencies of {@link FallbacksCard} (slot `inject`). */
|
|
86
85
|
export interface FallbacksCardInjected {
|
|
87
86
|
/** The card store (loaded on mount, refreshed on pushed invalidations). */
|
|
88
87
|
controller: FallbacksSettingsController;
|
|
89
|
-
/**
|
|
90
|
-
|
|
88
|
+
/** Bare snapshot source the renderer binds as `useSnapshot`. */
|
|
89
|
+
hooks: {
|
|
90
|
+
snapshot: import('@deepseek-ai/dsh-client-store').SnapshotStore<FallbacksSettingsState>;
|
|
91
|
+
};
|
|
91
92
|
}
|
|
92
93
|
/** Props delivered by the slot outlet: runtime share + locale seat + inject face. */
|
|
93
|
-
export type FallbacksCardProps = PropsRuntime<'
|
|
94
|
+
export type FallbacksCardProps = PropsRuntime<'plugins.bundle.config'> & PropsLocale<'fallbacks'> & InjectFace<FallbacksCardInjected>;
|
|
94
95
|
/**
|
|
95
96
|
* Render the Fallbacks settings card inside the plugin-config section,
|
|
96
97
|
* replicating the upstream PluginCard chrome (KD-U1). The body carries the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Fallbacks settings controller — the client half's own store (slot owner
|
|
3
|
-
* props are empty; data rides this store, per the `
|
|
3
|
+
* props are empty; data rides this store, per the `plugins.bundle.config`
|
|
4
4
|
* card contract).
|
|
5
5
|
*
|
|
6
6
|
* Read path: the fallbacks config rides the plugin's own gateway channel —
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* dsh-llm-fallbacks client half: registers the Fallbacks card into the
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* edits, appearing after the upstream bash / agent-loop / web-search cards
|
|
6
|
-
* and the advisor card in registration order).
|
|
3
|
+
* Plugins page `plugins.bundle.config` keyed slot (key = bundle package name
|
|
4
|
+
* `dsh-llm-fallbacks`).
|
|
7
5
|
*
|
|
8
6
|
* Wiring (mirrors dsh-advisor):
|
|
9
7
|
* - Registers the `fallbacks` locale dictionaries (zh/en).
|
|
@@ -13,13 +11,10 @@
|
|
|
13
11
|
* namespace directory), the provider/model catalog, and the switch-history
|
|
14
12
|
* tail page ride the typed `ctx.remote` namespaces (0.1.2:
|
|
15
13
|
* `ConnectionHandle` dropped `api`; see `fallbacks-store.ts`).
|
|
16
|
-
* - Registers the `
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* ({@link FallbacksSettingsController} + the snapshot-selector hook); the
|
|
21
|
-
* old Settings-nav section registration is removed — deleting the section
|
|
22
|
-
* registration deletes the nav entry.
|
|
14
|
+
* - Registers the `plugins.bundle.config` card `key: 'dsh-llm-fallbacks'`
|
|
15
|
+
* (bundle package name) with a business-only inject face
|
|
16
|
+
* ({@link FallbacksSettingsController} + hooks.snapshot); the old
|
|
17
|
+
* Settings-nav section registration stays removed.
|
|
23
18
|
* - Refreshes the store on pushed invalidations — the forwarded remote
|
|
24
19
|
* events `settings/document-updated` (ns-filtered to the fallbacks
|
|
25
20
|
* namespace; refetches the descriptor + recent-switch summary) and
|
|
@@ -63,7 +58,7 @@ export { FallbacksSettingsController, FALLBACKS_SETTINGS_NS } from './fallbacks-
|
|
|
63
58
|
export declare const inject: string[];
|
|
64
59
|
/**
|
|
65
60
|
* Register the `fallbacks` dictionaries and the plugin-config card once the
|
|
66
|
-
* `
|
|
61
|
+
* `plugins.bundle.config` declaration is on the ledger.
|
|
67
62
|
* @param ctx - client root context.
|
|
68
63
|
*/
|
|
69
64
|
export declare function apply(ctx: ClientContext): void;
|
package/dist/client/index.js
CHANGED
|
@@ -199,10 +199,10 @@ window.__ModuleLoader__.load({
|
|
|
199
199
|
};
|
|
200
200
|
}
|
|
201
201
|
/** The two official all-day tail ids (XOR — exactly one legal tail). */
|
|
202
|
-
const OFFICIAL_ALL_DAY_IDS = ["deepseek-official/deepseek-flash", "deepseek-official/deepseek-pro"];
|
|
202
|
+
const OFFICIAL_ALL_DAY_IDS = ["deepseek-official/deepseek-flash", "deepseek-official/deepseek-v4-pro"];
|
|
203
203
|
/** Whether `id` is one of the two official all-day tail ids. */
|
|
204
204
|
function isOfficialAllDayId(id) {
|
|
205
|
-
return id === "deepseek-official/deepseek-flash" || id === "deepseek-official/deepseek-pro";
|
|
205
|
+
return id === "deepseek-official/deepseek-flash" || id === "deepseek-official/deepseek-v4-pro";
|
|
206
206
|
}
|
|
207
207
|
/**
|
|
208
208
|
* Frozen preset windows (UTC+8). `liang-peak` and `glm-peak` are
|
|
@@ -411,8 +411,10 @@ window.__ModuleLoader__.load({
|
|
|
411
411
|
* entry (the tail — the card's 默认模型 panel) is exactly one official
|
|
412
412
|
* model — Flash or Pro (XOR). Leading entries (the card's 默认降级链 block)
|
|
413
413
|
* are the ordered walk before that last-resort fallback. An empty chain or
|
|
414
|
-
* a chain whose tail is not an official model (
|
|
415
|
-
*
|
|
414
|
+
* a chain whose tail is not an official model (the retired
|
|
415
|
+
* `deepseek-v4-flash` and the never-served legacy
|
|
416
|
+
* `deepseek-official/deepseek-pro` included) keeps slot rows inert and
|
|
417
|
+
* refuses the virtual-row
|
|
416
418
|
* delegate; the v0.2.2 failure walk over the raw chain stays
|
|
417
419
|
* verbatim.
|
|
418
420
|
*/
|
|
@@ -1421,8 +1423,7 @@ window.__ModuleLoader__.load({
|
|
|
1421
1423
|
"timeSlots.selector.add": "添加选择器",
|
|
1422
1424
|
"allDay.hint": "全天链的最后一档兜底:官方 Flash 或 Pro 二选一",
|
|
1423
1425
|
"allDay.flash": "官方 Flash(deepseek-official/deepseek-flash)",
|
|
1424
|
-
"allDay.pro": "官方 Pro(deepseek-official/deepseek-pro)",
|
|
1425
|
-
"allDay.proCaveat": "(暂不可用)",
|
|
1426
|
+
"allDay.pro": "官方 Pro(deepseek-official/deepseek-v4-pro)",
|
|
1426
1427
|
"allDay.nonconforming": "当前默认模型不合法:请选择官方 Flash 或 Pro 后保存",
|
|
1427
1428
|
"roles.list.label": "角色实体",
|
|
1428
1429
|
"roles.list.hint": "先声明角色,规则才能引用",
|
|
@@ -1618,8 +1619,7 @@ window.__ModuleLoader__.load({
|
|
|
1618
1619
|
"timeSlots.selector.add": "Add selector",
|
|
1619
1620
|
"allDay.hint": "Last-resort fallback of the all-day chain: official Flash or Pro (pick exactly one)",
|
|
1620
1621
|
"allDay.flash": "Official Flash (deepseek-official/deepseek-flash)",
|
|
1621
|
-
"allDay.pro": "Official Pro (deepseek-official/deepseek-pro)",
|
|
1622
|
-
"allDay.proCaveat": " (not yet available)",
|
|
1622
|
+
"allDay.pro": "Official Pro (deepseek-official/deepseek-v4-pro)",
|
|
1623
1623
|
"allDay.nonconforming": "The current default model is not valid: pick official Flash or Pro before saving",
|
|
1624
1624
|
"roles.list.label": "Declared roles",
|
|
1625
1625
|
"roles.list.hint": "Declare roles before rules can reference them",
|
|
@@ -1849,9 +1849,9 @@ window.__ModuleLoader__.load({
|
|
|
1849
1849
|
//#endregion
|
|
1850
1850
|
//#region src/client/FallbacksCard.tsx
|
|
1851
1851
|
/**
|
|
1852
|
-
* Fallbacks settings card — the `fallbacks` plugin card on the web
|
|
1853
|
-
*
|
|
1854
|
-
* slot (key `fallbacks`, the
|
|
1852
|
+
* Fallbacks settings card — the `fallbacks` plugin card on the web
|
|
1853
|
+
* Plugins page (spec §4). Registered into the `plugins.bundle.config` keyed
|
|
1854
|
+
* slot (key `dsh-llm-fallbacks`, the bundle package name, alongside
|
|
1855
1855
|
* the upstream bash/agent-loop/web-search cards and the advisor card, in
|
|
1856
1856
|
* registration order); owner props are empty and all data flows
|
|
1857
1857
|
* through {@link FallbacksSettingsController}.
|
|
@@ -1860,7 +1860,7 @@ window.__ModuleLoader__.load({
|
|
|
1860
1860
|
* the upstream client value face exports no reusable card): a collapsible
|
|
1861
1861
|
* `<li>` whose header is a button stacking the plugin name over its
|
|
1862
1862
|
* description, with a dirty "unsaved" pill and a rotating chevron
|
|
1863
|
-
* (`
|
|
1863
|
+
* (`IconChevronDownOutlineMedium` from ui-primitives — a CLIENT_EXTERNALS value
|
|
1864
1864
|
* import), `aria-expanded`/`aria-label` like the upstream header; a divider
|
|
1865
1865
|
* under the header; then the form content. PR #62 UX round 2: the card
|
|
1866
1866
|
* footer is gone — each big section (主代理 / 子代理 / 高级选项) carries its
|
|
@@ -1929,9 +1929,6 @@ window.__ModuleLoader__.load({
|
|
|
1929
1929
|
* so the healthy card starts (and stays) collapsed through its first load.
|
|
1930
1930
|
*/
|
|
1931
1931
|
const ALL_DAY_LABEL_KEYS = ["allDay.flash", "allDay.pro"];
|
|
1932
|
-
/** Optional caveat suffix per option (parallel to OFFICIAL_ALL_DAY_IDS):
|
|
1933
|
-
* Pro's radio is always disabled — its model is not yet in the catalog. */
|
|
1934
|
-
const ALL_DAY_CAVEAT_KEYS = [void 0, "allDay.proCaveat"];
|
|
1935
1932
|
const SLOT_PRESET_IDS = [
|
|
1936
1933
|
"liang-peak",
|
|
1937
1934
|
"liang-valley",
|
|
@@ -2364,7 +2361,7 @@ window.__ModuleLoader__.load({
|
|
|
2364
2361
|
"data-tip": t("chains.selector.remove"),
|
|
2365
2362
|
"aria-label": t("chains.selector.remove"),
|
|
2366
2363
|
onClick: onRemove,
|
|
2367
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
2364
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutlineMedium, {})
|
|
2368
2365
|
})
|
|
2369
2366
|
})
|
|
2370
2367
|
]
|
|
@@ -2851,7 +2848,7 @@ window.__ModuleLoader__.load({
|
|
|
2851
2848
|
className: FallbacksCard_module_css_default.pending,
|
|
2852
2849
|
children: t("unsaved")
|
|
2853
2850
|
}) : null,
|
|
2854
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
2851
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineMedium, { className: open ? `${FallbacksCard_module_css_default.chevron} ${FallbacksCard_module_css_default.chevronOpen}` : FallbacksCard_module_css_default.chevron })
|
|
2855
2852
|
]
|
|
2856
2853
|
});
|
|
2857
2854
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
@@ -3047,7 +3044,7 @@ window.__ModuleLoader__.load({
|
|
|
3047
3044
|
updateTimeSlotRow(index, { collapsed: !row.collapsed });
|
|
3048
3045
|
},
|
|
3049
3046
|
children: [
|
|
3050
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
3047
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineMedium, { className: slotExpanded ? `${FallbacksCard_module_css_default.chevron} ${FallbacksCard_module_css_default.chevronOpen}` : FallbacksCard_module_css_default.chevron }),
|
|
3051
3048
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3052
3049
|
className: FallbacksCard_module_css_default.collapseTitle,
|
|
3053
3050
|
children: row.kind === "preset" ? t(`timeSlots.preset.${row.preset}.label`) : row.name !== "" ? row.name : `custom ${row.start}-${row.end}`
|
|
@@ -3084,7 +3081,7 @@ window.__ModuleLoader__.load({
|
|
|
3084
3081
|
setDraggedSlotIndex(null);
|
|
3085
3082
|
setOverSlotIndex(null);
|
|
3086
3083
|
},
|
|
3087
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
3084
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconEllipsisOutlineMedium, { className: FallbacksCard_module_css_default.dragHandleIcon })
|
|
3088
3085
|
})]
|
|
3089
3086
|
}), slotExpanded && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
3090
3087
|
row.kind === "preset" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
@@ -3235,7 +3232,7 @@ window.__ModuleLoader__.load({
|
|
|
3235
3232
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3236
3233
|
variant: "outline",
|
|
3237
3234
|
size: "sm",
|
|
3238
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
3235
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineMedium, { size: 14 }),
|
|
3239
3236
|
className: FallbacksCard_module_css_default.addButton,
|
|
3240
3237
|
onClick: () => {
|
|
3241
3238
|
addTimeSlotSelector(index);
|
|
@@ -3256,7 +3253,7 @@ window.__ModuleLoader__.load({
|
|
|
3256
3253
|
onClick: () => {
|
|
3257
3254
|
moveTimeSlotRow(index, -1);
|
|
3258
3255
|
},
|
|
3259
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
3256
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutlineMedium, {})
|
|
3260
3257
|
}),
|
|
3261
3258
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3262
3259
|
type: "button",
|
|
@@ -3267,7 +3264,7 @@ window.__ModuleLoader__.load({
|
|
|
3267
3264
|
onClick: () => {
|
|
3268
3265
|
moveTimeSlotRow(index, 1);
|
|
3269
3266
|
},
|
|
3270
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
3267
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineMedium, {})
|
|
3271
3268
|
}),
|
|
3272
3269
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3273
3270
|
type: "button",
|
|
@@ -3277,7 +3274,7 @@ window.__ModuleLoader__.load({
|
|
|
3277
3274
|
onClick: () => {
|
|
3278
3275
|
removeTimeSlotRow(index);
|
|
3279
3276
|
},
|
|
3280
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
3277
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutlineMedium, {})
|
|
3281
3278
|
})
|
|
3282
3279
|
]
|
|
3283
3280
|
})
|
|
@@ -3312,7 +3309,7 @@ window.__ModuleLoader__.load({
|
|
|
3312
3309
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3313
3310
|
variant: "outline",
|
|
3314
3311
|
size: "sm",
|
|
3315
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
3312
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineMedium, { size: 14 }),
|
|
3316
3313
|
disabled: !writable || presetToAdd === "",
|
|
3317
3314
|
onClick: addPresetSlotRow,
|
|
3318
3315
|
children: t("timeSlots.addPreset")
|
|
@@ -3320,7 +3317,7 @@ window.__ModuleLoader__.load({
|
|
|
3320
3317
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3321
3318
|
variant: "outline",
|
|
3322
3319
|
size: "sm",
|
|
3323
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
3320
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineMedium, { size: 14 }),
|
|
3324
3321
|
disabled: !writable,
|
|
3325
3322
|
onClick: addCustomSlotRow,
|
|
3326
3323
|
children: t("timeSlots.addCustom")
|
|
@@ -3378,7 +3375,7 @@ window.__ModuleLoader__.load({
|
|
|
3378
3375
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3379
3376
|
variant: "outline",
|
|
3380
3377
|
size: "sm",
|
|
3381
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
3378
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineMedium, { size: 14 }),
|
|
3382
3379
|
className: FallbacksCard_module_css_default.addButton,
|
|
3383
3380
|
onClick: addAllDayChainSelector,
|
|
3384
3381
|
children: t("timeSlots.selector.add")
|
|
@@ -3409,22 +3406,15 @@ window.__ModuleLoader__.load({
|
|
|
3409
3406
|
className: FallbacksCard_module_css_default.editorCard,
|
|
3410
3407
|
children: [OFFICIAL_ALL_DAY_IDS.map((id, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3411
3408
|
className: FallbacksCard_module_css_default.optionRow,
|
|
3412
|
-
children: [
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
}),
|
|
3422
|
-
t(ALL_DAY_LABEL_KEYS[index]),
|
|
3423
|
-
ALL_DAY_CAVEAT_KEYS[index] !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3424
|
-
className: FallbacksCard_module_css_default.hint,
|
|
3425
|
-
children: t(ALL_DAY_CAVEAT_KEYS[index])
|
|
3426
|
-
})
|
|
3427
|
-
]
|
|
3409
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3410
|
+
type: "radio",
|
|
3411
|
+
name: "fallbacks-all-day",
|
|
3412
|
+
checked: allDayModel === id,
|
|
3413
|
+
disabled: !writable,
|
|
3414
|
+
onChange: () => {
|
|
3415
|
+
setAllDayModel(id);
|
|
3416
|
+
}
|
|
3417
|
+
}), t(ALL_DAY_LABEL_KEYS[index])]
|
|
3428
3418
|
}, id)), allDayModel === "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3429
3419
|
className: FallbacksCard_module_css_default.hint,
|
|
3430
3420
|
children: t("allDay.nonconforming")
|
|
@@ -3544,7 +3534,7 @@ window.__ModuleLoader__.load({
|
|
|
3544
3534
|
updateRoleRow(index, { collapsed: !row.collapsed });
|
|
3545
3535
|
},
|
|
3546
3536
|
children: [
|
|
3547
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
3537
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineMedium, { className: roleExpanded ? `${FallbacksCard_module_css_default.chevron} ${FallbacksCard_module_css_default.chevronOpen}` : FallbacksCard_module_css_default.chevron }),
|
|
3548
3538
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3549
3539
|
className: FallbacksCard_module_css_default.collapseTitle,
|
|
3550
3540
|
children: row.id
|
|
@@ -3626,7 +3616,7 @@ window.__ModuleLoader__.load({
|
|
|
3626
3616
|
updateRoleRow(index, { personaOpen: !row.personaOpen });
|
|
3627
3617
|
}
|
|
3628
3618
|
},
|
|
3629
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
3619
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineMedium, { className: row.personaOpen ? `${FallbacksCard_module_css_default.chevron} ${FallbacksCard_module_css_default.chevronOpen}` : FallbacksCard_module_css_default.chevron })
|
|
3630
3620
|
})]
|
|
3631
3621
|
}), row.personaOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3632
3622
|
className: FallbacksCard_module_css_default.personaFull,
|
|
@@ -3681,7 +3671,7 @@ window.__ModuleLoader__.load({
|
|
|
3681
3671
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3682
3672
|
variant: "outline",
|
|
3683
3673
|
size: "sm",
|
|
3684
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
3674
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineMedium, { size: 14 }),
|
|
3685
3675
|
className: FallbacksCard_module_css_default.addButton,
|
|
3686
3676
|
onClick: () => {
|
|
3687
3677
|
addRoleSelector(index);
|
|
@@ -3698,7 +3688,7 @@ window.__ModuleLoader__.load({
|
|
|
3698
3688
|
onClick: () => {
|
|
3699
3689
|
removeRole(index);
|
|
3700
3690
|
},
|
|
3701
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
3691
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutlineMedium, {})
|
|
3702
3692
|
})
|
|
3703
3693
|
})
|
|
3704
3694
|
] })]
|
|
@@ -3708,7 +3698,7 @@ window.__ModuleLoader__.load({
|
|
|
3708
3698
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3709
3699
|
variant: "outline",
|
|
3710
3700
|
size: "sm",
|
|
3711
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
3701
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineMedium, { size: 14 }),
|
|
3712
3702
|
className: FallbacksCard_module_css_default.addButton,
|
|
3713
3703
|
onClick: addRole,
|
|
3714
3704
|
children: t("roles.add")
|
|
@@ -3875,7 +3865,7 @@ window.__ModuleLoader__.load({
|
|
|
3875
3865
|
onClick: () => {
|
|
3876
3866
|
setRuleRows((rows) => rows.filter((_, rowIndex) => rowIndex !== index));
|
|
3877
3867
|
},
|
|
3878
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
3868
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutlineMedium, {})
|
|
3879
3869
|
})
|
|
3880
3870
|
})
|
|
3881
3871
|
]
|
|
@@ -3885,7 +3875,7 @@ window.__ModuleLoader__.load({
|
|
|
3885
3875
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3886
3876
|
variant: "outline",
|
|
3887
3877
|
size: "sm",
|
|
3888
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
3878
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineMedium, { size: 14 }),
|
|
3889
3879
|
className: FallbacksCard_module_css_default.addButton,
|
|
3890
3880
|
onClick: () => {
|
|
3891
3881
|
setRuleRows((rows) => [...rows, {
|
|
@@ -3916,7 +3906,7 @@ window.__ModuleLoader__.load({
|
|
|
3916
3906
|
id: "fallbacks-advanced",
|
|
3917
3907
|
className: FallbacksCard_module_css_default.sectionToggleText,
|
|
3918
3908
|
children: t("advanced.label")
|
|
3919
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
3909
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineMedium, { className: advancedVisible ? `${FallbacksCard_module_css_default.chevron} ${FallbacksCard_module_css_default.chevronOpen}` : FallbacksCard_module_css_default.chevron })]
|
|
3920
3910
|
}), advancedVisible && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3921
3911
|
id: "fallbacks-advanced-body",
|
|
3922
3912
|
children: [
|
|
@@ -4600,8 +4590,26 @@ window.__ModuleLoader__.load({
|
|
|
4600
4590
|
"remote.session"
|
|
4601
4591
|
];
|
|
4602
4592
|
/**
|
|
4593
|
+
* The session the client is LOOKING at, derived from the sessions-list
|
|
4594
|
+
* snapshot. 0.1.7-rc.1 moved view ownership out of `SessionListState` (the
|
|
4595
|
+
* `current` field is gone — "navigation belongs to view owners"): the viewed
|
|
4596
|
+
* session is the one the shell retains under the `mainView` reference source,
|
|
4597
|
+
* surfaced as a positive `retainedBy.mainView` count on the row
|
|
4598
|
+
* (`SessionSummary.retainedBy`, the same signal `ui-session`'s main-view
|
|
4599
|
+
* derivation reads). First match in host list order; `undefined` while no
|
|
4600
|
+
* session is open — the switches face degrades to its empty state.
|
|
4601
|
+
*/
|
|
4602
|
+
function viewedSessionId(state) {
|
|
4603
|
+
if (!Array.isArray(state?.ids)) return void 0;
|
|
4604
|
+
for (const id of state.ids) {
|
|
4605
|
+
const row = state.byId[id];
|
|
4606
|
+
const mainView = (row?.retainedBy)?.mainView ?? 0;
|
|
4607
|
+
if (row !== void 0 && mainView > 0) return id;
|
|
4608
|
+
}
|
|
4609
|
+
}
|
|
4610
|
+
/**
|
|
4603
4611
|
* Register the `fallbacks` dictionaries and the plugin-config card once the
|
|
4604
|
-
* `
|
|
4612
|
+
* `plugins.bundle.config` declaration is on the ledger.
|
|
4605
4613
|
* @param ctx - client root context.
|
|
4606
4614
|
*/
|
|
4607
4615
|
function apply(ctx) {
|
|
@@ -4615,7 +4623,7 @@ window.__ModuleLoader__.load({
|
|
|
4615
4623
|
const useSnapshot = bindSnapshotSelector(controller.store);
|
|
4616
4624
|
ctx.effect(() => {
|
|
4617
4625
|
const syncSession = () => {
|
|
4618
|
-
controller.setCurrentSession(sessions
|
|
4626
|
+
controller.setCurrentSession(sessions === void 0 ? void 0 : viewedSessionId(sessions.list.getSnapshot()));
|
|
4619
4627
|
};
|
|
4620
4628
|
if (sessions !== void 0) syncSession();
|
|
4621
4629
|
const refresh = (ns) => {
|
|
@@ -4650,18 +4658,17 @@ window.__ModuleLoader__.load({
|
|
|
4650
4658
|
controller.dispose();
|
|
4651
4659
|
};
|
|
4652
4660
|
}, "llm-fallbacks: pushed invalidations");
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4661
|
+
const BUNDLE_NAME = "dsh-llm-fallbacks";
|
|
4662
|
+
ctx.slots.inject("plugins.bundle.config", function* () {
|
|
4663
|
+
yield ctx.slots.register({
|
|
4664
|
+
name: "plugins.bundle.config",
|
|
4665
|
+
key: BUNDLE_NAME,
|
|
4658
4666
|
locale: NS,
|
|
4659
4667
|
inject: () => ({
|
|
4660
4668
|
controller,
|
|
4661
|
-
|
|
4669
|
+
hooks: { snapshot: controller.store }
|
|
4662
4670
|
})
|
|
4663
|
-
};
|
|
4664
|
-
yield ctx.slots.register(cardOptions, FallbacksCard);
|
|
4671
|
+
}, FallbacksCard);
|
|
4665
4672
|
});
|
|
4666
4673
|
ctx.slots.inject("settings.general.item", function* () {
|
|
4667
4674
|
yield ctx.slots.register({
|
package/dist/client/locales.d.ts
CHANGED
|
@@ -102,7 +102,6 @@ export declare const zh: {
|
|
|
102
102
|
'allDay.hint': string;
|
|
103
103
|
'allDay.flash': string;
|
|
104
104
|
'allDay.pro': string;
|
|
105
|
-
'allDay.proCaveat': string;
|
|
106
105
|
'allDay.nonconforming': string;
|
|
107
106
|
'roles.list.label': string;
|
|
108
107
|
'roles.list.hint': string;
|
|
@@ -301,7 +300,6 @@ export declare const en: {
|
|
|
301
300
|
'allDay.hint': string;
|
|
302
301
|
'allDay.flash': string;
|
|
303
302
|
'allDay.pro': string;
|
|
304
|
-
'allDay.proCaveat': string;
|
|
305
303
|
'allDay.nonconforming': string;
|
|
306
304
|
'roles.list.label': string;
|
|
307
305
|
'roles.list.hint': string;
|