cortico-world-workbuddy 0.1.7 → 0.3.0
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 +89 -0
- package/README.md +53 -76
- package/SECURITY.md +3 -3
- package/describe.json +9 -9
- package/dist/webui.js +5 -47
- package/package.json +7 -6
- package/scripts/build-web.mjs +97 -0
- package/scripts/contract.mjs +342 -0
- package/scripts/gen-describe.mjs +97 -0
- package/scripts/lib/app-root.mjs +41 -0
- package/scripts/reinstall.ps1 +79 -53
- package/scripts/selfcheck.mjs +58 -13
- package/scripts/verify-ui.mjs +12 -33
- package/src/config.js +4 -10
- package/src/credentials.js +9 -1
- package/src/promo.js +91 -33
- package/src/safety.js +8 -3
- package/src/upstream.js +82 -52
- package/src/usage.js +55 -22
- package/src/wbproc.js +6 -1
- package/src/webui/client.js +5 -48
- package/src/world.js +144 -192
- package/ENV_PROMPT.md +0 -11
- package/assets/workbuddy-home.js +0 -266
- package/scripts/host-inject.mjs +0 -80
- package/src/host.js +0 -269
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,94 @@
|
|
|
1
1
|
# 更新日志
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
**撤除主界面注入,并按复检报告修掉 9 处中优先级问题。**
|
|
6
|
+
|
|
7
|
+
### 删掉的功能(以及随之消失的冗余)
|
|
8
|
+
|
|
9
|
+
- 不再往 Coopanion 主界面「开始」页注入「中转站优先」按钮:删除 `src/host.js`、
|
|
10
|
+
`scripts/host-inject.mjs`、`assets/workbuddy-home.js`;`world.js` 去掉 `syncHostUi()`、
|
|
11
|
+
`hostInjectorSource()`、`removeHostUi()`、`hostUiLine()` 与 60 秒自检定时器。
|
|
12
|
+
- 四盏灯回到三盏(WorkBuddy / 主进程 / 中转站优先),`hostInject` 配置项删除,
|
|
13
|
+
`priority` 面板不再有 `host` / `repair` 方法,面板里的「重新注入」按钮与相关文案一并移除。
|
|
14
|
+
- 扩展现在**不改写宿主任何文件**,卸载不需要还原;装过 0.2.x 的机器按 README
|
|
15
|
+
的「旧版本残留」一段手工清一次 `build\console` 即可。
|
|
16
|
+
|
|
17
|
+
### 按复检报告修复
|
|
18
|
+
|
|
19
|
+
- `rediscover` 之后不再残留「已登出」哨兵:新增 `TOKEN_AUTO = 'wb-auto'`,探测成功即改写,
|
|
20
|
+
重启后不会又变回未登录。
|
|
21
|
+
- `/v3/config` 返回 401/403 时直接判 `session_dead`,不再降级去读没有促销的旧目录。
|
|
22
|
+
- 自定义 `baseUrl` 时积分查询跟着走同一出口(以前固定打到 `www.codebuddy.cn`)。
|
|
23
|
+
- 构建可复现:`package-lock.json` 锁 esbuild 0.24.2;`build-web.mjs` 新增 `--strict`,
|
|
24
|
+
`prepack` 用它——找不到 esbuild 时直接失败,不再静默沿用旧 `dist`。
|
|
25
|
+
- 数量口径统一为 22 个安全模型(代码 / 配置描述 / README 一致),并注明只精确放行
|
|
26
|
+
`hy4-preview`(同前缀的新实验号仍需人工复核)。
|
|
27
|
+
- `describe.json` 生成化后补回 `wb_chat` / `wb_credits` 的「Requires the WorkBuddy desktop app
|
|
28
|
+
to be running」前提。
|
|
29
|
+
- `contract.mjs` 扩容到 68 条断言,新增复检点名缺口的回归项:哨兵语义、计费域选择、
|
|
30
|
+
429 软硬区分、面板方法白名单、账本并发(`append` 与 `prune` 串行)、SSE 尾行 flush、
|
|
31
|
+
`start()` 兜底、本地日期;同时修掉一条恒真断言。
|
|
32
|
+
- 顺手修:`recent` 按时间倒序(以前 `slice(-15).reverse()` 会先取到最旧那条)、
|
|
33
|
+
`wb-cleared` 时给出可操作提示、`selfcheck` 失败路径清理临时目录、`gen-describe` 英文语法。
|
|
34
|
+
|
|
35
|
+
## 0.2.0
|
|
36
|
+
|
|
37
|
+
按 hy4-preview 的审查报告把 17 类问题逐个修掉,并把 `hy4-preview` 纳入安全清单(仍只在本机,未推送 / 未发布)。
|
|
38
|
+
|
|
39
|
+
- **新模型**:`hy4-preview` 进入安全清单(0.1.7 探测时它正好繁忙、误判为不可用),同时标为「谨慎」
|
|
40
|
+
—— 预览档,不要把高频自动化打到它身上。
|
|
41
|
+
- **`worlds.workbuddy.hostInject` 真正生效**:关掉后 `start()` 与 60 秒巡检都不再改写宿主
|
|
42
|
+
`build\console\index.html`,并会主动清掉上一次留下的注入与备份;`stop()` 也先于开关判断执行还原
|
|
43
|
+
(装完再关掉的场景以前会漏还原)。
|
|
44
|
+
- **promo 计算改成同一条促销说了算**:原来「生效倍率」取自真正打折的那条,「徽标 / 时段 / promoId」
|
|
45
|
+
取自优先级最高的生效项,两者可能不是同一条,导致面板写着 A 的名字、收着 B 的价。现在
|
|
46
|
+
`selectPromoDiscount()` 一次挑出「真正改价」的促销,`priceViewOf()` 的
|
|
47
|
+
`effective / promoId / windowText / discount` 全部来自它,并新增 `discounted` 布尔。
|
|
48
|
+
- **促销时间解析**:`validFrom` / `validUntil` 现在同时接受 ISO 字符串与数字时间戳(<1e12 视为 Unix 秒
|
|
49
|
+
—— 以前数字时间戳被静默丢弃,过期活动会一直生效);`daily` 时段在时区无法识别时退回 UTC
|
|
50
|
+
(以前 `catch` 里 `return 0`,等于把所有活动当成 00:00 生效);`24:00` 与跨零点窗口照旧。
|
|
51
|
+
- **`base` 倍率不再误读**:`multiplierOfText()` 同时剥前缀与后缀的 `x`。
|
|
52
|
+
- **用量账本并发安全**:`append()` / `prune()` / `clear()` 共用一条串行队列,`prune` 与 `clear` 改成
|
|
53
|
+
写临时文件再 `rename` —— 以前 `prune()` 的整体重写会覆盖并发进行中的 `append()`。
|
|
54
|
+
- **用量面板 token 列修好**:账本字段名是 `total / prompt / completion`,面板却按
|
|
55
|
+
`totalTokens / promptTokens / completionTokens` 读,所以「最近调用」的 token 列一直是 0。
|
|
56
|
+
- **宿主注入自愈更彻底**:`inspectHostInjection()` 会真实比对注入脚本内容(新增 `fileStale` 与
|
|
57
|
+
`reason: injector-stale`),`ensureHostInjection()` 无论当前是否「看起来正常」都会把脚本更新到本版本
|
|
58
|
+
—— 以前脚本写进 `if (!state.ok)` 里,升级扩展后宿主跑的还是旧脚本。
|
|
59
|
+
- **`--restore` 不再用备份覆盖宿主**:`scripts/host-inject.mjs --restore` 改调 `removeHostInjection()`
|
|
60
|
+
(只剥引用行、删注入脚本与备份),与「绝不用旧备份覆盖、避免把宿主降级」的原则一致;
|
|
61
|
+
`--check` 也把「注入脚本过期」算作失败。
|
|
62
|
+
- **换行风格不再被改坏**:`stripInjection()` 按原文件的换行风格重建(以前会把 CRLF 全改成 LF)。
|
|
63
|
+
- **`clearToken` 真的清得掉**:写不清空时返回失败不再是「假成功」;清空后写哨兵 `wb-cleared`,
|
|
64
|
+
`loadTokens()` 见到哨兵就当作已登出(`rediscover` 才回落到本机凭据库)。
|
|
65
|
+
- **`/v3/config` 失败不再静默**:非 2xx、空数据、无模型条目分别打警告,方便判断是不是被降级到旧接口。
|
|
66
|
+
- **计费域按区域选**:`WbUpstream` 现在接收 `region`,`billingUrl()` 用 `WB_BILLING_BASE[region]`
|
|
67
|
+
(以前按域名子串猜,自定义 `baseUrl` 会掉到国际计费域 `www.workbuddy.ai`)。
|
|
68
|
+
- **SSE 收尾不再丢 usage**:流结束时 `decoder.decode()` 冲刷残留字节,并把最后一段没有换行的 `data:`
|
|
69
|
+
交给同一解析器 —— 以前末尾那段(正好带 `usage`)会被丢掉。
|
|
70
|
+
- **429 两种性质分开**:`classifyHttpFailure()` 按文案把「额度耗尽」判成 `hard_credit`,其余 429 才是
|
|
71
|
+
`soft_rate`(以前两支返回同一个值)。
|
|
72
|
+
- **解封密钥失败不再永久缓存**:`resolveTokensWithKey()` 的成功结果只复用 60 秒,失败也按 TTL 重试
|
|
73
|
+
—— 以前一次取密钥失败后,即使用户随后装了 WorkBuddy 桌面端也要重启扩展才能恢复。
|
|
74
|
+
- **`pgrep` 缺失不再算「没在跑」**:`probePosix()` 识别 `command not found` / 退出码 127,返回
|
|
75
|
+
`via: 'error'`,不写进「未运行」的缓存。
|
|
76
|
+
- **启动流程兜底**:`start()` 全程包 try/catch/finally,`pushEvent` 失败只警告;任何一步抛错都不会让
|
|
77
|
+
四盏灯永远停在「正在读取登录态…」。
|
|
78
|
+
- **面板方法白名单**:`handleInvoke()` 先校验 `panel`/`method`(`PANEL_METHODS`),未知组合直接拒绝
|
|
79
|
+
—— 以前任意 panel 都能触发 `setToken` / `clearToken` 写密钥库。
|
|
80
|
+
- **「今日」按本地日期**:`refreshToday()` 不再用 `toISOString()` 取日期(UTC+8 下会把 today 算成前一天)。
|
|
81
|
+
- **`describe.json` 变成生成物**:新增 `scripts/gen-describe.mjs`,工具名 / 描述 / 参数 / tags 来自
|
|
82
|
+
`WB_TOOL_DECLS`,环境提示词来自 `src/ENV_PROMPT.md`,摘要与事件写在生成器里;`--check` 可验一致性。
|
|
83
|
+
删掉包里那份 724 字节的旧 `ENV_PROMPT.md` 模板(真正的模板是 `src/ENV_PROMPT.md`)。
|
|
84
|
+
- **新增 `scripts/contract.mjs`**:静态契约 + 单元断言(describe 与源码一致、版本与 CHANGELOG 对齐、
|
|
85
|
+
提示词占位符都有对应变量、夜间/白天促销、数字时间戳、时区回退、安全清单、账本聚合、CRLF 保留),
|
|
86
|
+
没装 Coopanion 的机器上也能跑;`selfcheck.mjs` 找不到宿主时改为跑它。
|
|
87
|
+
- **`reinstall.ps1` 不再往作者机器路径写**:默认输出到 `$env:LOCALAPPDATA\cortico-world-workbuddy\build`,
|
|
88
|
+
优先 `npm pack`(会走 `prepack` 重建构建产物),手工 `tar` 只作兜底。
|
|
89
|
+
- **CI 补上真正的校验**:`npm run build:web` + `git diff --exit-code -- dist` + `node scripts/contract.mjs`;
|
|
90
|
+
Release 工作流与 CI 统一用 `npm ci`。
|
|
91
|
+
|
|
3
92
|
## 0.1.7
|
|
4
93
|
|
|
5
94
|
按 WorkBuddy 官方对话给出的合规口径,给桥接加「安全清单」闸门(仍只在本机,未推送 / 未发布)。
|
package/README.md
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
把 **本机已登录的 WorkBuddy 客户端**(国内版 / 国际版)的模型桥接进
|
|
4
4
|
[Coopanion](https://github.com/Pal-AI-Lab/Coopanion) 桌宠:Coo 可以直接调用你
|
|
5
5
|
WorkBuddy 账号里的模型,World 面板里可以浏览模型目录、查看每个模型的
|
|
6
|
-
**默认积分倍率**(如 `x0.79
|
|
7
|
-
|
|
6
|
+
**默认积分倍率**(如 `x0.79`)并点选要用的模型;World 详情页有一个「是否启用Workbuddy」
|
|
7
|
+
开关,打开后桌宠每轮对话都先问 WorkBuddy。
|
|
8
8
|
|
|
9
9
|
这是一个 Cortico 的 World 扩展(`kind: world`,`api: 6`),纯 ESM JS、零运行时依赖,
|
|
10
10
|
面板产物已随包构建好(`dist/webui.js`)。
|
|
@@ -14,12 +14,12 @@ WorkBuddy 账号里的模型,World 面板里可以浏览模型目录、查看
|
|
|
14
14
|
> 按上游给出的倍率真实扣费;扩展不提供账号、不共享凭据、不绕过计费。
|
|
15
15
|
> 请自行评估账号风险,官方 WorkBuddy 客户端始终是最安全的选择。
|
|
16
16
|
|
|
17
|
-
## 安装(0.
|
|
17
|
+
## 安装(0.3.0,Coopanion 0.2.17 实机验证)
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
一条命令(推荐,脚本会做完打包、装卸、哈希与版本校验):
|
|
20
20
|
|
|
21
21
|
```powershell
|
|
22
|
-
|
|
22
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/reinstall.ps1
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
手工装的话,三步:
|
|
@@ -32,7 +32,7 @@ pwsh -File scripts/reinstall.ps1
|
|
|
32
32
|
cd "C:\Users\<你>\AppData\Local\Programs\Coopanion\data\extensions"
|
|
33
33
|
node "C:\Users\<你>\AppData\Local\Programs\Coopanion\resources\app\node_modules\pnpm\bin\pnpm.cjs" remove cortico-world-workbuddy
|
|
34
34
|
node "C:\Users\<你>\AppData\Local\Programs\Coopanion\resources\app\node_modules\pnpm\bin\pnpm.cjs" `
|
|
35
|
-
add "
|
|
35
|
+
add "$env:LOCALAPPDATA\cortico-world-workbuddy\build\cortico-world-workbuddy-0.3.0.tgz" `
|
|
36
36
|
--config.strict-dep-builds=false `
|
|
37
37
|
--store-dir "C:\Users\<你>\AppData\Local\Programs\Coopanion\data\pnpm\store\v11"
|
|
38
38
|
```
|
|
@@ -49,23 +49,10 @@ pwsh -File scripts/reinstall.ps1
|
|
|
49
49
|
}
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
3.
|
|
52
|
+
3. 重启 Coopanion(ESM 模块缓存不支持热换代码),用带环境清理的启动器:
|
|
53
53
|
|
|
54
54
|
```powershell
|
|
55
|
-
|
|
56
|
-
node scripts/host-inject.mjs --check # 只检查(退出码:0=正常,1=缺注入)
|
|
57
|
-
node scripts/host-inject.mjs --restore # 从备份还原,彻底移除注入
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
它把 `assets/workbuddy-home.js` 复制到 `<Coopanion>\resources\app\build\console\`,并在
|
|
61
|
-
`index.html` 里 `<script type="module" src="./index.js"></script>` **之前**插一行;首次
|
|
62
|
-
改动前自动把 `index.html` 备份成 `index.html.workbuddy-backup`,注入脚本头部带
|
|
63
|
-
`/* bundled:<version> */` 便于核对。
|
|
64
|
-
|
|
65
|
-
4. 重启 Coopanion(ESM 模块缓存不支持热换代码),用带环境清理的启动器:
|
|
66
|
-
|
|
67
|
-
```powershell
|
|
68
|
-
pwsh -File scripts/launch-coopanion.ps1
|
|
55
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/launch-coopanion.ps1
|
|
69
56
|
```
|
|
70
57
|
|
|
71
58
|
> **为什么要有启动器**:终端里残留 `ELECTRON_RUN_AS_NODE=1`(比如跑过 Node 子进程)时,
|
|
@@ -73,22 +60,16 @@ pwsh -File scripts/reinstall.ps1
|
|
|
73
60
|
> 打印 `v24.x`(node 版本)、`--enable-logging` 报 `bad option`。这不是二进制损坏,
|
|
74
61
|
> 是环境变量被继承。启动器只清本进程树里的这个变量,不动用户/机器级设置。
|
|
75
62
|
|
|
76
|
-
> 宿主升级会覆盖 `build\console`,注入随之消失——但扩展每 60 秒自检一次,发现缺失会自动
|
|
77
|
-
> 重注入;「是否启用 WorkBuddy」面板里有「重新注入开始页按钮」按钮可手动触发;
|
|
78
|
-
> 四盏灯里的「开始页按钮」会直接显示状态(在线 / 需要修复)。`wb_*` 工具不受影响。
|
|
79
63
|
|
|
80
64
|
## 卸载与还原
|
|
81
65
|
|
|
82
66
|
- **只卸扩展**:在「World 扩展」里卸载 / 或 `pnpm remove cortico-world-workbuddy`。
|
|
83
|
-
之后开始页那一行会在 3 秒内自动消失(脚本检测到 `/api/worlds` 里没有 `workbuddy`),
|
|
84
67
|
详情页入口随之消失,桌宠工具表里也不再有 `wb_*`——Coopanion 主体不受影响。
|
|
85
|
-
-
|
|
86
|
-
`
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
- **开关状态**:`worlds.workbuddy.prefer` 留在 `data\home\companion\config.json` 里;
|
|
91
|
-
扩展不在时没人读它,重新装回来会恢复上次的状态。
|
|
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>` 这一行即可。
|
|
92
73
|
|
|
93
74
|
## 工作原理
|
|
94
75
|
|
|
@@ -99,7 +80,7 @@ Coopanion (Coo)
|
|
|
99
80
|
├─ 凭据发现 %LOCALAPPDATA%\CodeBuddyExtension\Data\Public\auth\workbuddy-desktop.info
|
|
100
81
|
│ ($wbEncrypted 信封 → 用桌面端自己的二进制自动解封)
|
|
101
82
|
├─ 上游客户端 copilot.tencent.com(对话)/ www.codebuddy.cn(计费)
|
|
102
|
-
│ ├─ GET /
|
|
83
|
+
│ ├─ GET /v3/config 模型目录 + 促销(models / modelPromotions / modelTiers)
|
|
103
84
|
│ ├─ POST /v2/chat/completions 对话(SSE 流式)
|
|
104
85
|
│ ├─ POST /v2/auth/refresh 刷新 token(X-Refresh-Token)
|
|
105
86
|
│ └─ POST /v2/billing/meter/get-user-resource 积分余额(只读)
|
|
@@ -122,17 +103,19 @@ Coopanion (Coo)
|
|
|
122
103
|
|
|
123
104
|
## 「中转站优先」开关
|
|
124
105
|
|
|
125
|
-
一份状态(`worlds.workbuddy.prefer
|
|
106
|
+
一份状态(`worlds.workbuddy.prefer`),一个入口,默认是**关**:
|
|
126
107
|
|
|
127
108
|
| 入口 | 位置 | 行为 |
|
|
128
109
|
|---|---|---|
|
|
129
|
-
|
|
|
130
|
-
|
|
110
|
+
| 详情页开关 | 「World 扩展」→ WorkBuddy 桥接 →「是否启用Workbuddy」 | 勾选=开;取消=关 |
|
|
111
|
+
|
|
112
|
+
> 0.3.0 起**不再往主界面「开始」页注入「中转站优先」按钮**(也就不需要改宿主文件)。
|
|
113
|
+
> 想快速开关,把它当书签存一下 World 详情页即可。
|
|
131
114
|
|
|
132
115
|
- 开 → 环境提示词告诉 Coo:每轮对话先 `wb_chat`(用 `worlds.workbuddy.model`),
|
|
133
116
|
再把回答用自己的话讲出来并说明是哪个模型答的。
|
|
134
117
|
- 关 → Coo 完全不碰 `wb_*`(用户明确点名 WorkBuddy 时除外)。
|
|
135
|
-
-
|
|
118
|
+
- 打开时若没检测到主进程:不会把开关打开,面板提示「未检测到Workbuddy」。
|
|
136
119
|
- 主进程在 6 秒轮询里退出时,开关自动熄灭,避免亮着却调不通。
|
|
137
120
|
|
|
138
121
|
## 面板
|
|
@@ -141,7 +124,7 @@ Coopanion (Coo)
|
|
|
141
124
|
|---|---|
|
|
142
125
|
| 模型目录 | 刷新目录;逐模型一行:名称/id、**合规档位**、**此刻倍率**(含限时折扣时显示 `x0.5 ← x0.79 23:00–07:50`,x0 标「免费」)、上下文、推理档、「选用」按钮;默认只列安全清单,勾选「显示全部模型(含不建议项)」才展开其余项 |
|
|
143
126
|
| 账号 | 登录态来源(本机发现 / 手动)、掩码 token、积分余额查询、重新检测、手动 token 存取 |
|
|
144
|
-
| 是否启用 WorkBuddy | 「中转站优先」开关 +
|
|
127
|
+
| 是否启用 WorkBuddy | 「中转站优先」开关 + WorkBuddy 主进程状态 |
|
|
145
128
|
| 用量 | 区间概览(今天 / 近 7 天 / 近 30 天)、按模型聚合、积分包明细、限时优惠清单、最近调用;带「刷新余额」「清空本地账本」 |
|
|
146
129
|
|
|
147
130
|
### 安全清单(合规闸门)
|
|
@@ -150,14 +133,15 @@ WorkBuddy 官方对话给出的口径是:只调用「官方公开目录里、
|
|
|
150
133
|
`disabled`、内部路由别名、媒体/代码补全与状态不明的模型都不要经外部软件调用,否则有风控/封号风险。
|
|
151
134
|
这里把它落成代码:
|
|
152
135
|
|
|
153
|
-
- 白名单
|
|
136
|
+
- 白名单 22 个(`src/safety.js` 的 `SAFE_MODEL_IDS`,按 DeepSeek / GLM / 混元 / Kimi / 其他分组):
|
|
154
137
|
`deepseek-v4.1-flash`、`deepseek-v4-flash`、`deepseek-v4-pro`、`deepseek-v3-2-volc`、
|
|
155
138
|
`glm-5.3-flash`、`glm-5.3`、`glm-5.2`、`hy3`、`hy3-b`、`hy3-c`、`hy3-x`、`hunyuan-chat`、
|
|
156
|
-
`kimi-k2.5`、`kimi-k2.8-preview`、`kimi-k3-1`、`kimi-k3.1-pro`、`minimax-m2.7`、
|
|
139
|
+
`hy4-preview`、`kimi-k2.5`、`kimi-k2.8-preview`、`kimi-k3-1`、`kimi-k3.1-pro`、`minimax-m2.7`、
|
|
157
140
|
`minimax-m3.1-flash`、`mimo-v2.6-pro`、`space-bunny`、`step-5-preview`。
|
|
158
|
-
其中 `hy3*` 与 `*preview`
|
|
141
|
+
其中 `hy3*` 与 `*preview`(含 `hy4-preview`)标为「谨慎」(免费试用/预览,别做高频自动化)。
|
|
159
142
|
- 其余全部**拒绝**:`wb-lite`(目录 `disabled:true`)、`auto` / `fast-model` / `balanced-model` /
|
|
160
|
-
`deep-model`(内部路由别名)、4 个媒体模型、`codewise
|
|
143
|
+
`deep-model`(内部路由别名)、4 个媒体模型、`codewise-*`、其他 `hy4-preview*` 变体(只精确放行
|
|
144
|
+
`hy4-preview`)、19 个已下架的、
|
|
161
145
|
`glm-5.0-turbo`(11150 请求格式不符)。
|
|
162
146
|
- 闸门是 `worlds.workbuddy.safeOnly`(默认 `true`)。开着时 `wb_chat` / `wb_select_model` / 面板「选用」
|
|
163
147
|
三处一致拒绝,并说明「判定档位 + 理由 + 怎么解除」;关掉才放行,属于明示的风险自负。
|
|
@@ -202,25 +186,31 @@ WorkBuddy 官方对话给出的口径是:只调用「官方公开目录里、
|
|
|
202
186
|
| `baseUrl` | `""` | 自定义上游地址,代理/中转用(重启生效) |
|
|
203
187
|
| `maxTokens` | `2048` | `wb_chat` 单次输出上限 |
|
|
204
188
|
| `envPrompt` | `true` | 是否把桥接状态写进 system 前缀(关掉后「中转站优先」也不生效) |
|
|
205
|
-
| `prefer` | `false` |
|
|
206
|
-
| `hostInject` | `true` | 是否注入「开始」页按钮(关掉后不碰宿主文件,只用详情页开关) |
|
|
189
|
+
| `prefer` | `false` | 「中转站优先」,由详情页开关写入 |
|
|
207
190
|
| `safeOnly` | `true` | 只允许调用安全清单内的公开对话模型;关掉会放行 disabled / 别名 / 预览等项,风险自负 |
|
|
208
191
|
|
|
209
192
|
## 开发与校验
|
|
210
193
|
|
|
211
194
|
```bash
|
|
212
195
|
# 重新构建面板产物(改了 src/webui/client.js 后)
|
|
213
|
-
|
|
214
|
-
|
|
196
|
+
# 优先用本地 devDependency(锁在 package-lock.json 的 0.24.2),没装则退回宿主自带的 esbuild;
|
|
197
|
+
# `prepack` 走 `--strict`:两条路都没有就直接失败,绝不静默发布过期 dist。
|
|
198
|
+
node scripts/build-web.mjs
|
|
199
|
+
|
|
200
|
+
# 契约检查(不依赖宿主,CI 必跑):describe.json 与源码一致、版本号与 CHANGELOG 对齐、
|
|
201
|
+
# 促销/安全清单/账本断言,以及哨兵、计费域、429 软硬、面板白名单、并发、SSE flush 等回归断言
|
|
202
|
+
node scripts/contract.mjs
|
|
203
|
+
|
|
204
|
+
# 由源码重新生成 describe.json(改过工具声明或 ENV_PROMPT.md 之后)
|
|
205
|
+
node scripts/gen-describe.mjs
|
|
215
206
|
|
|
216
207
|
# 框架契约自检(dry-mount:定义、工具、envPrompt、webUi)
|
|
208
|
+
# 缺宿主时(CI)自动改跑「离线检查」:全部文件 node --check + contract,不再无条件成功
|
|
217
209
|
node scripts/selfcheck.mjs
|
|
218
210
|
|
|
219
211
|
# 真实窗口 UI 验证(headless Chrome + CDP,连跑 5 轮;需 Coopanion 正在运行)
|
|
220
212
|
node scripts/verify-ui.mjs --runs 5
|
|
221
213
|
|
|
222
|
-
# 宿主注入状态
|
|
223
|
-
node scripts/host-inject.mjs --check
|
|
224
214
|
```
|
|
225
215
|
|
|
226
216
|
UI 验证脚本的两个约定(踩过坑,别再用固定 sleep):每轮导航都带 `?t=<时间戳>` 整页重载
|
|
@@ -228,7 +218,7 @@ UI 验证脚本的两个约定(踩过坑,别再用固定 sleep):每轮
|
|
|
228
218
|
并把「路由挂载」与「面板渲染」拆成两条断言——否则一次产物没加载就会被误判成「按钮没了」。
|
|
229
219
|
|
|
230
220
|
版本号规范:任何改动都 bump `package.json` 的 `version`,备份目录按版本命名
|
|
231
|
-
(`F:\coo-connect-wb\0.
|
|
221
|
+
(`F:\coo-connect-wb\0.3.0\`),再用 `scripts/reinstall.ps1` 装;它先把 tgz 解出来,再拿**解出来的内容**与安装目录逐文件比对哈希,
|
|
232
222
|
不一致直接非零退出。
|
|
233
223
|
|
|
234
224
|
打包注意:**不要用 PowerShell 的 `Get-Content -Raw | Set-Content` 改 `package.json`**
|
|
@@ -236,38 +226,25 @@ UI 验证脚本的两个约定(踩过坑,别再用固定 sleep):每轮
|
|
|
236
226
|
用 node 读写 JSON;tgz 必须以 `package/` 为前缀:
|
|
237
227
|
|
|
238
228
|
```bash
|
|
239
|
-
tar -czf cortico-world-workbuddy-0.
|
|
229
|
+
tar -czf cortico-world-workbuddy-0.3.0.tgz -C <stage> package
|
|
240
230
|
```
|
|
241
231
|
|
|
242
232
|
协议细节参照 [dsh-connect-workbuddy](https://github.com/dingminhua/dsh-connect-workbuddy)
|
|
243
233
|
(MIT)的实测结论;扩展框架契约见 Cortico 的 `docs/extensions.md` / `docs/worlds.md` /
|
|
244
234
|
`docs/webui.md`。
|
|
245
235
|
|
|
246
|
-
##
|
|
236
|
+
## 宿主文件:一个字节都不改
|
|
247
237
|
|
|
248
|
-
|
|
238
|
+
0.3.0 起本扩展**不再往 Coopanion 主界面注入任何东西**——「中转站优先」只剩 World 详情页里
|
|
239
|
+
那个勾选框,工具、面板、账本全在各自主张的地方,`resources\app` 下不会有任何改动,卸载即干净。
|
|
249
240
|
|
|
250
|
-
|
|
251
|
-
面板,主页没有插槽),所以只能用一行注入实现:
|
|
241
|
+
如果你装过 0.2.x,宿主 `build\console\` 里可能还留着两处痕迹,删掉即可:
|
|
252
242
|
|
|
253
|
-
| 文件 |
|
|
254
|
-
|
|
255
|
-
| `<app>\build\console\index.html` |
|
|
256
|
-
| `<app>\build\console\workbuddy-home.js` |
|
|
257
|
-
| `<app>\build\console\index.html.workbuddy-backup` |
|
|
258
|
-
|
|
259
|
-
```powershell
|
|
260
|
-
node scripts/host-inject.mjs --check # 查:缺注入时退出码 1
|
|
261
|
-
node scripts/host-inject.mjs # 补:幂等,顺带补齐备份
|
|
262
|
-
node scripts/host-inject.mjs --restore # 还原:有备份用备份,没有就地剥掉那一行
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
- 注入脚本自带 try/catch:查不到 `workbuddy` World(比如扩展被卸载)时整行按钮自动消失,
|
|
266
|
-
不会在主页留下死按钮,也不会抛异常影响主界面。
|
|
267
|
-
- Coopanion 更新(换 `app.asar` / 重装)会把 `build/console` 覆盖回出厂状态 —— 注入随之消失,
|
|
268
|
-
扩展下次启动时 60 秒内自己补回来,四盏灯里的「开始页按钮」会告诉你当前状态。
|
|
269
|
-
- 卸载扩展:`stop()` 会自动还原(无需手动 `--restore`),然后把包从 `data/extensions` 里
|
|
270
|
-
`pnpm remove` 掉即可;想直接禁止改写宿主文件,把 `worlds.workbuddy.hostInject` 设为 `false`。
|
|
243
|
+
| 文件 | 说明 |
|
|
244
|
+
|---|---|
|
|
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` 干净后可删 |
|
|
271
248
|
|
|
272
249
|
## 发布(GitHub / npm / 扩展市场)
|
|
273
250
|
|
|
@@ -275,7 +252,7 @@ Cortico 的扩展**从 npm 安装**;GitHub 是源码与申请的入口,官
|
|
|
275
252
|
[cortico-extensions](https://github.com/Pal-AI-Lab/cortico-extensions) 只放标签词表、认证与覆盖项。
|
|
276
253
|
Action 定时扫 npm 生成市场目录,所以发版顺序是:**先 npm publish,再 `[sync]` 催收录**。
|
|
277
254
|
|
|
278
|
-
|
|
255
|
+
本包发布元数据:
|
|
279
256
|
|
|
280
257
|
| 项 | 值 | 为什么 |
|
|
281
258
|
|---|---|---|
|
|
@@ -289,12 +266,12 @@ Action 定时扫 npm 生成市场目录,所以发版顺序是:**先 npm publ
|
|
|
289
266
|
|
|
290
267
|
```bash
|
|
291
268
|
# 1. 发版前三连检(需要本机真实宿主)
|
|
292
|
-
node scripts/
|
|
293
|
-
node scripts/
|
|
269
|
+
node scripts/contract.mjs # 不依赖宿主,68 条断言
|
|
270
|
+
node scripts/selfcheck.mjs # dry-mount 框架契约
|
|
294
271
|
node scripts/verify-ui.mjs --runs 3
|
|
295
272
|
|
|
296
273
|
# 2. 提交并打 tag
|
|
297
|
-
git tag v0.
|
|
274
|
+
git tag v0.3.0 && git push --tags
|
|
298
275
|
|
|
299
276
|
# 3. 发布(prepack 会自动重建 dist/webui.js)
|
|
300
277
|
npm publish --access public
|
package/SECURITY.md
CHANGED
|
@@ -21,7 +21,7 @@ the Coopanion deployment `.env` if you paste one in the account panel yourself (
|
|
|
21
21
|
|
|
22
22
|
## Where data goes
|
|
23
23
|
|
|
24
|
-
Only
|
|
24
|
+
Only three hosts, all WorkBuddy's:
|
|
25
25
|
|
|
26
26
|
- `https://copilot.tencent.com` — model catalogue and chat completions (region `cn`)
|
|
27
27
|
- `https://www.codebuddy.cn` — credit balance (region `cn`)
|
|
@@ -34,9 +34,9 @@ Nothing else. No logs contain tokens: every log line goes through `maskToken()`.
|
|
|
34
34
|
- `<Coopanion data>/worlds/workbuddy/workbuddy-catalog.json` — cached model list, no credentials.
|
|
35
35
|
- `worlds.workbuddy.*` in the companion config (region, model, `prefer`, `envPrompt`).
|
|
36
36
|
- **Host files, only when the start-page button is injected:** `resources/app/build/console/index.html`
|
|
37
|
-
(
|
|
37
|
+
(0.3.0 removed the home-page injection; the extension no longer touches host files).
|
|
38
38
|
The original `index.html` is kept as `index.html.workbuddy-backup` next to it.
|
|
39
|
-
|
|
39
|
+
Nothing to undo — the extension does not modify Coopanion files anymore. Earlier versions
|
|
40
40
|
one-line reference by hand. A Coopanion update that replaces `build/console` simply removes the
|
|
41
41
|
injection; the extension puts it back on the next start.
|
|
42
42
|
|
package/describe.json
CHANGED
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
"name": "wb_select_model",
|
|
26
|
-
"description": "Select which WorkBuddy model wb_chat should use by default. The id must come from wb_list_models.
|
|
26
|
+
"description": "Select which WorkBuddy model wb_chat should use by default. The id must come from wb_list_models. Persists across restarts.",
|
|
27
27
|
"summary": {
|
|
28
|
-
"zh": "选择 wb_chat
|
|
29
|
-
"en": "Selects the default WorkBuddy model for wb_chat."
|
|
28
|
+
"zh": "选择 wb_chat 默认使用的 WorkBuddy 模型,选择会持久保存。",
|
|
29
|
+
"en": "Selects the default WorkBuddy model for wb_chat; the choice persists across restarts."
|
|
30
30
|
},
|
|
31
31
|
"tags": [
|
|
32
32
|
"write"
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
},
|
|
48
48
|
{
|
|
49
49
|
"name": "wb_chat",
|
|
50
|
-
"description": "Ask the selected WorkBuddy model a single-turn question and return its answer.
|
|
50
|
+
"description": "Ask the selected WorkBuddy model a single-turn question and return its answer. This spends the user's own WorkBuddy credits at the model's multiplier; keep prompts concise. Use the model parameter only to override the selected model for one call.",
|
|
51
51
|
"summary": {
|
|
52
|
-
"zh": "
|
|
53
|
-
"en": "Asks the selected WorkBuddy model a single-turn question
|
|
52
|
+
"zh": "向当前选中的 WorkBuddy 模型发一句单轮提问并取回答,会消耗用户自己的 WorkBuddy 积分。",
|
|
53
|
+
"en": "Asks the selected WorkBuddy model a single-turn question; spends the user's own WorkBuddy credits."
|
|
54
54
|
},
|
|
55
55
|
"tags": [
|
|
56
56
|
"write"
|
|
@@ -81,8 +81,8 @@
|
|
|
81
81
|
"name": "wb_credits",
|
|
82
82
|
"description": "Show the remaining WorkBuddy credit balance of the signed-in account (read-only). Requires the WorkBuddy desktop app to be running.",
|
|
83
83
|
"summary": {
|
|
84
|
-
"zh": "
|
|
85
|
-
"en": "
|
|
84
|
+
"zh": "读取当前 WorkBuddy 账号的剩余积分与各积分包的已用/剩余(只读)。",
|
|
85
|
+
"en": "Shows remaining WorkBuddy credits and per-package usage (read-only)."
|
|
86
86
|
},
|
|
87
87
|
"tags": [
|
|
88
88
|
"read"
|
|
@@ -103,5 +103,5 @@
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
],
|
|
106
|
-
"envPrompt": "## WorkBuddy bridge\n\nThis machine has a WorkBuddy desktop sign-in bridged in (region: {{workbuddy.region}}; signed in: {{workbuddy.authed}}).\nThe model catalog holds {{workbuddy.catalogSize}} models. The currently selected model is `{{workbuddy.model}}` with default credit multiplier {{workbuddy.multiplier}}.\nWorkBuddy desktop main process: {{workbuddy.process}}. Relay-first switch: {{workbuddy.priority}}.\nSpent today through the bridge: {{workbuddy.todayCredit}} credits / {{workbuddy.todayTokens}} tokens (locally recorded).\nThe multiplier above already includes any time-limited discount or free window that is active right now; `wb_list_models` also marks which offers are active and their hours.\n\n- Use `wb_list_models` to see every model with its multiplier before choosing; prefer low-multiplier models for casual tasks.\n- Safe-list gate: {{workbuddy.safeOnly}}. When it is `on`, only the models WorkBuddy publishes as public chat models are callable — `disabled` entries, internal routing aliases (`auto`, `fast-model`, `balanced-model`, `deep-model`), media/code models and delisted ones are refused. Do not try to work around a refusal; tell the user why and offer a safe model instead. `wb_list_models` with `all=true` shows the refused ones with reasons.\n- Use `wb_select_model` when the user asks to switch the WorkBuddy model.\n- `wb_chat` only works while the WorkBuddy desktop main process is running; otherwise it returns「未检测到 WorkBuddy 主进程」. Every call spends the user's own credits at that model's multiplier.\n- `wb_credits` is read-only and costs nothing (also requires the desktop process).\n\n### Relay first: {{workbuddy.priority}}\n\n- Switch `on` **and** process `running`: every user turn that expects a conversational answer (question, chat, writing, reasoning, rewrite, translation, summary) must be answered by a WorkBuddy model first — call `wb_chat` (omit `model` to use `{{workbuddy.model}}`), then speak the returned answer back in your own voice and name the model that answered. Only fall back to your own model if the call fails.\n- Switch `off` (default): do not call `wb_chat`; answer with your own model. If the user explicitly asks for WorkBuddy, `wb_chat` is still allowed — the desktop process must be running.\n- Tool errors and empty answers are not a reason to flip the switch; just say what happened
|
|
106
|
+
"envPrompt": "## WorkBuddy bridge\n\nThis machine has a WorkBuddy desktop sign-in bridged in (region: {{workbuddy.region}}; signed in: {{workbuddy.authed}}).\nThe model catalog holds {{workbuddy.catalogSize}} models. The currently selected model is `{{workbuddy.model}}` with default credit multiplier {{workbuddy.multiplier}}.\nWorkBuddy desktop main process: {{workbuddy.process}}. Relay-first switch: {{workbuddy.priority}}.\nSpent today through the bridge: {{workbuddy.todayCredit}} credits / {{workbuddy.todayTokens}} tokens (locally recorded).\nThe multiplier above already includes any time-limited discount or free window that is active right now; `wb_list_models` also marks which offers are active and their hours.\n\n- Use `wb_list_models` to see every model with its multiplier before choosing; prefer low-multiplier models for casual tasks.\n- Safe-list gate: {{workbuddy.safeOnly}}. When it is `on`, only the models WorkBuddy publishes as public chat models are callable — `disabled` entries, internal routing aliases (`auto`, `fast-model`, `balanced-model`, `deep-model`), media/code models and delisted ones are refused. Do not try to work around a refusal; tell the user why and offer a safe model instead. `wb_list_models` with `all=true` shows the refused ones with reasons.\n- Use `wb_select_model` when the user asks to switch the WorkBuddy model.\n- `wb_chat` only works while the WorkBuddy desktop main process is running; otherwise it returns「未检测到 WorkBuddy 主进程」. Every call spends the user's own credits at that model's multiplier.\n- `wb_credits` is read-only and costs nothing (also requires the desktop process).\n\n### Relay first: {{workbuddy.priority}}\n\n- Switch `on` **and** process `running`: every user turn that expects a conversational answer (question, chat, writing, reasoning, rewrite, translation, summary) must be answered by a WorkBuddy model first — call `wb_chat` (omit `model` to use `{{workbuddy.model}}`), then speak the returned answer back in your own voice and name the model that answered. Only fall back to your own model if the call fails.\n- Switch `off` (default): do not call `wb_chat`; answer with your own model. If the user explicitly asks for WorkBuddy, `wb_chat` is still allowed — the desktop process must be running.\n- Tool errors and empty answers are not a reason to flip the switch; just say what happened."
|
|
107
107
|
}
|
package/dist/webui.js
CHANGED
|
@@ -36,19 +36,12 @@ var TEXT = {
|
|
|
36
36
|
currentModel: "\u5F53\u524D\u6A21\u578B",
|
|
37
37
|
priorityTitle: "\u4E2D\u8F6C\u7AD9\u4F18\u5148",
|
|
38
38
|
priorityLabel: "\u662F\u5426\u542F\u7528Workbuddy",
|
|
39
|
-
priorityDesc: "\
|
|
39
|
+
priorityDesc: "\u6253\u5F00\u540E\u684C\u5BA0\u6BCF\u8F6E\u5BF9\u8BDD\u4F18\u5148\u8C03\u7528 WorkBuddy \u7684\u6A21\u578B\uFF0C\u5173\u95ED\u5219\u5B8C\u5168\u8DF3\u8FC7 WorkBuddy\u3002\u9700\u8981 WorkBuddy \u684C\u9762\u7AEF\u4E3B\u8FDB\u7A0B\u5728\u8FD0\u884C\u3002",
|
|
40
40
|
procRunning: "WorkBuddy \u4E3B\u8FDB\u7A0B\uFF1A\u8FD0\u884C\u4E2D",
|
|
41
41
|
procStopped: "WorkBuddy \u4E3B\u8FDB\u7A0B\uFF1A\u672A\u68C0\u6D4B\u5230",
|
|
42
42
|
noProcess: "\u672A\u68C0\u6D4B\u5230Workbuddy",
|
|
43
43
|
enabledOn: "\u5DF2\u5F00\u542F\uFF1A\u684C\u5BA0\u4F18\u5148\u8D70 WorkBuddy \u6A21\u578B",
|
|
44
44
|
enabledOff: "\u5DF2\u5173\u95ED\uFF1A\u684C\u5BA0\u8DF3\u8FC7 WorkBuddy",
|
|
45
|
-
hostOk: "\u5F00\u59CB\u9875\u6309\u94AE\uFF1A\u5DF2\u6CE8\u5165",
|
|
46
|
-
hostBroken: "\u5F00\u59CB\u9875\u6309\u94AE\uFF1A\u672A\u6CE8\u5165\uFF08\u5BBF\u4E3B\u5347\u7EA7\u53EF\u80FD\u8986\u76D6\u4E86\u63A7\u5236\u53F0\u6587\u4EF6\uFF09",
|
|
47
|
-
hostUnknown: "\u5F00\u59CB\u9875\u6309\u94AE\uFF1A\u72B6\u6001\u672A\u77E5",
|
|
48
|
-
repair: "\u91CD\u65B0\u6CE8\u5165\u5F00\u59CB\u9875\u6309\u94AE",
|
|
49
|
-
repairing: "\u6B63\u5728\u91CD\u65B0\u6CE8\u5165\u2026",
|
|
50
|
-
repaired: "\u5DF2\u4FEE\u590D\uFF0C\u91CD\u65B0\u6253\u5F00\u63A7\u5236\u53F0\u5373\u53EF\u770B\u5230\u6309\u94AE",
|
|
51
|
-
repairFail: "\u4FEE\u590D\u5931\u8D25",
|
|
52
45
|
usageTitle: "\u7528\u91CF",
|
|
53
46
|
usageDesc: "\u672C\u673A\u8BB0\u8D26\u7684\u8C03\u7528\u7528\u91CF\u4E0E WorkBuddy \u79EF\u5206\u5305\u4F59\u989D\u3002\u79EF\u5206\u53D6\u4E0A\u6E38\u6BCF\u6B21\u8C03\u7528\u56DE\u4F20\u7684\u771F\u5B9E\u6263\u8D39\uFF08\u53EF\u80FD\u4E3A 0\uFF09\uFF0C\u500D\u7387\u6309\u76EE\u5F55 + \u9650\u65F6\u4F18\u60E0\u5B9E\u65F6\u8BA1\u7B97\u3002",
|
|
54
47
|
usageRefresh: "\u5237\u65B0\u4F59\u989D",
|
|
@@ -128,13 +121,6 @@ var TEXT = {
|
|
|
128
121
|
noProcess: "Workbuddy not detected",
|
|
129
122
|
enabledOn: "On: the pet asks WorkBuddy first",
|
|
130
123
|
enabledOff: "Off: the pet skips WorkBuddy",
|
|
131
|
-
hostOk: "Home button: injected",
|
|
132
|
-
hostBroken: "Home button: not injected (a host update may have replaced the console files)",
|
|
133
|
-
hostUnknown: "Home button: unknown",
|
|
134
|
-
repair: "Re-inject the home button",
|
|
135
|
-
repairing: "Re-injecting\u2026",
|
|
136
|
-
repaired: "Fixed. Reopen the console to see the button",
|
|
137
|
-
repairFail: "Repair failed",
|
|
138
124
|
usageTitle: "Usage",
|
|
139
125
|
usageDesc: "Locally recorded call usage plus the WorkBuddy credit balance. Credits come from the per-call figure the upstream returns (may be 0); multipliers combine the catalog with time-limited offers in real time.",
|
|
140
126
|
usageRefresh: "Refresh balance",
|
|
@@ -435,40 +421,10 @@ function mountPriority(ctx) {
|
|
|
435
421
|
const sheet = ui.sheet({ title: s.priorityTitle, desc: s.priorityDesc });
|
|
436
422
|
ctx.root.append(sheet.el);
|
|
437
423
|
const statusLine = ui.msgline();
|
|
438
|
-
const hostLine = ui.msgline();
|
|
439
|
-
const hostBar = ui.actions();
|
|
440
|
-
const repairBtn = ui.button(s.repair, {
|
|
441
|
-
size: "sm",
|
|
442
|
-
variant: "plain",
|
|
443
|
-
onClick: async () => {
|
|
444
|
-
repairBtn.disabled = true;
|
|
445
|
-
hostLine.textContent = s.repairing;
|
|
446
|
-
try {
|
|
447
|
-
const r = await ctx.invoke("repair");
|
|
448
|
-
hostLine.textContent = r?.ok ? s.repaired : `${s.repairFail}\uFF1A${r?.error ?? r?.hostUi?.reason ?? ""}`;
|
|
449
|
-
ui.toast(r?.ok ? s.repaired : s.repairFail, r?.ok ? "ok" : "bad");
|
|
450
|
-
await load();
|
|
451
|
-
} catch (err) {
|
|
452
|
-
hostLine.textContent = `${s.repairFail}\uFF1A${String(err?.message ?? err)}`;
|
|
453
|
-
ui.toast(s.repairFail, "bad");
|
|
454
|
-
} finally {
|
|
455
|
-
repairBtn.disabled = false;
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
});
|
|
459
|
-
hostBar.append(repairBtn);
|
|
460
424
|
function apply(r) {
|
|
461
425
|
if (!r) return;
|
|
462
426
|
box.setChecked(r.prefer === true);
|
|
463
427
|
statusLine.textContent = r.running ? s.procRunning : s.procStopped;
|
|
464
|
-
const host = r.hostUi;
|
|
465
|
-
if (!host) {
|
|
466
|
-
hostLine.textContent = s.hostUnknown;
|
|
467
|
-
hostBar.style.display = "none";
|
|
468
|
-
return;
|
|
469
|
-
}
|
|
470
|
-
hostLine.textContent = host.ok ? s.hostOk : `${s.hostBroken}\uFF08${host.label ?? host.reason}\uFF09`;
|
|
471
|
-
hostBar.style.display = host.ok ? "none" : "";
|
|
472
428
|
}
|
|
473
429
|
const box = ui.checkbox(s.priorityLabel, {
|
|
474
430
|
checked: false,
|
|
@@ -490,7 +446,7 @@ function mountPriority(ctx) {
|
|
|
490
446
|
}
|
|
491
447
|
}
|
|
492
448
|
});
|
|
493
|
-
sheet.body.append(box.el, statusLine
|
|
449
|
+
sheet.body.append(box.el, statusLine);
|
|
494
450
|
async function load() {
|
|
495
451
|
apply(await ctx.invoke("state"));
|
|
496
452
|
}
|
|
@@ -612,7 +568,9 @@ function mountUsage(ctx) {
|
|
|
612
568
|
recentTable.addRow([
|
|
613
569
|
when,
|
|
614
570
|
r.model ?? "\u2014",
|
|
615
|
-
|
|
571
|
+
// 账本里的字段名就是 total/prompt/completion(不是 totalTokens),
|
|
572
|
+
// 以前这里恒读出 0,最近调用表的 token 列一直是 0。
|
|
573
|
+
fmtNum(r.total ?? (r.prompt ?? 0) + (r.completion ?? 0)),
|
|
616
574
|
r.ok === false ? "\u2014" : fmtNum(r.credit),
|
|
617
575
|
typeof r.durationMs === "number" ? `${r.durationMs} ms` : "\u2014"
|
|
618
576
|
]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cortico-world-workbuddy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "把 Windows 端已登录的 WorkBuddy 客户端模型桥接进 Coopanion:读取本机登录态,列出模型目录与默认积分倍率,供 Coo 调用。",
|
|
6
6
|
"license": "MIT",
|
|
@@ -49,16 +49,17 @@
|
|
|
49
49
|
"CHANGELOG.md",
|
|
50
50
|
"describe.json",
|
|
51
51
|
"scripts",
|
|
52
|
+
"!scripts/visual",
|
|
52
53
|
"LICENSE",
|
|
53
|
-
"SECURITY.md"
|
|
54
|
-
"ENV_PROMPT.md"
|
|
54
|
+
"SECURITY.md"
|
|
55
55
|
],
|
|
56
56
|
"scripts": {
|
|
57
|
-
"build:web": "
|
|
57
|
+
"build:web": "node scripts/build-web.mjs",
|
|
58
58
|
"selfcheck": "node scripts/selfcheck.mjs",
|
|
59
|
-
"host-inject": "node scripts/host-inject.mjs",
|
|
60
59
|
"verify": "node scripts/verify-ui.mjs --runs 3",
|
|
61
|
-
"prepack": "
|
|
60
|
+
"prepack": "node scripts/build-web.mjs --strict",
|
|
61
|
+
"gen:describe": "node scripts/gen-describe.mjs",
|
|
62
|
+
"contract": "node scripts/contract.mjs"
|
|
62
63
|
},
|
|
63
64
|
"author": {
|
|
64
65
|
"name": "大肥鱼 (aechoa215)",
|