Files
cursornew2026/docs/系统设计文档.md
ccdojox-crypto 73a71f198f 蜂鸟Pro v2.0.1 - 基础框架版本 (待完善)
## 当前状态
- 插件界面已完成重命名 (cursorpro → hummingbird)
- 双账号池 UI 已实现 (Auto/Pro 卡片)
- 后端已切换到 MySQL 数据库
- 添加了 Cursor 官方用量 API 文档

## 已知问题 (待修复)
1. 激活时检查账号导致无账号时激活失败
2. 未启用无感换号时不应获取账号
3. 账号用量模块不显示 (seamless 未启用时应隐藏)
4. 积分显示为 0 (后端未正确返回)
5. Auto/Pro 双密钥逻辑混乱,状态不同步
6. 账号添加后无自动分析功能

## 下一版本计划
- 重构数据模型,优化账号状态管理
- 实现 Cursor API 自动分析账号
- 修复激活流程,不依赖账号
- 启用无感时才分配账号
- 完善账号用量实时显示

## 文件说明
- docs/系统设计文档.md - 完整架构设计
- cursor 官方用量接口.md - Cursor API 文档
- 参考计费/ - Vibeviewer 开源项目参考

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 11:21:52 +08:00

43 KiB
Raw Blame History

蜂鸟Pro 系统设计文档 v2.0

一、系统概述

蜂鸟Pro 是一个 Cursor 账号管理与智能换号工具支持双账号池Auto/Pro、无感换号、用量监控等功能。

1.1 核心功能

功能 描述
双账号池 Auto池按时间计费+ Pro池按积分计费
无感换号 注入代码实现不重启切换账号
用量监控 实时获取 Cursor 官方用量数据
智能换号 根据用量自动触发换号
密钥合并 多个密钥合并到主密钥,累加资源

二、数据模型设计

2.1 账号表 (cursor_accounts)

CREATE TABLE cursor_accounts (
    id INT PRIMARY KEY AUTO_INCREMENT,
    email VARCHAR(255) NOT NULL COMMENT '账号邮箱',
    token TEXT NOT NULL COMMENT '认证Token (user_id::jwt)',
    password VARCHAR(255) COMMENT '账号密码(可选)',

    -- 状态管理
    status ENUM('pending', 'analyzing', 'available', 'in_use', 'exhausted', 'invalid', 'disabled')
           DEFAULT 'pending' COMMENT '账号状态',

    -- 账号类型 (从Cursor API自动分析得出)
    account_type ENUM('free_trial', 'pro', 'free', 'business', 'unknown')
                 DEFAULT 'unknown' COMMENT '账号类型',

    -- 用量信息 (从Cursor API获取)
    membership_type VARCHAR(50) COMMENT '会员类型原始值',
    billing_cycle_start DATETIME COMMENT '计费周期开始',
    billing_cycle_end DATETIME COMMENT '计费周期结束',
    trial_days_remaining INT DEFAULT 0 COMMENT '试用剩余天数',

    -- 用量统计
    usage_limit INT DEFAULT 0 COMMENT '用量上限',
    usage_used INT DEFAULT 0 COMMENT '已用用量',
    usage_remaining INT DEFAULT 0 COMMENT '剩余用量',
    usage_percent DECIMAL(5,2) DEFAULT 0 COMMENT '用量百分比',

    -- 详细用量 (从聚合API获取)
    total_requests INT DEFAULT 0 COMMENT '总请求次数',
    total_input_tokens BIGINT DEFAULT 0 COMMENT '总输入Token',
    total_output_tokens BIGINT DEFAULT 0 COMMENT '总输出Token',
    total_cost_cents DECIMAL(10,2) DEFAULT 0 COMMENT '总花费(美分)',

    -- 锁定信息
    locked_by_key_id INT COMMENT '被哪个激活码锁定',
    locked_at DATETIME COMMENT '锁定时间',

    -- 分析信息
    last_analyzed_at DATETIME COMMENT '最后分析时间',
    analyze_error VARCHAR(500) COMMENT '分析错误信息',

    -- 元数据
    remark VARCHAR(500) COMMENT '备注',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

    INDEX idx_status (status),
    INDEX idx_account_type (account_type),
    INDEX idx_locked_by (locked_by_key_id)
);

