cortico-world-workbuddy 0.3.0 → 0.3.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/CHANGELOG.md CHANGED
@@ -1,5 +1,175 @@
1
1
  # 更新日志
2
2
 
3
+ ## 0.3.5
4
+
5
+ 继续做减法:删掉只在页面挂载时算一次的顶部徽标,避免「顶部当前模型」与「面板里刚选的模型」同屏不一致。
6
+
7
+ ### 删掉的功能
8
+
9
+ - **顶部徽标行整体移除**(当前模型 / 倍率 / 今日积分)。这三个值由 `webUi()` 在挂载时一次性计算,
10
+ 之后既不随点选刷新、也不随限时折扣时段变化,属于「假状态」;对应的真实值分别以
11
+ 模型目录顶部芯片、逐模型倍率列、用量与成本面板为准。
12
+ - 两盏灯(WorkBuddy / 主进程)保留:它们是页面外唯一能一眼判断可用性的信号,
13
+ 主进程的实时状态另有模型目录顶部的只读芯片兜底。
14
+
15
+ ### 安全清单与目录
16
+
17
+ - 安全清单与 WorkBuddy「选择模型」列表逐项对齐(22 → 17):补 `glm-5.3-flashx`、`minimax-m3-pay`
18
+ (显示名 MiniMax-M3)、`kimi-k3.1-pro-highspeed`;把已不存在的 `kimi-k3-1` 换成 `kimi-k3-2`;
19
+ 移除应用选择器不显示、但目录里仍可调用的 8 个 id(`deepseek-v4-flash`、`deepseek-v3-2-volc`、
20
+ `hy3-b`、`hy3-c`、`hy3-x`、`kimi-k2.5`、`minimax-m2.7`、`hunyuan-chat`)。`hunyuan-chat` 在 v3
21
+ 目录里没有 `credits` 字段,倍率无法核验,属于第 2 条原则的例外。
22
+ - `refreshCatalog()` 增加降级保护:v3 接口失败退回 legacy 目录时,如果本地已有 v3 目录就保留它
23
+ (legacy 目录只有 33 个模型、没有促销),避免倍率与限时折扣被一次失败刷新抹掉。
24
+
25
+ ### 用途边界与免责声明
26
+
27
+ - README 新增「用途与边界」一节:**只在你与桌宠 Coo 的文字对话中按需调用**本机已登录的
28
+ WorkBuddy 模型;明确它不是 API 网关、不是批量/自动化工具、不做多账号或凭据共享、
29
+ 不绕过计费,并写明「请勿改造成对第三方开放的模型服务」。
30
+ - README「免责」扩写为四条(设计用途、积分自担、风控由上游裁量、超范围使用后果自负),
31
+ 附 WorkBuddy 服务条款与 AUP 链接;`SECURITY.md` 同步新增 "Scope of use" 一节;
32
+ `package.json` 的 description 也标注「仅用于桌宠文字对话」。
33
+ - `safeOnly` 的配置说明由「22 个」更正为「17 个」,与 0.3.5 的安全清单一致。
34
+
35
+ ### 契约与文档
36
+
37
+ - `contract.mjs` 新增 `!('badges' in ui)`;`contract-regression.mjs` 删除依赖徽标的跨日断言
38
+ (跨日归零仍由提示词变量断言覆盖)。
39
+ - README 介绍段漏掉的「是否启用Workbuddy 开关」描述一并删除(0.3.4 已移除该功能)。
40
+
41
+ ### 测试工具(实机测试中发现并修掉)
42
+
43
+ - `reinstall.ps1`:`pnpm remove` 补 `--store-dir`。全局 pnpm 的 store 与宿主不一致时 remove 会失败,
44
+ 而 add 会因 lockfile 已有同 spec 直接「Already up to date」跳过链接,留下指向不存在目录的坏 junction;
45
+ 现在 remove 失败立即报错退出,不再假装装好。
46
+ - `verify-ui.mjs`:等「今日积分」芯片真正有数字再取值,避免面板首帧读到空串。
47
+
48
+ ## 0.3.4
49
+
50
+ 按复核结论做减法:移除反复「假开启」的「中转站优先」功能,只保留可确认的事实。
51
+
52
+ ### 删掉的功能
53
+
54
+ - **「中转站优先」整体移除**:详情页页签与复选框、`worlds.workbuddy.prefer` 配置、
55
+ `priority` 面板方法(`state` / `set` / `process`)、环境提示词里的「每轮先 `wb_chat`」强制规则、
56
+ 第三盏「中转站优先」灯,以及主进程退出时自动熄灯的逻辑全部删除。`wb_*` 工具改为按需调用:
57
+ Coo 在用户点名 WorkBuddy 或明显更合适时才调用,不再每轮强制消耗积分。
58
+ - **`storage: [{ key: 'workbuddy-catalog' }]` 声明删除**:宿主不再为本扩展生成空的「数据清理」页签。
59
+ - **死代码**:`world.js` 的 `canRelay`、未使用的 `dailyWindowText` / `DEFAULT_SAFE_MODEL` /
60
+ `SAFE_MODEL_IDS` 导入,`wbproc.js` 的 `describeProc`,`upstream.js` 里永远为空的
61
+ `X-User-Id` / `X-Domain` 请求头,一并删除。
62
+
63
+ ### 修正
64
+
65
+ - **主进程状态改为只读**:放在「模型目录」面板顶部(6 秒轮询,状态翻转才推送),不再参与任何开关。
66
+ - **优惠状态判定**:`wb_list_models` 的「生效中 / 即将生效」改用 `promoActiveAt()`,
67
+ 只有徽标、不改价的促销不再被误标成「即将生效」。
68
+ - **环境提示词收敛**:倍率说明改成「模型自身价格 + 本桥接此刻能核实的限时改价(含免费窗口)」,
69
+ 并明确「只挂徽标的优惠可能不改价」;`{{workbuddy.priority}}` 变量与其段落删除。
70
+ - 契约与 UI 验证同步更新:断言没有 `priority` 面板、只有两盏灯、无 `storage`、配置无 `prefer`;
71
+ UI 脚本改为断言页签不含「是否启用 WorkBuddy」与「数据清理」。
72
+
73
+ ## 0.3.3
74
+
75
+ 按 0.3.2 审查结果修复现有功能,不新增模型、面板或上游能力。
76
+
77
+ - **折扣时间**:纯日期 `validFrom` / `validUntil` 按 `schedule.timezone` 的当地午夜解释,
78
+ `validUntil` 包含所写日期的整日;`daily` 省略时区时默认 `Asia/Shanghai`,非法时区仍回退 UTC。
79
+ - **用量准确性**:分段 SSE `usage` 改为逐字段合并,末帧只有 `credit` 时不再丢 token;
80
+ 未回传积分与明确 0 积分分开统计,面板以 `+ ?` 标出未知缺口;账本补记折扣前倍率,
81
+ 并在响应完成时取倍率,避免跨折扣窗口写旧值。
82
+ - **只做减法**:删除未接线的 `usageState(days)`、`spanDays` / `windowDays`;按模型表固定为
83
+ 近 30 天并明确标注,与概览同口径。
84
+ - **开关就绪**:环境提示词与第三盏灯同时检查主进程、登录态和已选模型,模型为空时不再假开启。
85
+ - **卸载清理**:新增显式 `scripts/clean-workbuddy.mjs --check | --clean`,只清本扩展的配置块、
86
+ 三份数据文件与 `.env` 的 `accessToken` 行。普通 `stop()` / 重启不删数据;宿主界面卸载后
87
+ 执行该脚本即可无残留,其他配置和密钥不受影响。
88
+ - 文案只称“本机已登录的 WorkBuddy 客户端”,删除多余的区域版本区分。
89
+
90
+ ## 0.3.2
91
+
92
+ 只桥接本机已登录的 WorkBuddy 桌面端,不再提供区域切换;同时把「用量」面板对齐宿主的
93
+ 「用量与成本」口径。仍然只在本机验证,未推送 / 未发布。
94
+
95
+ ### 删掉的功能
96
+
97
+ - **区域(region)配置整体移除**:`worlds.workbuddy.region`、`WB_REGION_BASE`、区域枚举与
98
+ 对应的上游 / 计费域切换全部删除。扩展现在固定走
99
+ `copilot.tencent.com`(目录 / 对话)与 `www.codebuddy.cn`(积分);自定义 `baseUrl` 仍可用,
100
+ 它同时替换这两个域。README、SECURITY、CHANGELOG、`describe.json`、环境提示词里的相关文案同步删除。
101
+ - 环境提示词不再输出 `workbuddy.region` 变量;`catalog.json` 与账本里也不再写 `region` 字段
102
+ (旧文件里的该字段读入后直接忽略)。
103
+
104
+ ### 修正
105
+
106
+ - **开关可以「假开启」**:`priority/set` 以前只检查主进程,登录态失效或没选模型时也能点亮,
107
+ 结果每轮 `wb_chat` 都失败。现在开启前依次校验主进程、登录态、模型目录,分别返回
108
+ `no-process` / `no-auth` / `no-model`,面板按原因提示;没有选过模型时自动落到
109
+ `preferredSafeModel(safeModelIds())` 并持久化。
110
+ - **环境提示词与实际状态脱节**:`workbuddy.priority` 只有在「开关开 + 主进程在跑 + 已登录」
111
+ 时才输出 `on`,避免提示词命令桌宠调用一个必然失败的通道。
112
+ - `loadTokens()` / `setToken()` 成功时清空 `lastError`,登录态恢复后面板不再挂着旧错误。
113
+ - `usageState(days)` 支持区间参数(0/1/7/30/90,默认 30);`summarize().spanDays` 不再恒为 1。
114
+ - 面板「用量」改名「用量与成本」:区间概览新增失败数、缓存命中、合计 token 与「全部」一行,
115
+ 按模型聚合同样补上失败数与合计 token;数据仍全部来自账本,不新增任何存储。
116
+ - `world.js` 构造器补上漏声明的 `_procConfirm`,删掉 0.3.0 遗留的孤儿 JSDoc。
117
+
118
+ ## 0.3.1
119
+
120
+ 按 0.3.0 审查报告复核并修复(仍只在本机验证,未推送 / 未发布)。
121
+
122
+ ### 高 / 中优先级
123
+
124
+ - **`/v3/config` 401/403 的错误分类(最严重)**:`upstream.js` 把 `kind` 字符串当成
125
+ `WbUpstreamError` 的第二参(`info` 对象)传,错误恒为 `kind='server'`、`status=0`;
126
+ 连锁导致 `models.refresh` 不返回 `noAuth`、`toolChat` 不清 token、前端不提示重新登录。
127
+ 现在传 `{ status: 401|403, kind: 'session_dead' }`;`fetchCatalog` 每次重置认证标记,
128
+ `fetchModelsLegacy` 的 403 也判 `session_dead`。
129
+ - **`dailyUnusable` 恒为 false**:`parseSchedule` 过滤后 `daily` 是 `[]` 而不是 `undefined`,
130
+ 写错的时段会被当成「全天打折」。现在按「上游给了时段但一条都解析不出来」判定,
131
+ 并让该促销按「不生效」处理(宁可少报一次折扣)。
132
+ - **`rediscover` 静默覆盖手动 token**:手动粘贴 token 后点「重新检测」,0.3.0 仍写
133
+ `wb-auto` 把密钥库里的真 token 覆盖掉,重启后丢失。现在只有密钥库里确实是
134
+ `wb-cleared` 登出哨兵、且探测成功时才改写。
135
+ - **「今日积分」跨午夜不归零**:新增 `localDay()` / `rollTodayIfNeeded()`,
136
+ `envPromptVars()` / `webUi()` / `toolChat()` 累加前都翻篇;详情页徽标、环境提示词与
137
+ 用量面板 `summary.totals.today` 从此一致。
138
+ - **发布流程**:Release 不再与 CI 各自监听 `v*` tag。现在 `release.yml` 里 `publish`
139
+ `needs: verify`(同一条流水线跑 contract / 构建 / dist 一致性),CI 校验没过就不会发布;
140
+ `ci.yml` 只负责 push/PR,tag 触发交给 Release。
141
+ - **0.2.x 升级残留**:新增 `scripts/clean-legacy-injection.mjs`(`--check` / `--clean`,
142
+ 幂等、只删本扩展留下的三样东西、绝不覆盖 `index.html` 其他内容)。扩展本体仍
143
+ **一个字节都不改宿主文件**,清理是用户主动跑的一次性迁移工具。
144
+ - **SECURITY.md 自相矛盾**:删掉「下次启动会重新注入」的残句,写清 0.3.0 起不碰宿主、
145
+ 自定义 `baseUrl` 时 token 会发往该主机、可执行文件覆盖两种安装形态。
146
+ - **`refresh()` 死代码**:`WbUpstream.refresh()` 与 `/v2/auth/refresh` 全仓库无调用点,
147
+ README 原理图却列了它。现在删掉未接入的实现与原理图那一行,如实写明
148
+ 「登录态失效 → 重新从本机凭据发现」;`credentials.js` 仍解析 `refreshToken`(不外发),
149
+ chat 请求绝不携带它。
150
+ - **`candidateAppExecutables()` 漏 `WorkBuddy AI.exe`**:桌面端两种安装形态的目录名与
151
+ exe 名都覆盖,另一种形态也能自动解封 at-rest 密钥。
152
+
153
+ ### 低优先级 / 一致性
154
+
155
+ - `wb_chat` 描述补回 "Requires the WorkBuddy desktop app to be running"(`WB_TOOL_DECLS`、
156
+ `definition.js`,`describe.json` 重新生成)。
157
+ - 英文面板不再写已删除的「开始页 Relay first 按钮」;`dist/webui.js` 重新构建。
158
+ - `writeBalance()` 走与账本同一条写队列、临时文件名带 pid;`usageState()` 只在确有
159
+ 超期行时才整文件重写账本。
160
+ - `clearToken` 当下就写 `lastError`(可操作提示不必等重启);`tools()` handler 不再假设
161
+ `args` 一定存在;`offlineChecks()` 与 CI 语法检查覆盖 `scripts/lib/*.mjs`;
162
+ `reinstall.ps1` 删掉空 `if` 死代码。
163
+ - README 统一:CI 是「改跑离线检查」而非「跳过」、三个域名口径、版本号与安装示例。
164
+ - `reinstall.ps1` 的 `npm pack` 不再被误判:Windows PowerShell 5.1 在
165
+ `$ErrorActionPreference='Stop'` 下把 npm 的 stderr `notice` 当 `NativeCommandError` 抛出,
166
+ 于是静默退回手工 tar、绕过 `prepack`(审查报告第 6 条的真正触发点)。现在临时降为
167
+ `Continue` 并按真实退出码判断,打包必走 `prepack`。
168
+ - `contract.mjs` 从 68 条扩到 95 条(+27):新增 `scripts/contract-regression.mjs`
169
+ 承载 0.3.1 回归防线(session_dead 分类与不降级、无效时段不打折、
170
+ rediscover 不覆盖手动 token、跨日归零、两种安装形态、余额快照并发写),
171
+ 并修掉 0.3.0 的断言数量口径(声称「补 25 条」,实际 55→68 只 +13)。
172
+
3
173
  ## 0.3.0
4
174
 
5
175
  **撤除主界面注入,并按复检报告修掉 9 处中优先级问题。**
@@ -63,8 +233,8 @@
63
233
  - **`clearToken` 真的清得掉**:写不清空时返回失败不再是「假成功」;清空后写哨兵 `wb-cleared`,
64
234
  `loadTokens()` 见到哨兵就当作已登出(`rediscover` 才回落到本机凭据库)。
65
235
  - **`/v3/config` 失败不再静默**:非 2xx、空数据、无模型条目分别打警告,方便判断是不是被降级到旧接口。
66
- - **计费域按区域选**:`WbUpstream` 现在接收 `region`,`billingUrl()` 用 `WB_BILLING_BASE[region]`
67
- (以前按域名子串猜,自定义 `baseUrl` 会掉到国际计费域 `www.workbuddy.ai`)。
236
+ - **计费域固定**:`WbUpstream` 的 `billingUrl()` 使用 `WB_BILLING_BASE`
237
+ (早期版本按域名子串猜,自定义 `baseUrl` 时会掉到错误的计费域)。
68
238
  - **SSE 收尾不再丢 usage**:流结束时 `decoder.decode()` 冲刷残留字节,并把最后一段没有换行的 `data:`
69
239
  交给同一解析器 —— 以前末尾那段(正好带 `usage`)会被丢掉。
