src/setup/(22 文件)承载两条职责:① botmux setup 的机器人配置流程(飞书应用创建 → 权限/事件/redirect/发版自动化 → 写 bots.json);② botmux start/restart 前的依赖引导(tmux/字体/herdr)。命令入口在 cli.ts(cmdSetup / cmdSetupScripted,见 cli)。
两种 setup 模式
- 交互 TUI(空参 / 纯 flag):
cmdSetup(src/cli.ts:2334)。已有 bots.json 时进多机器人菜单(添加/编辑/删除/重新配置),首次进promptBotConfig。 - 脚本化(
setup list|add|configure|edit|remove):src/setup/setup-args.ts解析字段级 flag(--app-id/--cli/--backend/--allowed-users/...)。设计动机:给 coding agent / 脚本一个不依赖 TUI 问题顺序的稳定接口(管道喂数字会因问题序列变化静默错位)。
两种模式的共同安全约束:写盘前用凭证换 tenant_access_token 校验(verify-permissions.ts validateCredentials),失败不写 bots.json;覆盖前先 copyFileSync 备份 .bak 再原子写(bots-store.ts)。
飞书应用自动创建(扫码)
三条来源路径,均仅支持 feishu.cn 租户(Lark 国际版回退 SDK device flow):
- SDK 扫码建应用(
register-app.ts):对接@larksuiteoapi/node-sdk的registerApp,走 OAuth 2.0 Device Flow(RFC 8628)——accounts.feishu.cn/oauth/v1/app/registration发action=begin(archetype 写死 PersonalAgent)→ 终端qrcode-terminal渲染二维码 → 轮询action=poll拿到 client_id/client_secret(即 AppID/AppSecret)。错误分类 aborted/expired/denied/network;secret 永不打印(错误消息先过滤长随机串)。扫码人 open_id 用作 allowedUsers 默认值。 - Web session 一键建应用(
open-platform-automation.tscreateOpenPlatformAppWithClient,manifest 模板developer_console):复用 Feishu Web 登录态直接经 console API 建普通企业自建应用,可带 botmux 图标。 - 复用已有应用(cli.ts
pickExistingAppCredentials):Web 登录态拉当前账号可见的自建应用列表,交互选择后自动读取 AppSecret。
Web 登录态本身也是扫码:prepareFeishuWebSession 按「缓存 session 文件(~/.botmux)→ Feishu Web QR 登录 → bytedcli fallback」顺序获取 cookies,登录态可跨 setup 步骤复用(建应用那次的扫码覆盖后续权限/发版,不再二次扫码)。
开放平台自动化管线
automateOpenPlatformSetup(src/setup/open-platform-automation.ts:625)用拿到的 Web session 驱动 console 内部 API(/developers/v1/*,带页面提取的 CSRF token):
- 权限导入:
scope/all拉租户目录 → 与 manifest 映射 →scope/update批量注册。非致命(「部分权限即成功」,个别租户拒个别权限时只告警继续)。 - 能力开关(致命):
robot/switch开启机器人能力 +event/switch切长连接事件(LONG_CONNECTION_EVENT_MODE = 4)。 - 事件/回调订阅(增量契约:读现状 →
operation:add补缺失 → 回读确认)。基线事件含im.message.receive_v1(critical,缺了 daemon 完全收不到消息)+ 成员变更等可选事件 + VC 会议事件;回调card.action.trigger。fail-closed:核心项回读仍缺失直接判失败,避免产出「建好了却不回话」的坏 bot。批量失败时逐个补,防长尾事件拖垮核心。 - redirect URL:写死
http://127.0.0.1:9768/callback(本地 daemon OAuth 回调)。 - 发版:先读现有可见范围(
visible/online,读不可靠则中止发版,绝不发一个可能把人关在门外的版本)→app_version/create(版本号自增)→publish/commit。
结果由 open-platform-outcome.ts 分类(ok/partial/manual/skipped);setup configure <bot> 可对 partial 的应用重跑后半段而不重建应用。--no-open-platform-auto 全程跳过并打印手动步骤深链。
lark-scopes.json 权限清单
src/setup/lark-scopes.json 是 botmux 所需 scope 的 manifest(tenant + user 两节,覆盖 im/calendar/docs/drive/board/contact/vc 等域)。自动配置时映射到租户目录里的 scope id 批量导入;同时拷一份到 ~/.botmux/lark-scopes.json,供「开放平台权限管理 → 批量导入」手动兜底。verify-permissions.ts 的 BOTMUX_REQUIRED_SCOPES 标注 critical 子集(im:message、im:message.group_at_msg:readonly、im:message.group_msg、im:resource 等)用于启动自检与深链提示——注意它只检测不自动申请:飞书 scope.apply 只能提交已声明未授权的 scope,无法给 manifest 加新声明。
依赖引导(ensureDependencies)
src/setup/index.ts 在 botmux start/restart 时调用:
- tmux 必需(PTY 退役):二进制真缺失 + 有 bot 要用 tmux 后端 + 未显式
BACKEND_TYPE=pty时硬失败拒绝启动(shouldHardFailStartupForMissingTmux);「存在但探测失败」不硬失败,交给 per-session worker gate 优雅降级。实现见ensure-tmux.ts。 - 字体 best-effort(
ensure-fonts.ts,截图渲染用),失败只警告。 - herdr 按需:只有 bots.json 里有
backendType: 'herdr'才装(ensure-herdr.ts+ensure-herdr-integrations.ts,含 TraeX plugin 门控)。另有ensure-zellij.ts/ensure-zmx.ts/ensure-opus.ts。
文件速查
| 文件 | 职责 |
|---|---|
| setup-args.ts | 脚本化模式 argv 解析(纯函数) |
| bot-config-editor.ts | bot 配置规范化/编辑/唯一性校验 |
| cli-selection.ts / cli-availability.ts | CLI 适配器选择(含网关键)与可用性检查 |
| interactive-select.ts | TUI 选择器 |
| register-app.ts | SDK device flow 扫码建应用 |
| open-platform-automation.ts | Web session + console API 全自动化(78KB 核心) |
| open-platform-outcome.ts / -visibility.ts | 结果分类 / 可见范围解析 |
| verify-permissions.ts | 凭证校验 + critical scope 自检 |
| agent-preset.ts / app-name.ts / bots-store.ts | preset 导出 / 应用名生成 / bots.json 原子写 |
| detect-platform.ts | 平台探测 |