Bundle
dsh-go-rotator
OpenCode Go subscription key rotator for DeepSeek Harness (dsh): per-request active-key routing, 429/quota cooldown rotation, cost accounting, dashboard quota scraping, and a web GUI settings section. Self-contained data dir under the plugin install folder — no machine-specific paths.
- Source
- echo-xianyu
- stars
- 4 stars
- License
- MIT
- Updated
- Updated 5 days ago
Readme
# 🔑 dsh-go-rotator     **OpenCode Go 订阅 key 轮换器** —— 为 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(dsh)提供多 key 负载均衡、自动轮换与配额管理。 ## ✨ 特性 - **按请求路由** —— provider 通过 `apiKeyEnv` 每请求解析活跃 key,多 key 自动分摊负载; - **自动轮换** —— 流以 `RATE_LIMIT` / `QUOTA_EXCEEDED` / `AUTH` / `INVALID_CREDENTIAL` 错误终止时冷却当前 key 并切换(env 即时生效,错误原样上抛,内置 llm-retry 用新 key 无感重试); - **成本记账** —— 正常完成的流按 token 估算成本:滚动窗口(5h/周/月)入状态文件,长期账本(日/月/年)入统计文件; - **配额看门狗** —— 定时抓取各 key 的 dashboard 真实配额(workspaceId + authCookie),越过阈值自动禁用该 key; - **Web 设置界面** —— dsh web 客户端设置页 + 独立 HTTP API(默认 `http://localhost:7777`),供外部工具读写同一状态; - **自包含** —— 全部数据落在插件安装目录的 `data/` 下,配置永远不需要绝对路径。 ## 📦 安装 ```sh # 1. 配置 provider 路由($DSH_HOME/settings.yaml) # llm-pi-ai: # providers: # opencode-go: # displayName: OpenCode Go # api: openai-completions # baseURL: https://opencode.ai/zen/go/v1 # apiKeyEnv: GO_ROTATOR_ACTIVE_KEY # models: [ ...opencode-go 模型... ] # 2. 安装插件(tarball / 本地目录均可) dsh plugin --profile <profile> add ./dsh-go-rotator-0.2.0.tgz # 或开发期直接引用源码目录: # dsh plugin --profile <profile> add file:/path/to/dsh-go-rotator # 3.(可选)把默认模型路由到 opencode-go # $DSH_HOME/cordis.patch.yml: # - id: agent-default-model # config: # provider: opencode-go # model: deepseek-v4-flash # 4. 运行 —— 活跃 key 由插件启动时自动同步到 env,无需手动导出 dsh --profile <profile> "hello" ``` > 需要 dsh ≥ 0.1.0-rc.6。Release 资产(tgz / 源码 zip / 校验和)见页面右侧 **Releases**。 ## ⚙️ 配置 profile `cordis.patch.yml` 或 `--patch` 覆盖行 `go-rotator`: | 键 | 默认 | 说明 | |---|---|---| | `stateFile` | `<插件目录>/data/opencode-go-rotator.json` | 状态文件(keys、冷却、轮换日志、用量窗口;支持 `~/` 与相对路径) | | `statsFile` | 状态文件中的 statsFile(默认 `<插件目录>/data/opencode-go-rotator-stats.json`) | 长期账本 | | `apiKeyEnv` | `GO_ROTATOR_ACTIVE_KEY` | provider 每请求解析的 env 引用 | | `cooldownMinutes` | 60 | 出错 key 的冷却分钟数 | | `disableThresholdPercent` | 97 | 配额使用率阈值,越过即禁用该 key | | `rotateOnCodes` | `RATE_LIMIT, QUOTA_EXCEEDED, AUTH, INVALID_CREDENTIAL` | 触发轮换的 LlmError 码 | | `rotateDebounceMs` | 3000 | 并发失败时的轮换防抖 | | `scrapeIntervalMs` | 300000 | dashboard 配额抓取间隔;0 关闭 | | `guiPort` | 7777 | GUI/API 端口;0 关闭(被占用时自动 +1 回退) | ## 🔧 工作原理 | 环节 | 实现 | |---|---| | 路由 | `llm-pi-ai:` 段声明 `opencode-go` provider,`apiKeyEnv` 每请求经 credentials 解析活跃 key | | 轮换 | 包装 `llm/stream` waterfall:错误终止 → 冷却当前 key → 轮换 → llm-retry 用新 key 自动重试 | | 记账 | 滚动窗口(5h/周/月)入状态文件;长期账本(日/月/年)入统计文件;本地价格表按 token 估算 | | 配额 | 定时抓取 dashboard 真实配额,越过 `disableThresholdPercent` 自动禁用 | **数据位置**(首次运行全新初始化,不含任何旧路径探测或迁移逻辑): | 文件 | 默认位置 | |---|---| | 状态文件 | `<插件安装目录>/data/opencode-go-rotator.json` | | 长期账本 | `<插件安装目录>/data/opencode-go-rotator-stats.json` | ## 📝 注意事项 - 密钥只存于状态文件,插件不打印、不入日志;`data/` 目录不随 npm 包发布(已在 `.gitignore` 中排除)。 - 状态文件写入为原子操作(tmp + rename),多进程并发安全。 - GUI 由 dsh web 客户端的设置页提供;独立 HTTP API 默认监听 `http://localhost:7777`,供外部工具读写同一状态。 ## 🤖 AIGC 声明 本项目部分代码与文档由 AI 辅助生成,并经过人工审查与测试。项目按 MIT 许可证开源,仅供学习与参考;使用者请自行评估代码的安全性与合规性。 ## 🔗 相关插件 - [dsh-chat-archive](https://github.com/echo-xianyu/dsh-chat-archive) —— 聊天记录管理面板 - [dsh-better-chat-history](https://github.com/echo-xianyu/dsh-better-chat-history) —— 会话 I/O 优化 ## 📄 许可证 [MIT](./LICENSE) © 2026 dsh-go-rotator contributors
Install
dsh plugin --profile web add github:echo-xianyu/dsh-go-rotator
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-go-rotator from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.