dsh-reasoning-distill 0.1.9 → 0.1.11

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/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  本插件的版本变更记录。
4
4
 
5
+ ## 0.1.11
6
+
7
+ - **新增无写入后端 `derive`**:不写会话日志、不建分支、不需要宿主补丁或第三方插件,只在本插件的派生消息包裹器里替换思考。压缩记录保存在 sidecar,重启后继续生效;对话页面显示会话日志里的原文,模型实际收到压缩版。打包版 DSH(如 dsh-desktop)也能用。
8
+ - **后端顺序与推荐**:设置页与 README 的后端顺序改为 `derive`、`in-place`、`message-edit`。能打补丁且愿意给 DSH 源码打补丁时优先 `in-place`,否则优先 `derive`;`message-edit` 仅作实验性场景,会缩小可用场景,不推荐。
9
+ - **提示词**:新增「保留被否定的方向及其原因」要求,压缩后的思考要写明推导与原因(「X 被否决,因为 Y」),防止后续重新走进同一条错误路线;同时继续提取有效部分并压缩。
10
+ - **主开关**:仍要求至少选中一个后端才解锁,未选择时锁定。
11
+ - 无写入模式下 sidecar 读取期限不再受蒸馏超时限制,避免请求退回原文;记录不可读时会明确警告。
12
+
13
+ ## 0.1.10
14
+
15
+ - **计费口径修正**:只统计「产出压缩的那一轮」内、用户发下一条消息之前后续请求的重放;跨轮次的重放不再计入节省(DeepSeek 的 API 不参考之前轮次的 `reasoning_content`),报告里的当前减量也按这一轮计算,旧轮次的改写不再显示为节省。
16
+ - **兼容性标注**:`dsh.compatibility.dshReleases` 增补 `0.2.1-rc.2`。核对了 rc.1 与 rc.2 的 6 个 in-place 补丁目标文件与公开 API catalog,两者逐字节相同,因此 rc.1 的完整验证结论同样适用;README 的测试版本表同步更新。
17
+
5
18
  ## 0.1.9
6
19
 
7
20
  - README 开头补充「适用场景」说明:本插件只在单轮次、多步工具调用的超长单轮对话里划算;多轮问答中每轮步骤少、压缩收益有限,且 DeepSeek 的 API 默认不会参考之前轮次的 `reasoning_content`(仅请求携带 tools 时拼接进上下文),改写还会让缓存前缀失效、后续请求按未命中计费,整体往往难以抵消。插件面向「说完任务就不管」的许愿式编程,在根据用户反馈反复精修的阶段建议关闭。
package/README.md CHANGED
@@ -14,9 +14,9 @@
14
14
 
15
15
  > **版本与安装方式(先看这里)**
16
16
  >
17
- > - **可能适配的 DSH 版本**:`0.2.0-rc.1` ~ `0.2.1-rc.1`。这一范围内的补丁、类型与语义都逐版本验证过,明细见下文「经过测试的 DSH 版本」。
17
+ > - **可能适配的 DSH 版本**:`0.2.0-rc.1` ~ `0.2.1-rc.2`(`0.2.1-rc.2` 与 `0.2.1-rc.1` 的补丁目标文件、公开 API catalog 逐字节相同,结论直接适用)。这一范围内的补丁、类型与语义都逐版本验证过,明细见下文「经过测试的 DSH 版本」。
18
18
  > - **已知可以正常运行 in-place 后端**的版本:`0.2.1-alpha.1`、`0.2.1-alpha.5`。
19
- > - **想要全部功能与最佳体验,请使用从源码构建的 DSH**(clone 官方仓库后从源码运行或构建)。**从 npm 直接下载的版本**和**第三方打包版**(例如 dsh-desktop)无法给宿主源码打补丁,in-place 后端用不了,只能退而使用 message-edit。
19
+ > - **想要全部功能与最佳体验,请使用从源码构建的 DSH**(clone 官方仓库后从源码运行或构建)。**从 npm 直接下载的版本**和**第三方打包版**(例如 dsh-desktop)无法给宿主源码打补丁,in-place 后端用不了,优先改用无写入的 `derive`;message-edit 仅实验性,不推荐。
20
20
 
21
21
  ---
22
22
 
