Skip to content
Merged

Dev #22

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: CI

on:
push:
branches: [main, master, dev]
pull_request:
branches: [main, master]

jobs:
go-build:
name: Go Build & Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version-file: go.mod

- name: Format check
run: test -z "$(gofmt -l .)"

- name: Build
run: go build -o /dev/null ./cmd/server

- name: Test
run: go test ./...

frontend-build:
name: Frontend Build
runs-on: ubuntu-latest
defaults:
run:
working-directory: web
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm
cache-dependency-path: web/package-lock.json

- name: Install dependencies
run: npm ci

- name: Lint
run: npm run lint

- name: Build
run: npm run build

embed-check:
name: Embed Sync Check
runs-on: ubuntu-latest
needs: [go-build, frontend-build]
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm
cache-dependency-path: web/package-lock.json

- name: Install frontend dependencies
working-directory: web
run: npm ci

- name: Build frontend
working-directory: web
run: npm run build

- name: Sync web_static
run: |
find internal/managementasset/web_static -type f ! -name README.md -delete
find internal/managementasset/web_static -type d -empty -delete
cp -r web/out/* internal/managementasset/web_static/

- name: Check embedded assets are up to date
run: |
if [ -n "$(git diff --name-only internal/managementasset/web_static -- . ':!internal/managementasset/web_static/README.md')" ]; then
echo "::error::Embedded web assets are out of date. Run: cp -r web/out internal/managementasset/web_static"
git diff --stat internal/managementasset/web_static -- . ':!internal/managementasset/web_static/README.md'
exit 1
fi
echo "Embedded assets are up to date."
18 changes: 17 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ cli-proxy-api
cliproxy
/server
*.exe

test-output

# Configuration
config.yaml
.env
.mcp.json

# Generated content
bin/*
logs/*
Expand All @@ -25,6 +26,11 @@ objectstore/*
# Static assets
static/*

# Embedded web assets (generated from web/out)
internal/managementasset/web_static/*
!internal/managementasset/web_static/.gitkeep
!internal/managementasset/web_static/README.md

# Authentication data
auths/*
!auths/.gitkeep
Expand Down Expand Up @@ -62,3 +68,13 @@ _bmad-output/*
.cli-proxy-api/
.venv/
*.bak

# Web frontend
web/node_modules/
web/.next/
web/out/

# Private
private/
cli-proxy-api-plus
server-1
19 changes: 19 additions & 0 deletions .trae/specs/fix-codearts-integration/checklist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
- [x] `signer.go` 的 `SignRequest` 对 POST 请求计算实际 body SHA256 hash,不再始终使用空 hash
- [x] `buildCodeArtsPayload` 输出的 JSON 包含 chat_id、client、task、task_parameters、is_delta_response、user_id、attempt、parent_message_id 字段
- [x] `buildCodeArtsPayload` 的 messages 格式为 `[{type: "text", content: "..."}]`
- [x] `PrepareRequest` 设置 Accept: text/event-stream、Heartbeat-Enable、Ide-Name、X-Snap-Traceid 等请求头
- [x] `sdk/auth/codearts.go` 存在且实现 Authenticator 接口(Provider、Login、RefreshLead)
- [x] `sdk/auth/refresh_registry.go` 中注册了 codearts
- [x] `internal/cmd/auth_manager.go` 中注册了 NewCodeArtsAuthenticator()
- [x] `cmd/server/main.go` 中有 `--codearts-login` flag
- [x] `internal/cmd/codearts_login.go` 存在且实现 DoCodeArtsLogin
- [x] `--codearts-login` flag 处理分支正确调用 DoCodeArtsLogin
- [x] `internal/thinking/provider/codearts/apply.go` 存在且注册了 "codearts" provider
- [x] `internal/runtime/executor/helps/thinking_providers.go` 导入了 codearts thinking provider
- [x] `config.example.yaml` 中 oauth-model-alias Supported channels 包含 codearts
- [x] `config.example.yaml` 中 oauth-excluded-models Supported channels 包含 codearts 且不包含 qwen
- [x] `internal/config/config.go` 中 OAuthExcludedModels 注释包含 codearts
- [x] `internal/api/server.go` 中无中文注释
- [x] `internal/watcher/watcher.go` 中无中文注释
- [x] `go build -o test-output ./cmd/server && rm test-output` 编译通过
- [x] `gofmt -w .` 格式化通过
113 changes: 113 additions & 0 deletions .trae/specs/fix-codearts-integration/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# CodeArts 集成修复与优化 Spec

## Why
CodeArts 是项目中唯一一个有完整 executor/auth/translator/OAuth web handler 但**缺少 CLI 登录命令** (`--codearts-login`) 的 provider。用户只能通过浏览器 Web OAuth 流程登录,且 token 无法通过 SDK 自动刷新机制续期。此外,executor 的 payload 构建与 Python 参考实现存在显著差距,签名算法有 bug,以及多处代码规范问题。

## What Changes
- 新增 `--codearts-login` CLI flag 及完整登录链路
- 新增 `sdk/auth/codearts.go` SDK Authenticator
- 在 `sdk/auth/refresh_registry.go` 注册 CodeArts refresh lead
- 在 `internal/cmd/auth_manager.go` 注册 CodeArts authenticator
- 修复 `signer.go` 中 body hash 始终为空的 bug(POST 请求签名不包含 body)
- 修复 `buildCodeArtsPayload` 与 Python 参考实现的差距(缺少 chat_id、task_parameters、is_delta_response 等关键字段)
- 修复 `buildCodeArtsPayload` 中 messages 格式与 Python 参考实现不一致(缺少 `type` 字段)
- 新增 CodeArts thinking provider
- 修复 `config.example.yaml` 和 `config.go` 注释中遗漏 `codearts` channel
- 修复 `oauth-excluded-models` 注释中不存在的 `qwen` channel
- 翻译 `server.go` 和 `watcher.go` 中的中文注释为英文

## Impact
- Affected specs: CodeArts 认证、token 自动刷新、thinking pipeline
- Affected code:
- `cmd/server/main.go` — 新增 flag
- `internal/cmd/codearts_login.go` — 新文件
- `sdk/auth/codearts.go` — 新文件
- `sdk/auth/refresh_registry.go` — 注册 codearts
- `internal/cmd/auth_manager.go` — 注册 codearts authenticator
- `internal/auth/codearts/signer.go` — 修复 body hash bug
- `internal/runtime/executor/codearts_executor.go` — 修复 payload 构建
- `internal/thinking/provider/codearts/apply.go` — 新文件
- `internal/runtime/executor/helps/thinking_providers.go` — 注册 codearts
- `config.example.yaml` — 修复注释
- `internal/config/config.go` — 修复注释
- `internal/api/server.go` — 翻译中文注释
- `internal/watcher/watcher.go` — 翻译中文注释

## ADDED Requirements

### Requirement: CodeArts CLI Login Command
系统 SHALL 提供 `--codearts-login` 命令行 flag,允许用户通过 CLI 完成 CodeArts OAuth 登录流程。

#### Scenario: 用户通过 CLI 登录 CodeArts
- **WHEN** 用户执行 `./server --codearts-login`
- **THEN** 系统启动本地回调服务器,生成 ticket_id,打开浏览器到 HuaweiCloud 登录页面
- **AND** 用户完成登录后,系统轮询获取认证结果
- **AND** 系统将 AK/SK/SecurityToken 凭证保存到 auth 目录
- **AND** 输出 "CodeArts authentication successful!"

### Requirement: CodeArts SDK Authenticator
系统 SHALL 在 `sdk/auth/` 包中提供 `CodeArtsAuthenticator`,实现 `Authenticator` 接口。

#### Scenario: Authenticator 注册与使用
- **WHEN** 系统初始化 auth manager
- **THEN** `CodeArtsAuthenticator` 被注册到 manager 中,provider 为 "codearts"
- **AND** `RefreshLead()` 返回 4 小时(token 有效期 24h,提前 4h 刷新)

### Requirement: CodeArts Refresh Lead 注册
系统 SHALL 在 `sdk/auth/refresh_registry.go` 中注册 codearts 的 refresh lead。

#### Scenario: 自动刷新调度
- **WHEN** auto refresh loop 检查 codearts auth 的过期时间
- **THEN** `ProviderRefreshLead("codearts", nil)` 返回 4 小时 duration
- **AND** token 在过期前 4 小时自动触发刷新

### Requirement: Signer Body Hash 修复
`SignRequest` SHALL 对 POST 请求计算实际 body 的 SHA256 hash,而非始终使用空 body hash。

#### Scenario: POST 请求签名
- **WHEN** 对 POST 请求调用 `SignRequest`
- **THEN** body hash 应为请求 body 的 SHA256 哈希值
- **AND** 签名结果与 Python 参考实现一致

### Requirement: CodeArts Payload 构建对齐 Python 参考
`buildCodeArtsPayload` SHALL 生成与 Python 参考实现 (`CodeArts-2api.py`) 一致的请求格式。

#### Scenario: 完整 payload 构建
- **WHEN** 构建 CodeArts chat 请求
- **THEN** payload 包含 `chat_id`(UUID)、`client: "IDE"`、`task: "chat"`、`task_parameters`(含 is_intent_recognition、W3_Search、codebase_search、related_question、preferred_language、enable_code_interpreter、ide、routerVersion、isNewClient、features.support_end_tag 等)
- **AND** payload 包含 `is_delta_response: true`、`user_id`、`attempt: 1`、`parent_message_id: ""`
- **AND** messages 格式为 `[{type: "text", content: "..."}]`(而非当前的 `[{role: "...", content: "..."}]`)
- **AND** system 消息格式为 `[System]\n{content}`,assistant 消息格式为 `[Assistant]\n{content}`

### Requirement: CodeArts Thinking Provider
系统 SHALL 提供 CodeArts thinking provider,将 thinking level 映射到 CodeArts 的 `task_parameters.temperature` 或其他合适字段。

#### Scenario: Thinking suffix 应用
- **WHEN** 用户请求模型 `Glm-5-internal(high)`
- **THEN** thinking provider 将 level "high" 应用到 CodeArts 请求中

### Requirement: 文档注释更新
配置文件和代码注释 SHALL 正确列出所有支持的 channel。

#### Scenario: oauth-model-alias 和 oauth-excluded-models 注释
- **WHEN** 用户查看 `config.example.yaml` 或 `config.go`
- **THEN** `oauth-model-alias` 的 Supported channels 注释包含 `codearts`
- **AND** `oauth-excluded-models` 的 Supported channels 注释包含 `codearts` 且不包含不存在的 `qwen`

### Requirement: 中文注释翻译
代码中的中文注释 SHALL 被翻译为英文。

#### Scenario: server.go 和 watcher.go 注释
- **WHEN** 检查 `server.go` 和 `watcher.go` 中的注释
- **THEN** 所有注释均为英文

## MODIFIED Requirements

### Requirement: CodeArts Executor PrepareRequest
`PrepareRequest` SHALL 设置与 Python 参考实现一致的请求头,包括 `Accept: text/event-stream`、`Heartbeat-Enable: true`、`Ide-Name`、`Ide-Version`、`Is-Confidential`、`X-Language`、`X-Snap-Traceid` 等。

### Requirement: CodeArts Executor Non-Stream Mode
`Execute`(非流式)方法 SHALL 在 payload 中设置 `stream: true`(因为 CodeArts API 即使非流式请求也返回 SSE),并添加注释说明此行为。

## REMOVED Requirements
59 changes: 59 additions & 0 deletions .trae/specs/fix-codearts-integration/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Tasks

- [x] Task 1: 修复 `signer.go` body hash bug — POST 请求签名必须包含实际 body 的 SHA256 hash
- [x] SubTask 1.1: 修改 `SignRequest` 函数签名,接受 body 参数
- [x] SubTask 1.2: 计算 body SHA256 hash 替代空 hash
- [x] SubTask 1.3: 更新所有 `SignRequest` 调用点(executor、auth refresh)
- [x] SubTask 1.4: 验证签名结果与 Python 参考实现一致

- [x] Task 2: 修复 `buildCodeArtsPayload` 对齐 Python 参考实现
- [x] SubTask 2.1: 将 messages 格式从 `[{role, content}]` 改为 `[{type: "text", content}]`
- [x] SubTask 2.2: 添加 chat_id (UUID)、client、task、task_parameters 完整结构
- [x] SubTask 2.3: 添加 is_delta_response、user_id、attempt、parent_message_id 字段
- [x] SubTask 2.4: 修复 tool_calls/tool result 消息格式对齐 Python 实现
- [x] SubTask 2.5: 添加 tools 和 temperature 到 task_parameters 中

- [x] Task 3: 修复 `PrepareRequest` 请求头对齐 Python 参考
- [x] SubTask 3.1: 添加 Accept: text/event-stream、Heartbeat-Enable: true 等缺失头
- [x] SubTask 3.2: 添加 Ide-Name、Ide-Version、Is-Confidential、X-Language、X-Snap-Traceid
- [x] SubTask 3.3: 更新 SignRequest 调用传入 body

- [x] Task 4: 新增 `sdk/auth/codearts.go` SDK Authenticator
- [x] SubTask 4.1: 实现 `CodeArtsAuthenticator` struct,Provider() 返回 "codearts"
- [x] SubTask 4.2: 实现 `RefreshLead()` 返回 4 小时
- [x] SubTask 4.3: 实现 `Login()` 方法:启动回调服务器 → 生成 ticket → 打开浏览器 → 轮询 → 保存凭证

- [x] Task 5: 注册 CodeArts 到 SDK auth 系统
- [x] SubTask 5.1: 在 `sdk/auth/refresh_registry.go` 注册 codearts refresh lead
- [x] SubTask 5.2: 在 `internal/cmd/auth_manager.go` 注册 `NewCodeArtsAuthenticator()`

- [x] Task 6: 新增 `--codearts-login` CLI flag 和登录命令
- [x] SubTask 6.1: 在 `cmd/server/main.go` 添加 `codeartsLogin` flag
- [x] SubTask 6.2: 在 flag 处理分支添加 `else if codeartsLogin` 调用
- [x] SubTask 6.3: 创建 `internal/cmd/codearts_login.go` 实现 `DoCodeArtsLogin`

- [x] Task 7: 新增 CodeArts thinking provider
- [x] SubTask 7.1: 创建 `internal/thinking/provider/codearts/apply.go`
- [x] SubTask 7.2: 实现 Apply 方法,将 thinking level 映射到请求参数
- [x] SubTask 7.3: 在 `internal/runtime/executor/helps/thinking_providers.go` 注册

- [x] Task 8: 修复文档注释
- [x] SubTask 8.1: 更新 `config.example.yaml` 中 oauth-model-alias Supported channels 添加 codearts
- [x] SubTask 8.2: 更新 `config.example.yaml` 中 oauth-excluded-models Supported channels 添加 codearts 移除 qwen
- [x] SubTask 8.3: 更新 `internal/config/config.go` 中 OAuthExcludedModels 注释添加 codearts

- [x] Task 9: 翻译中文注释为英文
- [x] SubTask 9.1: 翻译 `internal/api/server.go` 中的中文注释
- [x] SubTask 9.2: 翻译 `internal/watcher/watcher.go` 中的中文注释

- [x] Task 10: 编译验证
- [x] SubTask 10.1: `go build -o test-output ./cmd/server && rm test-output`
- [x] SubTask 10.2: `gofmt -w .`

# Task Dependencies
- Task 1 (signer fix) → Task 3 (PrepareRequest uses signer)
- Task 4 (SDK authenticator) → Task 5 (registration) → Task 6 (CLI flag)
- Task 2 (payload fix) and Task 3 (headers) are independent of Task 4-6
- Task 7 (thinking provider) is independent
- Task 8 (docs) and Task 9 (comments) are independent
- Task 10 depends on all others
16 changes: 16 additions & 0 deletions .trae/specs/web-management-center/checklist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
- [x] Next.js + shadcn/ui 项目在 `./web` 下成功初始化,`npm run dev` 可正常启动
- [x] API client 层封装所有 `/v0/management/*` 端点,包含认证 header 管理
- [x] Management Key 登录页面可用,输入 key 后可访问管理面板
- [x] Dashboard 页面显示服务器版本、状态、Provider 概览
- [x] Config 页面可查看和编辑 config.yaml,各项设置控件可用
- [x] Auth Files 页面可列出、上传、删除、启用/禁用、编辑认证文件
- [x] OAuth 页面可列出所有 OAuth Provider,发起 OAuth 流程并轮询状态
- [x] API Keys 页面可管理所有类型的 Key(api-keys、gemini、claude、codex、vertex、openai-compatibility)
- [x] Usage 页面可查看统计、导出和导入数据
- [x] Logs 页面可实时查看日志、查看错误日志、清理日志
- [x] `GET /v0/management/oauth-providers` 端点返回正确的 Provider 列表
- [x] `//go:embed` 成功嵌入 Next.js 静态导出产物
- [x] 磁盘文件优先、嵌入资源 fallback 的逻辑正确
- [x] `go build -o test-output ./cmd/server && rm test-output` 编译通过
- [x] 前端 `npm run build` 成功生成静态导出产物
- [x] 所有代码注释使用英文
Loading
Loading