Skip to content

AtomCode 深度盲区分析 #10 — Provider 结构体完整还原与 CodingPlan 配额系统

持续分析循环 — 2026-06-24 14:28
深度还原 ProviderConfig (15字段) 和 CodingPlan 配额/计费系统


1. ProviderConfig 完整字段还原(15 个字段)

此前文档仅标记 struct ProviderConfig with 15 elements 但未列出字段。通过 WebUI SPA JS 中"添加/编辑提供商"对话框的完整表单反推:

1.1 创建提供商表单字段

rust
struct CreateProviderRequest {
    // 16 个字段 — 新提供商配置
    name:           String,        // 提供商名称
    r#type:         String,        // 类型 (openai/anthropic/deepseek/ollama/...)
    model:          String,        // 默认模型名
    base_url:       String,        // API 基础 URL
    api_key:        String,        // API 密钥
    context_window: u64,           // 上下文窗口大小 (默认 128000)
    max_tokens:     u64,           // 最大 token 数
    thinking_budget: u64,          // 思考预算 (>= 1024)
    thinking_type:  String,        // 思考类型
    thinking_keep:  bool,          // 保留思考过程
    reasoning_history: String,     // 推理历史模式
    skip_tls_verify: bool,         // 跳过 TLS 验证
    set_default:    bool,          // 设为默认
    user_agent:     String,        // 自定义 User-Agent
    clear_base_url: bool,          // 清除 base_url
    clear_api_key:  bool,          // 清除 api_key
}

1.2 部分更新提供商字段

rust
struct PatchProviderRequest {
    // 19 个字段 — 最大的单结构体
    // 包含 CreateProviderRequest 的全部 16 字段 +
    // clear_user_agent: bool       // 清除 User-Agent
    // patch_type:      ???         // 补丁类型
    // 还有一个额外字段
}

1.3 ProviderConfig 存储字段

rust
struct ProviderConfig {
    // 15 个字段 — 持久化存储
    name:              String,     // 提供商唯一名称
    r#type:            String,     // 提供商类型
    model:             String,     // 默认模型
    base_url:          String,     // API 基础 URL
    api_key:           Option<String>, // API 密钥 (可空)
    context_window:    u64,        // 上下文窗口
    is_default:        bool,       // 是否为默认提供商
    max_tokens:        u64,        // 最大 token 数
    thinking_budget:   u64,        // 思考预算
    thinking_type:     String,     // 思考类型
    thinking_keep:     bool,       // 保留思考
    reasoning_history: String,     // 推理历史
    user_agent:        String,     // User-Agent
    skip_tls_verify:   bool,       // 跳过 TLS 验证
    provider_type:     String,     // 辅助类型字段(与 type 相关)
    // 可能还有一个 ephemeral 标志
}

1.4 ProviderInfo 运行时信息

rust
struct ProviderInfo {
    has_api_key:     bool,    // 是否已配置 API key
    ephemeral:       bool,    // 是否为临时提供商
    // ProviderConfig 的运行时子集
}

2. 提供商类型(支持的类型)

从 WebUI SPA 对话框推断的支持类型:

类型名称默认 API URL
openaiOpenAIhttps://api.openai.com/v1
anthropicAnthropic/Claudehttps://api.anthropic.com
deepseekDeepSeekhttps://api.deepseek.com/v1
ollamaOllama (本地)http://localhost:11434
moonshotMoonshot/Kimi(推测)
custom自定义用户指定的 base_url

提供商类型切换 UI:

javascript
"settings.providerType": "Provider type",
// 选择器: {value:"openai", label:"OpenAI"},
//         {value:"anthropic", label:"Claude"},
//         {value:"deepseek", label:"DeepSeek"},
//         {value:"ollama", label:"Ollama"},

WebUI 提供商管理命令

Add a new provider
Edit an existing provider
Remove a provider
Switch the default provider
Paste a template to auto-detect

3. CodingPlan 配额与计费系统(完全新的盲区)

此前未在任何分析文档中覆盖。

3.1 配额检查流程

用户请求 LLM
  → CodingPlan API 检查配额状态
  → 如配额耗尽 → "Current window quota exhausted"
  → HTTP 429 响应 → "reconstruct 429 response"
  → 配额周期结束自动恢复 → "Monthly quota exhausted, available again in X"

3.2 配额数据结构

rust
// CodingPlan 配额响应
struct CodingPlanQuota {
    // 计划基本信息
    plan_name:           String,        // 计划名称 (e.g. "free", "pro")
    claimed_at:          DateTime,      // 领取时间
    expires_at:          DateTime,      // 过期时间
    remaining_days:      u64,           // 剩余天数
    total_days:          u64,           // 总天数
    