2.2 账号状态流转

pending (待分析)
    ↓ 后台分析任务
analyzing (分析中)
    ↓ 分析成功
available (可用)
    ↓ 被激活码锁定
in_use (使用中)
    ↓ 用量耗尽 / 手动释放
exhausted (已耗尽) / available (可用)

异常状态:
- invalid: Token无效/过期
- disabled: 管理员禁用

2.3 激活码表 (activation_keys)

CREATE TABLE activation_keys (
    id INT PRIMARY KEY AUTO_INCREMENT,
    `key` VARCHAR(64) NOT NULL UNIQUE COMMENT '激活码',

    -- 状态
    status ENUM('unused', 'active', 'expired', 'disabled') DEFAULT 'unused' COMMENT '状态',

    -- 套餐类型
    membership_type ENUM('auto', 'pro') DEFAULT 'pro' COMMENT '套餐类型',

    -- 密钥合并 (支持多密钥合并到主密钥)
    master_key_id INT COMMENT '主密钥ID (如果已合并到其他密钥)',
    merged_count INT DEFAULT 0 COMMENT '已合并的子密钥数量',
    merged_at DATETIME COMMENT '合并时间',

    -- 设备绑定
    device_id VARCHAR(255) COMMENT '绑定的设备ID',

    -- ===== Auto密钥专属字段 =====
    duration_days INT DEFAULT 30 COMMENT '该密钥贡献的天数',
    expire_at DATETIME COMMENT '到期时间 (首次激活时计算)',

    -- ===== Pro密钥专属字段 =====
    quota_contribution INT DEFAULT 500 COMMENT '该密钥贡献的积分',
    quota INT DEFAULT 500 COMMENT '总积分 (主密钥累加值)',
    quota_used INT DEFAULT 0 COMMENT '已用积分',

    -- ===== 无感换号 =====
    seamless_enabled TINYINT(1) DEFAULT 0 COMMENT '是否启用无感换号',
    current_account_id INT COMMENT '当前使用的账号ID',

    -- ===== 统计 =====
    switch_count INT DEFAULT 0 COMMENT '总换号次数',
    last_switch_at DATETIME COMMENT '最后换号时间',

    -- ===== 设备限制 =====
    max_devices INT DEFAULT 2 COMMENT '最大设备数',

    -- 激活信息
    first_activated_at DATETIME COMMENT '首次激活时间',
    last_active_at DATETIME COMMENT '最后活跃时间',

    -- 备注
    remark VARCHAR(500) COMMENT '备注',

    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

    INDEX idx_status (status),
    INDEX idx_membership_type (membership_type),
    INDEX idx_device_id (device_id),
    INDEX idx_master_key_id (master_key_id),
    FOREIGN KEY (master_key_id) REFERENCES activation_keys(id),
    FOREIGN KEY (current_account_id) REFERENCES cursor_accounts(id)
);

2.4 设备绑定表 (key_devices)

CREATE TABLE key_devices (
    id INT PRIMARY KEY AUTO_INCREMENT,
    key_id INT NOT NULL COMMENT '激活码ID',
    device_id VARCHAR(255) NOT NULL COMMENT '设备标识',
    device_name VARCHAR(255) COMMENT '设备名称',
    platform VARCHAR(50) COMMENT '平台: windows/macos/linux',
    last_active_at DATETIME COMMENT '最后活跃时间',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,

    UNIQUE KEY uk_key_device (key_id, device_id),
    FOREIGN KEY (key_id) REFERENCES activation_keys(id)
);

2.5 使用日志表 (usage_logs)

