refactor(task-0): initialize go-zero project structure
- Add go-zero dependency to go.mod - Create api/chat.api with OpenAI-compatible types - Create etc/chat.yaml configuration - Update Makefile with goctl commands - Generate go-zero scaffold (types, handlers, logic, svc) - Move chat.go to cmd/chat/chat.go - Add Config struct for go-zero (keep BridgeConfig for backward compatibility)
This commit is contained in:
parent
b18e3d82f0
commit
8b6abbbba7
20
Makefile
20
Makefile
|
|
@ -3,6 +3,26 @@
|
|||
# 編輯下方變數,然後執行 make env 產生 .env 檔
|
||||
# ──────────────────────────────────────────────
|
||||
|
||||
# ── go-zero 代碼生成 ───────────────────────────
|
||||
.PHONY: api api-doc gen fmt lint
|
||||
|
||||
api:
|
||||
goctl api go -api api/chat.api -dir . --style go_zero
|
||||
|
||||
api-doc:
|
||||
goctl api doc -api api/chat.api -dir docs/api/
|
||||
|
||||
gen: api
|
||||
go mod tidy
|
||||
go fmt ./...
|
||||
|
||||
fmt:
|
||||
go fmt ./...
|
||||
|
||||
lint:
|
||||
go vet ./...
|
||||
go fmt ./...
|
||||
|
||||
# ── 伺服器設定 ─────────────────────────────────
|
||||
HOST ?= 127.0.0.1
|
||||
PORT ?= 8766
|
||||
|
|
|
|||
|
|
@ -0,0 +1,141 @@
|
|||
syntax = "v1"
|
||||
|
||||
info (
|
||||
title: "Cursor API Proxy"
|
||||
desc: "OpenAI-compatible API proxy for Cursor/Gemini"
|
||||
author: "cursor-api-proxy"
|
||||
version: "1.0"
|
||||
)
|
||||
|
||||
// ============ Types ============
|
||||
type (
|
||||
// Health
|
||||
HealthRequest {}
|
||||
HealthResponse {
|
||||
Status string `json:"status"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
// Models
|
||||
ModelsRequest {}
|
||||
ModelsResponse {
|
||||
Object string `json:"object"`
|
||||
Data []ModelData `json:"data"`
|
||||
}
|
||||
ModelData {
|
||||
Id string `json:"id"`
|
||||
Object string `json:"object"`
|
||||
OwnedBy string `json:"owned_by"`
|
||||
}
|
||||
// Chat Completions
|
||||
ChatCompletionRequest {
|
||||
Model string `json:"model"`
|
||||
Messages []Message `json:"messages"`
|
||||
Stream bool `json:"stream,optional"`
|
||||
Tools []Tool `json:"tools,optional"`
|
||||
Functions []Function `json:"functions,optional"`
|
||||
MaxTokens int `json:"max_tokens,optional"`
|
||||
Temperature float64 `json:"temperature,optional"`
|
||||
}
|
||||
Message {
|
||||
Role string `json:"role"`
|
||||
Content interface{} `json:"content"`
|
||||
}
|
||||
Tool {
|
||||
Type string `json:"type"`
|
||||
Function ToolFunction `json:"function"`
|
||||
}
|
||||
ToolFunction {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Parameters interface{} `json:"parameters"`
|
||||
}
|
||||
Function {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description,optional"`
|
||||
Parameters interface{} `json:"parameters,optional"`
|
||||
}
|
||||
ChatCompletionResponse {
|
||||
Id string `json:"id"`
|
||||
Object string `json:"object"`
|
||||
Created int64 `json:"created"`
|
||||
Model string `json:"model"`
|
||||
Choices []Choice `json:"choices"`
|
||||
Usage Usage `json:"usage"`
|
||||
}
|
||||
Choice {
|
||||
Index int `json:"index"`
|
||||
Message RespMessage `json:"message,optional"`
|
||||
Delta Delta `json:"delta,optional"`
|
||||
FinishReason string `json:"finish_reason"`
|
||||
}
|
||||
RespMessage {
|
||||
Role string `json:"role"`
|
||||
Content string `json:"content,optional"`
|
||||
ToolCalls []ToolCall `json:"tool_calls,optional"`
|
||||
}
|
||||
Delta {
|
||||
Role string `json:"role,optional"`
|
||||
Content string `json:"content,optional"`
|
||||
ReasoningContent string `json:"reasoning_content,optional"`
|
||||
ToolCalls []ToolCall `json:"tool_calls,optional"`
|
||||
}
|
||||
ToolCall {
|
||||
Index int `json:"index"`
|
||||
Id string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Function FunctionCall `json:"function"`
|
||||
}
|
||||
FunctionCall {
|
||||
Name string `json:"name"`
|
||||
Arguments string `json:"arguments"`
|
||||
}
|
||||
Usage {
|
||||
PromptTokens int `json:"prompt_tokens"`
|
||||
CompletionTokens int `json:"completion_tokens"`
|
||||
TotalTokens int `json:"total_tokens"`
|
||||
}
|
||||
// Anthropic Messages
|
||||
AnthropicRequest {
|
||||
Model string `json:"model"`
|
||||
Messages []Message `json:"messages"`
|
||||
MaxTokens int `json:"max_tokens"`
|
||||
Stream bool `json:"stream,optional"`
|
||||
System string `json:"system,optional"`
|
||||
}
|
||||
AnthropicResponse {
|
||||
Id string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Role string `json:"role"`
|
||||
Content []ContentBlock `json:"content"`
|
||||
Model string `json:"model"`
|
||||
Usage AnthropicUsage `json:"usage"`
|
||||
}
|
||||
ContentBlock {
|
||||
Type string `json:"type"`
|
||||
Text string `json:"text,optional"`
|
||||
}
|
||||
AnthropicUsage {
|
||||
InputTokens int `json:"input_tokens"`
|
||||
OutputTokens int `json:"output_tokens"`
|
||||
}
|
||||
)
|
||||
|
||||
// ============ Routes ============
|
||||
@server (
|
||||
prefix: /v1
|
||||
group: chat
|
||||
)
|
||||
service chat-api {
|
||||
@handler Health
|
||||
get /health returns (HealthResponse)
|
||||
|
||||
@handler Models
|
||||
get /v1/models returns (ModelsResponse)
|
||||
|
||||
@handler ChatCompletions
|
||||
post /v1/chat/completions (ChatCompletionRequest)
|
||||
|
||||
@handler AnthropicMessages
|
||||
post /v1/messages (AnthropicRequest)
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
// Code scaffolded by goctl. Safe to edit.
|
||||
// goctl 1.10.1
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"cursor-api-proxy/internal/config"
|
||||
"cursor-api-proxy/internal/handler"
|
||||
"cursor-api-proxy/internal/svc"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/conf"
|
||||
"github.com/zeromicro/go-zero/rest"
|
||||
)
|
||||
|
||||
var configFile = flag.String("f", "etc/chat-api.yaml", "the config file")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
var c config.Config
|
||||
conf.MustLoad(*configFile, &c)
|
||||
|
||||
server := rest.MustNewServer(c.RestConf)
|
||||
defer server.Stop()
|
||||
|
||||
ctx := svc.NewServiceContext(c)
|
||||
handler.RegisterHandlers(server, ctx)
|
||||
|
||||
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
|
||||
server.Start()
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,462 @@
|
|||
# REFACTOR TASKS
|
||||
|
||||
重構任務拆分,支援 git worktree 並行開發。
|
||||
|
||||
---
|
||||
|
||||
## Task Overview
|
||||
|
||||
### 並行策略
|
||||
|
||||
```
|
||||
時間軸 ──────────────────────────────────────────────────────────────►
|
||||
|
||||
Task 0: Init (必須先完成)
|
||||
│
|
||||
├── Task 1: Domain Layer ─────────────────────────┐
|
||||
│ │
|
||||
│ ┌── Task 2: Infrastructure Layer ────────────┤── 並行
|
||||
│ │ │
|
||||
│ └── Task 3: Repository Layer ────────────────┘
|
||||
│ (依賴 Task 1)
|
||||
│
|
||||
├── Task 4: Provider Layer ──────────────────────┐
|
||||
│ (依賴 Task 1) │
|
||||
│ │── 可並行
|
||||
├── Task 5: Usecase Layer ───────────────────────┤
|
||||
│ (依賴 Task 3) │
|
||||
│ │
|
||||
├── Task 6: Adapter Layer ───────────────────────┘
|
||||
│ (依賴 Task 1)
|
||||
│
|
||||
├── Task 7: Internal Layer ──────────────────────┐
|
||||
│ (整合所有,必須最後) │
|
||||
│ │── 序列
|
||||
├── Task 8: CLI Tools │
|
||||
│ │
|
||||
└── Task 9: Cleanup & Tests ────────────────────┘
|
||||
```
|
||||
|
||||
### Worktree 分支規劃
|
||||
|
||||
| 分支名稱 | 基於 | 任務 | 可並行 |
|
||||
|---------|------|------|--------|
|
||||
| `refactor/init` | `master` | Task 0 | ❌ |
|
||||
| `refactor/domain` | `refactor/init` | Task 1 | ✅ |
|
||||
| `refactor/infrastructure` | `refactor/init` | Task 2 | ✅ |
|
||||
| `refactor/repository` | `refactor/domain` | Task 3 | ✅ |
|
||||
| `refactor/provider` | `refactor/domain` | Task 4 | ✅ |
|
||||
| `refactor/usecase` | `refactor/repository` | Task 5 | ✅ |
|
||||
| `refactor/adapter` | `refactor/domain` | Task 6 | ✅ |
|
||||
| `refactor/internal` | 合併所有 | Task 7 | ❌ |
|
||||
| `refactor/cli` | `refactor/init` | Task 8 | ✅ |
|
||||
| `refactor/cleanup` | 合併所有 | Task 9 | ❌ |
|
||||
|
||||
---
|
||||
|
||||
## Task 0: 初始化
|
||||
|
||||
### 分支
|
||||
`refactor/init`
|
||||
|
||||
### 依賴
|
||||
無(必須先完成)
|
||||
|
||||
### 小任務
|
||||
|
||||
- [ ] **0.1** 更新 go.mod (5min)
|
||||
- `go get github.com/zeromicro/go-zero@latest`
|
||||
- `go mod tidy`
|
||||
|
||||
- [ ] **0.2** 建立目錄 (1min)
|
||||
- `mkdir -p api etc`
|
||||
|
||||
- [ ] **0.3** 建立 `api/chat.api` (15min)
|
||||
- 定義 API types
|
||||
- 定義 routes
|
||||
|
||||
- [ ] **0.4** 建立 `etc/chat.yaml` (5min)
|
||||
- 配置參數
|
||||
|
||||
- [ ] **0.5** 更新 Makefile (10min)
|
||||
- 新增 goctl 命令
|
||||
|
||||
- [ ] **0.6** 提交 (2min)
|
||||
|
||||
**預估時間**: ~30min
|
||||
|
||||
---
|
||||
|
||||
## Task 1: Domain Layer
|
||||
|
||||
### 分支
|
||||
`refactor/domain`
|
||||
|
||||
### 依賴
|
||||
Task 0 完成
|
||||
|
||||
### 小任務
|
||||
|
||||
- [ ] **1.1** 建立目錄結構 (1min)
|
||||
- `pkg/domain/entity`
|
||||
- `pkg/domain/repository`
|
||||
- `pkg/domain/usecase`
|
||||
- `pkg/domain/const`
|
||||
|
||||
- [ ] **1.2** `entity/message.go` (10min)
|
||||
- Message, Tool, ToolFunction, ToolCall
|
||||
|
||||
- [ ] **1.3** `entity/chunk.go` (5min)
|
||||
- StreamChunk, ChunkType
|
||||
|
||||
- [ ] **1.4** `entity/account.go` (5min)
|
||||
- Account, AccountStat
|
||||
|
||||
- [ ] **1.5** `repository/account.go` (10min)
|
||||
- AccountPool interface
|
||||
|
||||
- [ ] **1.6** `repository/provider.go` (5min)
|
||||
- Provider interface
|
||||
|
||||
- [ ] **1.7** `usecase/chat.go` (15min)
|
||||
- ChatUsecase interface
|
||||
|
||||
- [ ] **1.8** `usecase/agent.go` (5min)
|
||||
- AgentRunner interface
|
||||
|
||||
- [ ] **1.9** `const/models.go` (10min)
|
||||
- Model 常數
|
||||
|
||||
- [ ] **1.10** `const/errors.go` (5min)
|
||||
- 錯誤定義
|
||||
|
||||
- [ ] **1.11** 提交 (2min)
|
||||
|
||||
**預估時間**: ~2h
|
||||
|
||||
---
|
||||
|
||||
## Task 2: Infrastructure Layer
|
||||
|
||||
### 分支
|
||||
`refactor/infrastructure`
|
||||
|
||||
### 依賴
|
||||
Task 0 完成(可與 Task 1 並行)
|
||||
|
||||
### 小任務
|
||||
|
||||
- [ ] **2.1** 建立目錄 (2min)
|
||||
- `pkg/infrastructure/{process,parser,httputil,logger,env,workspace,winlimit}`
|
||||
|
||||
- [ ] **2.2** 遷移 process (10min)
|
||||
- runner.go, kill_unix.go, kill_windows.go, process_test.go
|
||||
|
||||
- [ ] **2.3** 遷移 parser (5min)
|
||||
- stream.go, stream_test.go
|
||||
|
||||
- [ ] **2.4** 遷移 httputil (5min)
|
||||
- httputil.go, httputil_test.go
|
||||
|
||||
- [ ] **2.5** 遷移 logger (5min)
|
||||
- logger.go
|
||||
|
||||
- [ ] **2.6** 遷移 env (5min)
|
||||
- env.go, env_test.go
|
||||
|
||||
- [ ] **2.7** 遷移 workspace (5min)
|
||||
- workspace.go
|
||||
|
||||
- [ ] **2.8** 遷移 winlimit (5min)
|
||||
- winlimit.go, winlimit_test.go
|
||||
|
||||
- [ ] **2.9** 驗證編譯 (5min)
|
||||
|
||||
- [ ] **2.10** 提交 (2min)
|
||||
|
||||
**預估時間**: ~1h
|
||||
|
||||
---
|
||||
|
||||
## Task 3: Repository Layer
|
||||
|
||||
### 分支
|
||||
`refactor/repository`
|
||||
|
||||
### 依賴
|
||||
Task 1 完成
|
||||
|
||||
### 小任務
|
||||
|
||||
- [ ] **3.1** 建立目錄 (1min)
|
||||
|
||||
- [ ] **3.2** 遷移 account.go (20min)
|
||||
- AccountPool 實作
|
||||
- 移除全局變數
|
||||
|
||||
- [ ] **3.3** 遷移 provider.go (10min)
|
||||
- Provider 工廠
|
||||
|
||||
- [ ] **3.4** 遷移測試 (5min)
|
||||
|
||||
- [ ] **3.5** 驗證編譯 (5min)
|
||||
|
||||
- [ ] **3.6** 提交 (2min)
|
||||
|
||||
**預估時間**: ~1h
|
||||
|
||||
---
|
||||
|
||||
## Task 4: Provider Layer
|
||||
|
||||
### 分支
|
||||
`refactor/provider`
|
||||
|
||||
### 依賴
|
||||
Task 1 完成
|
||||
|
||||
### 小任務
|
||||
|
||||
- [ ] **4.1** 建立目錄 (1min)
|
||||
- `pkg/provider/cursor`
|
||||
- `pkg/provider/geminiweb`
|
||||
|
||||
- [ ] **4.2** 遷移 cursor provider (5min)
|
||||
|
||||
- [ ] **4.3** 遷移 geminiweb provider (10min)
|
||||
|
||||
- [ ] **4.4** 更新 import (5min)
|
||||
|
||||
- [ ] **4.5** 驗證編譯 (5min)
|
||||
|
||||
- [ ] **4.6** 提交 (2min)
|
||||
|
||||
**預估時間**: ~30min
|
||||
|
||||
---
|
||||
|
||||
## Task 5: Usecase Layer
|
||||
|
||||
### 分支
|
||||
`refactor/usecase`
|
||||
|
||||
### 依賴
|
||||
Task 3 完成
|
||||
|
||||
### 小任務
|
||||
|
||||
- [ ] **5.1** 建立目錄 (1min)
|
||||
|
||||
- [ ] **5.2** 建立 chat.go (30min)
|
||||
- 核心聊天邏輯
|
||||
|
||||
- [ ] **5.3** 遷移 agent.go (20min)
|
||||
- runner, token, cmdargs, maxmode
|
||||
|
||||
- [ ] **5.4** 遷移 sanitizer (10min)
|
||||
|
||||
- [ ] **5.5** 遷移 toolcall (10min)
|
||||
|
||||
- [ ] **5.6** 驗證編譯 (5min)
|
||||
|
||||
- [ ] **5.7** 提交 (2min)
|
||||
|
||||
**預估時間**: ~2h
|
||||
|
||||
---
|
||||
|
||||
## Task 6: Adapter Layer
|
||||
|
||||
### 分支
|
||||
`refactor/adapter`
|
||||
|
||||
### 依賴
|
||||
Task 1 完成
|
||||
|
||||
### 小任務
|
||||
|
||||
- [ ] **6.1** 建立目錄 (1min)
|
||||
|
||||
- [ ] **6.2** 遷移 openai adapter (10min)
|
||||
|
||||
- [ ] **6.3** 遷移 anthropic adapter (10min)
|
||||
|
||||
- [ ] **6.4** 更新 import (5min)
|
||||
|
||||
- [ ] **6.5** 驗證編譯 (5min)
|
||||
|
||||
- [ ] **6.6** 提交 (2min)
|
||||
|
||||
**預估時間**: ~30min
|
||||
|
||||
---
|
||||
|
||||
## Task 7: Internal Layer
|
||||
|
||||
### 分支
|
||||
`refactor/internal`
|
||||
|
||||
### 依賴
|
||||
Task 1-6 全部完成
|
||||
|
||||
### 小任務
|
||||
|
||||
- [ ] **7.1** 合併所有分支 (5min)
|
||||
|
||||
- [ ] **7.2** 更新 config/config.go (15min)
|
||||
- 使用 rest.RestConf
|
||||
|
||||
- [ ] **7.3** 建立 svc/servicecontext.go (30min)
|
||||
- DI 容器
|
||||
|
||||
- [ ] **7.4** 建立 logic/ (1h)
|
||||
- chatcompletionlogic.go
|
||||
- geminichatlogic.go
|
||||
- anthropiclogic.go
|
||||
- healthlogic.go
|
||||
- modelslogic.go
|
||||
|
||||
- [ ] **7.5** 建立 handler/ (1h)
|
||||
- 自訂 SSE handler
|
||||
|
||||
- [ ] **7.6** 建立 middleware/ (20min)
|
||||
- auth.go
|
||||
- recovery.go
|
||||
|
||||
- [ ] **7.7** 建立 types/ (5min)
|
||||
- goctl 生成
|
||||
|
||||
- [ ] **7.8** 更新 import (30min)
|
||||
- 批量更新
|
||||
|
||||
- [ ] **7.9** 驗證編譯 (10min)
|
||||
|
||||
- [ ] **7.10** 提交 (2min)
|
||||
|
||||
**預估時間**: ~4h
|
||||
|
||||
---
|
||||
|
||||
## Task 8: CLI Tools
|
||||
|
||||
### 分支
|
||||
`refactor/cli`
|
||||
|
||||
### 依賴
|
||||
Task 0 完成
|
||||
|
||||
### 小任務
|
||||
|
||||
- [ ] **8.1** 建立目錄 (1min)
|
||||
|
||||
- [ ] **8.2** 遷移 CLI 工具 (10min)
|
||||
|
||||
- [ ] **8.3** 遷移 gemini-login (5min)
|
||||
|
||||
- [ ] **8.4** 更新 import (5min)
|
||||
|
||||
- [ ] **8.5** 提交 (2min)
|
||||
|
||||
**預估時間**: ~30min
|
||||
|
||||
---
|
||||
|
||||
## Task 9: Cleanup & Tests
|
||||
|
||||
### 分支
|
||||
`refactor/cleanup`
|
||||
|
||||
### 依賴
|
||||
Task 7 完成
|
||||
|
||||
### 小任務
|
||||
|
||||
- [ ] **9.1** 移除舊目錄 (5min)
|
||||
|
||||
- [ ] **9.2** 更新 import (30min)
|
||||
- 批量 sed
|
||||
|
||||
- [ ] **9.3** 建立 cmd/chat/chat.go (10min)
|
||||
|
||||
- [ ] **9.4** SSE 整合測試 (2h)
|
||||
|
||||
- [ ] **9.5** 回歸測試 (1h)
|
||||
|
||||
- [ ] **9.6** 更新 README (15min)
|
||||
|
||||
- [ ] **9.7** 提交 (2min)
|
||||
|
||||
**預估時間**: ~4h
|
||||
|
||||
---
|
||||
|
||||
## 並行執行計劃
|
||||
|
||||
### Wave 1 (可完全並行)
|
||||
```
|
||||
Terminal 1: Task 0 (init) → 30min
|
||||
Terminal 2: (等待 Task 0)
|
||||
```
|
||||
|
||||
### Wave 2 (可完全並行)
|
||||
```
|
||||
Terminal 1: Task 1 (domain) → 2h
|
||||
Terminal 2: Task 2 (infrastructure) → 1h
|
||||
Terminal 3: Task 8 (cli) → 30min
|
||||
```
|
||||
|
||||
### Wave 3 (可部分並行)
|
||||
```
|
||||
Terminal 1: Task 3 (repository) → 1h (依賴 Task 1)
|
||||
Terminal 2: Task 4 (provider) → 30min (依賴 Task 1)
|
||||
Terminal 3: Task 6 (adapter) → 30min (依賴 Task 1)
|
||||
Terminal 4: (等待 Task 3)
|
||||
```
|
||||
|
||||
### Wave 4 (可部分並行)
|
||||
```
|
||||
Terminal 1: Task 5 (usecase) → 2h (依賴 Task 3)
|
||||
Terminal 2: (等待 Task 5)
|
||||
```
|
||||
|
||||
### Wave 5 (序列)
|
||||
```
|
||||
Task 7 (internal) → 4h
|
||||
Task 9 (cleanup) → 4h
|
||||
```
|
||||
|
||||
**總時間估計**:
|
||||
- 完全序列: ~15h
|
||||
- 並行執行: ~9h
|
||||
- 節省: ~40%
|
||||
|
||||
---
|
||||
|
||||
## Git Worktree 指令
|
||||
|
||||
```bash
|
||||
# 創建 worktrees
|
||||
git worktree add ../worktrees/init -b refactor/init
|
||||
git worktree add ../worktrees/domain -b refactor/domain
|
||||
git worktree add ../worktrees/infrastructure -b refactor/infrastructure
|
||||
git worktree add ../worktrees/repository -b refactor/repository
|
||||
git worktree add ../worktrees/provider -b refactor/provider
|
||||
git worktree add ../worktrees/usecase -b refactor/usecase
|
||||
git worktree add ../worktrees/adapter -b refactor/adapter
|
||||
git worktree add ../worktrees/cli -b refactor/cli
|
||||
|
||||
# 並行工作
|
||||
cd ../worktrees/domain && # Terminal 1
|
||||
cd ../worktrees/infrastructure && # Terminal 2
|
||||
cd ../worktrees/cli && # Terminal 3
|
||||
|
||||
# 清理 worktrees
|
||||
git worktree remove ../worktrees/init
|
||||
git worktree remove ../worktrees/domain
|
||||
# ... 等等
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**文件版本**: v1.0
|
||||
**建立日期**: 2026-04-03
|
||||
|
|
@ -0,0 +1,312 @@
|
|||
# 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
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
Name: chat-api
|
||||
Host: 0.0.0.0
|
||||
Port: 8888
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
Name: chat-api
|
||||
Host: ${CURSOR_BRIDGE_HOST:0.0.0.0}
|
||||
Port: ${CURSOR_BRIDGE_PORT:8080}
|
||||
|
||||
# API Key 驗證(可選)
|
||||
# Auth:
|
||||
# AccessSecret: ${CURSOR_API_KEY:}
|
||||
# AccessExpire: 86400
|
||||
|
||||
# Cursor 配置
|
||||
AgentBin: ${CURSOR_AGENT_BIN:cursor-agent}
|
||||
DefaultModel: ${CURSOR_DEFAULT_MODEL:claude-3.5-sonnet}
|
||||
Provider: ${CURSOR_PROVIDER:cursor}
|
||||
|
||||
# 超時設定
|
||||
TimeoutMs: ${CURSOR_TIMEOUT_MS:300000}
|
||||
|
||||
# 多帳號池
|
||||
ConfigDirs:
|
||||
- ${HOME}/.cursor-api-proxy/accounts/default
|
||||
MultiPort: false
|
||||
|
||||
# TLS
|
||||
TLSCertPath: ${CURSOR_TLS_CERT_PATH:}
|
||||
TLSKeyPath: ${CURSOR_TLS_KEY_PATH:}
|
||||
|
||||
# 日誌
|
||||
SessionsLogPath: ${CURSOR_SESSIONS_LOG_PATH:}
|
||||
Verbose: ${CURSOR_VERBOSE:false}
|
||||
|
||||
# Gemini 設定
|
||||
GeminiAccountDir: ${GEMINI_ACCOUNT_DIR:}
|
||||
GeminiBrowserVisible: ${GEMINI_BROWSER_VISIBLE:false}
|
||||
GeminiMaxSessions: ${GEMINI_MAX_SESSIONS:10}
|
||||
|
||||
# 工作區設定
|
||||
Workspace: ${CURSOR_WORKSPACE:}
|
||||
ChatOnlyWorkspace: ${CURSOR_CHAT_ONLY_WORKSPACE:true}
|
||||
WinCmdlineMax: ${CURSOR_WIN_CMDLINE_MAX:32768}
|
||||
|
||||
# Agent 設定
|
||||
Force: ${CURSOR_FORCE:false}
|
||||
ApproveMcps: ${CURSOR_APPROVE_MCPS:false}
|
||||
MaxMode: ${CURSOR_MAX_MODE:false}
|
||||
StrictModel: ${CURSOR_STRICT_MODEL:true}
|
||||
46
go.mod
46
go.mod
|
|
@ -3,26 +3,68 @@ module cursor-api-proxy
|
|||
go 1.25.0
|
||||
|
||||
require (
|
||||
github.com/go-rod/rod v0.116.2
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/playwright-community/playwright-go v0.5700.1
|
||||
github.com/zeromicro/go-zero v1.10.1
|
||||
modernc.org/sqlite v1.48.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/deckarep/golang-set/v2 v2.8.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/go-jose/go-jose/v3 v3.0.5 // indirect
|
||||
github.com/go-rod/rod v0.116.2 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-stack/stack v1.8.1 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||
github.com/grafana/pyroscope-go v1.2.8 // indirect
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.9 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/ncruces/go-strftime v1.0.0 // indirect
|
||||
github.com/playwright-community/playwright-go v0.5700.1 // indirect
|
||||
github.com/openzipkin/zipkin-go v0.4.3 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.3.0 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.66.1 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/titanous/json5 v1.0.0 // indirect
|
||||
github.com/ysmood/fetchup v0.2.3 // indirect
|
||||
github.com/ysmood/goob v0.4.0 // indirect
|
||||
github.com/ysmood/got v0.40.0 // indirect
|
||||
github.com/ysmood/gson v0.7.3 // indirect
|
||||
github.com/ysmood/leakless v0.9.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/otel v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/zipkin v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.40.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.40.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
|
||||
go.uber.org/automaxprocs v1.6.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/net v0.50.0 // indirect
|
||||
golang.org/x/sys v0.42.0 // indirect
|
||||
golang.org/x/text v0.34.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 // indirect
|
||||
google.golang.org/grpc v1.79.3 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
modernc.org/libc v1.70.0 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
modernc.org/memory v1.11.0 // indirect
|
||||
|
|
|
|||
131
go.sum
131
go.sum
|
|
@ -1,44 +1,148 @@
|
|||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/deckarep/golang-set/v2 v2.8.0 h1:swm0rlPCmdWn9mESxKOjWk8hXSqoxOp+ZlfuyaAdFlQ=
|
||||
github.com/deckarep/golang-set/v2 v2.8.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||
github.com/go-jose/go-jose/v3 v3.0.5 h1:BLLJWbC4nMZOfuPVxoZIxeYsn6Nl2r1fITaJ78UQlVQ=
|
||||
github.com/go-jose/go-jose/v3 v3.0.5/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-rod/rod v0.116.2 h1:A5t2Ky2A+5eD/ZJQr1EfsQSe5rms5Xof/qj296e+ZqA=
|
||||
github.com/go-rod/rod v0.116.2/go.mod h1:H+CMO9SCNc2TJ2WfrG+pKhITz57uGNYU43qYHh438Mg=
|
||||
github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
|
||||
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grafana/pyroscope-go v1.2.8 h1:UvCwIhlx9DeV7F6TW/z8q1Mi4PIm3vuUJ2ZlCEvmA4M=
|
||||
github.com/grafana/pyroscope-go v1.2.8/go.mod h1:SSi59eQ1/zmKoY/BKwa5rSFsJaq+242Bcrr4wPix1g8=
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.9 h1:c1Us8i6eSmkW+Ez05d3co8kasnuOY813tbMN8i/a3Og=
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.9/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7 h1:X+2YciYSxvMQK0UZ7sg45ZVabVZBeBuvMkmuI2V3Fak=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.7/go.mod h1:lW34nIZuQ8UDPdkon5fmfp2l3+ZkQ2me/+oecHYLOII=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
|
||||
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||
github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg=
|
||||
github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c=
|
||||
github.com/pelletier/go-toml/v2 v2.3.0 h1:k59bC/lIZREW0/iVaQR8nDHxVq8OVlIzYCOJf421CaM=
|
||||
github.com/pelletier/go-toml/v2 v2.3.0/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/playwright-community/playwright-go v0.5700.1 h1:PNFb1byWqrTT720rEO0JL88C6Ju0EmUnR5deFLvtP/U=
|
||||
github.com/playwright-community/playwright-go v0.5700.1/go.mod h1:MlSn1dZrx8rszbCxY6x3qK89ZesJUYVx21B2JnkoNF0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
||||
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
||||
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
|
||||
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/robertkrimen/otto v0.2.1 h1:FVP0PJ0AHIjC+N4pKCG9yCDz6LHNPCwi/GKID5pGGF0=
|
||||
github.com/robertkrimen/otto v0.2.1/go.mod h1:UPwtJ1Xu7JrLcZjNWN8orJaM5n5YEtqL//farB5FlRY=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/titanous/json5 v1.0.0 h1:hJf8Su1d9NuI/ffpxgxQfxh/UiBFZX7bMPid0rIL/7s=
|
||||
github.com/titanous/json5 v1.0.0/go.mod h1:7JH1M8/LHKc6cyP5o5g3CSaRj+mBrIimTxzpvmckH8c=
|
||||
github.com/ysmood/fetchup v0.2.3 h1:ulX+SonA0Vma5zUFXtv52Kzip/xe7aj4vqT5AJwQ+ZQ=
|
||||
github.com/ysmood/fetchup v0.2.3/go.mod h1:xhibcRKziSvol0H1/pj33dnKrYyI2ebIvz5cOOkYGns=
|
||||
github.com/ysmood/goob v0.4.0 h1:HsxXhyLBeGzWXnqVKtmT9qM7EuVs/XOgkX7T6r1o1AQ=
|
||||
github.com/ysmood/goob v0.4.0/go.mod h1:u6yx7ZhS4Exf2MwciFr6nIM8knHQIE22lFpWHnfql18=
|
||||
github.com/ysmood/gop v0.2.0 h1:+tFrG0TWPxT6p9ZaZs+VY+opCvHU8/3Fk6BaNv6kqKg=
|
||||
github.com/ysmood/gop v0.2.0/go.mod h1:rr5z2z27oGEbyB787hpEcx4ab8cCiPnKxn0SUHt6xzk=
|
||||
github.com/ysmood/got v0.40.0 h1:ZQk1B55zIvS7zflRrkGfPDrPG3d7+JOza1ZkNxcc74Q=
|
||||
github.com/ysmood/got v0.40.0/go.mod h1:W7DdpuX6skL3NszLmAsC5hT7JAhuLZhByVzHTq874Qg=
|
||||
github.com/ysmood/gotrace v0.6.0 h1:SyI1d4jclswLhg7SWTL6os3L1WOKeNn/ZtzVQF8QmdY=
|
||||
github.com/ysmood/gotrace v0.6.0/go.mod h1:TzhIG7nHDry5//eYZDYcTzuJLYQIkykJzCRIo4/dzQM=
|
||||
github.com/ysmood/gson v0.7.3 h1:QFkWbTH8MxyUTKPkVWAENJhxqdBa4lYTQWqZCiLG6kE=
|
||||
github.com/ysmood/gson v0.7.3/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg=
|
||||
github.com/ysmood/leakless v0.9.0 h1:qxCG5VirSBvmi3uynXFkcnLMzkphdh3xx5FtrORwDCU=
|
||||
github.com/ysmood/leakless v0.9.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/zeromicro/go-zero v1.10.1 h1:1nM3ilvYx97GUqyaNH2IQPtfNyK7tp5JvN63c7m6QKU=
|
||||
github.com/zeromicro/go-zero v1.10.1/go.mod h1:z41DXmO6gx/Se7Ow5UIwPxcUmpVj3ebhoNCcZ1gfp5k=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms=
|
||||
go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 h1:QKdN8ly8zEMrByybbQgv8cWBcdAarwmIPZ6FThrWXJs=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0/go.mod h1:bTdK1nhqF76qiPoCCdyFIV+N/sRHYXYCTQc+3VCi3MI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0 h1:DvJDOPmSWQHWywQS6lKL+pb8s3gBLOZUtw4N+mavW1I=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0/go.mod h1:EtekO9DEJb4/jRyN4v4Qjc2yA7AtfCBuz2FynRUWTXs=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.40.0 h1:wVZXIWjQSeSmMoxF74LzAnpVQOAFDo3pPji9Y4SOFKc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.40.0/go.mod h1:khvBS2IggMFNwZK/6lEeHg/W57h/IX6J4URh57fuI40=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.40.0 h1:MzfofMZN8ulNqobCmCAVbqVL5syHw+eB2qPRkCMA/fQ=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.40.0/go.mod h1:E73G9UFtKRXrxhBsHtG00TB5WxX57lpsQzogDkqBTz8=
|
||||
go.opentelemetry.io/otel/exporters/zipkin v1.40.0 h1:zu+I4j+FdO6xIxBVPeuncQVbjxUM4LiMgv6GwGe9REE=
|
||||
go.opentelemetry.io/otel/exporters/zipkin v1.40.0/go.mod h1:zS6cC4nFBYXbu18e7aLfMzubBjOiN7ZcROu477qtMf8=
|
||||
go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g=
|
||||
go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc=
|
||||
go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8=
|
||||
go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg=
|
||||
go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw=
|
||||
go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA=
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
|
||||
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
|
||||
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
||||
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
|
||||
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
|
|
@ -51,6 +155,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
|
@ -61,6 +167,7 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
|
@ -78,6 +185,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
|
|
@ -85,8 +194,30 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
|||
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
|
||||
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 h1:merA0rdPeUV3YIIfHHcH4qBkiQAc1nfCKSI7lB4cV2M=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409/go.mod h1:fl8J1IvUjCilwZzQowmw2b7HQB2eAuYBabMXzWurF+I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||
google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=
|
||||
google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=
|
||||
gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0=
|
||||
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
|
||||
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 h1:kBawHLSnx/mYHmRnNUf9d4CpjREbeZuxoSGOX/J+aYM=
|
||||
k8s.io/utils v0.0.0-20260319190234-28399d86e0b5/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
|
||||
modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis=
|
||||
modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||
modernc.org/ccgo/v4 v4.32.0 h1:hjG66bI/kqIPX1b2yT6fr/jt+QedtP2fqojG2VrFuVw=
|
||||
|
|
|
|||
|
|
@ -2,8 +2,53 @@ package config
|
|||
|
||||
import (
|
||||
"cursor-api-proxy/internal/env"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest"
|
||||
)
|
||||
|
||||
// Config for go-zero (generated by goctl)
|
||||
type Config struct {
|
||||
rest.RestConf
|
||||
|
||||
// Cursor 配置
|
||||
AgentBin string
|
||||
DefaultModel string
|
||||
Provider string
|
||||
TimeoutMs int
|
||||
|
||||
// 多帳號池
|
||||
ConfigDirs []string
|
||||
MultiPort bool
|
||||
|
||||
// TLS
|
||||
TLSCertPath string
|
||||
TLSKeyPath string
|
||||
|
||||
// 日誌
|
||||
SessionsLogPath string
|
||||
Verbose bool
|
||||
|
||||
// Gemini
|
||||
GeminiAccountDir string
|
||||
GeminiBrowserVisible bool
|
||||
GeminiMaxSessions int
|
||||
|
||||
// 工作區
|
||||
Workspace string
|
||||
ChatOnlyWorkspace bool
|
||||
WinCmdlineMax int
|
||||
|
||||
// Agent
|
||||
Force bool
|
||||
ApproveMcps bool
|
||||
MaxMode bool
|
||||
StrictModel bool
|
||||
|
||||
// API Key
|
||||
RequiredKey string
|
||||
}
|
||||
|
||||
// BridgeConfig for backward compatibility with existing code
|
||||
type BridgeConfig struct {
|
||||
AgentBin string
|
||||
Host string
|
||||
|
|
@ -31,6 +76,7 @@ type BridgeConfig struct {
|
|||
GeminiMaxSessions int
|
||||
}
|
||||
|
||||
// LoadBridgeConfig loads config from environment (for backward compatibility)
|
||||
func LoadBridgeConfig(e env.EnvSource, cwd string) BridgeConfig {
|
||||
loaded := env.LoadEnvConfig(e, cwd)
|
||||
return BridgeConfig{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
// Code scaffolded by goctl. Safe to edit.
|
||||
// goctl 1.10.1
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"cursor-api-proxy/internal/logic/chat"
|
||||
"cursor-api-proxy/internal/svc"
|
||||
"cursor-api-proxy/internal/types"
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
)
|
||||
|
||||
func AnthropicMessagesHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.AnthropicRequest
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
return
|
||||
}
|
||||
|
||||
l := chat.NewAnthropicMessagesLogic(r.Context(), svcCtx)
|
||||
err := l.AnthropicMessages(&req)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
httpx.Ok(w)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// Code scaffolded by goctl. Safe to edit.
|
||||
// goctl 1.10.1
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"cursor-api-proxy/internal/logic/chat"
|
||||
"cursor-api-proxy/internal/svc"
|
||||
"cursor-api-proxy/internal/types"
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
)
|
||||
|
||||
func ChatCompletionsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.ChatCompletionRequest
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
return
|
||||
}
|
||||
|
||||
l := chat.NewChatCompletionsLogic(r.Context(), svcCtx)
|
||||
err := l.ChatCompletions(&req)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
httpx.Ok(w)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// Code scaffolded by goctl. Safe to edit.
|
||||
// goctl 1.10.1
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"cursor-api-proxy/internal/logic/chat"
|
||||
"cursor-api-proxy/internal/svc"
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
)
|
||||
|
||||
func HealthHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
l := chat.NewHealthLogic(r.Context(), svcCtx)
|
||||
resp, err := l.Health()
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// Code scaffolded by goctl. Safe to edit.
|
||||
// goctl 1.10.1
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"cursor-api-proxy/internal/logic/chat"
|
||||
"cursor-api-proxy/internal/svc"
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
)
|
||||
|
||||
func ModelsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
l := chat.NewModelsLogic(r.Context(), svcCtx)
|
||||
resp, err := l.Models()
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// Code generated by goctl. DO NOT EDIT.
|
||||
// goctl 1.10.1
|
||||
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
chat "cursor-api-proxy/internal/handler/chat"
|
||||
"cursor-api-proxy/internal/svc"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest"
|
||||
)
|
||||
|
||||
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
server.AddRoutes(
|
||||
[]rest.Route{
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/health",
|
||||
Handler: chat.HealthHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/v1/chat/completions",
|
||||
Handler: chat.ChatCompletionsHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodPost,
|
||||
Path: "/v1/messages",
|
||||
Handler: chat.AnthropicMessagesHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
Method: http.MethodGet,
|
||||
Path: "/v1/models",
|
||||
Handler: chat.ModelsHandler(serverCtx),
|
||||
},
|
||||
},
|
||||
rest.WithPrefix("/v1"),
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Code scaffolded by goctl. Safe to edit.
|
||||
// goctl 1.10.1
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"cursor-api-proxy/internal/svc"
|
||||
"cursor-api-proxy/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type AnthropicMessagesLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAnthropicMessagesLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AnthropicMessagesLogic {
|
||||
return &AnthropicMessagesLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AnthropicMessagesLogic) AnthropicMessages(req *types.AnthropicRequest) error {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Code scaffolded by goctl. Safe to edit.
|
||||
// goctl 1.10.1
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"cursor-api-proxy/internal/svc"
|
||||
"cursor-api-proxy/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type ChatCompletionsLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewChatCompletionsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ChatCompletionsLogic {
|
||||
return &ChatCompletionsLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ChatCompletionsLogic) ChatCompletions(req *types.ChatCompletionRequest) error {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Code scaffolded by goctl. Safe to edit.
|
||||
// goctl 1.10.1
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"cursor-api-proxy/internal/svc"
|
||||
"cursor-api-proxy/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type HealthLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewHealthLogic(ctx context.Context, svcCtx *svc.ServiceContext) *HealthLogic {
|
||||
return &HealthLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *HealthLogic) Health() (resp *types.HealthResponse, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Code scaffolded by goctl. Safe to edit.
|
||||
// goctl 1.10.1
|
||||
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"cursor-api-proxy/internal/svc"
|
||||
"cursor-api-proxy/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type ModelsLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewModelsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ModelsLogic {
|
||||
return &ModelsLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *ModelsLogic) Models() (resp *types.ModelsResponse, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
// Code scaffolded by goctl. Safe to edit.
|
||||
// goctl 1.10.1
|
||||
|
||||
package svc
|
||||
|
||||
import (
|
||||
"cursor-api-proxy/internal/config"
|
||||
)
|
||||
|
||||
type ServiceContext struct {
|
||||
Config config.Config
|
||||
}
|
||||
|
||||
func NewServiceContext(c config.Config) *ServiceContext {
|
||||
return &ServiceContext{
|
||||
Config: c,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
// Code generated by goctl. DO NOT EDIT.
|
||||
// goctl 1.10.1
|
||||
|
||||
package types
|
||||
|
||||
type AnthropicRequest struct {
|
||||
Model string `json:"model"`
|
||||
Messages []Message `json:"messages"`
|
||||
MaxTokens int `json:"max_tokens"`
|
||||
Stream bool `json:"stream,optional"`
|
||||
System string `json:"system,optional"`
|
||||
}
|
||||
|
||||
type AnthropicResponse struct {
|
||||
Id string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Role string `json:"role"`
|
||||
Content []ContentBlock `json:"content"`
|
||||
Model string `json:"model"`
|
||||
Usage AnthropicUsage `json:"usage"`
|
||||
}
|
||||
|
||||
type AnthropicUsage struct {
|
||||
InputTokens int `json:"input_tokens"`
|
||||
OutputTokens int `json:"output_tokens"`
|
||||
}
|
||||
|
||||
type ChatCompletionRequest struct {
|
||||
Model string `json:"model"`
|
||||
Messages []Message `json:"messages"`
|
||||
Stream bool `json:"stream,optional"`
|
||||
Tools []Tool `json:"tools,optional"`
|
||||
Functions []Function `json:"functions,optional"`
|
||||
MaxTokens int `json:"max_tokens,optional"`
|
||||
Temperature float64 `json:"temperature,optional"`
|
||||
}
|
||||
|
||||
type ChatCompletionResponse struct {
|
||||
Id string `json:"id"`
|
||||
Object string `json:"object"`
|
||||
Created int64 `json:"created"`
|
||||
Model string `json:"model"`
|
||||
Choices []Choice `json:"choices"`
|
||||
Usage Usage `json:"usage"`
|
||||
}
|
||||
|
||||
type Choice struct {
|
||||
Index int `json:"index"`
|
||||
Message RespMessage `json:"message,optional"`
|
||||
Delta Delta `json:"delta,optional"`
|
||||
FinishReason string `json:"finish_reason"`
|
||||
}
|
||||
|
||||
type ContentBlock struct {
|
||||
Type string `json:"type"`
|
||||
Text string `json:"text,optional"`
|
||||
}
|
||||
|
||||
type Delta struct {
|
||||
Role string `json:"role,optional"`
|
||||
Content string `json:"content,optional"`
|
||||
ReasoningContent string `json:"reasoning_content,optional"`
|
||||
ToolCalls []ToolCall `json:"tool_calls,optional"`
|
||||
}
|
||||
|
||||
type Function struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description,optional"`
|
||||
Parameters interface{} `json:"parameters,optional"`
|
||||
}
|
||||
|
||||
type FunctionCall struct {
|
||||
Name string `json:"name"`
|
||||
Arguments string `json:"arguments"`
|
||||
}
|
||||
|
||||
type HealthRequest struct {
|
||||
}
|
||||
|
||||
type HealthResponse struct {
|
||||
Status string `json:"status"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
Role string `json:"role"`
|
||||
Content interface{} `json:"content"`
|
||||
}
|
||||
|
||||
type ModelData struct {
|
||||
Id string `json:"id"`
|
||||
Object string `json:"object"`
|
||||
OwnedBy string `json:"owned_by"`
|
||||
}
|
||||
|
||||
type ModelsRequest struct {
|
||||
}
|
||||
|
||||
type ModelsResponse struct {
|
||||
Object string `json:"object"`
|
||||
Data []ModelData `json:"data"`
|
||||
}
|
||||
|
||||
type RespMessage struct {
|
||||
Role string `json:"role"`
|
||||
Content string `json:"content,optional"`
|
||||
ToolCalls []ToolCall `json:"tool_calls,optional"`
|
||||
}
|
||||
|
||||
type Tool struct {
|
||||
Type string `json:"type"`
|
||||
Function ToolFunction `json:"function"`
|
||||
}
|
||||
|
||||
type ToolCall struct {
|
||||
Index int `json:"index"`
|
||||
Id string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Function FunctionCall `json:"function"`
|
||||
}
|
||||
|
||||
type ToolFunction struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Parameters interface{} `json:"parameters"`
|
||||
}
|
||||
|
||||
type Usage struct {
|
||||
PromptTokens int `json:"prompt_tokens"`
|
||||
CompletionTokens int `json:"completion_tokens"`
|
||||
TotalTokens int `json:"total_tokens"`
|
||||
}
|
||||
Loading…
Reference in New Issue