70
240
  - **429 两种性质分开**:`classifyHttpFailure()` 按文案把「额度耗尽」判成 `hard_credit`,其余 429 才是
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # cortico-world-workbuddy
2
2
 
3
- 把 **本机已登录的 WorkBuddy 客户端**(国内版 / 国际版)的模型桥接进
3
+ 把 **本机已登录的 WorkBuddy 客户端**的模型桥接进
4
4
  [Coopanion](https://github.com/Pal-AI-Lab/Coopanion) 桌宠:Coo 可以直接调用你
5
5
  WorkBuddy 账号里的模型,World 面板里可以浏览模型目录、查看每个模型的
6
- **默认积分倍率**(如 `x0.79`)并点选要用的模型;World 详情页有一个「是否启用Workbuddy」
7
- 开关,打开后桌宠每轮对话都先问 WorkBuddy。
6
+ **默认积分倍率**(如 `x0.79`)并点选要用的默认模型;`wb_*` 工具按需调用,
7
+ 不开启任何「每轮强制走 WorkBuddy」的行为。
8
8
 
9
9
  这是一个 Cortico 的 World 扩展(`kind: world`,`api: 6`),纯 ESM JS、零运行时依赖,
10
10
  面板产物已随包构建好(`dist/webui.js`)。
@@ -14,7 +14,26 @@ WorkBuddy 账号里的模型,World 面板里可以浏览模型目录、查看
14
14
  > 按上游给出的倍率真实扣费;扩展不提供账号、不共享凭据、不绕过计费。
15
15
  > 请自行评估账号风险,官方 WorkBuddy 客户端始终是最安全的选择。
16
16
 
17
- ## 安装(0.3.0,Coopanion 0.2.17 实机验证)
17
+ ## 用途与边界
18
+
19
+ 本扩展只做一件事:在你与桌宠 Coo 进行**文字对话**时,让 Coo 按需调用你**本机已登录的
20
+ WorkBuddy 账号**里的对话模型,并把回答转述给你。
21
+
22
+ 它不是、也不应被当作:
23
+
24
+ - **通用 API 网关 / OpenAI 兼容服务**:扩展不监听端口、不对外提供 HTTP 接口,
25
+ 除宿主内的 Coo 外没有任何调用方;
26
+ - **批量、自动化或爬取工具**:没有批量接口、没有循环调用、没有后台任务,
27
+ 每一次调用都由 Coo 在一次对话中显式发起;
28
+ - **多账号池、凭据共享或转售服务**:只读取本机当前登录态,不收集、不上传、不共享凭据;
29
+ - **绕过计费的手段**:每次 `wb_chat` 都按上游倍率真实扣你自己的积分,
30
+ 扩展不伪造计费、不改写用量、不模拟官方客户端以外的身份。
31
+
32
+ 请勿把本扩展或其组件用于上述任何用途,也不要把它改造成对第三方开放的模型服务。
33
+ 把它接进「每回合强制调用」「多账号轮询」「给别的应用当 API」这类场景,既超出本扩展的设计,
34
+ 也超出 WorkBuddy 服务条款允许的使用范围,风险与后果由使用者自行承担。
35
+
36
+ ## 安装(0.3.5,Coopanion 0.2.17 实机验证)
18
37
 
19
38
  一条命令(推荐,脚本会做完打包、装卸、哈希与版本校验):
20
39
 
@@ -32,7 +51,7 @@ powershell -NoProfile -ExecutionPolicy Bypass -File scripts/reinstall.ps1
32
51
  cd "C:\Users\<你>\AppData\Local\Programs\Coopanion\data\extensions"
33
52
  node "C:\Users\<你>\AppData\Local\Programs\Coopanion\resources\app\node_modules\pnpm\bin\pnpm.cjs" remove cortico-world-workbuddy
34
53
  node "C:\Users\<你>\AppData\Local\Programs\Coopanion\resources\app\node_modules\pnpm\bin\pnpm.cjs" `
35
- add "$env:LOCALAPPDATA\cortico-world-workbuddy\build\cortico-world-workbuddy-0.3.0.tgz" `
54
+ add "$env:LOCALAPPDATA\cortico-world-workbuddy\build\cortico-world-workbuddy-0.3.5.tgz" `
36
55
  --config.strict-dep-builds=false `
37
56
  --store-dir "C:\Users\<你>\AppData\Local\Programs\Coopanion\data\pnpm\store\v11"
38
57
  ```
@@ -43,9 +62,9 @@ powershell -NoProfile -ExecutionPolicy Bypass -File scripts/reinstall.ps1
43
62
 
44
63
  ```json
45
64
  "workbuddy": {
46
- "enabled": true, "region": "cn", "model": "deepseek-v4.1-flash",
65
+ "enabled": true, "model": "deepseek-v4.1-flash",
47
66
  "credentialsDir": "", "baseUrl": "", "maxTokens": 2048,
48
- "envPrompt": true, "prefer": false
67
+ "envPrompt": true
49
68
  }
50
69
  ```
51
70
 
@@ -63,13 +82,25 @@ powershell -NoProfile -ExecutionPolicy Bypass -File scripts/reinstall.ps1
63
82
 
64
83
  ## 卸载与还原
65
84
 
66
- - **只卸扩展**:在「World 扩展」里卸载 / 或 `pnpm remove cortico-world-workbuddy`。
67
- 详情页入口随之消失,桌宠工具表里也不再有 `wb_*`——Coopanion 主体不受影响。
68
- - **不碰宿主文件**:0.3.0 起扩展**不再往 Coopanion 主界面注入任何脚本或按钮**,
69
- `resources\app` 下一个字节都不会被改写,卸载后不需要还原任何东西。
70
- - **旧版本残留**:如果装过 0.2.x,宿主 `build\console\` 里可能还留着 `workbuddy-home.js`
71
- 与 `index.html` 里的一行引用;删掉那个文件、去掉 `index.html` 里
72
- `<script type="module" src="./workbuddy-home.js"></script>` 这一行即可。
85
+ 1. 在「World 扩展」里卸载,或执行 `pnpm remove cortico-world-workbuddy`,然后重启 Coopanion。
86
+ 详情页入口与 `wb_*` 工具随之消失,Coopanion 主体和其他 World 不受影响。
87
+ 2. 宿主的卸载接口只删除扩展包,不会调用扩展清理逻辑,也不会删除部署配置和账本。
88
+ 因此在源码目录再执行一次显式清理(先检查、后清理):
89
+
90
+ ```bash
91
+ node scripts/clean-workbuddy.mjs --check
92
+ node scripts/clean-workbuddy.mjs --clean
93
+ ```
94
+
95
+ 清理范围只有:`config.json` 的 `worlds.workbuddy` 块、`.env` 的 `accessToken` 行
96
+ (真实 token 或 `wb-cleared` / `wb-auto` 哨兵),以及数据目录里的
97
+ `workbuddy-usage.jsonl`、`workbuddy-catalog.json`、`workbuddy-balance.json`。
98
+ 其他配置、其他密钥和宿主文件不动,命令输出也不会显示 token。
99
+ - **不碰宿主程序文件**:0.3.0 起扩展不再往 Coopanion 主界面注入脚本或按钮,
100
+ `resources\app` 不会被改写。普通 `stop()` / 重启不会删除账本;只有上面的显式卸载清理会删。
101
+ - **旧版本残留(0.2.x → 0.3.x)**:装过 0.2.x 的机器,另外执行
102
+ `node scripts/clean-legacy-injection.mjs --check` 并按结果使用 `--clean`,清除旧版留在
103
+ `build\console\` 的注入行、脚本与备份;脚本不覆盖 `index.html` 的其他内容。
73
104
 
74
105
  ## 工作原理
75
106
 
@@ -82,10 +113,9 @@ Coopanion (Coo)
82
113
  ├─ 上游客户端 copilot.tencent.com(对话)/ www.codebuddy.cn(计费)
83
114
  │ ├─ GET /v3/config 模型目录 + 促销(models / modelPromotions / modelTiers)
84
115
  │ ├─ POST /v2/chat/completions 对话(SSE 流式)
85
- │ ├─ POST /v2/auth/refresh 刷新 token(X-Refresh-Token)
86
116
  │ └─ POST /v2/billing/meter/get-user-resource 积分余额(只读)
87
117
  ├─ 工具 wb_list_models / wb_select_model / wb_chat / wb_credits
88
- └─ WebUI 面板 模型目录、账号、是否启用 WorkBuddy(中转站优先)
118
+ └─ WebUI 面板 模型目录(含只读主进程状态)、账号、用量与成本
89
119
  ```
90
120
 
91
121
  - **主进程检测**:桌面端的渲染进程都是主进程的子进程,所以「有 `WorkBuddy.exe`」等价于
@@ -98,34 +128,31 @@ Coopanion (Coo)
98
128
  token 只经 `ctx.storeSecret()` 进部署的密钥库,**不写配置、不进日志、面板只显示掩码**。
99
129
  - **积分倍率**:完全来自上游目录的 `credits` 字段,扩展不写死;刷新后缓存到
100
130
  `workbuddy-catalog.json`,重启不丢。
101
- - **区域**:国内版 `copilot.tencent.com` 与国际版 `www.workbuddy.ai` 是两个上游;
102
- 计费域国内是 `www.codebuddy.cn`。切 `worlds.workbuddy.region` 后重新刷新目录。
131
+ - **登录态失效**:`/v3/config` 返回 401/403 时直接判 `session_dead` 并清掉本次 token;
132
+ 下一次调用重新从本机凭据发现(桌面端自行刷新落盘)。本扩展不调用刷新接口,
133
+ chat 请求也绝不携带 refresh token。
134
+ - **上游**:目录与对话固定走 `copilot.tencent.com`,积分余额走 `www.codebuddy.cn`。
135
+ 本扩展只支持这一套上游(本机已登录的 WorkBuddy 桌面端);配了自定义 `baseUrl` 时两个域都由它替换。
103
136
 
104
- ## 「中转站优先」开关
137
+ ## 主进程状态与按需调用
105
138
 
106
- 一份状态(`worlds.workbuddy.prefer`),一个入口,默认是**关**:
139
+ 0.3.4 起没有「中转站优先」开关,也没有任何「每轮强制走 WorkBuddy」的行为:
107
140
 
108
- | 入口 | 位置 | 行为 |
109
- |---|---|---|
110
- | 详情页开关 | 「World 扩展」→ WorkBuddy 桥接 →「是否启用Workbuddy」 | 勾选=开;取消=关 |
111
-
112
- > 0.3.0 起**不再往主界面「开始」页注入「中转站优先」按钮**(也就不需要改宿主文件)。
113
- > 想快速开关,把它当书签存一下 World 详情页即可。
114
-
115
- - 开 → 环境提示词告诉 Coo:每轮对话先 `wb_chat`(用 `worlds.workbuddy.model`),
116
- 再把回答用自己的话讲出来并说明是哪个模型答的。
117
- - 关 → Coo 完全不碰 `wb_*`(用户明确点名 WorkBuddy 时除外)。
118
- - 打开时若没检测到主进程:不会把开关打开,面板提示「未检测到Workbuddy」。
119
- - 主进程在 6 秒轮询里退出时,开关自动熄灭,避免亮着却调不通。
141
+ - 「模型目录」面板顶部只读显示 WorkBuddy 主进程是否在跑(6 秒轮询,翻转时才推送);
142
+ 勾选框已删除,状态不参与任何开关逻辑。
143
+ - `wb_*` 工具由 Coo 按需调用:用户点名 WorkBuddy、或某个 WorkBuddy 模型明显更合适时才用。
144
+ 不调用就不花积分——这是「每个调用都真实扣积分」的默认前提。
145
+ - 环境提示词只描述事实(登录态、模型、倍率、主进程状态、今日用量)和工具用法,
146
+ 不再命令「每轮先 `wb_chat`」。
147
+ - 主进程退出时面板状态会变成「未检测到」,工具调用直接返回明确错误,不需要切换任何开关。
120
148
 
121
149
  ## 面板
122
150
 
123
151
  | 面板 | 内容 |
124
152
  |---|---|
125
- | 模型目录 | 刷新目录;逐模型一行:名称/id、**合规档位**、**此刻倍率**(含限时折扣时显示 `x0.5 ← x0.79 23:00–07:50`,x0 标「免费」)、上下文、推理档、「选用」按钮;默认只列安全清单,勾选「显示全部模型(含不建议项)」才展开其余项 |
153
+ | 模型目录 | 顶部只读显示 WorkBuddy 主进程状态;刷新目录;逐模型一行:名称/id、**合规档位**、**此刻倍率**(含限时折扣时显示 `x0.5 ← x0.79 23:00–07:50`,x0 标「免费」)、上下文、推理档、「选用」按钮;默认只列安全清单,勾选「显示全部模型(含不建议项)」才展开其余项 |
126
154
  | 账号 | 登录态来源(本机发现 / 手动)、掩码 token、积分余额查询、重新检测、手动 token 存取 |
127
- | 是否启用 WorkBuddy | 「中转站优先」开关 + WorkBuddy 主进程状态 |
128
- | 用量 | 区间概览(今天 / 近 7 天 / 近 30 天)、按模型聚合、积分包明细、限时优惠清单、最近调用;带「刷新余额」「清空本地账本」 |
155
+ | 用量与成本 | 区间概览(今天 / 近 7 天 / 近 30 天 / 全部,列:调用、失败、积分、输入/输出/缓存命中/合计 token)、按模型近 30 天聚合、积分包明细、限时优惠清单、最近调用;带「刷新余额」「清空本地账本」 |
129
156
 
130
157
  ### 安全清单(合规闸门)
131
158
 
@@ -133,12 +160,16 @@ WorkBuddy 官方对话给出的口径是:只调用「官方公开目录里、
133
160
  `disabled`、内部路由别名、媒体/代码补全与状态不明的模型都不要经外部软件调用,否则有风控/封号风险。
134
161
  这里把它落成代码:
135
162
 
136
- - 白名单 22 个(`src/safety.js` 的 `SAFE_MODEL_IDS`,按 DeepSeek / GLM / 混元 / Kimi / 其他分组):
137
- `deepseek-v4.1-flash`、`deepseek-v4-flash`、`deepseek-v4-pro`、`deepseek-v3-2-volc`、
138
- `glm-5.3-flash`、`glm-5.3`、`glm-5.2`、`hy3`、`hy3-b`、`hy3-c`、`hy3-x`、`hunyuan-chat`、
139
- `hy4-preview`、`kimi-k2.5`、`kimi-k2.8-preview`、`kimi-k3-1`、`kimi-k3.1-pro`、`minimax-m2.7`、
140
- `minimax-m3.1-flash`、`mimo-v2.6-pro`、`space-bunny`、`step-5-preview`。
141
- 其中 `hy3*` 与 `*preview`(含 `hy4-preview`)标为「谨慎」(免费试用/预览,别做高频自动化)。
163
+ - 白名单 17 个(`src/safety.js` 的 `SAFE_MODEL_IDS`,0.3.5 起与 WorkBuddy「选择模型」列表逐项对齐,
164
+ 按 DeepSeek / GLM / 混元 / Kimi / 其他分组):
165
+ `deepseek-v4.1-flash`、`deepseek-v4-pro`、`glm-5.3`、`glm-5.3-flash`、`glm-5.3-flashx`、`glm-5.2`、
166
+ `hy3`、`hy4-preview`、`kimi-k2.8-preview`、`kimi-k3-2`、`kimi-k3.1-pro`、`kimi-k3.1-pro-highspeed`、
167
+ `minimax-m3-pay`、`minimax-m3.1-flash`、`mimo-v2.6-pro`、`space-bunny`、`step-5-preview`。
168
+ 其中 `hy3`、`kimi-k2.8-preview`、`step-5-preview`、`hy4-preview` 标为「谨慎」(免费试用/预览,别做高频自动化)。
169
+ - 旧 id `kimi-k3-1` 在 v3 目录里已不存在(Kimi-K3 现在只对应 `kimi-k3-2`),0.3.5 一并换掉;
170
+ 同时移除了应用选择器不显示、但目录里仍可调用的 8 个 id(`deepseek-v4-flash`、`deepseek-v3-2-volc`、
171
+ `hy3-b`、`hy3-c`、`hy3-x`、`kimi-k2.5`、`minimax-m2.7`、`hunyuan-chat`)——其中 `hunyuan-chat`
172
+ 在 v3 目录里没有 `credits` 字段,倍率无法核验。
142
173
  - 其余全部**拒绝**:`wb-lite`(目录 `disabled:true`)、`auto` / `fast-model` / `balanced-model` /
143
174
  `deep-model`(内部路由别名)、4 个媒体模型、`codewise-*`、其他 `hy4-preview*` 变体(只精确放行
144
175
  `hy4-preview`)、19 个已下架的、
@@ -152,8 +183,9 @@ WorkBuddy 官方对话给出的口径是:只调用「官方公开目录里、
152
183
 
153
184
  - 目录来自 `GET /v3/config`(应用身份 UA):一次同时拿到 `models`、`modelPromotions`、`modelTiers`。
154
185
  用 CLI 身份只能读到精简目录,促销字段会整段缺失——这是「倍率永远显示原价」的根因。
155
- - 一条促销的生效条件是 `schedule`:`timezone`(默认按条目给的时区算)、`validFrom`/`validUntil`、
156
- `daily` 时段(支持 `23:00`→`07:50` 这类跨零点窗口)。命中的条目按 `priority` 取最高;平手时促销优先于档位。
186
+ - 一条促销的生效条件是 `schedule`:`timezone`(省略时按 `Asia/Shanghai`)、`validFrom`/`validUntil`、
187
+ `daily` 时段(支持 `23:00`→`07:50` 这类跨零点窗口)。纯日期按当地自然日解释,`validUntil` 包含当天;
188
+ 命中的条目按 `priority` 取最高,平手时促销优先于档位。
157
189
  - `discount.discountedCredits`(如 `0.50x`)**就是生效倍率本身**,不是相对原价的系数。
158
190
  `displayMode: "replace"` 直接替换显示,`"strikethrough"` 表示「划线原价 + 新价」并排。
159
191
  - `badge.display: "activeOnly"` 的徽标只在生效时段出现(如「限时免费」试用)。
@@ -161,8 +193,9 @@ WorkBuddy 官方对话给出的口径是:只调用「官方公开目录里、
161
193
  ### 用量统计口径
162
194
 
163
195
  - 每次 `wb_chat` 记一行到 `%APPDATA%\..\Coopanion\data\home\companion\data\workbuddy-usage.jsonl`
164
- (实机路径;实际就是 `ctx.dataDir`):`ts/model/region/ok/promptTokens/completionTokens/totalTokens/cachedTokens/reasoningTokens/credit/multiplier/promoId/source/durationMs`。
165
- - `credit` 取 SSE 最后一段的 `usage.credit`,即**上游真实扣费**;倍率 0.11 的模型单次请求不足 1 分时上游就是 0,这里照抄不折算。
196
+ (实机路径;实际就是 `ctx.dataDir`):`ts/model/ok/promptTokens/completionTokens/totalTokens/cachedTokens/reasoningTokens/credit/multiplier/baseMultiplier/promoId/source/durationMs`。
197
+ - `credit` 取 SSE 各段合并后的 `usage.credit`,即**上游真实扣费**;倍率 0.11 的模型单次请求不足 1 分时上游就是 0,这里照抄不折算。
198
+ 上游未回传时记为未知,概览用 `+ ?` 标出缺口,绝不当成 0;`multiplier` 是响应完成时的生效倍率,`baseMultiplier` 是目录原价。
166
199
  - 积分包余额另存 `workbuddy-balance.json`(`POST /v2/billing/meter/get-user-resource` 的 `*Precise` 字段求和),
167
200
  面板上的「刷新余额」会重取一次。
168
201
  - 账本只保留 90 天,读的时候顺带裁掉;「清空本地账本」会把它清成空文件,服务端数据不受影响。
@@ -180,13 +213,11 @@ WorkBuddy 官方对话给出的口径是:只调用「官方公开目录里、
180
213
 
181
214
  | 键 | 默认 | 说明 |
182
215
  |---|---|---|
183
- | `region` | `cn` | `cn` / `global` |
184
216
  | `model` | `""` | 当前模型 id(面板点选即写这里) |
185
217
  | `credentialsDir` | `""` | 自定义凭据目录,留空自动发现(重启生效) |
186
218
  | `baseUrl` | `""` | 自定义上游地址,代理/中转用(重启生效) |
187
219
  | `maxTokens` | `2048` | `wb_chat` 单次输出上限 |
188
- | `envPrompt` | `true` | 是否把桥接状态写进 system 前缀(关掉后「中转站优先」也不生效) |
189
- | `prefer` | `false` | 「中转站优先」,由详情页开关写入 |
220
+ | `envPrompt` | `true` | 是否把桥接状态写进 system 前缀 |
190
221
  | `safeOnly` | `true` | 只允许调用安全清单内的公开对话模型;关掉会放行 disabled / 别名 / 预览等项,风险自负 |
191
222
 
192
223
  ## 开发与校验
@@ -198,7 +229,8 @@ WorkBuddy 官方对话给出的口径是:只调用「官方公开目录里、
198
229
  node scripts/build-web.mjs
199
230
 
200
231
  # 契约检查(不依赖宿主,CI 必跑):describe.json 与源码一致、版本号与 CHANGELOG 对齐、
201
- # 促销/安全清单/账本断言,以及哨兵、计费域、429 软硬、面板白名单、并发、SSE flush 等回归断言
232
+ # 促销/安全清单/账本断言,以及哨兵、计费域、429 软硬、面板白名单、并发、SSE flush 等回归断言;
233
+ # 0.3.1 另加 session_dead 分类、无效时段、rediscover 覆盖、跨日归零等防线(contract-regression.mjs)
202
234
  node scripts/contract.mjs
203
235
 
204
236
  # 由源码重新生成 describe.json(改过工具声明或 ENV_PROMPT.md 之后)
@@ -218,7 +250,7 @@ UI 验证脚本的两个约定(踩过坑,别再用固定 sleep):每轮
218
250
  并把「路由挂载」与「面板渲染」拆成两条断言——否则一次产物没加载就会被误判成「按钮没了」。
219
251
 
220
252
  版本号规范:任何改动都 bump `package.json` 的 `version`,备份目录按版本命名
221
- (`F:\coo-connect-wb\0.3.0\`),再用 `scripts/reinstall.ps1` 装;它先把 tgz 解出来,再拿**解出来的内容**与安装目录逐文件比对哈希,
253
+ (`F:\coo-connect-wb\0.3.5\`),再用 `scripts/reinstall.ps1` 装;它先把 tgz 解出来,再拿**解出来的内容**与安装目录逐文件比对哈希,
222
254
  不一致直接非零退出。
223
255
 
224
256
  打包注意:**不要用 PowerShell 的 `Get-Content -Raw | Set-Content` 改 `package.json`**
@@ -226,7 +258,7 @@ UI 验证脚本的两个约定(踩过坑,别再用固定 sleep):每轮
226
258
  用 node 读写 JSON;tgz 必须以 `package/` 为前缀:
227
259
 
228
260
  ```bash
229
- tar -czf cortico-world-workbuddy-0.3.0.tgz -C <stage> package
261
+ tar -czf cortico-world-workbuddy-0.3.5.tgz -C <stage> package
230
262
  ```
231
263
 
232
264
  协议细节参照 [dsh-connect-workbuddy](https://github.com/dingminhua/dsh-connect-workbuddy)
@@ -235,16 +267,22 @@ tar -czf cortico-world-workbuddy-0.3.0.tgz -C <stage> package
235
267
 
236
268
  ## 宿主文件:一个字节都不改
237
269
 
238
- 0.3.0 起本扩展**不再往 Coopanion 主界面注入任何东西**——「中转站优先」只剩 World 详情页里
239
- 那个勾选框,工具、面板、账本全在各自主张的地方,`resources\app` 下不会有任何改动,卸载即干净。
270
+ 0.3.0 起本扩展**不再往 Coopanion 主界面注入任何东西**——详情页只有三个只读/配置面板,
271
+ 没有开关勾选框,`resources\app` 下不会有任何改动;部署配置、账本与手动 token 按上一节的显式步骤清理。
240
272
 
241
- 如果你装过 0.2.x,宿主 `build\console\` 里可能还留着两处痕迹,删掉即可:
273
+ 如果你装过 0.2.x,宿主 `build\console\` 里可能还留着三处痕迹。扩展本体不会自动改
274
+ 宿主文件(这正是 0.3.0 起的承诺),请用一次性迁移脚本清理:
275
+
276
+ ```bash
277
+ node scripts/clean-legacy-injection.mjs --check # 只列出会动的项
278
+ node scripts/clean-legacy-injection.mjs --clean # 执行清理(幂等)
279
+ ```
242
280
 
243
- | 文件 | 说明 |
281
+ | 文件 | 脚本会做什么 |
244
282
  |---|---|
245
- | `<app>\build\console\index.html` | 删掉 `<script type="module" src="./workbuddy-home.js"></script>` 这一行 |
246
- | `<app>\build\console\workbuddy-home.js` | 旧的注入脚本,直接删 |
247
- | `<app>\build\console\index.html.workbuddy-backup` | 首次注入前的原件备份,确认 `index.html` 干净后可删 |
283
+ | `<app>\build\console\index.html` | 只剥掉 `<script type="module" src="./workbuddy-home.js"></script>` 这一行,保留原有换行风格与其余内容 |
284
+ | `<app>\build\console\workbuddy-home.js` | 删除旧的注入脚本 |
285
+ | `<app>\build\console\index.html.workbuddy-backup` | 删除首次注入前的原件备份 |
248
286
 
249
287
  ## 发布(GitHub / npm / 扩展市场)
250
288
 
@@ -266,12 +304,12 @@ Action 定时扫 npm 生成市场目录,所以发版顺序是:**先 npm publ
266
304
 
267
305
  ```bash
268
306
  # 1. 发版前三连检(需要本机真实宿主)
269
- node scripts/contract.mjs # 不依赖宿主,68 条断言
307
+ node scripts/contract.mjs # 不依赖宿主,全部断言
270
308
  node scripts/selfcheck.mjs # dry-mount 框架契约
271
309
  node scripts/verify-ui.mjs --runs 3
272
310
 
273
311
  # 2. 提交并打 tag
274
- git tag v0.3.0 && git push --tags
312
+ git tag v0.3.5 && git push --tags
275
313
 
276
314
  # 3. 发布(prepack 会自动重建 dist/webui.js)
277
315
  npm publish --access public
@@ -283,16 +321,30 @@ gh issue create -R Pal-AI-Lab/cortico-extensions --title "[sync] cortico-world-w
283
321
  对标签有异议用 `[tags]`、申请蓝标认证用 `[certify]`、被拉黑申诉用 `[appeal]`,
284
322
  正文一行一项 `键: 值`(`package` / `add` / `remove` / `reason` / `evidence`)。
285
323
 
286
- CI 里没有 Coopanion,自检会跳过而不是红叉:
324
+ CI 里没有 Coopanion:自检改跑离线检查(全部源码 `node --check` + `contract`),
325
+ 不会红叉,也不会无条件算通过:
287
326
 
288
327
  ```bash
289
328
  node scripts/selfcheck.mjs --allow-missing-host # 找不到宿主 → 警告 + 退出码 0
290
329
  ```
291
330
 
292
- 凭据读取范围与网络出口见 [SECURITY.md](./SECURITY.md):读哪些文件、只发给哪两个域名、哪些从不写盘。
331
+ 凭据读取范围与网络出口见 [SECURITY.md](./SECURITY.md):读哪些文件、默认只发给哪两个官方域名
332
+ (配了自定义 `baseUrl` 时从该出口走)、哪些从不写盘。
293
333
 
294
334
  ## 免责
295
335
 
296
336
  本扩展与腾讯 / WorkBuddy 官方无关,也不代表 Pal AI Lab / Cortico / Coopanion 官方立场。
297
- 使用即表示你理解:所有调用消耗自己账号的积分,账号状态由上游管理,
298
- 扩展作者不对账号限制或扣费负责。凭据处理细节见 [SECURITY.md](./SECURITY.md)。
337
+ 它使用的不是 WorkBuddy 官方开放 API,而是本机客户端自身的接口;上游一旦调整或收紧,
338
+ 扩展可能失效,也可能带来账号层面的风险。
339
+
340
+ 使用即表示你理解并接受:
341
+
342
+ 1. **仅限个人、本地、桌宠文字对话中的按需调用**——这是本扩展唯一的设计用途;
343
+ 2. 所有调用消耗**你自己账号**的积分,倍率与扣费以上游为准,扩展只做记录与展示;
344
+ 3. 账号状态、积分变动、风控与封禁由上游裁量,本扩展作者不承担任何责任;
345
+ 4. 把本扩展用于对外提供接口、批量调用、多账号共享、绕过计费或其它未声明用途,
346
+ 属于超出设计范围的使用,后果由使用者自行承担。
347
+
348
+ 凭据读取范围、网络出口与本扩展写盘内容见 [SECURITY.md](./SECURITY.md)。
349
+ 官方 [服务条款](https://www.workbuddy.cn/document/term) 与
350
+ [可接受使用政策](https://www.workbuddy.cn/document/acceptable-use-policy) 始终优先于本扩展的任何行为。
package/SECURITY.md CHANGED
@@ -4,6 +4,23 @@ This extension talks to *your own* WorkBuddy account on *your own* machine. It h
4
4
  no telemetry and no third-party analytics. This file states exactly what it touches, so you can
5
5
  judge the risk before installing.
6
6
 
7
+ ## Scope of use
8
+
9
+ This extension exists for one purpose: letting the Coo desktop pet answer **text conversations**
10
+ with you by calling a model from **your own, locally signed-in WorkBuddy account**, one call at a
11
+ time, only when a turn actually needs it.
12
+
13
+ It is **not** an API gateway, an OpenAI-compatible server, a batch/automation/crawling tool, a
14
+ multi-account pool, a credential-sharing service, or a way to bypass WorkBuddy billing. It opens no
15
+ listening port, exposes no HTTP endpoint, runs no background chat job, and sends only what your own
16
+ WorkBuddy client would send. Every `wb_chat` call is user-driven and consumes your own credits at
17
+ the upstream rate.
18
+
19
+ Do not redistribute, resell, or repurpose this extension as a model service for third parties.
20
+ That is outside its design and outside WorkBuddy's terms of service — see the Acceptable Use Policy
21
+ (§4 Restricted Use) and the Terms of Service (§3.5 Monitoring and Circumvention, §12) under
22
+ <https://www.workbuddy.cn/document/>.
23
+
7
24
  ## What it reads
8
25
 
9
26
  | Path | Why | Data |
@@ -11,34 +28,47 @@ judge the risk before installing.
11
28
  | `%LOCALAPPDATA%\CodeBuddyExtension\Data\Public\auth\workbuddy-desktop.info` | To learn your WorkBuddy login | `auth.accessToken`, `auth.refreshToken`, `auth.expiresAt`, `auth.domain`, `account` |
12
29
  | `%APPDATA%\WorkBuddy*\*.json` (if present) | Older WorkBuddy builds store the login here | same fields when stored in plain text |
13
30
  | `%LOCALAPPDATA%\CodeBuddyExtension\Data\Public\auth` (fallback) | Same as above, directory scan | same fields |
14
- | `C:\Program Files\WorkBuddy\WorkBuddy.exe` | Only to ask the app for its own at-rest key | the key payload printed by the app's own `loggerGet()` binding; never stored |
15
- | `<Coopanion data>\home\companion\config.json` | Read/write `worlds.workbuddy` | region, model id, `prefer` flag |
31
+ | `WorkBuddy.exe` / `WorkBuddy AI.exe` (known install locations) | Only to ask the app for its own at-rest key | the key payload printed by the app's own `loggerGet()` binding; never stored |
32
+ | `<Coopanion data>\home\companion\config.json` | Read `worlds.workbuddy` | model id, `envPrompt` / `safeOnly` flags |
16
33
 
17
34
  The token is decrypted in memory only when the file is encrypted, is used only as the
18
35
  `Authorization: Bearer` header for WorkBuddy's own endpoints, and is never written anywhere except
19
36
  the Coopanion deployment `.env` if you paste one in the account panel yourself (the framework's
20
- `storeSecret`).
37
+ `storeSecret`). Refresh tokens are never sent with chat requests.
21
38
 
22
39
  ## Where data goes
23
40
 
24
- Only three hosts, all WorkBuddy's:
41
+ By default, only these two hosts, both WorkBuddy's:
25
42
 
26
- - `https://copilot.tencent.com` — model catalogue and chat completions (region `cn`)
27
- - `https://www.codebuddy.cn` — credit balance (region `cn`)
28
- - `https://www.workbuddy.ai` — catalogue, chat, credits (region `global`)
43
+ - `https://copilot.tencent.com` — model catalogue and chat completions
44
+ - `https://www.codebuddy.cn` — credit balance
29
45
 
30
- Nothing else. No logs contain tokens: every log line goes through `maskToken()`.
46
+ If you set `worlds.workbuddy.baseUrl` (a proxy or mirror), **every** request — catalogue,
47
+ chat and credit balance — goes to that host instead, and the token is sent there too. That is
48
+ your own configuration choice, not a default. No other hosts are contacted. No logs contain
49
+ tokens: every log line goes through `maskToken()`.
31
50
 
32
51
  ## What it writes
33
52
 
34
- - `<Coopanion data>/worlds/workbuddy/workbuddy-catalog.json` — cached model list, no credentials.
35
- - `worlds.workbuddy.*` in the companion config (region, model, `prefer`, `envPrompt`).
36
- - **Host files, only when the start-page button is injected:** `resources/app/build/console/index.html`
37
- (0.3.0 removed the home-page injection; the extension no longer touches host files).
38
- The original `index.html` is kept as `index.html.workbuddy-backup` next to it.
39
- Nothing to undo — the extension does not modify Coopanion files anymore. Earlier versions
40
- one-line reference by hand. A Coopanion update that replaces `build/console` simply removes the
41
- injection; the extension puts it back on the next start.
53
+ - `<Coopanion data>/home/companion/data/workbuddy-catalog.json` — cached model list, no credentials.
54
+ - `<Coopanion data>/home/companion/data/workbuddy-usage.jsonl` and `workbuddy-balance.json` — local
55
+ usage ledger and credit snapshot, no tokens.
56
+ - `worlds.workbuddy.*` in the companion config (model, `envPrompt`, `safeOnly`).
57
+ - The deployment `.env` — only when you paste a token or clear it in the Account panel
58
+ (the sentinels `wb-cleared` / `wb-auto` are written there; a real token only if you pasted one).
59
+
60
+ **Coopanion program files are never touched by the running extension.** Since 0.3.0 it does not
61
+ inject anything into `resources/app/build/console` and keeps no backup of host files. Coopanion's
62
+ own uninstall route removes only the package; it does not run extension cleanup code. After
63
+ uninstalling, run `node scripts/clean-workbuddy.mjs --check`, then `--clean`, from the source tree.
64
+ That explicit command removes only the `worlds.workbuddy` config block, the three data files above,
65
+ and the `accessToken` line in `.env`; it preserves every other setting and secret and never prints
66
+ the token. Ordinary `stop()` and restart never delete usage data.
67
+
68
+ If you upgraded from 0.2.x, an old one-line `<script>` reference, `workbuddy-home.js` and
69
+ `index.html.workbuddy-backup` may still be left over from that older version. Remove them once with
70
+ `node scripts/clean-legacy-injection.mjs --clean` (`--check` lists what it would touch). Neither
71
+ cleanup script runs automatically, and the extension never re-adds the injection.
42
72
 
43
73
  ## Reporting a vulnerability
44
74