跨 Agent 的模型管理器。它维护一份你自己的上游与模型库 —— 从上游直接拉取模型清单、 缓存到本地、测试可用性,再一键写入 WorkBuddy、CodeBuddy 或任何其它 agent 的配置。
同时统计各 Agent 的 Token 用量——扫描它们自己写下的会话记录,按天、按模型、 按会话看清消耗与缓存命中率。
一次配置,多处复用:同一个上游下的模型,不必在每个 agent 里重复录入一遍。
侧栏分成两块,职责不重叠:
| 视图 | 数据来源 | 用来做什么 |
|---|---|---|
| 本地模型 | data/upstreams.json(BuddySwitch 自己维护) |
主视图。新增上游、拉取模型清单、手动补充、测试、再推到任意 agent |
| 各 Agent | 该 agent 自己的配置文件与会话记录 | 看它当前配了什么、跑了多少 token;编辑 / 删除会直接写回它的配置 |
「本地模型」是按上游分组的(同一个接入点 + 同一把密钥算一个上游), 默认全部收起以免页面过长;搜索时会自动展开。
为什么不做「所有 Agent 模型的汇总视图」:多个 agent 常共用同一个上游, 汇总只会让同一批模型重复出现。以 Agent 为轴没有意义,以上游为轴才有。
| 能力 | 说明 |
|---|---|
| 向上游拉取 | 用上游的密钥直接问它有哪些模型(GET /models),而不是读本地配置 —— 所以还没被任何 agent 用上的新模型也能发现 |
| 本地模型缓存 | 拉回来的清单存进本地库,跨 agent 复用;可手工维护、可导出 |
| 手动补充 | 有些上游的模型清单接口返回不全,拉不到的可以直接填 id |
| 一键应用 | 把某个上游下的模型勾选后写入指定 agent,整批只写一次盘、只留一份快照 |
| 可用性测试 | 按定义构造探针请求,测出可用 / 密钥无效 / 不可达,并记录延迟 |
| Token 用量统计 | 扫描 agent 自己写下的会话记录,按天 / 按模型 / 按会话统计 token 消耗与缓存命中率 |
| 快照与还原 | 每次写入前自动留快照,按份数轮转,任意一次修改都能一键回退 |
| 插件化接入 | 新增一个 agent 只需要写一份 JSON 定义,不需要改一行代码 |
| 层级 | 技术 |
|---|---|
| 后端 | Go + Wails v2(无边框窗口、原生对话框、事件推送) |
| 前端 | React 19 + Tailwind CSS 4 + Vite 7 |
| 用量数据源 | 纯 Go 的 SQLite 驱动(modernc.org/sqlite,无 CGO),只被 usage/sqlite.go 引用 |
| 国际化 | 内嵌多语言包,缺失文案自动回落到默认语言;后端错误与探测结论同样走语言包 |
| 日志 | Logrus,按启动时间归档,自动清理旧文件(日志文案固定中文,便于排障) |
├── upstream/ # 本地模型库:上游 + 模型清单(data/upstreams.json)
├── plugin/ # 插件体系(Agent 接入的核心)
│ ├── types.go # 插件定义、统一模型、探测与清单规格
│ ├── document.go # 按 schema 解析 / 写回 agent 原生配置
│ ├── probe.go # 模板化探针请求与结果判定
│ ├── listing.go # 向上游索要模型清单
│ ├── registry.go # 内置 + 磁盘插件的加载与查询
│ ├── util.go # JSONC 去注释、路径变量展开
│ └── builtin/ # 内置插件定义(workbuddy / codebuddy)
├── usage/ # Token 用量统计(声明式数据源扫描)
│ ├── spec.go # 声明归一化与路径取值(a.b.c / a[].b / ../)
│ ├── scan.go # jsonl / json / sqlite 三种来源的读取
│ ├── summary.go # 聚合(总览 / 按日 / 按模型 / 按会话)
│ ├── cache.go # 增量缓存(mtime+size + spec 指纹)
│ ├── collect.go # 编排与数据源发现
│ ├── index.go # 会话元信息(标题等)的第二数据源
│ └── sqlite.go # SQLite 驱动的隔离层
├── backup/ # 配置快照:留档、轮转、还原
├── store/ # BuddySwitch 自身的状态(探测结果)
├── service/ # Wails 绑定层,业务编排
├── api/ # 不依赖 Wails 上下文的业务函数
├── global/ # 配置、语言包、日志
├── lang/ # 内嵌语言包(zh-CN / en-US / ja-JP / ko-KR)
├── scripts/ # 开发期脚本(语言包完整性校验等)
├── docs/ # 文档(插件定义参考、Agent 数据源速查)
├── frontend/ # React + Tailwind 前端
├── main.go
└── wails.json
运行期会在工作目录产生:
config.json # 应用设置
plugins/ # 用户自定义或覆盖用的插件定义
data/upstreams.json # 本地模型库(含上游密钥,注意保管)
data/state.json # 探测结果
data/usage/<插件id>.json # Token 用量的增量缓存
data/backups/<插件id>/ # 配置快照
logs/ # 日志
环境要求:Go ≥ 1.25、Node.js ≥ 18、Wails CLI v2。
# 安装 Wails CLI(如果还没有)
go install github.com/wailsapp/wails/v2/cmd/wails@latest
# 安装前端依赖
cd frontend && npm install && cd ..
# 开发模式(热重载)
wails dev
# 构建生产版本
wails build本项目使用 Wails 的构建链路,不通过
go build单独编译。 Go ≥ 1.25 的要求来自 SQLite 驱动modernc.org/sqlite。
一个插件 = 一份「该 Agent 的模型配置格式定义」+(可选的)「Token 用量数据源声明」。
| 段 | 回答的问题 |
|---|---|
source |
配置文件放在哪 |
schema |
文件长什么样、怎么读写 |
probe |
怎么判断这个模型还能不能用 |
listing |
怎么向上游索要模型清单(可选) |
usage |
该 Agent 的 token 用量数据在哪(可选) |
内置插件随二进制分发(plugin/builtin/*.json);磁盘上的 plugins/*.json(已被
.gitignore 忽略)可以覆盖同 id 的内置定义,也可以新增插件。因此修正一个
字段映射不需要重新编译。
完整的字段说明、对象形式与通配容器的写法、usage 的三种格式与口径说明, 见 插件定义参考。
- 在界面左下角点「导出示例插件定义」,得到
plugins/example-agent.json; - 照着改成目标 agent 的真实路径与字段映射;
- 点「重新加载插件」,新插件立即出现在侧栏。
整个过程不需要动代码,也不需要重新编译。
| Agent | 插件 | 模型配置 | Token 用量 |
|---|---|---|---|
| WorkBuddy | 内置 workbuddy |
✅ | ✅ |
| CodeBuddy(CLI / VSCode 插件 / IDE) | 内置 codebuddy |
✅ | ✅ |
| Z Code | 外部 zcode |
✅ | ✅ |
| OpenCode | 外部 opencode |
✅ | ✅ |
| MiniMax Code | 外部 minimax-code |
❌ | ✅ |
每个 agent 的数据文件位置、记录格式与 token 口径(input 含不含缓存——
各家定义不同,这是最容易算错的地方),见 Agent 数据源速查。
写入 agent 配置是一件有风险的事,所以每次写入之前都会先留一份快照:
data/backups/workbuddy/models.json.2026-09-14_22-05-31.417.bak
- 快照目录按插件隔离,文件名内嵌毫秒级时间戳;
- 保留份数在「设置」里可调(默认 10,范围 1–100),超出后自动清理最旧的;
- 界面上可以查看快照列表、预览内容、还原到任意版本;在「本地模型」视图下也能打开, 面板里切换要查看哪个 agent;
- 还原本身也会先备份当前内容,所以还原动作同样可以撤销。
写入采用「先写临时文件再改名」的方式,中途失败不会破坏原配置; 未被插件映射到的字段会被完整保留,BuddySwitch 只碰它认识的那几个字段。
- 所有操作都在本机进行,不发送任何遥测;
api_key会出现在两处:agent 自己的配置,以及 BuddySwitch 的data/upstreams.json。 后者是本地模型库为了跨 agent 复用而必须保存的,是明文,请和 agent 配置同等对待: 别把它放进同步目录或版本库,共享机器上注意该文件的读写权限;- 一些 agent 自己的数据文件也含有明文密钥(如 Z Code 的
v2/config.json、 OpenCode 的auth.json),BuddySwitch 会读取它们以统计用量,但不会复制或外传内容; - 密钥仅用于构造请求头,日志里不会输出其内容;界面上以打码形式展示;
- 路径类接口都会校验,拒绝
..与路径分隔符,防止越权读写; - 用量扫描一律跳过名为
auth、credentials、secrets、tokens、keys、cookies的目录——这条写死在代码里,不交给插件定义。
MIT