蜂鸟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:
149
参考计费/.cursor/rules/api_guideline.mdc
Normal file
149
参考计费/.cursor/rules/api_guideline.mdc
Normal file
@@ -0,0 +1,149 @@
|
||||
---
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user