Cli-Proxy-API-Management-Center

异步探测与密钥可用性运维服务

1. 建设目标

该服务将 CPA 每次真实账号请求视为一次被动探测结果,在不阻塞请求采集链路的前提下,持续评估公益密钥和 CPA 账号的可用性,并按全局策略或单密钥策略执行以下动作:

2. 总体架构

CPA 请求上报
  -> collector 写入 usage_events
  -> collector 将同批事件投递到有界异步探测队列
  -> probe.Manager 归一化并生成 probe_results
  -> 匹配 cpa_auth_detail 与单密钥 probe_policy
  -> 计算连续成功/失败、状态、优先级和续期动作
  -> 更新 cpa_auth_detail
  -> 可选调用 CPA Management API 上下线账号
  -> 写入 probe_action_logs 供统计和审计

探测队列与请求采集解耦。队列已满时不会阻塞 collector,而是记录 dropped_batches;运维人员可在探测统计页观察队列深度、丢弃批次和最后错误。

3. 数据模型

3.1 渠道与提供商基础目录

cpa_channel_info 与 cpa_provider_info 均新增 description TEXT NOT NULL DEFAULT '',用于记录用途、来源和运营说明。迁移会对已有数据库幂等补列,并保留已有自定义记录。

系统启动时固定校准以下渠道记录。如果 channel_id=1/2/3 已被其他记录占用,会更新为预置定义并恢复为有效状态;其他 ID 的自定义渠道保持不变。

channel_id 渠道名称 状态
1 内置渠道商 1
2 官方渠道商 1
3 第三方渠道商 1

系统同时按照规范化后的 base_url 补齐 CPA 原生提供商目录。匹配时忽略大小写、首尾空白和末尾 /,不依赖 provider_id 或名称;已经存在相同端点时保留原记录的名称、状态、渠道、策略和参数。当前预置端点包括 Codex、OpenAI、Anthropic、Gemini、Gemini CLI、Grok 和 Kimi,缺失项默认归属“官方渠道商”。

3.2 cpa_auth_detail 扩展字段

字段 类型 语义
expires_at_ms INTEGER NULL Unix 毫秒过期时间;空值或小于等于 0 表示没有明确过期时间。
probe_policy TEXT NOT NULL DEFAULT '{}' 单密钥 JSON 策略;空对象表示继承全局配置。

3.3 probe_results

每条采集请求最多形成一条去重后的探测结果,保存请求时间、账号标识、密钥哈希、关联密钥和提供商、模型、端点、状态码、延迟、错误及本次自动动作。event_hash 唯一索引用于避免重复消费。

3.4 probe_action_logs

保存状态调整、优先级调整、过期、续期和 CPA 上下线等副作用的执行结果。动作日志同时记录成功标记和错误信息,便于区分“策略已命中”和“外部 CPA 调用已成功”。

3.5 服务配置

全局配置以 settings.probe_service_config_v1 保存,主要参数如下:

提供商 probe_policy 是策略运营的主要配置单元,可选择继承全局、自定义或不参与探测,并可覆盖自动优先级、自动状态、CPA 推送、成功续期及各项阈值。历史单密钥 probe_policy 继续保留为兼容覆盖层。

策略解析顺序为:

系统全局策略 -> 提供商策略 -> 历史单密钥策略

提供商设置为“不参与探测”时,其下密钥不能通过单密钥策略反向启用。

/charitable/token 的提供商新增与编辑面板提供代理服务器选择器,数据来源为 /charitable/proxies 中状态为有效的代理记录。选中后将代理 URI 和记录 ID 分别写入提供商 param.proxy_url、param.proxy_id;也允许直接输入自定义代理 URI。

提供商策略选择“继承全局”时,策略抽屉会展示当前系统全局策略;切换为自定义时以该全局策略作为编辑初始值。策略页查看提供商密钥后,可直接切换到对应密钥编辑面板,提供商编辑同样通过页内回调完成,不依赖重复 URL 导航。

策略运营和提供商列表中的“查看密钥”使用原地抽屉展示,不切换 /charitable/token 的主标签。点击密钥编辑时,密钥列表抽屉暂时让位给按密钥 ID 重新查询的编辑抽屉;保存或取消后恢复原密钥列表,并在保存成功后重新加载列表。策略页“编辑提供商”同样按提供商 ID 重新查询并在独立抽屉中保存,完成后直接更新当前策略列表和已打开的提供商信息。