@@ -29,15 +29,32 @@
29
29
  - 被采用的压缩版会替换"模型看到的思考内容",因此之后每个请求都少带这些 token;会话日志里的思考原文保持不动,本插件的账本存放在会话日志旁边的 sidecar 文件里。
30
30
  - 「思考压缩」标签页显示:触发次数、蒸馏开销、已采用次数、当前单次请求减量、历史累计节省、净收益,以及最近一步"为什么没有触发"。
31
31
 
32
- 三种会话有各自独立的开关:**主对话**、**可续聊子代理**(例如队友)、**一次性子代理**(跑完即结束的委派)。默认只对主对话和可续聊子代理开启。
32
+ 三种会话有各自独立的开关:**主对话**、**可续聊子代理**(例如队友)、**一次性子代理**(跑完即结束的委派)。默认只对主对话开启;可续聊子代理、一次性子代理、附带工具调用结果、压缩最终回答轮默认都关。
33
33
 
34
34
  **关于"缓存断裂"**:改写被放在该思考块第一次被重放之前,所以正常情况下这一步本来就是缓存未命中,不额外产生缓存断裂开销,报告里的 `cacheBreakTokens` / `cacheBreakCost` 恒为 0。少数回退路径(sidecar 读失败后恢复、写回失败留给轮询补写、插件停用后宿主仍持有压缩版)会让改写点之后的整段重新按未命中计费,这时报告会高估净收益。
35
35
 
36
36
  ---
37
37
 
38
- ## 二、助手消息改写后端:二选一
38
+ ## 二、助手消息改写后端:三选一
39
39
 
40
- 本插件只负责"算出压缩版";把压缩版真正写回会话历史需要一个**改写后端**。两个后端里必须装好并选中一个,否则总开关会被强制关闭并锁定。
40
+ 本插件只负责"算出压缩版";把压缩版交给会话需要一个**改写后端**。三个后端里选中一个,否则总开关会被强制关闭并锁定;其中 `derive` 不需要任何安装或补丁。
41
+
42
+ **怎么选:**
43
+
44
+ - **能打补丁、也愿意给 DSH 源码打补丁 → 优先 `in-place`**:最干净,不新建会话、不产生分支。
45
+ - **不能或不想打补丁(例如打包版 dsh-desktop)→ 用 `derive`(无写入)**:不需要安装,只在本插件内存里替换,重启后靠 sidecar 记录继续生效。
46
+ - `message-edit` **仅作实验性场景,不推荐**:它是分支型后端,会缩小可用场景(不能承接委派、子代理开关会被锁、有后台工作的会话默认不压缩),每压缩一次还多一个分支会话。
47
+
48
+ 下面按这个推荐顺序说明:`derive`、`in-place`、`message-edit`。
49
+
50
+ ### 无写入后端 `derive`(仅内存替换)
51
+
52
+ - 不需要安装任何东西,也不需要宿主补丁或第三方插件:它直接使用本插件在把历史交给模型前的那层**派生消息包裹器**,在内存里把思考块换成压缩版。
53
+ - 好处:**打包版 DSH(例如 dsh-desktop)也能用**;不改会话日志、不建分支,也不在会话里留下写入痕迹。
54
+ - 压缩记录照旧保存在会话日志旁边的 sidecar 文件里,**重启不会丢**:插件重新加载记录后,会继续在每次请求前把思考块替换成压缩版。只有插件被停用、卸载或记录被删除时,才没有东西执行替换,模型才会回到原文。
55
+ - **对话页面显示的是会话日志里的原文**:该模式不写历史,所以对话页面/原生对话界面里看到的始终是原始思考,压缩后的内容只出现在本插件的「思考压缩」报告与账本里。但模型每次请求实际收到的是压缩版,**页面上的原文不等于模型看到的内容**。
56
+ - 唯一会退回原文的情况:**冷启动时 sidecar 读不出来**。插件不会因此阻塞对话,该会话的请求会暂时带原始思考(日志里会明确警告),记录恢复可读后自动重新应用。
57
+ - 报告、节省统计、触发规则、上下文占用闸门等其余功能与其它后端一致。
41
58
 
42
59
  ### 内置原位后端(in-place)与宿主补丁(首选)
43
60
 
@@ -46,7 +63,7 @@
46
63
  - 好处:不新建分支、不产生额外会话,对话列表和归档列表保持干净。
