Files
cursornew2026/参考计费/.cursor/rules/api_guideline.mdc
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

150 lines
5.6 KiB
Plaintext

---
alwaysApply: false
---
# API Authoring Guidelines (VibeviewerAPI)
## Goals
- Unify API naming, directories, abstractions, dependency injection, and decoding patterns
- Keep all APIs in a single module `VibeviewerAPI` to enforce isolation and modularity
- Standardize `DecodableTargetType` and the `HttpClient.decodableRequest(_:)` usage (async/await only) on top of Moya/Alamofire
## Hard rules
- API targets must be declared with `struct` (no `enum`/case-style targets)
- Use async/await-only decoding; callback-based styles are forbidden
- Separate API declarations from model declarations:
- API Targets/Services → `VibeviewerAPI`
- Data models/aggregations → `VibeviewerModel`
- Views/upper layers must use `Service` protocols via dependency injection, and must not call API targets or `HttpClient` directly
- The API module only exposes `Service` protocols and default implementations; API targets, networking details, and common header configuration remain internal
## Dependencies & imports
- API module imports only:
- `Foundation`
- `Moya`
- `Alamofire` (used via `HttpClient`)
- `VibeviewerModel`
- Never import UI frameworks in the API module (`SwiftUI`/`AppKit`/`UIKit`)
## Naming conventions
- Targets: Feature name + `API`, e.g., `YourFeatureAPI`
- Protocols: `YourFeatureService`
- Default implementations: `DefaultYourFeatureService`
- Models: `YourFeatureResponse`, `YourFeatureDetail`, etc.
## Directory structure (VibeviewerAPI)
```text
VibeviewerAPI/
Sources/VibeviewerAPI/
Mapping/
... DTOs & Mappers
Plugins/
RequestHeaderConfigurationPlugin.swift
RequestErrorHandlingPlugin.swift
SimpleNetworkLoggerPlugin.swift
Service/
MoyaProvider+DecodableRequest.swift
HttpClient.swift # Unified Moya provider & session wrapper
HttpClientError.swift
Targets/
CursorGetMeAPI.swift # internal target
CursorUsageAPI.swift # internal target
CursorTeamSpendAPI.swift # internal target
CursorService.swift # public protocol + default implementation (service only)
```
## Target and decoding conventions
- Targets conform to `DecodableTargetType`:
- `associatedtype ResultType: Decodable`
- `var decodeAtKeyPath: String? { get }` (default `nil`)
- Implement `baseURL`, `path`, `method`, `task`, `headers`, `sampleData`
- Avoid overriding `validationType` unless necessary
Example:
```swift
import Foundation
import Moya
import VibeviewerModel
struct UserProfileDetailAPI: DecodableTargetType {
typealias ResultType = UserProfileResponse
let userId: String
var baseURL: URL { APIConfig.baseURL }
var path: String { "/users/\(userId)" }
var method: Moya.Method { .get }
var task: Task { .requestPlain }
var headers: [String: String]? { APIHeadersBuilder.basicHeaders(cookieHeader: nil) }
var sampleData: Data { Data("{\"id\":\"1\",\"name\":\"foo\"}".utf8) }
}
```
## Service abstraction & dependency injection
- Expose protocol + default implementation (expose services only; hide networking details)
- The default `public init(decoding:)` must not leak internal protocol types; provide `internal init(network:decoding:)` for test injection
```swift
import Foundation
import Moya
import VibeviewerModel
public protocol UserProfileService {
func fetchDetail(userId: String) async throws -> UserProfileResponse
}
public struct DefaultUserProfileService: UserProfileService {
private let network: NetworkClient
private let decoding: JSONDecoder.KeyDecodingStrategy
// Business-facing: do not expose internal NetworkClient abstraction
public init(decoding: JSONDecoder.KeyDecodingStrategy = .useDefaultKeys) {
self.network = DefaultNetworkClient()
self.decoding = decoding
}
// Test injection: available within the API module (same package or @testable)
init(network: any NetworkClient, decoding: JSONDecoder.KeyDecodingStrategy = .useDefaultKeys) {
self.network = network
self.decoding = decoding
}
public func fetchDetail(userId: String) async throws -> UserProfileResponse {
try await network.decodableRequest(
UserProfileDetailAPI(userId: userId),
decodingStrategy: decoding
)
}
}
```
> Note: `DefaultNetworkClient`, the `NetworkClient` protocol, and the concrete `HttpClient` implementation details remain `internal` and are not exposed.
## View usage (dependency injection)
Views must not call API targets or `HttpClient` directly. Use injected services instead:
```swift
import VibeviewerAPI
import VibeviewerModel
let service: UserProfileService = DefaultUserProfileService()
let model = try await service.fetchDetail(userId: "1")
```
## Error handling & logging
- Enable `SimpleNetworkLoggerPlugin` by default to log requests/responses
- Enable `RequestErrorHandlingPlugin` by default:
- Timeouts/offline → unified handling
- Customizable via strategy protocols
## Testing & mock conventions
- Within the `VibeviewerAPI` module, inject a `FakeNetworkClient` via `internal init(network:decoding:)` to replace real networking
- Provide `sampleData` for each target; prefer minimal realistic JSON to ensure robust decoding
- Use `@testable import VibeviewerAPI` to access internal symbols when external tests are required
## Alignment with modular architecture (architecture.mdc)
- Do not import UI frameworks in the API module
- Expose only `Service` protocols and default implementations; hide targets and networking details
- Dependency direction: `VibeviewerModel` ← `VibeviewerAPI` ← `VibeviewerFeature`
- Strict “one file, one type/responsibility”; clear feature aggregation; one-way dependencies