CREATE TABLE usage_logs (
    id INT PRIMARY KEY AUTO_INCREMENT,
    key_id INT NOT NULL COMMENT '激活码ID',
    account_id INT COMMENT '账号ID',

    action ENUM('activate', 'verify', 'enable_seamless', 'disable_seamless',
                'switch', 'auto_switch', 'release', 'merge') NOT NULL COMMENT '操作类型',

    success TINYINT(1) DEFAULT 1 COMMENT '是否成功',
    message VARCHAR(500) COMMENT '消息',

    -- 请求信息
    ip_address VARCHAR(50),
    user_agent VARCHAR(500),
    device_id VARCHAR(255),

    -- 用量快照 (换号时记录)
    usage_snapshot JSON COMMENT '用量快照',

    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_key_id (key_id),
    INDEX idx_action (action),
    INDEX idx_created_at (created_at)
);

2.6 全局设置表 (global_settings)

CREATE TABLE global_settings (
    id INT PRIMARY KEY AUTO_INCREMENT,
    `key` VARCHAR(100) NOT NULL UNIQUE COMMENT '设置键',
    value VARCHAR(500) NOT NULL COMMENT '设置值',
    value_type ENUM('string', 'int', 'float', 'bool', 'json') DEFAULT 'string',
    description VARCHAR(500) COMMENT '描述',
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- 默认设置
INSERT INTO global_settings (`key`, value, value_type, description) VALUES
('auto_switch_threshold', '98', 'int', 'Auto池自动换号阈值(用量百分比)'),
('pro_switch_threshold', '98', 'int', 'Pro池自动换号阈值(用量百分比)'),
('account_analyze_interval', '300', 'int', '账号分析间隔(秒)'),
('max_switch_per_day', '50', 'int', '每日最大换号次数'),
('auto_daily_switches', '999', 'int', 'Auto密钥每日换号次数限制'),
('pro_quota_per_switch', '1', 'int', 'Pro密钥每次换号消耗积分');

三、业务流程设计

3.1 账号添加与分析流程

┌─────────────────────────────────────────────────────────────┐
│                    管理员添加账号                            │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 1. 保存账号,状态 = pending                                  │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 2. 后台定时任务 (每5分钟扫描 pending/available 状态账号)      │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 3. 调用 Cursor API 分析账号                                  │
│    ├─ GET /api/usage-summary                                │
│    │   → membershipType, usageLimit, usageUsed              │
│    │   → daysRemainingOnTrial, billingCycle                 │
│    │                                                        │
│    └─ POST /api/dashboard/get-aggregated-usage-events       │
│        → totalRequests, totalCostCents                      │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 4. 更新账号信息                                              │
│    ├─ account_type = 根据 membershipType 判断               │
│    ├─ 更新所有用量字段                                       │
│    ├─ last_analyzed_at = NOW()                              │
│    └─ status = available (如果用量未耗尽)                    │
│              = exhausted (如果用量已耗尽)                    │
│              = invalid (如果Token无效)                       │
└─────────────────────────────────────────────────────────────┘

3.2 密钥激活流程

┌─────────────────────────────────────────────────────────────┐
│                    用户输入激活码                            │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 1. 验证激活码                                                │
│    ├─ 检查激活码是否存在                                     │
│    ├─ 检查状态是否为 unused 或 active                        │
│    └─ 检查是否过期 (Auto: expire_at, Pro: quota剩余)         │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 2. 处理设备绑定                                              │
│    ├─ 检查当前设备数是否超过 max_devices                     │
│    ├─ 如果是新设备,添加到 key_devices                       │
│    └─ 更新 last_active_at                                   │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 3. 首次激活处理                                              │
│    ├─ 如果 first_activated_at 为空:                         │
│    │   ├─ Auto: 计算 expire_at = NOW() + duration_days      │
│    │   └─ 设置 first_activated_at = NOW()                   │
│    └─ 更新 status = active                                  │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 4. 返回激活结果 (不分配账号!)                                │
│    {                                                        │
│      success: true,                                         │
│      membership_type: "auto" / "pro",                       │
│      expire_at: "2025-12-25 18:00:00",  // Auto             │
│      quota: 500, quota_used: 0,          // Pro             │
│      seamless_enabled: false                                │
│    }                                                        │
└─────────────────────────────────────────────────────────────┘

3.3 启用无感换号流程

┌─────────────────────────────────────────────────────────────┐
│                用户点击"启用无感换号"                         │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 1. 前端: 注入代码到 Cursor workbench.js                      │
│    ├─ 检查是否有写入权限                                     │
│    ├─ 备份原文件                                            │
│    └─ 注入换号代码                                          │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 2. 前端: 调用后端 API 启用无感                               │
│    POST /api/client/enable-seamless                         │
│    { key, device_id }                                       │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 3. 后端: 分配账号                                            │
│    ├─ 根据密钥类型选择账号池:                                │
│    │   ├─ Auto密钥 → 优先 free_trial 类型账号               │
│    │   └─ Pro密钥 → 优先 pro 类型账号                       │
│    ├─ 从 available 状态账号中选择用量最低的                  │
│    ├─ 锁定账号: locked_by_key_id = key.id, status = in_use  │
│    └─ 更新密钥: current_account_id, seamless_enabled = 1    │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 4. 返回账号信息                                              │
│    {                                                        │
│      success: true,                                         │
│      account: {                                             │
│        email: "xxx@gmail.com",                              │
│        token: "user_id::jwt_token",                         │
│        membership_type: "free_trial",                       │
│        trial_days_remaining: 6,                             │
│        usage_percent: 20,                                   │
│        total_requests: 201,                                 │
│        total_cost_usd: 12.63                                │
│      }                                                      │
│    }                                                        │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 5. 前端: 显示账号用量模块,提示重启 Cursor                   │
└─────────────────────────────────────────────────────────────┘

3.4 换号流程 (手动/自动)

┌─────────────────────────────────────────────────────────────┐
│            手动换号 / 自动换号 (用量超阈值)                   │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 1. 检查换号条件                                              │
│    ├─ 密钥是否有效                                          │
│    ├─ 是否启用了无感换号                                     │
│    ├─ Pro密钥: 检查剩余积分是否足够                          │
│    └─ 检查今日换号次数是否超限                               │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 2. 释放当前账号                                              │
│    ├─ 获取当前账号用量快照 (用于日志)                        │
│    ├─ 判断账号状态:                                         │
│    │   ├─ 用量 < 90% → status = available                   │
│    │   └─ 用量 >= 90% → status = exhausted                  │
│    └─ 清除锁定: locked_by_key_id = NULL                     │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 3. 分配新账号 (同启用无感流程)                               │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 4. 更新统计                                                  │
│    ├─ Pro密钥: quota_used += 1                              │
│    ├─ switch_count += 1                                     │
│    ├─ last_switch_at = NOW()                                │
│    └─ 记录日志到 usage_logs                                 │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 5. 返回新账号信息                                            │
└─────────────────────────────────────────────────────────────┘

3.5 密钥合并流程

┌─────────────────────────────────────────────────────────────┐
│              用户输入新密钥到已激活的设备                     │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 1. 检查合并条件                                              │
│    ├─ 新密钥状态必须是 unused                                │
│    ├─ 新密钥类型必须与主密钥相同 (Auto+Auto / Pro+Pro)       │
│    └─ 检查主密钥是否已被合并过 (已合并的不能再当主密钥)       │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 2. 执行合并                                                  │
│    ├─ 新密钥: master_key_id = 主密钥ID, merged_at = NOW()   │
│    ├─ 新密钥: status = active                               │
│    │                                                        │
│    ├─ 主密钥 (Auto): expire_at += 新密钥.duration_days      │
│    └─ 主密钥 (Pro): quota += 新密钥.quota_contribution       │
│                                                             │
│    └─ 主密钥: merged_count += 1                             │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│ 3. 返回合并结果                                              │
│    {                                                        │
│      success: true,                                         │
│      message: "密钥已合并",                                  │
│      new_expire_at / new_quota: ...                         │
│    }                                                        │
└─────────────────────────────────────────────────────────────┘

四、API 接口设计

4.1 客户端 API (/api/client/*)

4.1.1 验证/激活密钥

POST /api/client/activate
Request:
{
    "key": "XXXX-XXXX-XXXX",
    "device_id": "machine_id_hash"
}

Response (成功):
{
    "success": true,
    "data": {
        "key": "XXXX-XXXX-XXXX",
        "membership_type": "auto",  // auto | pro
        "status": "active",

        // Auto密钥
        "expire_at": "2025-12-25T18:00:00Z",
        "days_remaining": 7,

        // Pro密钥
        "quota": 500,
        "quota_used": 50,
        "quota_remaining": 450,

        // 无感状态
        "seamless_enabled": false,
        "current_account": null
    }
}

Response (失败):
{
    "success": false,
    "error": "激活码无效",
    "code": "INVALID_KEY"
}

4.1.2 启用无感换号

POST /api/client/enable-seamless
Request:
{
    "key": "XXXX-XXXX-XXXX",
    "device_id": "machine_id_hash"
}

Response:
{
    "success": true,
    "data": {
        "account": {
            "email": "user@gmail.com",
            "token": "user_id::jwt_token",
            "account_type": "free_trial",
            "membership_type": "free_trial",
            "trial_days_remaining": 6,
            "usage_percent": 20.5,
            "total_requests": 201,
            "total_cost_usd": 12.63
        }
    }
}

4.1.3 禁用无感换号

POST /api/client/disable-seamless
Request:
{
    "key": "XXXX-XXXX-XXXX"
}

Response:
{
    "success": true,
    "message": "无感换号已禁用"
}

4.1.4 手动换号

POST /api/client/switch
Request:
{
    "key": "XXXX-XXXX-XXXX"
}

Response:
{
    "success": true,
    "data": {
        "old_account": "old@gmail.com",
        "new_account": {
            "email": "new@gmail.com",
            "token": "user_id::jwt_token",
            ...
        },
        "switch_count": 5,
        "quota_remaining": 495  // Pro密钥
    }
}

4.1.5 获取状态

GET /api/client/status?key=XXXX-XXXX-XXXX

Response:
{
    "success": true,
    "data": {
        "key_info": {
            "membership_type": "auto",
            "status": "active",
            "expire_at": "2025-12-25T18:00:00Z",
            "days_remaining": 7,
            "seamless_enabled": true,
            "switch_count": 3
        },
        "account_info": {  // 仅当 seamless_enabled=true
            "email": "user@gmail.com",
            "account_type": "free_trial",
            "trial_days_remaining": 6,
            "usage_percent": 20.5,
            "total_requests": 201,
            "total_cost_usd": 12.63,
            "last_analyzed_at": "2025-12-18T14:12:35Z"
        }
    }
}

4.1.6 获取账号用量 (实时)

GET /api/client/account-usage?key=XXXX-XXXX-XXXX&refresh=true

Response:
{
    "success": true,
    "data": {
        "email": "user@gmail.com",
        "membership_type": "free_trial",
        "trial_days_remaining": 6,
        "billing_cycle": {
            "start": "2025-12-15T00:00:00Z",
            "end": "2026-01-15T00:00:00Z"
        },
        "usage": {
            "limit": 1000,
            "used": 201,
            "remaining": 799,
            "percent": 20.1
        },
        "cost": {
            "total_requests": 201,
            "total_input_tokens": 346883,
            "total_output_tokens": 45356,
            "total_cost_usd": 12.63
        },
        "updated_at": "2025-12-18T14:12:35Z"
    }
}

4.2 管理后台 API (/api/admin/*)

4.2.1 账号管理

GET    /api/admin/accounts              # 账号列表
POST   /api/admin/accounts              # 添加账号 (只需token)
GET    /api/admin/accounts/{id}         # 账号详情
PUT    /api/admin/accounts/{id}         # 更新账号
DELETE /api/admin/accounts/{id}         # 删除账号
POST   /api/admin/accounts/{id}/analyze # 手动分析账号
POST   /api/admin/accounts/batch        # 批量添加账号

4.2.2 激活码管理

GET    /api/admin/keys                  # 激活码列表
POST   /api/admin/keys/generate         # 生成激活码
GET    /api/admin/keys/{id}             # 激活码详情
PUT    /api/admin/keys/{id}             # 更新激活码
DELETE /api/admin/keys/{id}             # 删除激活码
POST   /api/admin/keys/{id}/extend      # 延期/加积分

五、前端界面设计

5.1 控制面板布局

┌─────────────────────────────────────────────────────────────┐
│ 🔐 软件授权                                         已授权  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌───────────────────┐  ┌───────────────────┐              │
│  │     🌿 Auto       │  │     ⚡ Pro        │              │
│  │  基础模型·无限换号 │  │  高级模型·积分制  │              │
│  │      已激活       │  │      已激活       │              │
│  └───────────────────┘  └───────────────────┘              │
│                                                             │
│  [请输入CDK激活码                              ]  [激活]    │
│                                                             │
│  ┌─ AUTO 密钥 ──────────┐  ┌─ PRO 密钥 ──────────┐        │
│  │ HIOR03M0GT8VDTL****  │  │ LAXFY1EY7QZJ9C3L****│        │
│  │ 到期: 2025/12/19     │  │ 积分: 450/500       │        │
│  │ 18:49:36             │  │                     │        │
│  │ [清除]               │  │ [清除]              │        │
│  └──────────────────────┘  └─────────────────────┘        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│ ⚡ 无感换号                                         已启用  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  当前账号      user123@gmail.com                           │
│                                                             │
│  使用池        ● Auto池  ○ Pro池                           │
│                                                             │
│  免魔法模式 PRO                              [====○    ]   │
│                                                             │
│  [    一键换号 (Auto无限/Pro扣1积分)    ]                   │
│                                                             │
│  [重置机器码]                    [禁用无感换号]             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│ 📊 账号用量                                           [🔄]  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────┬─────────────────┐                     │
│  │ 会员类型        │ 免费试用        │                     │
│  ├─────────────────┼─────────────────┤                     │
│  │ 试用剩余        │ 6 天            │                     │
│  ├─────────────────┼─────────────────┤                     │
│  │ 请求次数        │ 201 次          │                     │
│  ├─────────────────┼─────────────────┤                     │
│  │ 已用额度        │ $12.63          │                     │
│  ├─────────────────┼─────────────────┤                     │
│  │ 用量百分比      │ ████░░░░ 20%    │                     │
│  └─────────────────┴─────────────────┘                     │
│                                                             │
│  更新于 14:12:35                                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│ 📢 公告                                              通知   │
├─────────────────────────────────────────────────────────────┤
│ 欢迎使用蜂鸟Pro                                            │
│ 感谢使用蜂鸟Pro!                                           │
│                                                             │
│ 如有问题请联系客服。                                        │
│                                           2024/12/17 00:00 │
└─────────────────────────────────────────────────────────────┘

5.2 状态显示规则

条件 显示内容
未激活任何密钥 "请先激活授权码", 启用无感按钮禁用
已激活Auto 显示Auto密钥卡片, 到期时间
已激活Pro 显示Pro密钥卡片, 积分 xxx/xxx
已激活但未启用无感 "账号用量"模块隐藏
已启用无感 显示当前账号邮箱, 显示"账号用量"模块

六、注入代码设计

6.1 注入位置

Cursor安装目录/resources/app/out/vs/workbench/workbench.desktop.main.js

6.2 注入代码功能

// 注入的代码 (伪代码)
(function() {
    const API_BASE = 'https://api.aicode.edu.pl';
    const CHECK_INTERVAL = 60000;  // 每60秒检查一次

    // 从 localStorage 读取配置
    const config = JSON.parse(localStorage.getItem('hummingbird_config') || '{}');

    // 定时检查用量
    setInterval(async () => {
        if (!config.enabled) return;

        try {
            // 获取用量
            const usage = await fetch(`${API_BASE}/api/client/account-usage?key=${config.key}`);
            const data = await usage.json();

            // 检查是否需要换号
            if (data.usage.percent >= config.threshold) {
                // 自动换号
                const switchRes = await fetch(`${API_BASE}/api/client/switch`, {
                    method: 'POST',
                    body: JSON.stringify({ key: config.key })
                });
                const newAccount = await switchRes.json();

                // 更新本地 Token
                if (newAccount.success) {
                    updateLocalToken(newAccount.data.new_account.token);
                }
            }
        } catch (e) {
            console.error('[HummingbirdPro] Check failed:', e);
        }
    }, CHECK_INTERVAL);

    function updateLocalToken(token) {
        // 更新 Cursor 的认证存储
        // ...
    }
})();

七、后台定时任务

7.1 账号分析任务

# 每5分钟执行一次
async def analyze_accounts_task():
    """分析待处理和可用状态的账号"""

    # 获取需要分析的账号
    accounts = db.query(CursorAccount).filter(
        CursorAccount.status.in_(['pending', 'available']),
        or_(
            CursorAccount.last_analyzed_at == None,
            CursorAccount.last_analyzed_at < datetime.now() - timedelta(minutes=30)
        )
    ).limit(10).all()

    for account in accounts:
        try:
            # 调用 Cursor API
            usage_data = await cursor_api.get_usage_summary(account.token)
            aggregated = await cursor_api.get_aggregated_usage(account.token)

            # 更新账号信息
            account.account_type = map_membership_type(usage_data['membershipType'])
            account.membership_type = usage_data['membershipType']
            account.trial_days_remaining = usage_data.get('daysRemainingOnTrial', 0)
            account.usage_limit = usage_data['individualUsage']['plan']['limit']
            account.usage_used = usage_data['individualUsage']['plan']['used']
            account.usage_percent = (account.usage_used / account.usage_limit * 100) if account.usage_limit > 0 else 0
            account.total_requests = aggregated.get('totalRequests', 0)
            account.total_cost_cents = aggregated.get('totalCostCents', 0)
            account.last_analyzed_at = datetime.now()

            # 更新状态
            if account.usage_percent >= 95:
                account.status = AccountStatus.EXHAUSTED
            elif account.status == AccountStatus.PENDING:
                account.status = AccountStatus.AVAILABLE

        except TokenInvalidError:
            account.status = AccountStatus.INVALID
            account.analyze_error = "Token无效或已过期"
        except Exception as e:
            account.analyze_error = str(e)

    db.commit()

八、错误码定义

错误码 描述
INVALID_KEY 激活码无效
KEY_EXPIRED 激活码已过期
KEY_DISABLED 激活码已禁用
QUOTA_EXCEEDED 积分不足
DEVICE_LIMIT 设备数超限
NO_AVAILABLE_ACCOUNT 无可用账号
SEAMLESS_NOT_ENABLED 未启用无感换号
SWITCH_LIMIT_EXCEEDED 换号次数超限
ACCOUNT_LOCKED 账号已被锁定
TOKEN_INVALID Token无效

九、部署配置

9.1 环境变量

# 数据库
USE_SQLITE=false
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=cursorpro
DB_PASSWORD=xxx
DB_NAME=cursorpro

# JWT
SECRET_KEY=your-secret-key
ACCESS_TOKEN_EXPIRE_MINUTES=10080

# 管理员
ADMIN_USERNAME=admin
ADMIN_PASSWORD=your-password

# API
API_TOKEN=your-api-token

9.2 依赖

fastapi
uvicorn
sqlalchemy
pymysql
pydantic
httpx
apscheduler

十、开发计划

Phase 1: 后端重构

  1. 更新数据模型 (models.py)
  2. 实现 Cursor API 服务 (cursor_usage_service.py)
  3. 重写账号服务 (account_service.py)
  4. 重写客户端 API (client.py)
  5. 添加定时任务 (tasks.py)

Phase 2: 前端优化

  1. 重构 panel.html 界面
  2. 修复状态显示逻辑
  3. 添加账号用量模块
  4. 优化错误提示

Phase 3: 测试与部署

  1. 单元测试
  2. 集成测试
  3. 部署到生产环境