47
64
  - 风险:这是修改 DSH 本体源码的补丁。**DSH 跨版本升级很容易出问题**——补丁按字面锚点匹配,任何一处对不上就整体拒绝,不会写一半。升级 DSH 前建议先回退,升级后再用 `--check` 复查、必要时重打;打不上就用 `--checkout <DSH 源码目录>` 指路,不要手工改宿主源码。
48
65
  - 打完补丁需要重启 `dsh web` 才生效。回退:`node scripts/dsh-inplace-patch.mjs --revert --build`。
49
- - **打包版 DSH 用不了这个后端**:像 dsh-desktop 这类把 harness 装成只读、只有 `node_modules` 而没有源码的安装,没有可写的源码树可以打补丁;这类安装请用 message-edit。
66
+ - **打包版 DSH 用不了这个后端**:像 dsh-desktop 这类把 harness 装成只读、只有 `node_modules` 而没有源码的安装,没有可写的源码树可以打补丁;这类安装请用 `derive` 或 message-edit。
50
67
 
51
68
  #### 经过测试的 DSH 版本
52
69
 
@@ -57,21 +74,22 @@
57
74
  | 已知可运行 in-place | `0.2.1-alpha.1`、`0.2.1-alpha.5` | alpha.1 是本插件开发机(补丁已长期在真实会话中使用);alpha.5 是反馈该问题的用户所在版本,补丁与插件均确认可用 |
58
75
  | 完整启动 | `0.2.1-rc.1` | 独立 clone 全量构建后装入插件并启动 `web`,插件的安装页与报告页路由都能正常应答 |
59
76
  | 补丁 + 类型 + 语义 | `0.2.0-rc.1`、`0.2.0-rc.2`、`0.2.1-alpha.1`~`0.2.1-alpha.5`、`0.2.1-rc.1` | 独立 clone 上逐版本 `--apply` → `--check` → `--revert`(回退后工作树逐字节干净)、打过补丁的包 `tsc -b` 通过、持久化探针 `scripts/probe-inplace-durability.mjs` 通过(none 与 zstd)、插件依赖的宿主 API 兼容探针通过 |
77
+ | 等价核对 | `0.2.1-rc.2` | 6 个补丁目标文件与公开 API catalog 和 `0.2.1-rc.1` 逐字节相同,故上一行对 rc.1 的全部结论直接适用 |
60
78
 
61
79
  - 也就是说:**在 0.2.x 范围内,in-place 补丁与插件的宿主 API 都有逐版本实测依据**;其中 `0.2.1-alpha.1` 与 `0.2.1-alpha.5` 已知可正常运行 in-place,完整启动验证过的是 `0.2.1-rc.1`。其余版本请先在可回退的环境里试。
62
80
  - 版本差异最大的一处:`packages/session/session-persistence-jsonl/src/storage.ts` 的 `install()` 从 `0.2.1-alpha.3` 起改成了 generator effect + 闭包变量(`writers` 取代 `this.writers`,在 generator 内部 `this` 已不是那个实例)。补丁脚本为此处带**两份锚点**,会按宿主实际形态自动选择匹配的那份。
63
81
  - `scripts/probe-inplace-durability.mjs` 同时适配了 jsonl 后端的两种导出形态:`0.2.1-alpha.2` 及以前 default export 提供者类,`0.2.1-alpha.3` 起是 `name` + `apply` 的 Cordis 插件。
64
82
 
65
- ### 旧后端 `message-edit`(保留兼容,不推荐)
83
+ ### 旧后端 `message-edit`(实验性,不推荐)
66
84
 
67
85
  - 这是**其他开发者发布的第三方插件**:<https://github.com/Moeblack/dsh-message-edit>。
68
- - 本仓库在开发初期引入它,只作为**不想给 DSH 本体打补丁时的临时体验后端**,不推荐长期使用。
86
+ - 本仓库在开发初期引入它,仅作为**实验性后端**保留:它会让可用场景反而变少,不推荐日常使用。
69
87
  - 它的做法是每次压缩都新建一个分支会话。由此带来几个限制:
70
88
  - **每压缩一次就多出一个分支会话**,很快会堆满对话列表或归档列表,需要自己清理。
71
89
  - 它是分支型后端,**不能承接委派**:选中它时两条子代理开关会被强制关闭并锁定;再加上默认「有后台工作/子代理时不压缩」,因此**在有后台任务或子代理的会话里无法使用**。