密钥批量探测会为每个请求独立生成随机大整数求和题目,避免所有探测请求重复使用固定提示词;单密钥探测仍允许在面板中手动调整提示词。

密钥导入会根据每条配置中的 type / provider 和 base_url 自动关联提供商:优先按规范化 Base URL 匹配,其次在没有 Base URL 时按类型别名匹配;仍未找到且存在可用 Base URL 时,自动创建归属官方渠道的提供商。所有导入密钥初始状态统一为未知(0),等待真实使用或探测结果确认。

批量探测完成后集中写回状态:成功结果设置为有效(1);HTTP 401、402、403 直接设置为失效(-1);其他失败设置为未知(0)继续观察。人工禁用(-2)的密钥不会被批量探测覆盖。

密钥主表除“探测所选”外,还支持“探测全部筛选结果”。前端会保留当前搜索、提供商、状态和优先级过滤条件,以每页 500 条循环读取全部分页结果后执行探测,不受当前页勾选范围限制。策略运营和提供商页面共用的密钥明细抽屉同时提供单行探测与当前提供商全部密钥探测。

多密钥导入按每条凭证自身的类型和显式 Base URL 分别解析提供商。显式 Base URL 优先精确匹配;没有显式地址时优先按类型别名匹配,避免 Gemini、AI Studio 等共享规范端点的不同凭证类型被错误合并。导入完成后立即将本次匹配或创建的提供商写入前端缓存,再刷新密钥列表,因此新记录会直接展示提供商名称而不是临时 ID。

4. 状态与优先级规则

密钥状态约定:

状态值 含义 自动探测行为
>= 1 有效 继续观察;失败达到门槛后可转为探测管理的失败状态。
0 未知、待观察 保留在探测范围内;成功达到恢复门槛后可转为有效。
-1 无效 视为人工或业务状态,不由探测自动恢复。
-2 禁用 不作为可路由账号使用。
-3 已过期 由过期扫描直接设置。
< -99 探测管理的 HTTP 失败状态 例如 HTTP 401 对应 -401;连续成功达到门槛后可恢复为 1。

自动状态只恢复“待观察”或探测产生的失败状态,不覆盖 -1、-2、-3 等人工或明确生命周期状态。优先级调整始终限制在 minPriority 与 maxPriority 之间。

5. 过期时间策略

5.1 明确过期时间

5.2 未设置过期时间

5.3 成功续期

开启 renewExpiryOnSuccess 后,成功使用可按 renewalSeconds 延长过期时间。该能力适用于“持续使用即续期”的账号,不建议用于具有供应商硬性到期日的凭证。

6. CPA 推送与安全边界

7. 前端入口

8. HTTP API

方法 路径 用途
GET / PUT /v0/cpamc/charitable/probe/config 查询或保存全局探测配置。
GET /v0/cpamc/charitable/probe/status 查询队列、处理量、动作量和最后错误。
GET /v0/cpamc/charitable/probe/summary 查询指定窗口的探测汇总。
GET /v0/cpamc/charitable/probe/results 分页查询探测结果,支持账号、密钥、提供商、成功状态和时间过滤。
GET /v0/cpamc/charitable/probe/stats 查询按账号或密钥聚合的健康统计。
GET /v0/cpamc/charitable/probe/actions 分页查询自动动作日志。

密钥详情的过期时间和 probe_policy 继续通过 charitable 密钥 CRUD 接口读取和保存。

9. 请求监控 SSE 联动

/realtime/request 使用 /v0/cpamc/usage/realtime/stream 建立带管理密钥认证的 SSE 长连接。服务端在 usage_events 最新游标增长时发送 usage 事件,前端收到通知后按当前筛选条件重新加载请求页。

10. 运维与验证建议

  1. 首次启用后先确认探测统计中的队列深度能够回落、dropped_batches 持续为 0。
  2. 使用较大的失败门槛观察真实流量,避免瞬时网络错误批量下线账号。
  3. 开启 CPA 自动推送前,核对 auth index、auth-file 和提供商关联是否准确。
  4. 对供应商明确到期的账号设置 expires_at_ms,并关闭不符合业务规则的成功续期。
  5. 定期检查动作日志中的失败记录和 Usage Service 的最后错误。

建议验证命令:

npm run type-check
cd services
env GOCACHE=/tmp/agent-tools-gocache CGO_ENABLED=0 go test ./internal/core/store ./internal/core/httpapi ./internal/core/probe