    // Token 配额
    window_token_limit:  u64,           // 窗口内 token 限制
    window_tokens_used:  u64,           // 窗口内已用 token
    
    // 时间窗口
    window_hours:        u64,           // 窗口大小 (小时)
    usage_percent:       f64,           // 使用百分比
    
    // 速率限制规则
    rate_limit_windows:  Vec<RateLimitWindow>, // 速率限制窗口列表
    
    // 重置信息
    seconds_until_reset: u64,           // 距重置的秒数
    reset_label:         String,        // 重置标签 (e.g. "in 2h 30m")
    
    // 状态描述
    usage_status_desc:   String,        // 使用状态描述
    usage_status:        UsageStatus,   // 使用状态枚举
    
    // 独占模型标识
    is_infinity:         bool,          // 无限配额
    is_atomcode_exclusive: bool,        // AtomCode 独占标记
    
    // 显示
    display_model_name:  String,        // 显示用模型名
    
    // 计划可用性
    plan_available:      bool,          // 计划是否可用
    duplicate:           bool,          // 是否重复
    codingplan_free:     bool,          // 是否免费 CodingPlan
    current_usage:       u64,           // 当前用量
    audit_status:        String,        // 审计状态
    
    // 旧的 window 配额
    window_quota_exhausted: bool,       // 窗口配额是否耗尽
    window_quota_hint:      String,     // 窗口配额提示
}

3.3 速率限制窗口

rust
struct RateLimitWindow {
    rule_index:          usize,    // 规则索引
    show_enable:         bool,     // 显示启用状态
    window_size_seconds: u64,      // 窗口大小(秒)
    call_limit:          u64,      // 调用限制
    calls_used:          u64,      // 已用调用数
    quota_exhausted:     bool,     // 是否耗尽
}

3.4 计费状态枚举

rust
enum UsageStatus {
    Ok,                  // 正常使用
    RateLimited,         // 被限速
    QuotaExhausted,      // 配额耗尽
    StreamInterrupted,   // 流中断
    StreamTimeout,       // 流超时
    Timeout,             // 超时
    Error,               // 错误
    // ... 其他
}

3.5 配额错误处理

rust
// 429 处理
"reconstruct 429 response"
"reconstruct empty 429 responses"
"send_with_retry: loop terminated without ..."

// 配额错误消息
"Current window quota exhausted"
"Monthly quota exhausted, available again in {}"
"Usage: monthly quota exhausted, available again in {}"
"Rate limited: {}"

// 日志
"calls.log"           // 调用日志文件
"%Y-%m-%d_%H-%M-%S_" // 日志时间戳格式

3.6 与 API 提供商的交互

text
CodingPlan API → https://api.gitcode.com/api/v5
  GET /models-v2          → 获取模型列表(含配额信息)
  POST /chat/completions  → 发送聊天请求(配额自动扣减)

配额检查发生在 LLM API 调用之前和过程中:
  1. 请求前:检查 window_quota_exhausted
  2. 响应中:解析 429 → 触发配额错误
  3. 请求后:更新 calls_used, window_tokens_used

4. ModelEntry 结构

rust
struct ModelEntry {
    name:              String,   // 模型名
    provider:          String,   // 提供商名
    is_default:        bool,     // 是否默认
    context_window:    u64,      // 上下文窗口
    effort_applicable: bool,     // 是否可设置推理努力度
    reasoning_effort:  Option<String>, // 默认推理努力度
    display_model_name: String,  // 显示用模型名
    plan_available:    bool,     // 计划可用
    // 可能包含 quota 信息
}

5. thinking_budget 校验

rust
"thinking_budget must be >= 1024"
// 最小预算 1024 tokens

总结

#盲区此前覆盖本次新增
1ProviderConfig 15 字段完整还原仅提及名称✅ 完整字段列表 + 类型标注
2CreateProviderRequest 16 字段✅ 完整字段
3PatchProviderRequest 19 字段✅ 最大结构体
4CodingPlan 配额系统✅ 20+ 字段完整还原
5RateLimitWindow 6 字段✅ 完整结构
6UsageStatus 枚举变体✅ 计费状态机
7ModelEntry 结构✅ 字段列表
8配额错误处理 (429/重试)部分✅ 完整流程
9提供商类型支持列表✅ openai/anthropic/deepseek/ollama/custom
10thinking_budget >= 1024 约束✅ 最小预算校验

报告份数总计: 52 份


本报告由持续分析循环生成 — 第 10 轮盲区挖掘

基于 VitePress 构建 · AtomCode v4.25.3 逆向工程分析文档