72
90
  - 当前**测试不充分**,行为不保证。
73
91
  - 本仓库通过 `vendor/dsh-message-edit-0.2.3-patched4.tgz` 加 `scripts/patch-message-edit.py` 来安装与修补它;装完同样要重启 `dsh web`。
74
- - 它是**打包版 DSH(例如 dsh-desktop)唯一可用的后端**:只装进 profile,不需要给宿主打补丁。
92
+ - 打包版 DSH(例如 dsh-desktop)优先用无需安装的 `derive`;message-edit 只作为实验性备选。
75
93
 
76
94
  #### (旧)`message-edit` 后端安装流程
77
95
 
@@ -120,9 +138,9 @@ scripts/install.sh web
120
138
 
121
139
  `scripts/install.sh` 做三件事:构建插件、把 profile 共享的 `@deepseek-ai/*` 运行时软链进插件、用官方 CLI 把本插件加进 profile。注意:之后只要重跑过 `npm install`(任何依赖变化),脚本建的软链会被清掉,需要重新执行一次 `scripts/install.sh`。
122
140
 
123
- ### 2. 装好并选中一个后端
141
+ ### 2. 装好并选中一个后端(选 `derive` 可跳过安装)
124
142
 
125
- 打开「设置 → 思考压缩 → 快速安装后端」,选好后端后可以:
143
+ 如果打算用 `derive`,不需要安装任何东西,直接在设置里选中即可。否则打开「设置 → 思考压缩 → 快速安装后端」,选好后端后可以:
126
144
 
127
145
  - **用脚本安装**:走本仓库验证过的固定流程,可复现、有逐步进度、随时取消,装完自动校验;
128
146
  - **让 agent 安装**:会把对应的安装提示词填进一个新会话的输入框,发不发由你决定。
@@ -140,7 +158,7 @@ node scripts/dsh-inplace-patch.mjs --check # 打全了输出 PATCHED
140
158
 
141
159
  ### 3. 启用
142
160
 
143
- 在「设置 → 思考压缩」里:选中一个已安装的后端 → 打开「启用思考压缩」。之后按需调整下面的配置。
161
+ 在「设置 → 思考压缩」里:选中一个后端(`derive` 无需安装,选中即用)→ 打开「启用思考压缩」。之后按需调整下面的配置。
144
162
 
145
163
  ---
146
164
 
@@ -153,7 +171,7 @@ node scripts/dsh-inplace-patch.mjs --check # 打全了输出 PATCHED
153
171
  | 选项 | 含义 |
154
172
  | --- | --- |
155
173
  | 启用思考压缩(`enabled`) | 总开关,默认关。没有选择后端时强制关闭并锁定。 |
156
- | 助手消息改写后端(`rewriteBackend`) | 单选,只列出已安装的后端;再次点击已选中的那一项可以取消选择。 |
174
+ | 助手消息改写后端(`rewriteBackend`) | 单选,只列出可用的后端;再次点击已选中的那一项可以取消选择。`in-place` 需要宿主补丁,`message-edit` 需要第三方插件,`derive` 不需要任何安装(仅内存替换,不写回历史)。 |
157
175
 
158
176
  ### 规则(分为"默认规则"和"逐模型规则")
159
177
 
@@ -194,7 +212,7 @@ node scripts/dsh-inplace-patch.mjs --check # 打全了输出 PATCHED
194
212
 
195
213
  | 选项 | 含义 |
196
214
  | --- | --- |
197
- | 蒸馏提示词(`prompt`) | 替换内置的压缩指令;留空 = 使用内置提示词(可点"预览内置提示词"查看)。内置提示词明确要求保留原思考中正确且有效的推理过程:可以压缩措辞、合并重复,但不能省掉推导步骤直接给结论,重放后的思考要能沿着同一条路径推出同样的结论。 |
215
+ | 蒸馏提示词(`prompt`) | 替换内置的压缩指令;留空 = 使用内置提示词(可点"预览内置提示词"查看)。内置提示词要求保留原思考中正确且有效的推理过程:可以压缩措辞、合并重复,但不能省掉推导步骤直接给结论;还要保留**被否定的方向及其原因**("X 被否决,因为 Y"),让后续轮次不会重新走进同一条错误路线。 |
198
216
 
