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 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
- 打开后桌宠每轮对话都先问 WorkBuddy。
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.1.5,Coopanion 0.2.17 实机验证)
17
+ ## 安装(0.3.0,Coopanion 0.2.17 实机验证)
18
18
 
19
- 一条命令(推荐,脚本会做完打包、装卸、哈希与版本校验、开始页注入):
19
+ 一条命令(推荐,脚本会做完打包、装卸、哈希与版本校验):
20
20
 
21
21
  ```powershell
22
- pwsh -File scripts/reinstall.ps1
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 "F:\coo-connect-wb\cortico-world-workbuddy-0.1.4.tgz" `
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. 装「开始」页按钮(0.1.3 起脚本化,幂等):
52
+ 3. 重启 Coopanion(ESM 模块缓存不支持热换代码),用带环境清理的启动器:
53
53
 
54
54
  ```powershell
55
- node scripts/host-inject.mjs # 检查 + 修复
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
- - **注入会自动清**:停用 World、卸扩展、退出 Coopanion 时 `stop()` 都会调用
86
- `removeHostInjection()`,把 `index.html` 的引用行剥掉并删掉注入脚本与备份——
87
- 宿主目录回到「没装过这个扩展」的样子,不会留下永久改动。
88
- - **想手动清**:`node scripts/host-inject.mjs --restore`(或手工删
89
- `build\console\workbuddy-home.js` 并去掉 `index.html` 里那行)。
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 /v2/enterprises/personal/models 模型目录(credits = 积分倍率)
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
- | 开始页按钮 | 主界面「开始」→「可选择的模型:」下一排「中转站优先:」+ WorkBuddy 图标 | 点击高亮=开;再点熄灭=关 |
130
- | 详情页开关 | 「World 扩展」→ WorkBuddy 桥接 →「是否启用Workbuddy」 | 与按钮同步,任一入口改两处都变 |
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
- - 点按钮时若没检测到主进程:按钮保持熄灭 + 弹「未检测到Workbuddy」,不会把开关打开。
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
- - 白名单 21 个(`src/safety.js` 的 `SAFE_MODEL_IDS`,按 DeepSeek / GLM / 混元 / Kimi / 其他分组):
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-*`、`hy4-preview*`、19 个已下架的、
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
- node <Coopanion>/resources/app/node_modules/esbuild/bin/esbuild \
214
- src/webui/client.js --bundle --format=esm --outfile=dist/webui.js
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.1.4\`),再用 `scripts/reinstall.ps1` 装;它会在装完后逐文件比对哈希,
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.1.4.tgz -C <stage> package
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
- > 这是本扩展唯一会碰到 Coopanion 安装目录的地方,装之前请务必看完。
238
+ 0.3.0 起本扩展**不再往 Coopanion 主界面注入任何东西**——「中转站优先」只剩 World 详情页里
239
+ 那个勾选框,工具、面板、账本全在各自主张的地方,`resources\app` 下不会有任何改动,卸载即干净。
249
240
 
250
- 「开始」页的「中转站优先:」按钮没有官方扩展点(Cortico 的 WebUI 只给每个 World 提供自己的
251
- 面板,主页没有插槽),所以只能用一行注入实现:
241
+ 如果你装过 0.2.x,宿主 `build\console\` 里可能还留着两处痕迹,删掉即可:
252
242
 
253
- | 文件 | 改动 | 还原 |
254
- |---|---|---|
255
- | `<app>\build\console\index.html` | 在 `<script type="module" src="./index.js">` 前插入一行 `<script type="module" src="./workbuddy-home.js">` | 用备份 `index.html.workbuddy-backup` 覆盖,或删掉那一行 |
256
- | `<app>\build\console\workbuddy-home.js` | 新增注入脚本(约 11 KB,自包含,内嵌图标 data URL) | 删除该文件 |
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
- 本包发布元数据(0.1.4 起):
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/selfcheck.mjs
293
- node scripts/host-inject.mjs --check
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.1.4 && git push --tags
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 two hosts, both WorkBuddy's:
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
- (one extra `<script>` line before the app bundle) and `resources/app/build/console/workbuddy-home.js`.
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
- Undo with `node scripts/host-inject.mjs --restore`, or delete `workbuddy-home.js` and the
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. Refused when worlds.workbuddy.safeOnly is on and the model is outside the safe list. Persists across restarts.",
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 默认调用的 WorkBuddy 模型。",
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. Requires the WorkBuddy desktop app to be running; otherwise the call fails with a not-detected message. 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.",
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": "用选中的 WorkBuddy 模型回答一个单轮问题(消耗本人账号积分)。",
53
- "en": "Asks the selected WorkBuddy model a single-turn question (spends your own credits)."
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": "只读查询当前账号的 WorkBuddy 积分余额。",
85
- "en": "Read-only check of the WorkBuddy credit balance."
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.\n"
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: "\u4E0E\u300C\u5F00\u59CB\u300D\u9875\u7684\u300C\u4E2D\u8F6C\u7AD9\u4F18\u5148\u300D\u6309\u94AE\u662F\u540C\u4E00\u4EFD\u72B6\u6001\uFF1A\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",
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, hostLine, hostBar);
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
- fmtNum(r.totalTokens ?? (r.promptTokens ?? 0) + (r.completionTokens ?? 0)),
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.1.7",
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": "esbuild src/webui/client.js --bundle --format=esm --outfile=dist/webui.js",
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": "npm run build:web"
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)",