Files
cliproxy-plugin-commandcode/README.md
T
yuez d7733552ee feat: commandcode usage query via /alpha endpoints with Provider API key (v0.5.0)
- New config commandcode_api_key (user_... provider key, long-lived);
  when set, usage queries hit /alpha/billing/credits + /alpha/usage/summary
  with Bearer auth — no more 7-day session cookie rotation
- session_token kept as optional fallback (legacy /internal + cookie path)
- alpha credits lack opensourceMonthlyCredits; formatter tolerates
- alpha non-200 passes through status without echoing upstream body
2026-09-23 17:13:01 +08:00

14 KiB
Raw Blame History

CLIProxyAPI Command Code Plugin (commandcode)

Go Version CLIProxyAPI Plugin ABI License: MIT

CLIProxyAPI 动态 C ABI 插件,用于提供 Command Code 与 OpenCode Go 两个上游的配额与窗口限额查询、以及嵌入式配额监控仪表盘卡片(QuotaCard,Tab: Command Code / OpenCode Go / All)。


目录


功能特性

  1. 标准 C ABI 兼容:
    • 导出 cliproxy_plugin_init、cliproxyPluginCall、cliproxyPluginFree、cliproxyPluginShutdown。
    • 遵照 CLIProxyAPI 官方 JSON Envelope 规范(ok, result, error)。
  2. 纯粹的管理监控能力 (management_api):
    • 注册插件自有的用量管理端点与浏览器嵌入式仪表盘资源页面。
    • 无多余的 OAuth 提供商注册,不污染 CLIProxyAPI 后台的 OAuth 授权列表。
  3. Session Token 灵活提取与支持:
    • 支持在 config.yaml 配置或在配额页面上直接输入。
    • 支持纯 token 或完整 Cookie 字符串(自动提取 __Secure-commandcode_prod_.session_token)。
  4. 精确用量与双滑动窗口限额解析:
    • 上游接口(v0.5.0+):配置 commandcode_api_key(Provider API key,长期凭据)时走 GET https://api.commandcode.ai/alpha/billing/credits 与 /alpha/usage/summary(Bearer 认证);否则回退 session cookie 查 /internal/billing/credits。
    • 请求优先走宿主提供的 host.http.do 回调(复用宿主代理、日志与鉴权管道),离线或未注入宿主时自动无缝降级至 Go 标准 net/http。
    • 全面解析 credits(月度基础额度、开源奖励额度、总可用额度)与 windowLimits(5小时短期滑动窗口、周度窗口限额,计算已用量、上限、剩余量、使用百分比及重置时间)。
  5. 嵌入式纯单文件 QuotaCard 资源页:
    • 页面挂载于 /v0/resource/plugins/commandcode/quota。
    • 零外部 CDN 依赖,纯内置 HTML + CSS + JS,深色/浅色模式自适应。
    • 具有进度条颜色变化、5小时/周限额卡片、秒级动态重置倒计时、同源 localStorage 鉴权与一键刷新。
    • Tab 切换:Command Code / OpenCode Go / All(#opencode / #all hash 记忆状态)。
  6. OpenCode Go 用量查询 (v0.3.0+):
    • 上游接口:GET https://opencode.ai/zen/go/v1/usage,Authorization: Bearer 认证(同样走 host.http.do 优先 + net/http 兜底)。
    • 解析 rolling(5h)/ weekly / monthly 三个窗口的 status/percent/resetsAt,容忍未知 status 值。
    • 聚合端点 /plugins/commandcode/all 一次返回两个 provider,部分失败不拖死另一 provider。

系统架构

┌────────────────────────────────────────────────────────┐
│                      CLIProxyAPI                       │
│                                                        │
│                       ┌─────────────────────┐          │
│                       │  Management Center  │          │
│                       │   (/v0/management)  │          │
│                       └──────────┬──────────┘          │
│                                  │ C ABI               │
│                                  ▼                     │
│  ┌──────────────────────────────────────────────────┐  │
│  │       cliproxy-plugin-commandcode.dylib/.so      │  │
│  │                                                  │  │
│  │  • management.register / management.handle       │  │
│  │  • Usage Parser & Window Limits Formatter        │  │
│  │  • Embedded Single-file HTML/CSS/JS QuotaCard    │  │
│  └───────────────────────────┬──────────────────────┘  │
│                              │                         │
│                              │ host.http.do            │
│                              ▼                         │
│  ┌──────────────────────────────────────────────────┐  │
│  │          Host Transport / Proxy Pipeline         │  │
│  └───────────────────────────┬──────────────────────┘  │
└──────────────────────────────┼─────────────────────────┘
                               │ Upstream HTTPS
                               ▼
  https://api.commandcode.ai/internal/billing/credits
  https://opencode.ai/zen/go/v1/usage        (v0.3.0+)

快速开始

构建插件

项目提供标准的 Makefile,可直接编译与操作系统相对应的 C 共享动态库:

# 自动编译出 commandcode.dylib (macOS) 或 commandcode.so (Linux)
make build

# 运行完整单元测试与竞态检测
make test

# 清理构建产物
make clean

安装与目录结构

将编译出的动态库放入 CLIProxyAPI 的插件目录中:

# macOS
mkdir -p plugins/darwin/arm64
cp commandcode.dylib plugins/darwin/arm64/commandcode.dylib

# Linux
mkdir -p plugins/linux/amd64
cp commandcode.so plugins/linux/amd64/commandcode.so

宿主配置 (config.yaml)

在 CLIProxyAPI 的 config.yaml 中启用插件并配置默认参数:

plugins:
  enabled: true
  dir: "plugins"
  configs:
    commandcode:
      enabled: true
      priority: 1
      session_token: "YOUR_COMMANDCODE_SESSION_TOKEN" # v0.4.5 前唯一凭据;v0.5.0 起为可选回退
      commandcode_api_key: "user_YOUR_COMMANDCODE_PROVIDER_KEY" # v0.5.0+ 推荐:非空则用量查询走 /alpha 端点(Bearer),无需 session cookie
      api_base: "https://api.commandcode.ai" # 可选,默认为官方接口
      opencode_api_key: "sk-YOUR_OPENCODE_GO_API_KEY" # 可选(单 key 兑底,v0.3.0+)
      # v0.4.0+ 多 key:list 优先于单 key 字段,每 key 独立账号独立配额窗口
      opencode_api_keys:
        - "sk-KEY1..."
        - "sk-KEY2..."

管理端点与资源页

1. 浏览器资源页 (QuotaCard)

  • 访问路径:GET http://<cpa-host>:8317/v0/resource/plugins/commandcode/quota
  • 菜单名:用量配额
  • 说明:
    • 资源请求本身无需经过管理认证,可在浏览器中直接打开或嵌入仪表盘。
    • 在同源模式下,页面 JavaScript 会自动读取 localStorage 中的管理密钥向 /v0/management/plugins/commandcode/all 请求数据(一次获取 Command Code + OpenCode Go)。
    • 若在独立或跨域测试环境下打开,页面提供内置的诊断面板,可手动输入 Management Key、测试 Session Token 或 OpenCode API Key(仅当次请求生效,不持久化)。

2. 管理 API: 查询用量 (GET)

  • 端点:GET /v0/management/plugins/commandcode/usage
  • 认证:需要管理密钥 (Authorization: Bearer <MANAGEMENT_KEY> 或 X-Management-Key: <MANAGEMENT_KEY>)
  • 可选查询参数:
    • session_token: 临时覆盖查询的 token
    • api_base: 临时覆盖的上游基础 URL
  • 响应示例:
{
  "ok": true,
  "credits": {
    "monthly_credits": 1000.0,
    "opensource_monthly_credits": 500.0,
    "total_credits": 1500.0,
    "details": {
      "monthlyCredits": 1000,
      "opensourceMonthlyCredits": 500
    }
  },
  "window_limits": {
    "five_hour": {
      "used": 12.5,
      "cap": 100.0,
      "remaining": 87.5,
      "percentage": 12.5,
      "exceeded": false,
      "reset_at": "2025-03-04T16:30:00Z",
      "reset_in_seconds": 7200
    },
    "weekly": {
      "used": 150.0,
      "cap": 1000.0,
      "remaining": 850.0,
      "percentage": 15.0,
      "exceeded": false,
      "reset_at": "2025-03-10T00:00:00Z",
      "reset_in_seconds": 475200
    }
  },
  "updated_at": "2025-03-04T14:30:00Z"
}

3. 管理 API: 测试用量 (POST)

  • 端点:POST /v0/management/plugins/commandcode/usage
  • 请求体:
{
  "session_token": "YOUR_TEMPORARY_TOKEN",
  "api_base": "https://api.commandcode.ai"
}

4. 管理 API: OpenCode Go 用量 (opencode/usage)

  • 端点:GET /v0/management/plugins/commandcode/opencode/usage(认证同上,仅读插件配置;凭据覆盖走 POST)
  • 端点:POST /v0/management/plugins/commandcode/opencode/usage
  • POST 请求体(多 key 数组优先;scalar 为 v0.3.0 兼容):
{ "opencode_api_keys": ["sk-KEY1", "sk-KEY2"] }
  • 响应(v0.4.0+,逐 key 结果数组):
{
  "ok": true,
  "provider": "opencode_go",
  "keys": [
    {
      "key_id": "sk-L…KqYB",
      "ok": true,
      "windows": {
        "rolling": { "status": "ok", "percent": 4, "exceeded": false,
                     "reset_at": "2026-09-17T06:58:53Z", "reset_in_seconds": 2520 },
        "weekly":  { "status": "ok", "percent": 46, "exceeded": false,
                     "reset_at": "2026-09-21T00:00:00Z", "reset_in_seconds": 259200 },
        "monthly": { "status": "ok", "percent": 23, "exceeded": false,
                     "reset_at": "2026-10-14T09:13:49Z", "reset_in_seconds": 1728000 }
      },
      "updated_at": "2026-09-16T12:00:00Z",
      "status_code": 200
    },
    {
      "key_id": "sk-U…PNHn",
      "ok": false,
      "updated_at": "2026-09-16T12:00:01Z",
      "status_code": 401,
      "error": "opencode upstream returned 401: check opencode_api_key"
    }
  ],
  "updated_at": "2026-09-16T12:00:01Z"
}
  • key_id 为服务端脱敏标识(前4+…+后4),原始 key 永不出现在响应中;失败 key 无 windows 字段,单 key 失败不影响其他 key。
  • HTTP 状态:≥1 key 成功 → 200;key 全配但全失败 → 502;未配置任何 key → 400。

5. 管理 API: 聚合查询 (all)

  • 端点:GET /v0/management/plugins/commandcode/all(仅读插件配置)
  • 端点:POST /v0/management/plugins/commandcode/all
  • POST 请求体(可只带其一;多 key 覆盖为数组):
{ "session_token": "...", "opencode_api_keys": ["sk-KEY1", "sk-KEY2"] }
  • 部分失败语义:HTTP 200 表示至少一个 provider(Command Code 或 ≥1 个 OpenCode key)成功;失败 provider 记入 errors,其响应字段整个省略;全失败且为本地凭据缺失 → 400,全失败且为上游错误 → 502。
{
  "ok": true,
  "commandcode": { "ok": true, "plan": {...}, "credits": {...}, "window_limits": {...}, "updated_at": "..." },
  "opencode": { "ok": true, "provider": "opencode_go", "keys": [ ...同上... ], "updated_at": "..." },
  "updated_at": "2026-09-16T12:00:00Z"
}

v0.4.0 breaking note:opencode 字段从单 key 对象变为 {ok, provider, keys[], updated_at} 多 key 结构(keys[].windows 为 v0.3.0 原窗口结构)。唯一消费方是同仓 QuotaCard 资源页,已同版本同步更新。


用量数据结构说明

字段 类型 说明
credits.monthly_credits float64 当前账单周期的月度基础 Credits 额度
credits.opensource_monthly_credits float64 开源项目贡献者获得的奖励额度
credits.total_credits float64 可用 Credits 总计 (monthly + opensource)
window_limits.five_hour.used float64 5小时滑动窗口内已消耗的量
window_limits.five_hour.cap float64 5小时滑动窗口上限
window_limits.five_hour.remaining float64 5小时滑动窗口剩余可用量
window_limits.five_hour.percentage float64 5小时窗口使用百分比(0-100%)
window_limits.five_hour.exceeded bool 是否已触发 5 小时限额熔断
window_limits.five_hour.reset_at string 5小时窗口重置时间的 RFC3339 字符串
window_limits.five_hour.reset_in_seconds int64 距离 5 小时窗口重置的剩余秒数
window_limits.weekly.* - 每周限额对应指标(结构同 5 小时窗口)
windows.<rolling|weekly|monthly>.status string OpenCode Go 窗口状态("ok"/上游其他值,未知值不报错)
keys[].key_id string 服务端脱敏 key 标识(前4+…+后4),原始 key 不出响应
keys[].ok bool 该 key 查询是否成功(单 key 401 隔离)
keys[].windows.<...> object 成功 key 的三窗口指标(结构同上;失败 key 无此字段)
keys[].status_code / error int / string 该 key 上游 HTTP 状态与失败原因

开发与测试

# 运行单元测试
go test -v ./...

# 运行代码规范检查
go vet ./...

# 运行竞态检查测试
go test -race -v ./...

许可证

本项目基于 MIT License 开源。