199
217
  ### 模型价格与峰谷时段
200
218
 
@@ -208,8 +226,8 @@ node scripts/dsh-inplace-patch.mjs --check # 打全了输出 PATCHED
208
226
 
209
227
  ### 报告里的几个数字
210
228
 
211
- - **当前单次请求减量**:当前生效的改写让**这一次**请求少带的估算 token,是存量而不是累计;改写被整段压缩淘汰后相应减少,全部淘汰归零。
212
- - **历史累计节省**:永不重置。
229
+ - **当前单次请求减量**:当前这一轮(用户发下一条消息之前)里,下一次请求会少带的估算 token,是存量而不是累计;改写被整段压缩淘汰后相应减少,全部淘汰归零。用户发新消息后归零,因为新的一轮不会重放上一轮的思考。
230
+ - **历史累计节省**:永不重置,但只统计**产出压缩的那一轮**里、用户发下一条消息之前后续请求的重放;跨轮次的重放不计入(DeepSeek 的 API 不参考之前轮次的 reasoning_content)。
213
231
  - **净收益** = 历史累计节省 − 蒸馏开销 − 缓存断裂开销。
214
232
  - **最近一步未触发的原因**:面板会直接给出(总开关关、未选择后端、规则关、未到阈值、上下文占用超过上限、这一步没有思考、有多个思考块、有后台工作在跑等)。
215
233
  - **压缩会话**:每次蒸馏都会开一个旁路会话,用来查看这次压缩的提示词与回答。它**只存在于内存里、不写盘**:本次运行期间可以点开,重启后自动过期,报告里会显示"会话已随上次运行结束(内容见下方明细)"——完整内容本来就在明细里。
