# TODOS 重構 cursor-api-proxy → go-zero + DDD Architecture 的待辦事項。 --- ## Phase 1: API 定義與骨架生成 ### DONE - [x] 建立 `api/chat.api` 定義檔 - [x] 建立 `etc/chat.yaml` 配置檔 - [x] 生成代碼骨架 - [x] 移動 `chat.go` 到 `cmd/chat/` ### TODO #### TODO-1: 全局變數遷移清單 - **What**: 建立全局變數到 ServiceContext 的遷移清單 - **Why**: 現有代碼有多個全局變數,遷移時容易遺漏 - **Files**: - `internal/pool/pool.go:36-38` → `globalPool`, `globalMu` → ServiceContext - `internal/process/process.go:117` → `MaxModeFn` → ServiceContext - `internal/handlers/chat.go:28-29` → `rateLimitRe`, `retryAfterRe` → ServiceContext 或常數 - `internal/models/cursormap.go:8,47,51` → 正則表達式常數化 - **Decision**: ServiceContext 注入 - **Effort**: human ~2h / CC ~30min - **Depends on**: Phase 2 (Domain 層建立) - **Status**: pending #### TODO-2: go.mod 更新 - **What**: 添加 go-zero 依賴到 go.mod - **Why**: 現有 go.mod 沒有 go-zero 依賴 - **Command**: `go get github.com/zeromicro/go-zero@latest` - **Decision**: 使用最新穩定版 - **Effort**: human ~5min / CC ~1min - **Depends on**: Phase 1 開始前 - **Status**: pending #### TODO-3: Makefile 更新 - **What**: 更新 Makefile 以支援 go-zero 的建置流程 - **Why**: 需要新增 goctl 命令和整合現有 env/run 命令 - **Commands to add**: ```makefile .PHONY: api api: goctl api go -api api/chat.api -dir . --style go_zero .PHONY: api-doc api-doc: goctl api doc -api api/chat.api -dir docs/ .PHONY: gen gen: api go mod tidy ``` - **Decision**: 需要追蹤 - **Effort**: human ~30min / CC ~10min - **Depends on**: Phase 1 (API 定義與骨架生成) - **Status**: pending --- ## Phase 2: Domain 層建立 ### DONE - [ ] 建立 `pkg/domain/entity/` - [ ] 建立 `pkg/domain/repository/` - [ ] 建立 `pkg/domain/usecase/` - [ ] 建立 `pkg/domain/const/` ### TODO #### TODO-4: import 循環依賴檢測 - **What**: 在每個 Phase 完成後執行 `go build ./...` 檢測循環依賴 - **Why**: DDD 架構分層容易產生循環依賴 - **Potential cycles**: - `pkg/usecase` ↔ `pkg/domain/usecase` - `pkg/repository` ↔ `pkg/domain/repository` - **Command**: `go build ./... && go test ./... -run=none` - **Depends on**: 每個 Phase 完成後 - **Status**: pending --- ## Phase 8: Internal 層重組 ### DONE - [ ] 更新 `internal/config/config.go` - [ ] 建立 `internal/svc/servicecontext.go` - [ ] 建立 `internal/logic/` - [ ] 建立 `internal/handler/` - [ ] 建立 `internal/middleware/` ### TODO #### TODO-5: SSE 整合測試 - **What**: 增加 SSE streaming 的端對端測試 - **Why**: SSE 是核心功能,自訂 handler 容易出錯,沒有測試覆蓋 - **Test cases**: 1. SSE streaming 請求正常返回 2. SSE client disconnect 正確處理 3. SSE timeout 正確處理 4. 非串流請求轉 SSE 格式 - **Implementation**: ```go // tests/integration/sse_test.go func TestSSEStreaming(t *testing.T) { // 使用 httptest 模擬 SSE 客戶端 // 驗證 data: [DONE] 正確返回 } ``` - **Decision**: 使用 `rest.WithCustom` 路由 - **Effort**: human ~2h / CC ~30min - **Depends on**: Phase 8 完成(Internal 層重組) - **Status**: pending #### TODO-6: SSE Handler 實作 - **What**: 使用 `rest.WithCustom` 實作 SSE streaming handler - **Why**: go-zero 標準 handler 不支援 SSE,需要自訂 - **Implementation**: ```go // internal/handler/chat_handler.go func NewChatHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // SSE 設定 w.Header().Set("Content-Type", "text/event-stream") w.Header().Set("Cache-Control", "no-cache") w.Header().Set("Connection", "keep-alive") // 委託給 usecase svcCtx.ChatUsecase.Stream(r.Context(), input, callback) } } ``` - **Decision**: 使用 `rest.WithCustom` 路由 - **Effort**: human ~2h / CC ~30min - **Depends on**: Phase 6 (Usecase 層建立) - **Status**: pending --- ## Phase 10: 清理與測試 ### DONE - [ ] 移除舊目錄 - [ ] 更新 import 路徑 - [ ] 執行測試 ### TODO #### TODO-7: 測試文件遷移 - **What**: 測試文件跟隨源碼遷移到 pkg/ - **Why**: 測試應該與源碼在同一目錄 - **Files to migrate**: - `internal/httputil/httputil_test.go` → `pkg/infrastructure/httputil/` - `internal/config/config_test.go` → `internal/config/` (保留) - `internal/sanitize/sanitize_test.go` → `pkg/usecase/` - `internal/models/cursormap_test.go` → `pkg/domain/const/` - `internal/models/cursorcli_test.go` → `pkg/domain/const/` - `internal/parser/stream_test.go` → `pkg/infrastructure/parser/` - `internal/env/env_test.go` → `pkg/infrastructure/env/` - `internal/winlimit/winlimit_test.go` → `pkg/infrastructure/winlimit/` - `internal/anthropic/anthropic_test.go` → `pkg/adapter/anthropic/` - `internal/pool/pool_test.go` → `pkg/repository/` - `internal/openai/openai_test.go` → `pkg/adapter/openai/` - `internal/process/process_test.go` → `pkg/infrastructure/process/` - **Decision**: 測試遷移到 pkg/ - **Effort**: human ~1h / CC ~10min - **Depends on**: Phase 3-7 完成 - **Status**: pending #### TODO-8: ServiceContext 單例 Pool - **What**: AccountPool 使用單例模式,透過 sync.Once 確保只初始化一次 - **Why**: 避免每次請求創建新 Pool 的開銷 - **Implementation**: ```go // pkg/repository/account.go var ( globalPool *AccountPool globalPoolOnce sync.Once ) func GetAccountPool(configDirs []string) *AccountPool { globalPoolOnce.Do(func() { globalPool = NewAccountPool(configDirs) }) return globalPool } ``` - **Decision**: 使用單例 Pool - **Effort**: human ~30min / CC ~10min - **Depends on**: Phase 4 (Repository 層實作) - **Status**: pending --- ## Phase 獨立 TODO ### TODO-9: 回歸測試自動化 - **What**: 建立自動化回歸測試腳本 - **Why**: 確保每次遷移後功能正常 - **Script**: ```bash # scripts/regression-test.sh #!/bin/bash set -e echo "=== Health check ===" curl -s http://localhost:8080/health | jq . echo "=== Models list ===" curl -s http://localhost:8080/v1/models | jq . echo "=== Chat completion (non-streaming) ===" curl -s -X POST http://localhost:8080/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{"model":"test","messages":[{"role":"user","content":"hi"}],"stream":false}' | jq . echo "=== Chat completion (streaming) ===" curl -s -X POST http://localhost:8080/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{"model":"test","messages":[{"role":"user","content":"hi"}],"stream":true}' ``` - **Depends on**: Phase 10 完成 - **Status**: pending --- ## Summary | TODO | Phase | Effort | Status | |------|-------|--------|--------| | TODO-1: 全局變數遷移清單 | Phase 2 | 2h | pending | | TODO-2: go.mod 更新 | Phase 1 | 5min | pending | | TODO-3: Makefile 更新 | Phase 1 | 30min | pending | | TODO-4: import 循環依賴檢測 | Each Phase | 5min | pending | | TODO-5: SSE 整合測試 | Phase 8 | 2h | pending | | TODO-6: SSE Handler 實作 | Phase 8 | 2h | pending | | TODO-7: 測試文件遷移 | Phase 10 | 1h | pending | | TODO-8: ServiceContext 單例 Pool | Phase 4 | 30min | pending | | TODO-9: 回歸測試自動化 | Phase 10 | 30min | pending | --- ## Dependencies Graph ``` Phase 1 (API 定義) │ ├── TODO-2: go.mod 更新 (必须在開始前完成) ├── TODO-3: Makefile 更新 │ ▼ Phase 2 (Domain 層) │ ├── TODO-1: 全局變數遷移清單 ├── TODO-4: import 循環依賴檢測 │ ▼ Phase 3 (Infrastructure 層) │ ├── TODO-4: import 循環依賴檢測 │ ▼ Phase 4 (Repository 層) │ ├── TODO-8: ServiceContext 單例 Pool ├── TODO-4: import 循環依賴檢測 │ ▼ Phase 5 (Provider 層) │ ├── TODO-4: import 循環依賴檢測 │ ▼ Phase 6 (Usecase 層) │ ├── TODO-4: import 循環依賴檢測 │ ▼ Phase 7 (Adapter 層) │ ├── TODO-4: import 循環依賴檢測 │ ▼ Phase 8 (Internal 層) │ ├── TODO-5: SSE 整合測試 ├── TODO-6: SSE Handler 實作 ├── TODO-4: import 循環依賴檢測 │ ▼ Phase 9 (CLI 工具) │ ├── TODO-4: import 循環依賴檢測 │ ▼ Phase 10 (清理與測試) │ ├── TODO-7: 測試文件遷移 ├── TODO-9: 回歸測試自動化 ├── TODO-4: import 循環依賴檢測 │ ▼ 完成 ``` --- **文件版本**: v1.0 **建立日期**: 2026-04-03 **最後更新**: 2026-04-03