蜂鸟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>
This commit is contained in:
ccdojox-crypto
2025-12-18 11:21:52 +08:00
parent f310ca7b97
commit 73a71f198f
202 changed files with 19142 additions and 252 deletions

View File

@@ -0,0 +1,104 @@
"""
测试 CursorUsageService
"""
import asyncio
import sys
sys.path.insert(0, '.')
from app.services.cursor_usage_service import (
cursor_usage_service,
get_account_usage,
check_account_valid,
check_and_classify_account
)
# 测试 Token (free_trial)
TEST_TOKEN = "user_01KCG2G9K4Q37C1PKTNR7EVNGW::eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhdXRoMHx1c2VyXzAxS0NHMkc5SzRRMzdDMVBLVE5SN0VWTkdXIiwidGltZSI6IjE3NjU3ODc5NjYiLCJyYW5kb21uZXNzIjoiOTA1NTU4NjktYTlmMC00M2NhIiwiZXhwIjoxNzcwOTcxOTY2LCJpc3MiOiJodHRwczovL2F1dGhlbnRpY2F0aW9uLmN1cnNvci5zaCIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwgb2ZmbGluZV9hY2Nlc3MiLCJhdWQiOiJodHRwczovL2N1cnNvci5jb20iLCJ0eXBlIjoic2Vzc2lvbiJ9.vreEnprZ7q9pU7b6TTVGQ0HUIQTJrxLXcnkz4Ne4Dng"
async def test_check_valid():
"""测试账号有效性检查"""
print("\n========== 1. 检查账号有效性 ==========")
is_valid, error = await check_account_valid(TEST_TOKEN)
print(f"账号有效: {is_valid}")
if error:
print(f"错误: {error}")
async def test_get_usage():
"""测试获取用量信息"""
print("\n========== 2. 获取用量信息 ==========")
result = await get_account_usage(TEST_TOKEN)
if result["success"]:
data = result["data"]
print(f"会员类型: {data['membership_type']}")
if data.get('days_remaining_on_trial'):
print(f"试用剩余天数: {data['days_remaining_on_trial']}")
print(f"计费周期: {data['billing_cycle']['start']} ~ {data['billing_cycle']['end']}")
print(f"套餐用量: {data['plan_usage']['used']}/{data['plan_usage']['limit']} (剩余 {data['plan_usage']['remaining']})")
print(f"总请求次数: {data['total_requests']}")
print(f"Token 用量:")
print(f" - 输入: {data['token_usage']['input_tokens']}")
print(f" - 输出: {data['token_usage']['output_tokens']}")
print(f" - 缓存读取: {data['token_usage']['cache_read_tokens']}")
print(f" - 总费用: ${data['token_usage']['total_cost_usd']}")
else:
print(f"获取失败: {result['error']}")
async def test_full_info():
"""测试完整信息"""
print("\n========== 3. 完整验证结果 ==========")
info = await cursor_usage_service.validate_and_get_usage(TEST_TOKEN)
print(f"账号有效: {info.is_valid}")
print(f"会员类型: {info.membership_type}")
print(f"号池类型: {info.pool_type}")
print(f"是否Pro试用: {info.is_pro_trial}")
print(f"是否可用: {info.is_usable}")
if info.days_remaining_on_trial:
print(f"试用剩余天数: {info.days_remaining_on_trial}")
print(f"套餐用量: {info.plan_used}/{info.plan_limit} (剩余 {info.plan_remaining})")
print(f"总请求次数: {info.total_requests}")
print(f"总输入Token: {info.total_input_tokens}")
print(f"总输出Token: {info.total_output_tokens}")
print(f"总费用: ${info.total_cost_cents / 100:.4f}")
if info.error_message:
print(f"错误: {info.error_message}")
async def test_classify():
"""测试号池分类"""
print("\n========== 4. 号池分类 ==========")
result = await check_and_classify_account(TEST_TOKEN)
if result["success"]:
print(f"号池类型: {result['pool_type']}")
print(f"是否可用: {result['is_usable']}")
print(f"会员类型: {result['membership_type']}")
print(f"是否Pro试用: {result['is_pro_trial']}")
print(f"剩余额度: {result['plan_remaining']}")
print(f">>> {result['recommendation']}")
else:
print(f"分类失败: {result['error']}")
async def main():
print("=" * 50)
print(" CursorUsageService 测试")
print("=" * 50)
await test_check_valid()
await test_get_usage()
await test_full_info()
await test_classify()
print("\n" + "=" * 50)
print(" 测试完成")
print("=" * 50)
if __name__ == "__main__":
asyncio.run(main())