@@ -60,31 +60,38 @@ window.__ModuleLoader__.load({
60
60
  * @module dsh-reasoning-distill/backends
61
61
  */
62
62
  /** Backends this plugin knows how to drive, in panel order. */
63
- const REWRITE_BACKENDS = [{
64
- id: "message-edit",
65
- kind: "branch",
66
- plugin: "dsh-message-edit",
67
- probe: {
68
- method: "POST",
69
- path: "/message-edit",
70
- body: {
71
- action: "edit",
72
- sessionId: "",
73
- eventSeq: 0,
74
- blockIndex: 0,
75
- text: "probe"
63
+ const REWRITE_BACKENDS = [
64
+ {
65
+ id: "derive",
66
+ kind: "derive"
67
+ },
68
+ {
69
+ id: "in-place",
70
+ kind: "in-place",
71
+ hostPatch: true,
72
+ probe: {
73
+ method: "POST",
74
+ path: REWRITE_ROUTE,
75
+ body: { probe: true }
76
+ }
77
+ },
78
+ {
79
+ id: "message-edit",
80
+ kind: "branch",
81
+ plugin: "dsh-message-edit",
82
+ probe: {
83
+ method: "POST",
84
+ path: "/message-edit",
85
+ body: {
86
+ action: "edit",
87
+ sessionId: "",
88
+ eventSeq: 0,
89
+ blockIndex: 0,
90
+ text: "probe"
91
+ }
76
92
  }
77
93
  }
78
- }, {
79
- id: "in-place",
80
- kind: "in-place",
81
- hostPatch: true,
82
- probe: {
83
- method: "POST",
84
- path: REWRITE_ROUTE,
85
- body: { probe: true }
86
- }
87
- }];
94
+ ];
88
95
  /**
89
96
  * Whether a probe response proves the backend is installed.
90
97
  *
@@ -224,6 +231,7 @@ window.__ModuleLoader__.load({
224
231
  }
225
232
  };
226
233
  }
234
+ if (backend.kind === "derive") return;
227
235
  if (backend.id === "message-edit") {
228
236
  if (entry.targetBlockIndex < 0) return void 0;
229
237
  return {
@@ -309,9 +317,10 @@ window.__ModuleLoader__.load({
309
317
  "view.branchCreated": "已创建分支",
310
318
  "view.branchKept": "已按原会话继续",
311
319
  "settings.backend": "助手消息改写后端(单选)",
312
- "settings.backendHint": "只列出已安装的后端;未选的置灰。再次点击已选中的后端可取消选择。没有选择后端时无法把改写写回会话历史,因此「启用思考压缩」会强制关闭并锁定。",
320
+ "settings.backendHint": "只列出可用的后端;未选的置灰。再次点击已选中的后端可取消选择。没有选择后端时无法把改写交给会话历史,因此「启用思考压缩」会强制关闭并锁定。优先顺序:能打补丁就用 in-place,否则用 derive;message-edit 仅实验性,会缩小可用场景,不推荐。derive 只在本插件内存里替换思考,不写回宿主历史:压缩记录存在 sidecar 里,重启后仍会生效,只有停用/卸载或删除记录才会恢复原文;对话页面显示会话日志里的原文,模型实际收到的是压缩版。不需要宿主补丁或第三方插件。",
313
321
  "settings.backendBranch": "另开分支会话",
314
322
  "settings.backendInPlace": "就地改写模型可见历史",
323
+ "settings.backendDerive": "仅内存替换(不写回历史)",
315
324
  "settings.backendInstalled": "已安装",
316
325
  "settings.backendMissing": "未安装",
317
326
  "settings.backendPlaceholder": "占位(尚未实现,不可选)",
@@ -527,9 +536,10 @@ window.__ModuleLoader__.load({
527
536
  "view.branchCreated": "Branch created",
528
537
  "view.branchKept": "the original conversation carried on",
529
538
  "settings.backend": "Assistant-rewrite backend (one)",
530
- "settings.backendHint": "Only installed backends are listed; the rest are greyed out. Clicking the selected one again clears the choice. With no backend nothing can write a rewrite back into the history, so the master switch is forced off and locked.",
539
+ "settings.backendHint": "Only available backends are listed; the rest are greyed out. Clicking the selected one again clears the choice. With no backend nothing can hand a rewrite to the history, so the master switch is forced off and locked. Preference order: use in-place when the host can be patched, otherwise derive; message-edit is experimental and narrows the usable scenarios, so it is not recommended. derive replaces reasoning only inside this plugin (no history write). The compression record is kept in the sidecar and re-applied after a restart; only disabling/uninstalling the plugin or deleting the record restores the original. The conversation page keeps showing the original text from the log while the model receives the compressed version. It needs neither a host patch nor a third-party plugin.",
531
540
  "settings.backendBranch": "opens a branch session",
532
541
  "settings.backendInPlace": "rewrites the model-visible history in place",
542
+ "settings.backendDerive": "in-memory replacement (no history write)",
533
543
  "settings.backendInstalled": "installed",
534
544
  "settings.backendMissing": "not installed",
535
545
  "settings.backendPlaceholder": "placeholder (not implemented yet, not selectable)",
@@ -1359,49 +1369,49 @@ window.__ModuleLoader__.load({
1359
1369
  document.head.appendChild(tag);
1360
1370
  }
1361
1371
  var Settings_module_css_default = {
1362
- "logBox": "jP3NOa_logBox",
1363
- "modalHead": "jP3NOa_modalHead",
1364
- "holidayBox": "jP3NOa_holidayBox",
1365
- "pickerItem": "jP3NOa_pickerItem",
1372
+ "rule": "jP3NOa_rule",
1373
+ "route": "jP3NOa_route",
1374
+ "search": "jP3NOa_search",
1375
+ "picker": "jP3NOa_picker",
1376
+ "modeCard": "jP3NOa_modeCard",
1377
+ "installEntry": "jP3NOa_installEntry",
1378
+ "prompt": "jP3NOa_prompt",
1366
1379
  "section": "jP3NOa_section",
1367
- "iconButton": "jP3NOa_iconButton",
1380
+ "field": "jP3NOa_field",
1381
+ "error": "jP3NOa_error",
1382
+ "priceGrid": "jP3NOa_priceGrid",
1383
+ "modalBody": "jP3NOa_modalBody",
1384
+ "pickerPanel": "jP3NOa_pickerPanel",
1368
1385
  "peakBox": "jP3NOa_peakBox",
1369
- "picker": "jP3NOa_picker",
1386
+ "capBox": "jP3NOa_capBox",
1370
1387
  "muted": "jP3NOa_muted",
1371
- "modalBackdrop": "jP3NOa_modalBackdrop",
1372
- "checks": "jP3NOa_checks",
1388
+ "note": "jP3NOa_note",
1389
+ "pickerItem": "jP3NOa_pickerItem",
1390
+ "modalHead": "jP3NOa_modalHead",
1391
+ "installBlock": "jP3NOa_installBlock",
1392
+ "header": "jP3NOa_header",
1393
+ "badge": "jP3NOa_badge",
1373
1394
  "installProgress": "jP3NOa_installProgress",
1374
- "itemBody": "jP3NOa_itemBody",
1375
- "search": "jP3NOa_search",
1376
- "error": "jP3NOa_error",
1377
- "capBox": "jP3NOa_capBox",
1378
- "item": "jP3NOa_item",
1395
+ "modeCards": "jP3NOa_modeCards",
1396
+ "logBox": "jP3NOa_logBox",
1397
+ "modalBackdrop": "jP3NOa_modalBackdrop",
1398
+ "log": "jP3NOa_log",
1399
+ "modal": "jP3NOa_modal",
1400
+ "backendOptions": "jP3NOa_backendOptions",
1401
+ "page": "jP3NOa_page",
1379
1402
  "primary": "jP3NOa_primary",
1403
+ "iconButton": "jP3NOa_iconButton",
1404
+ "holidayBox": "jP3NOa_holidayBox",
1405
+ "itemBody": "jP3NOa_itemBody",
1406
+ "checks": "jP3NOa_checks",
1407
+ "actions": "jP3NOa_actions",
1408
+ "steps": "jP3NOa_steps",
1409
+ "preview": "jP3NOa_preview",
1380
1410
  "secondary": "jP3NOa_secondary",
1381
- "header": "jP3NOa_header",
1382
- "installBlock": "jP3NOa_installBlock",
1383
1411
  "toggle": "jP3NOa_toggle",
1384
- "modeCard": "jP3NOa_modeCard",
1385
- "log": "jP3NOa_log",
1386
- "installEntry": "jP3NOa_installEntry",
1387
- "actions": "jP3NOa_actions",
1388
- "pickerPanel": "jP3NOa_pickerPanel",
1389
- "badge": "jP3NOa_badge",
1412
+ "item": "jP3NOa_item",
1390
1413
  "sectionHeading": "jP3NOa_sectionHeading",
1391
- "priceGrid": "jP3NOa_priceGrid",
1392
- "field": "jP3NOa_field",
1393
- "preview": "jP3NOa_preview",
1394
- "backendOptions": "jP3NOa_backendOptions",
1395
- "rule": "jP3NOa_rule",
1396
- "modal": "jP3NOa_modal",
1397
- "pickerList": "jP3NOa_pickerList",
1398
- "modalBody": "jP3NOa_modalBody",
1399
- "steps": "jP3NOa_steps",
1400
- "note": "jP3NOa_note",
1401
- "modeCards": "jP3NOa_modeCards",
1402
- "prompt": "jP3NOa_prompt",
1403
- "route": "jP3NOa_route",
1404
- "page": "jP3NOa_page"
1414
+ "pickerList": "jP3NOa_pickerList"
1405
1415
  };
1406
1416
  //#endregion
1407
1417
  //#region src/client/InstallBackend.tsx
@@ -1822,8 +1832,15 @@ window.__ModuleLoader__.load({
1822
1832
  };
1823
1833
  };
1824
1834
  for (const backend of REWRITE_BACKENDS) {
1835
+ if (backend.placeholder === true) continue;
1825
1836
  const route = backend.probe;
1826
- if (route === void 0) continue;
1837
+ if (route === void 0) {
1838
+ if (alive) setAvailable((current) => ({
1839
+ ...current,
1840
+ [backend.id]: true
1841
+ }));
1842
+ continue;
1843
+ }
1827
1844
  probe(route.path, route.body).then(async (answer) => {
1828
1845
  const absent = await probe(`${route.path}-absent`, route.body);
1829
1846
  if (alive) setAvailable((current) => ({
@@ -1860,7 +1877,7 @@ window.__ModuleLoader__.load({
1860
1877
  ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
1861
1878
  backend.id,
1862
1879
  " · ",
1863
- backend.kind === "branch" ? t("settings.backendBranch") : t("settings.backendInPlace")
1880
+ backend.kind === "branch" ? t("settings.backendBranch") : backend.kind === "derive" ? t("settings.backendDerive") : t("settings.backendInPlace")
1864
1881
  ] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1865
1882
  className: Settings_module_css_default.muted,
1866
1883
  children: installed ? t("settings.backendInstalled") : backend.hostPatch === true ? t("settings.backendNeedsPatch") : t("settings.backendMissing")
@@ -2834,41 +2851,41 @@ window.__ModuleLoader__.load({
2834
2851
  document.head.appendChild(tag);
2835
2852
  }
2836
2853
  var View_module_css_default = {
2837
- "facts": "_7CZWHG_facts",
2838
- "popupHead": "_7CZWHG_popupHead",
2839
- "header": "_7CZWHG_header",
2840
- "entry": "_7CZWHG_entry",
2841
- "actions": "_7CZWHG_actions",
2842
- "blockedBanner": "_7CZWHG_blockedBanner",
2843
- "popupFacts": "_7CZWHG_popupFacts",
2844
- "metric": "_7CZWHG_metric",
2845
- "iconButton": "_7CZWHG_iconButton",
2846
- "activityDotBlocked": "_7CZWHG_activityDotBlocked",
2847
- "secondary": "_7CZWHG_secondary",
2848
2854
  "note": "_7CZWHG_note",
2855
+ "entry": "_7CZWHG_entry",
2856
+ "textBlock": "_7CZWHG_textBlock",
2857
+ "popup": "_7CZWHG_popup",
2858
+ "page": "_7CZWHG_page",
2849
2859
  "popupList": "_7CZWHG_popupList",
2850
- "summary": "_7CZWHG_summary",
2860
+ "facts": "_7CZWHG_facts",
2861
+ "entryBody": "_7CZWHG_entryBody",
2862
+ "negative": "_7CZWHG_negative",
2851
2863
  "activityDot": "_7CZWHG_activityDot",
2852
- "sessionInfo": "_7CZWHG_sessionInfo",
2853
2864
  "activityLabel": "_7CZWHG_activityLabel",
2865
+ "blockedBanner": "_7CZWHG_blockedBanner",
2866
+ "muted": "_7CZWHG_muted",
2867
+ "activityDotBlocked": "_7CZWHG_activityDotBlocked",
2868
+ "entryTitle": "_7CZWHG_entryTitle",
2869
+ "activity": "_7CZWHG_activity",
2870
+ "popupHead": "_7CZWHG_popupHead",
2854
2871
  "activityWhy": "_7CZWHG_activityWhy",
2855
- "error": "_7CZWHG_error",
2856
2872
  "positive": "_7CZWHG_positive",
2857
2873
  "section": "_7CZWHG_section",
2874
+ "metric": "_7CZWHG_metric",
2875
+ "error": "_7CZWHG_error",
2876
+ "actions": "_7CZWHG_actions",
2877
+ "popupActions": "_7CZWHG_popupActions",
2878
+ "iconButton": "_7CZWHG_iconButton",
2858
2879
  "rdPulse": "_7CZWHG_rdPulse",
2859
- "entryBody": "_7CZWHG_entryBody",
2860
- "muted": "_7CZWHG_muted",
2861
- "page": "_7CZWHG_page",
2862
- "sessionRow": "_7CZWHG_sessionRow",
2863
- "negative": "_7CZWHG_negative",
2864
2880
  "headerTrigger": "_7CZWHG_headerTrigger",
2865
- "popup": "_7CZWHG_popup",
2881
+ "activeRow": "_7CZWHG_activeRow",
2882
+ "popupFacts": "_7CZWHG_popupFacts",
2883
+ "summary": "_7CZWHG_summary",
2866
2884
  "popupRow": "_7CZWHG_popupRow",
2867
- "popupActions": "_7CZWHG_popupActions",
2868
- "textBlock": "_7CZWHG_textBlock",
2869
- "entryTitle": "_7CZWHG_entryTitle",
2870
- "activity": "_7CZWHG_activity",
2871
- "activeRow": "_7CZWHG_activeRow"
2885
+ "sessionInfo": "_7CZWHG_sessionInfo",
2886
+ "secondary": "_7CZWHG_secondary",
2887
+ "sessionRow": "_7CZWHG_sessionRow",
2888
+ "header": "_7CZWHG_header"
2872
2889
  };
2873
2890
  //#endregion
2874
2891
  //#region src/client/ActivityChip.tsx