dsh-xdpool 2.5.0 → 2.5.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/CHANGELOG.md +41 -52
- package/README.en.md +11 -2
- package/README.md +12 -3
- package/assets/community-qr.png +0 -0
- package/cordis.patch.yml +17 -41
- package/lib/bin.js +194 -30
- package/lib/client.js +285 -774
- package/lib/index.d.ts +54 -82
- package/lib/index.js +276 -409
- package/package.json +1 -4
- package/vendor/channel-pack/pack.js +8 -124
package/CHANGELOG.md
CHANGED
|
@@ -1,78 +1,73 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
本项目的所有重要变更都会记录在此文件。
|
|
3
3
|
版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
|
|
4
|
+
## 2.5.1 — 六张 issue、一个交流群入口,外加拿掉 billion-context
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
> 2.5.0 之后收到的反馈集中在两类:**看得见却点不动的界面**(链不显示、单选互顶、卡片空白),和**说错话的报错**(额度已用尽、密钥无效、为预留让你调低预留)。这一版把这两类都按「根因 + 可复现断言」的方式收掉,同时按你的要求移除了 billion-context 那一页,并在「点Star」旁边加了「交流群」。
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
### 修掉六张 issue
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
**#99 路由页有链却不显示,保存还会把链删掉**
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
| --- | --- |
|
|
13
|
-
| 一个失效账号吃掉整次请求的 8 次重试,最后报「API 密钥无效」 | 以「刷新拿到了新 token」判定账号仍可用。有一类账号 refresh 长期有效、chat 恒回 403,判死条件因此恒假 |
|
|
14
|
-
| buddy 某一轮被中断后,之后每一轮都失败(`a message has empty content`) | 中断留下的 assistant 消息只有 reasoning、没有正文,序列化时空字符串被原样发到 wire,国内网关 400/11151 且不在重试集合里 |
|
|
15
|
-
| zcode 全部模型勾选后,每次重启又变回全禁用 | 用户全开时黑名单是空对象,与「从未选过」无法区分,启动补静音据此又把它们全关一遍 |
|
|
16
|
-
|
|
17
|
-
### #68 失效账号耗尽重试预算
|
|
18
|
-
|
|
19
|
-
池车道以「刷新成功」当「账号可用」。对 refresh 长期有效而业务侧恒 403 的账号,`recovered` 与 `accessToken !== before` 恒真 ⇒ 永不 `penalizeCredentialDead` ⇒ `available()` 不排除 ⇒ `priority` 下 `acquire()` 一直返回同一个 ⇒ 8 次预算全花在它身上。
|
|
20
|
-
|
|
21
|
-
改法:单次请求内只允许该账号换一次票(`refreshedThisRequest`),第二次仍报 `session_dead` 就直接判死并轮到下一个账号。压缩重试路径同步。取「第二次」而不是把惩罚提到刷新之前,是为了仍给真正过期的 token 一次机会。
|
|
22
|
-
|
|
23
|
-
### #70 侧栏入口开关
|
|
24
|
-
|
|
25
|
-
新增 `sidebarRow` 配置(默认开)。**只**控制左侧栏那一行:设置页的 XD Pool 卡片始终注册,模型池不受影响 —— 关掉入口不能把开关本身也锁在门外。开关写在卡片里,`apply()` 与卡片读同一份设置镜像,因此两边不会给出不同答案;宿主发布了变更通知的平台上无需重启。
|
|
12
|
+
`setDrafts(prev => seeded.current ? prev : …)` 把守卫放进了函数式更新回调,紧接着一行同步 `seeded.current = true`。React 的回调在提交阶段才跑,那时标志位已经是 `true`,于是恒走 `prev` 分支 —— 初始值 `[]` 原样返回。列表恒空,而保存提交的是整张表,**第一次保存就把服务端那条链覆盖成空**。
|
|
26
13
|
|
|
27
|
-
|
|
14
|
+
改成同步判断再置位(与同项目 `GatewayPage.tsx` 同形)。回归用例现在连「形状」一起锁:不许再出现 `setDrafts(prev => seeded …)`。
|
|
28
15
|
|
|
29
|
-
|
|
16
|
+
**#101 国内版/国际版的「1M」互相顶掉**
|
|
30
17
|
|
|
31
|
-
`
|
|
18
|
+
两张区域卡同时挂载(折叠面板用 `hidden`,不是卸载),预算单选 `name` 只用了 `budget-${model.id}`,同名即同组,浏览器只保留最后一个 `checked`。后渲染的国际版把国内版的黑点顶掉,表现为「点了没保存」。用 `useId()` 给每一行实例加作用域 —— 只加 region 不够,设置页与侧栏可能同时挂载同一区域。
|
|
32
19
|
|
|
33
|
-
|
|
20
|
+
**#102 切回账号池就重拉全部数据(2–4 秒空白)**
|
|
34
21
|
|
|
35
|
-
|
|
22
|
+
页签正文是三选一表达式,切页即卸载,`useState` 随之清零;而且 `load()` 把 `account.list` / `model.list` / `credits.balances` / `credits.status` 四合一一 `await Promise.all`,让整张卡等唯一走网络的余额查询。
|
|
36
23
|
|
|
37
|
-
|
|
24
|
+
- 快照提到模块作用域,且**写在 `mountedRef` 判据之前**:已经发出去的结果即便在卸载后才回来,仍然落进快照
|
|
25
|
+
- 拆两波:wave1 只问内存里的三项,先把卡画全(余额格写 `…`);wave2 每渠道各自回填
|
|
26
|
+
- `balancePending` 原来被硬编成 `false`,让渲染层那条 `…` 分支成了死代码 —— 现在真正用上了
|
|
27
|
+
- 每次加载带单调序号,旧答案盖不掉新答案
|
|
38
28
|
|
|
39
|
-
|
|
29
|
+
**#95 扫码渠道卡整片空白,且不报错**
|
|
40
30
|
|
|
41
|
-
|
|
31
|
+
`if (entries.length === 0 && error === undefined) return <></>`。而 RPC 桥解析失败时 `provider.status` 回 `ok: false`、映射出空 map、`entries` 为空、`error` 仍是 `undefined` —— **「桥断了」和「没有扫码账号」渲染成同一片空气**。
|
|
42
32
|
|
|
43
|
-
|
|
33
|
+
改成三态:读取中一行字、失败写明原因、成功但确实没有账号才保持安静。
|
|
44
34
|
|
|
45
|
-
|
|
35
|
+
**#98 自动化三处**
|
|
46
36
|
|
|
47
|
-
|
|
37
|
+
- 「体验XX专家」任务族(`expert_use_maidehao` / `douyinyin` / `shangjia_xuanchuan` / `bowangwang`,加同族的 `WorkBuddy_Valorant`)不在 `EVENT_CHAIN_BUILDERS` 里,所以 accept 和 claim 都正常、进度永远 0/1。这批专家**不在市场列表里**,expertId 只存在于任务自己的 `jump_url` 里(percent-encoded deeplink),因此新增 `expertIdFromJumpUrl()`:先解 `deeplink` 参数、再读内层 `expertId`。use 事件保持默认 `craft` 模式 —— `LOCAL`/零成本是 lighthouse 的专属判据。
|
|
38
|
+
- `unavailableReason()` 遇到第一个低于预留的账号就 `return reserve`,后面账号根本没检查。一张 5 账号池里只要有一个长期低于预留线,任何失败都会被归因成 402「调低预留」。改为计数式:`dead`/`cooling`/`disabled` 先报(这些改数字改不好),只有**无可用账号且全部被预留挡住**才报 `reserve`。
|
|
39
|
+
- `automationEarnings` 写入是 fire-and-forget,领取完成到进程退出的窗口里丢账(实测领了 21 个任务,落盘仍是 `credit: 0`)。`persistEarnings()` 改为返回 promise,`runJob` 收尾 `await this.flushEarnings()`。
|
|
48
40
|
|
|
49
|
-
|
|
41
|
+
**#96 免密 lane 全失败,却报「额度已用尽」**
|
|
50
42
|
|
|
51
|
-
|
|
43
|
+
403 指纹拒绝被渲染成宿主自己的措辞,指向「等待」;真正该做的是「升级插件」。新增 `withFreeTierHint()`:先说指纹失配、明确「等待无用,请更新」,再保留 per-conversation 配额这一可能(两者从外部无法区分,不自作聪明)。429 仍走原有的会话配额提示。
|
|
52
44
|
|
|
53
|
-
|
|
45
|
+
### 新增:「交流群」
|
|
54
46
|
|
|
55
|
-
|
|
47
|
+
- 卡片右上角「点Star」旁边多一个「交流群」按钮,点开在原位弹层显示微信群码
|
|
48
|
+
- 底部导航网格从 `1fr auto` 扩成 `1fr auto auto`,否则第二个按钮会掉到标签栏下面
|
|
49
|
+
- 二维码以 data URI 内嵌进 `lib/client.js`:客户端是宿主加载的单个脚本,解析不了包内相对路径,而 `<img>` 加载失败是**静默**的
|
|
50
|
+
- Esc 与点击遮罩都能关;`alt` 写的是操作指引(读屏用户扫不了码)
|
|
51
|
+
- 同一张图放在 `README.md` 与 `README.en.md` 第 13 行(标题与徽章之后),过期了换 `assets/community-qr.png` 并重跑 `tools/make-community-qr.mjs`
|
|
56
52
|
|
|
57
|
-
|
|
53
|
+
### 移除:billion-context
|
|
58
54
|
|
|
59
|
-
|
|
55
|
+
那一页只读观测另一个插件的回环代理。连同 `src/billion.ts`、`src/billion-mount.ts`、`src/client/BillionPage.tsx`、`/plugins/dsh-xdpool/billion` 路由、`POOL_BILLION_PATH` 与两个文档类型、84 个 `billion.*`/`shell.tabBillion` 语言键、`BILLION_CARD_CSS`、`optionalDependencies.billion-context`,以及 `cordis.patch.yml` 里那行长期 `disabled: true` 的条目一起删掉。README 的页面表随之从七页改回六页。
|
|
60
56
|
|
|
61
|
-
|
|
57
|
+
### 一并发布的两个既有改动
|
|
62
58
|
|
|
63
|
-
|
|
59
|
+
- **CodeArts 的输出上限是上限,不是默认值** —— `listModels()` 报 `maxTokens`、`resolveModel()` 报 `defaultMaxTokens`、线上 `max_tokens` 做 `Math.min` clamp。原先 `?? 65536` 只兜底不设界,宿主把别的 provider 的 384000 原样递过来就触发 HTTP-200 的 SSE 错误帧。见 #83 / #69。
|
|
60
|
+
- **第三条内容指纹** —— 「Relative paths resolve from the workspace root」改成过去分词形式,池车道与渠道车道同步。见 #77 / #79。
|
|
64
61
|
|
|
65
|
-
###
|
|
66
|
-
|
|
67
|
-
- **#81([@jmglsi](https://github.com/jmglsi))** 第三条内容指纹:`Relative paths resolve from the workspace root` → `are resolved against the workspace root`。用陈述句的过去分词形式,语义、长度、换行位置都不变,被网关字符串表收录的子串消失。
|
|
68
|
-
- **#84([@Refeain](https://github.com/Refeain))** CodeArts 输出上限见下节。
|
|
62
|
+
### 验证
|
|
69
63
|
|
|
70
|
-
|
|
64
|
+
- 全套 **83 文件 1057 用例全绿**;host 侧 `tsc --noEmit` 干净
|
|
65
|
+
- 新增 6 个测试文件:`billion-removed` / `card-shell`(交流群)/ `channel-pool-loading` / `expert-task-family` / `free-lane-refusal` / `reserve-floor-scope`
|
|
66
|
+
- 交互验证不只做源码断言:`tools/probe-card-render.mjs` 用最小 hook 调度器驱动真实 `PoolShell`,完成「点击 → 重渲染 → 弹层出现 → 二维码 8666 字符 data URI → 遮罩关闭」整条链路
|
|
71
67
|
|
|
72
|
-
|
|
73
|
-
`#71 kimi k3.1 pro 没有响应` 同样只有一句话,且目录里没有 `kimi-k3.1-pro` 这个 id(有 `kimi-k3-1`)。请在 issue 里补一下:是空回复、卡住不动、还是有报错文案。
|
|
68
|
+
Refs #95 #96 #98 #99 #101 #102。
|
|
74
69
|
|
|
75
|
-
|
|
70
|
+
## 附:CodeArts 的输出上限是上限,不是默认值(细节,已并入 2.5.1)
|
|
76
71
|
|
|
77
72
|
> 华为这条链接 65536 能用、131072 就空流,代码里也一直写着这个数字。但它是 `options.maxTokens ?? 65536` —— 只兜底,不设界。
|
|
78
73
|
|
|
@@ -109,7 +104,7 @@ TRAE 与 Cline 早就这么做了(`clampTraeMaxTokens` / `clampClineMaxTokens`
|
|
|
109
104
|
|
|
110
105
|
Refs #83, #69。
|
|
111
106
|
|
|
112
|
-
|
|
107
|
+
## 附:第三条内容指纹 —— 文件引用指引里的 “resolve from the workspace root”(细节,已并入 2.5.1)
|
|
113
108
|
|
|
114
109
|
> 2.4.1/2.4.2 修好的两个指纹管了一周,10 月 28 日又整片 400/11128。这次被点名的不是产品名,而是一句普通说明。
|
|
115
110
|
|
|
@@ -130,12 +125,6 @@ DSH 在 agent 有 `read` 工具时会贡献一段文件引用指引,开头是
|
|
|
130
125
|
### 其他
|
|
131
126
|
- 全套 79 文件 1028 用例(1026 通过 + 2 跳过)。
|
|
132
127
|
|
|
133
|
-
### 验证
|
|
134
|
-
|
|
135
|
-
- 全套 **80 文件 / 1033 用例**(含 #81 的 5 例、#84 的 5 例、本批新增)
|
|
136
|
-
- `pack.js` 每次改动后 `node --check` 通过
|
|
137
|
-
- server `tsc` 0 错;client `tsc` 的 6 条是既存问题(`accounts.ts` / `context-budget.ts` / `free-upstream.ts` 的 Node 类型不匹配),改前改后数量一致
|
|
138
|
-
|
|
139
128
|
## 2.4.6 — 扫码账号每次打开都空白:一份数据卡在两个细节里
|
|
140
129
|
|
|
141
130
|
> 2.4.4/2.4.5 之后侧栏能进、能滚了,但扫码过的渠道在账号池里经常整片空白,重开也一样。磁盘上账号是齐的(`state.json` 里 15 条),所以问题全在读取链。
|
package/README.en.md
CHANGED
|
@@ -7,6 +7,16 @@
|
|
|
7
7
|
<a href="https://github.com/XDTrees/dsh-xdpool/stargazers"><img src="https://img.shields.io/github/stars/XDTrees/dsh-xdpool?style=flat-square" alt="GitHub stars"></a>
|
|
8
8
|
</p>
|
|
9
9
|
|
|
10
|
+
## Join the group
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<img src="assets/community-qr.png" width="300" alt="WeChat group code: XD community group">
|
|
14
|
+
<br>
|
|
15
|
+
<sub>Scan with WeChat to join the <b>XD community group</b>. The code is valid for 7 days; if it has expired, say so in <a href="https://github.com/XDTrees/dsh-xdpool/issues">issues</a> and it will be refreshed.</sub>
|
|
16
|
+
<br>
|
|
17
|
+
<sub>The 交流群 button next to “Star” in the card's top-right corner opens this same code — no need to come back to the README.</sub>
|
|
18
|
+
</p>
|
|
19
|
+
|
|
10
20
|
<p align="center">
|
|
11
21
|
<sub>Download stats still come from the previous package name <code>dsh-workbuddy-xdpool</code> (8,976/month as of 2026-10-12 — every download before the rename; the live shields badge kept getting rate-limited by the npm upstream, hence the snapshot figure). The new <code>dsh-xdpool</code> package accumulates its own stats, and the badge switches back to live data later.</sub>
|
|
12
22
|
</p>
|
|
@@ -17,7 +27,7 @@ English | [中文](./README.md)
|
|
|
17
27
|
|
|
18
28
|
It started as one thing: every account you've signed into the WorkBuddy desktop app, merged into one auto-failing-over pool. An account gets rate-limited or runs out of credits, and the request moves to the next one that works. No picking favourites, no manual import.
|
|
19
29
|
|
|
20
|
-
Then it grew into
|
|
30
|
+
Then it grew into six pages. Beyond the account pool: sign in to thirteen vendors' free models by web or QR, aggregate **76 vendors'** free quotas into one lane, read a usage ledger, chain models together, and expose the pool as a local OpenAI-compatible gateway.
|
|
21
31
|
|
|
22
32
|
| Page | What it does |
|
|
23
33
|
| --- | --- |
|
|
@@ -25,7 +35,6 @@ Then it grew into seven pages. Beyond the account pool: sign in to thirteen vend
|
|
|
25
35
|
| **Login channels** | Thirteen vendors that sign in by web or QR — once, and their free models join the picker |
|
|
26
36
|
| **Aggregate** | 76 vendors' free quotas into one pool (none on by default; a vendor lights up when it has a key) |
|
|
27
37
|
| **Dashboard** | Today's turns, calls, failures, failover rescues, tokens, cache hits, speed |
|
|
28
|
-
| **billion-context** | Read-only view of the local billion-context compressor |
|
|
29
38
|
| **Routing** | Chain several models, in order or round-robin |
|
|
30
39
|
| **Gateway** | Expose the pool as a local OpenAI-compatible endpoint, optionally to your LAN |
|
|
31
40
|
|
package/README.md
CHANGED
|
@@ -7,6 +7,16 @@
|
|
|
7
7
|
<a href="https://github.com/XDTrees/dsh-xdpool/stargazers"><img src="https://img.shields.io/github/stars/XDTrees/dsh-xdpool?style=flat-square" alt="GitHub stars"></a>
|
|
8
8
|
</p>
|
|
9
9
|
|
|
10
|
+
## 先加群
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<img src="assets/community-qr.png" width="300" alt="微信群二维码:XD 交流群">
|
|
14
|
+
<br>
|
|
15
|
+
<sub>微信扫一扫加入 <b>XD 交流群</b>。二维码 7 天内有效;过期了在 <a href="https://github.com/XDTrees/dsh-xdpool/issues">issues</a> 说一声会换新。</sub>
|
|
16
|
+
<br>
|
|
17
|
+
<sub>卡片右上角「点Star」旁边的「交流群」按钮打开的也是这个码 —— 不用回头找 README。</sub>
|
|
18
|
+
</p>
|
|
19
|
+
|
|
10
20
|
<p align="center">
|
|
11
21
|
<sub>下载量统计沿用旧包名 <code>dsh-workbuddy-xdpool</code>(截至 2026-10-12 为 8,976 次/月,改名前的全部下载;shields 的实时徽章常被 npm 上游限流,所以这里用了快照数字)。新包 <code>dsh-xdpool</code> 的统计会随时间累积,之后徽章会换回实时数据。</sub>
|
|
12
22
|
</p>
|
|
@@ -17,7 +27,7 @@
|
|
|
17
27
|
|
|
18
28
|
它从一件事开始——把本机 WorkBuddy 桌面 App 里登录过的**所有账号**合成一个自动容错的池子,哪个号被限流了、积分用光了,请求自动换到下一个能用的号上去。你不用挑号,不用手动导入。
|
|
19
29
|
|
|
20
|
-
|
|
30
|
+
然后它长成了六页:账号池之外,还能扫码登录十三家厂商的免费模型、把 **76 家**厂商的免费额度聚合成一条通道、看用量账本、把几个模型串成链、把池子开成一个本地 OpenAI 兼容网关。
|
|
21
31
|
|
|
22
32
|
| 页面 | 干什么 |
|
|
23
33
|
| --- | --- |
|
|
@@ -25,7 +35,6 @@
|
|
|
25
35
|
| **扫码登录** | 十三家支持网页 / 扫码登录的厂商,登一次,它们的免费模型就进选择器 |
|
|
26
36
|
| **聚合渠道** | 76 家厂商的免费额度接进同一个池(默认一家都不开,填了 key 才亮) |
|
|
27
37
|
| **数据看板** | 今天的轮次、调用、失败、换号救回、token、缓存命中、速度 |
|
|
28
|
-
| **billion-context** | 只读观测本机 billion-context 压缩器的运行状态 |
|
|
29
38
|
| **路由** | 把多个模型串成一条链,按顺序或轮换使用 |
|
|
30
39
|
| **网关** | 把池子开成本地 OpenAI 兼容接口,可转发给局域网其它设备 |
|
|
31
40
|
|
|
@@ -38,7 +47,7 @@
|
|
|
38
47
|
|
|
39
48
|
## 先看几张图
|
|
40
49
|
|
|
41
|
-
**账号池(卡片首页:品牌栏 +
|
|
50
|
+
**账号池(卡片首页:品牌栏 + 六个页面标签,顶部就是用量)**
|
|
42
51
|
|
|
43
52
|

|
|
44
53
|
|
|
Binary file
|
package/cordis.patch.yml
CHANGED
|
@@ -4,45 +4,21 @@
|
|
|
4
4
|
- insert:
|
|
5
5
|
- id: llm-xdpool
|
|
6
6
|
name: dsh-xdpool
|
|
7
|
-
# billion-context is deliberately NOT mounted by this layer.
|
|
8
7
|
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
# in
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
# 1. Addressability. `disabled: true` keeps the row's id resolvable, so a
|
|
27
|
-
# profile that wants to flip it on can do so with one edit instead of
|
|
28
|
-
# inventing a row.
|
|
29
|
-
# 2. It states the decision where the old attempt lived, where the next person
|
|
30
|
-
# to wonder "why doesn't the pool bring up the compressor?" will look.
|
|
31
|
-
# 3. It keeps `bili-native` (billion-context's own row) as the ONLY mount of
|
|
32
|
-
# that module, which is the arrangement that actually works.
|
|
33
|
-
#
|
|
34
|
-
# CONSEQUENCE, STATED PLAINLY
|
|
35
|
-
#
|
|
36
|
-
# A profile that has not installed billion-context sees the billion card report
|
|
37
|
-
# "not installed". That is the honest reading of the facts, and it is already a
|
|
38
|
-
# first-class state on that page — the page distinguishes not-installed from
|
|
39
|
-
# no-answer from ready precisely so this case reads as information rather than
|
|
40
|
-
# as a bug. Installing billion-context remains a decision the user makes; the
|
|
41
|
-
# pool no longer makes it for them.
|
|
42
|
-
#
|
|
43
|
-
# `src/billion-mount.ts` no longer calls `create()` for the same reason: with
|
|
44
|
-
# this row disabled, a runtime create would fight the very row it sits beside.
|
|
45
|
-
# The function still runs — it is what lets the card distinguish
|
|
46
|
-
# already-installed from not-installed — it just never mounts anything.
|
|
47
|
-
- id: billion-context-xdpool
|
|
48
|
-
disabled: true
|
|
8
|
+
# billion-context is gone from this plugin, and so is the row that used to sit
|
|
9
|
+
# here (`billion-context-xdpool`, kept disabled).
|
|
10
|
+
#
|
|
11
|
+
# 2.0.0 inserted that row so a profile without the compressor would get one for
|
|
12
|
+
# free. Measured against a profile that had ALREADY installed billion-context —
|
|
13
|
+
# the normal state for anyone using it, since `bili-native` comes from that
|
|
14
|
+
# plugin's own `dsh.bundle.patch.yml` — the host did not disable the duplicate
|
|
15
|
+
# and did not resolve it to a no-op: it ran the fiber to `failed`, because the
|
|
16
|
+
# plugin registers a cordis service under its own name and a second registration
|
|
17
|
+
# is refused outright (`service "…" has been registered at <…>`). Every user who
|
|
18
|
+
# had installed it got a permanently failed entry, unexplained, pointing at us.
|
|
19
|
+
#
|
|
20
|
+
# The follow-up kept the row, disabled, "for addressability". That was the wrong
|
|
21
|
+
# trade: it left a name in this file for a feature the plugin no longer has, and
|
|
22
|
+
# the page that read it (`billion-context`) is deleted too. Installing the
|
|
23
|
+
# compressor is its own decision, made by installing it — which is the
|
|
24
|
+
# arrangement that always worked.
|