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

912 lines
43 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 蜂鸟Pro 系统设计文档 v2.0
## 一、系统概述
蜂鸟Pro 是一个 Cursor 账号管理与智能换号工具支持双账号池Auto/Pro、无感换号、用量监控等功能。
### 1.1 核心功能
| 功能 | 描述 |
|------|------|
| 双账号池 | Auto池按时间计费+ Pro池按积分计费 |
| 无感换号 | 注入代码实现不重启切换账号 |
| 用量监控 | 实时获取 Cursor 官方用量数据 |
| 智能换号 | 根据用量自动触发换号 |
| 密钥合并 | 多个密钥合并到主密钥,累加资源 |
---
## 二、数据模型设计
### 2.1 账号表 (cursor_accounts)
```sql
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)
```sql
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)
```sql
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)
```sql
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)
```sql
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 注入代码功能
```javascript
// 注入的代码 (伪代码)
(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 账号分析任务
```python
# 每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 环境变量
```bash
# 数据库
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. [ ] 部署到生产环境