feat(dashboard): TraeX herdr 插件 opt-in 即时安装 + per-bot 会话后端实时切换 - #397
Conversation
|
Babysit update: I checked the contribution rules and the PR already has the required Chinese summary/impact/validation sections and a valid I also synced the branch with latest
The reason CI appears to have “no response” is that the GitHub Actions run is in |
deepcoldy
left a comment
There was a problem hiding this comment.
Hi @Phoobobo,感谢这个 PR!我做了一轮 review。功能方向没问题,spawnHerdr 重构很干净(还顺手改进了 ENOENT 报错)、warn-only 非阻塞设计是对的、i18n/help 文案也准确。pnpm build + 相关 setup/herdr 单测(merge master 后)本地都绿。
但有一个合并前需要重做的点,maintainer 已拍板:改成 dashboard 可选的 opt-in,而不是自动安装 fork 版本。下面是具体反馈。
🔴 主要问题:daemon 启动路径自动 --yes 安装并执行「个人仓库」插件(供应链风险)
当前 ensureTraexPlugin() 会在每次 botmux start/restart(存在 herdr+traex bot 时)于 ensureDependencies 同步执行:
herdr plugin install Phoobobo/herdr-traex-integration --yes && herdr plugin action invoke com.traex.herdr-integration.install
- 源是个人 GitHub 账号的仓库、无版本钉死(裸
user/repo永远拉默认分支最新),且 install action 会执行任意代码(写~/.traehooks)。账号改名 / 删库 / 内容变更 / 被盗,botmux 都会无声拉取并执行。 - 和现有行为性质不同:现有
herdr integration install claude/codex/...装的是 herdr.dev 官方 curate 的集成;这里是 botmux 源码里写死并自动执行一个第三方个人 repo。 - 即使是非阻塞、只 warn,「默认自动执行外部代码」这条本身就不应该发生。
✅ 需要的改法:dashboard opt-in(maintainer 决定)
1) 触发改 opt-in —— 全局开关,默认关
- 用全局配置开关,不要做成 per-bot:插件写的是 host 级
~/.traehooks,是整机一次性的东西,per-bot 语义会打架。 - 仓库里有现成模式可以直接抄 ——
chatBotDiscovery:见src/config.ts的resolveChatBotDiscoveryConfig(存~/.botmux/config.json的dashboard.chatBotDiscovery+ env 兜底 + 合理默认),dashboard Settings 开关通过src/dashboard/settings-write-applier.ts的applySettingsWrite持久化。 ensureTraexPlugin在「herdr+traex bot 存在」之外,再加这个开关做 gate;默认关 = 什么都不装。
2) 别在 botmux 源码里写死 fork spec
- 就算加了开关,如果「开」仍等于装写死的
Phoobobo/...,botmux 还是在背书一个 unpinned 个人 repo。 - 推荐:botmux 不带默认 spec,开关打开后由 operator 在 dashboard 自己填信得过的 plugin spec,botmux 保持中立。
- 次选:保留默认但钉 tag/SHA,且 UI 明确标注「第三方 / 社区源」;等这个插件被 herdr 官方收编后再换成官方 pinned 默认。
🟡 顺带修两个 correctness 点
#2 install action 每次启动都重跑 —— ensureTraexPlugin 里 plugin action invoke ...install 在 if (!alreadyInstalled) 块之外,所以即使插件已装也每次重写 hooks。这既给 start/restart 关键路径加了同步 spawn,又完全依赖那个外部 action 幂等;若它是 append 而非 replace,反复重启会污染 ~/.trae。建议仅 fresh install 时 invoke,或先廉价探测 hooks 是否已在。
#3 isTraexPluginInstalled 写死 herdr JSON 结构 —— 假设 parsed.result.plugins[].plugin_id。注意 catch 里的 substring 兜底只覆盖 JSON.parse 抛错:如果 JSON 能解析但结构不同(比如顶层是 plugins 而非 result.plugins),会直接返回 false 且不走兜底 → 「已安装」永远检测不到 → 每次重启都重试 install(120s 网络超时风险)。建议对着真实 herdr plugin list --json 输出核一下结构,并让 shape 不符时也走兜底。
🟢 测试
src/setup/ensure-herdr-integrations.ts 目前没有单测,而这个 PR 加了实打实的分支(装成功 / 已装 / 装失败 / action 失败 / JSON 兜底)。按仓库规范请补 mock spawnSync 的单测;PR 描述目前只有 pnpm build,建议补上测试运行结果。
辛苦!方向是对的,核心就是把「自动装 fork」换成「dashboard 开关(默认关)+ 源不写死」,另外把 #2 / #3 一起收一下。有问题欢迎在这里讨论 👌
287ec9f to
d3dc591
Compare
|
Addressed the review feedback in the latest force-push (
Validation:
Freshness after push verified with CI is still |
在 deepcoldy#397(TraeX herdr 插件 opt-in)基础上补齐两块能力,均可在 Dashboard 实时操作, 对现有用户默认零影响。 Part 1 · TraeX 插件(承接 review 反馈) - 开关打开并填写可信 spec 后「即时安装」,不再等下次 restart:install-now 挂在已 鉴权的 PUT /api/settings 处理里,安装结果回显到 Dashboard(成功/已装/失败) - 插件安装路径改为 async spawn(installTraexPluginNow),不阻塞 daemon 事件循环 - 作者推荐 spec 作为「一键填入」可选项呈现(第三方来源、附信任提示);botmux 仍不 内置默认源、不静默自动执行第三方代码 - 开了没填 spec 当场标红必填(不再静默 no-op);spec 输入框改「失焦/回车提交 + 未变跳过」,修复每键一次 PUT 会打断输入的问题 - 修复 reportHerdrIntegrations 早返回吞掉「开了没填 spec」告警(traex 为唯一 herdr CLI 时) Part 2 · per-bot 会话后端实时切换 - Bot Defaults 页新增 backend 下拉(pty/tmux/herdr/zellij/自动);PUT /api/bots/:id/backend-type 校验后 writeBotsJsonAtomic 落盘 + 同步内存 registry - 实时安全:运行中会话保留启动时 Session.backendType(getSessionPersistentBackendType 优先用冻结值、不回落当前全局默认),仅新会话采用新后端 → 切换不会打断/僵尸关旧会话 影响面:非 herdr / 非 traex bot 行为不变;两个开关默认关 / 默认「自动」;新增字段 可选,旧 config.json 照常工作。 测试:pnpm build ✅;新增 test/backend-type-store.test.ts(4)、重写 test/ensure-herdr-integrations.test.ts 覆盖 async 安装/幂等/兜底/install-now/ settings 触发(10);相关 322 测试全绿(含 daemon-internal-api 158)
在 deepcoldy#397(TraeX herdr 插件 opt-in)基础上补齐两块能力,均可在 Dashboard 实时操作, 对现有用户默认零影响。 Part 1 · TraeX 插件(承接 review 反馈) - 开关打开并填写可信 spec 后「即时安装」,不再等下次 restart:install-now 挂在已 鉴权的 PUT /api/settings 处理里,安装结果回显到 Dashboard(成功/已装/失败) - 插件安装路径改为 async spawn(installTraexPluginNow),不阻塞 daemon 事件循环 - 作者推荐 spec 作为「一键填入」可选项呈现(第三方来源、附信任提示);botmux 仍不 内置默认源、不静默自动执行第三方代码 - 开了没填 spec 当场标红必填(不再静默 no-op);spec 输入框改「失焦/回车提交 + 未变跳过」,修复每键一次 PUT 会打断输入的问题 - 修复 reportHerdrIntegrations 早返回吞掉「开了没填 spec」告警(traex 为唯一 herdr CLI 时) Part 2 · per-bot 会话后端实时切换 - Bot Defaults 页新增 backend 下拉(pty/tmux/herdr/zellij/自动);PUT /api/bots/:id/backend-type 校验后 writeBotsJsonAtomic 落盘 + 同步内存 registry - 实时安全:运行中会话保留启动时 Session.backendType(getSessionPersistentBackendType 优先用冻结值、不回落当前全局默认),仅新会话采用新后端 → 切换不会打断/僵尸关旧会话 影响面:非 herdr / 非 traex bot 行为不变;两个开关默认关 / 默认「自动」;新增字段 可选,旧 config.json 照常工作。 测试:pnpm build ✅;新增 test/backend-type-store.test.ts(4)、重写 test/ensure-herdr-integrations.test.ts 覆盖 async 安装/幂等/兜底/install-now/ settings 触发(10);相关 322 测试全绿(含 daemon-internal-api 158)
9d4cec1 to
ed82b7a
Compare
|
Babysit poll update: preserved the newly added dashboard live-install/per-bot backend commit, rebased both PR commits onto current master Validation after rebase:
PR is mergeable with no conflict, but still blocked on maintainer re-review and fork Actions approval: https://github.com/deepcoldy/botmux/actions/runs/29177121313 |
|
我让agent解下冲突 |
在 deepcoldy#397(TraeX herdr 插件 opt-in)基础上补齐两块能力,均可在 Dashboard 实时操作, 对现有用户默认零影响。 Part 1 · TraeX 插件(承接 review 反馈) - 开关打开并填写可信 spec 后「即时安装」,不再等下次 restart:install-now 挂在已 鉴权的 PUT /api/settings 处理里,安装结果回显到 Dashboard(成功/已装/失败) - 插件安装路径改为 async spawn(installTraexPluginNow),不阻塞 daemon 事件循环 - 作者推荐 spec 作为「一键填入」可选项呈现(第三方来源、附信任提示);botmux 仍不 内置默认源、不静默自动执行第三方代码 - 开了没填 spec 当场标红必填(不再静默 no-op);spec 输入框改「失焦/回车提交 + 未变跳过」,修复每键一次 PUT 会打断输入的问题 - 修复 reportHerdrIntegrations 早返回吞掉「开了没填 spec」告警(traex 为唯一 herdr CLI 时) Part 2 · per-bot 会话后端实时切换 - Bot Defaults 页新增 backend 下拉(pty/tmux/herdr/zellij/自动);PUT /api/bots/:id/backend-type 校验后 writeBotsJsonAtomic 落盘 + 同步内存 registry - 实时安全:运行中会话保留启动时 Session.backendType(getSessionPersistentBackendType 优先用冻结值、不回落当前全局默认),仅新会话采用新后端 → 切换不会打断/僵尸关旧会话 影响面:非 herdr / 非 traex bot 行为不变;两个开关默认关 / 默认「自动」;新增字段 可选,旧 config.json 照常工作。 测试:pnpm build ✅;新增 test/backend-type-store.test.ts(4)、重写 test/ensure-herdr-integrations.test.ts 覆盖 async 安装/幂等/兜底/install-now/ settings 触发(10);相关 322 测试全绿(含 daemon-internal-api 158)
…影响运行中会话 Codex deepcoldy#397 二审 P1-1:切 backend 只影响新会话的承诺,在 re-fork/cold-resume/shutdown 路径下不成立。forkWorker(worker-pool.ts) 每次从实时 botCfg 重算 backend 并覆盖 Session.backendType 冻结 stamp;shutdown(daemon.ts) 也按实时 backend 分流 → 旧会话 被改后端、persistent pane 孤儿化。 修:抽两个被生产实际调用的纯函数到 persistent-backend.ts—— · resolveSpawnBackendType(sessionStamp, botType, defaultType):forkWorker 用, 冻结值优先(旧会话保 stamp,新会话才用实时配置) · shutdownBackendDisposition(ds):shutdown 用,按 getSessionPersistentBackendType 的冻结值分流 detach/close 回归:persistent-backend-type.test 直接测这两个函数(旧实现上会真红——已验证: 把两函数还原成实时配置,3 条冻结断言即失败),而非只测本就正确的 getSessionPersistentBackendType。
ed82b7a to
dfe4061
Compare
在 deepcoldy#397(TraeX herdr 插件 opt-in)基础上补齐两块能力,均可在 Dashboard 实时操作, 对现有用户默认零影响。 Part 1 · TraeX 插件(承接 review 反馈) - 开关打开并填写可信 spec 后「即时安装」,不再等下次 restart:install-now 挂在已 鉴权的 PUT /api/settings 处理里,安装结果回显到 Dashboard(成功/已装/失败) - 插件安装路径改为 async spawn(installTraexPluginNow),不阻塞 daemon 事件循环 - 作者推荐 spec 作为「一键填入」可选项呈现(第三方来源、附信任提示);botmux 仍不 内置默认源、不静默自动执行第三方代码 - 开了没填 spec 当场标红必填(不再静默 no-op);spec 输入框改「失焦/回车提交 + 未变跳过」,修复每键一次 PUT 会打断输入的问题 - 修复 reportHerdrIntegrations 早返回吞掉「开了没填 spec」告警(traex 为唯一 herdr CLI 时) Part 2 · per-bot 会话后端实时切换 - Bot Defaults 页新增 backend 下拉(pty/tmux/herdr/zellij/自动);PUT /api/bots/:id/backend-type 校验后 writeBotsJsonAtomic 落盘 + 同步内存 registry - 实时安全:运行中会话保留启动时 Session.backendType(getSessionPersistentBackendType 优先用冻结值、不回落当前全局默认),仅新会话采用新后端 → 切换不会打断/僵尸关旧会话 影响面:非 herdr / 非 traex bot 行为不变;两个开关默认关 / 默认「自动」;新增字段 可选,旧 config.json 照常工作。 测试:pnpm build ✅;新增 test/backend-type-store.test.ts(4)、重写 test/ensure-herdr-integrations.test.ts 覆盖 async 安装/幂等/兜底/install-now/ settings 触发(10);相关 322 测试全绿(含 daemon-internal-api 158)
…影响运行中会话 Codex deepcoldy#397 二审 P1-1:切 backend 只影响新会话的承诺,在 re-fork/cold-resume/shutdown 路径下不成立。forkWorker(worker-pool.ts) 每次从实时 botCfg 重算 backend 并覆盖 Session.backendType 冻结 stamp;shutdown(daemon.ts) 也按实时 backend 分流 → 旧会话 被改后端、persistent pane 孤儿化。 修:抽两个被生产实际调用的纯函数到 persistent-backend.ts—— · resolveSpawnBackendType(sessionStamp, botType, defaultType):forkWorker 用, 冻结值优先(旧会话保 stamp,新会话才用实时配置) · shutdownBackendDisposition(ds):shutdown 用,按 getSessionPersistentBackendType 的冻结值分流 detach/close 回归:persistent-backend-type.test 直接测这两个函数(旧实现上会真红——已验证: 把两函数还原成实时配置,3 条冻结断言即失败),而非只测本就正确的 getSessionPersistentBackendType。
40a7a8f to
7d70da6
Compare
在 deepcoldy#397(TraeX herdr 插件 opt-in)基础上补齐两块能力,均可在 Dashboard 实时操作, 对现有用户默认零影响。 Part 1 · TraeX 插件(承接 review 反馈) - 开关打开并填写可信 spec 后「即时安装」,不再等下次 restart:install-now 挂在已 鉴权的 PUT /api/settings 处理里,安装结果回显到 Dashboard(成功/已装/失败) - 插件安装路径改为 async spawn(installTraexPluginNow),不阻塞 daemon 事件循环 - 作者推荐 spec 作为「一键填入」可选项呈现(第三方来源、附信任提示);botmux 仍不 内置默认源、不静默自动执行第三方代码 - 开了没填 spec 当场标红必填(不再静默 no-op);spec 输入框改「失焦/回车提交 + 未变跳过」,修复每键一次 PUT 会打断输入的问题 - 修复 reportHerdrIntegrations 早返回吞掉「开了没填 spec」告警(traex 为唯一 herdr CLI 时) Part 2 · per-bot 会话后端实时切换 - Bot Defaults 页新增 backend 下拉(pty/tmux/herdr/zellij/自动);PUT /api/bots/:id/backend-type 校验后 writeBotsJsonAtomic 落盘 + 同步内存 registry - 实时安全:运行中会话保留启动时 Session.backendType(getSessionPersistentBackendType 优先用冻结值、不回落当前全局默认),仅新会话采用新后端 → 切换不会打断/僵尸关旧会话 影响面:非 herdr / 非 traex bot 行为不变;两个开关默认关 / 默认「自动」;新增字段 可选,旧 config.json 照常工作。 测试:pnpm build ✅;新增 test/backend-type-store.test.ts(4)、重写 test/ensure-herdr-integrations.test.ts 覆盖 async 安装/幂等/兜底/install-now/ settings 触发(10);相关 322 测试全绿(含 daemon-internal-api 158)
…影响运行中会话 Codex deepcoldy#397 二审 P1-1:切 backend 只影响新会话的承诺,在 re-fork/cold-resume/shutdown 路径下不成立。forkWorker(worker-pool.ts) 每次从实时 botCfg 重算 backend 并覆盖 Session.backendType 冻结 stamp;shutdown(daemon.ts) 也按实时 backend 分流 → 旧会话 被改后端、persistent pane 孤儿化。 修:抽两个被生产实际调用的纯函数到 persistent-backend.ts—— · resolveSpawnBackendType(sessionStamp, botType, defaultType):forkWorker 用, 冻结值优先(旧会话保 stamp,新会话才用实时配置) · shutdownBackendDisposition(ds):shutdown 用,按 getSessionPersistentBackendType 的冻结值分流 detach/close 回归:persistent-backend-type.test 直接测这两个函数(旧实现上会真红——已验证: 把两函数还原成实时配置,3 条冻结断言即失败),而非只测本就正确的 getSessionPersistentBackendType。
7d70da6 to
0b543d4
Compare
背景
这个 PR 起于「为 herdr + TraeX bot 安装集成插件」。Review 发现原方案会在 daemon 启动时从写死的第三方源安装并执行代码,存在供应链与恢复安全问题,因此重构为:默认关闭、operator 明确选择来源、安装过程可验证、会话后端 freeze-once。
改了什么
Part 1 · TraeX herdr 插件(opt-in + 即时安装)
source与可选ref,botmux 不内置推荐源。旧 review 版本的spec配置/环境变量保留一周期兼容迁移。PUT /api/settings中触发即时安装并把结果回显到 Dashboard;使用 async child process,不阻塞 daemon 事件循环。herdr plugin --help,插件能力要求 herdr ≥ 0.7.0;不支持时明确提示herdr update,普通 herdr 后端不受影响。herdr plugin install <source> [--ref <ref>] --yes,不经过 shell 拼接。list → install → list → action → marker全链路使用按插件 ID 的跨进程文件锁;超时终止 POSIX 进程组并等待 close,Windows 回退终止直接子进程。Part 2 · per-bot 会话后端实时切换
PUT /api/bots/:id/backend-type,落盘bots.json并同步 registry,无需重启。Session.backendType;运行中/已持久化会话不会被实时 bot 配置覆盖,只有新会话采用新值。影响面
验证
pnpm build✅daemon-internal-api158、TraeX 并发/超时/幂等、backend availability/store、freeze-once restore/shutdown、Dashboard/i18n/settings)pnpm test:8018 passed / 17 failed;同机干净origin/master@f0da85c5在相同 5 个文件精确复现这 17 条失败(时区、远程 URL 环境与既有 CSS baseline),确认非本 PR 引入。--refargv 已核;bogus source 冒烟能通过 capability gate 并干净失败。pnpm switch:here && botmux restart后 live Dashboard 手工验证,37/37 bot online。master@f0da85c5(无冲突),补跑 build + 18 files / 544 tests 全绿,覆盖新 master 的会议监听、终端、worker-pool、daemon 与 dashboard 重叠路径。UI 截图
TraeX opt-in(默认关闭):
per-bot 会话后端: