From 6688d52beb7f9688595c20bbf2109063926a23f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=8F=8A?= <522caiji@gmail.com> Date: Sun, 30 Aug 2026 16:15:46 +0800 Subject: [PATCH] feat: persist Trae and WorkBuddy per-model reasoning and Max Parse live catalog options, save console defaults, and send them on chat without rewriting shipped SQLite migrations. --- CHANGELOG.md | 2 + docs/DESIGN.md | 6 +- docs/PROVIDERS.md | 2 +- docs/PROVIDERS_TRAE_SOLO.md | 1 + frontend/src/api/overview.ts | 14 +++ frontend/src/api/types.ts | 2 + frontend/src/components/ModelDetailsModal.tsx | 4 +- frontend/src/i18n/messages.ts | 16 ++- frontend/src/pages/ProvidersPage.tsx | 69 ++++++++++-- internal/accounts/migrations.go | 2 + internal/accounts/store.go | 50 +++++++-- internal/accounts/store_test.go | 26 +++++ internal/api/auth_test.go | 22 ++++ internal/api/modelsettings.go | 79 +++++++------ internal/api/workerproxy.go | 3 + internal/providers/interfaces.go | 23 ++-- internal/providers/reasoning.go | 73 ++++++++++++ internal/providers/trae/catalog.go | 105 ++++++++++++++++-- internal/providers/trae/catalog_test.go | 41 +++++++ internal/providers/trae/client.go | 27 ++++- internal/providers/trae/client_test.go | 18 +++ internal/providers/trae/mapping.go | 55 ++------- internal/providers/trae/mapping_test.go | 17 ++- internal/providers/workbuddy/catalog.go | 99 +++++++++++++++++ internal/providers/workbuddy/client.go | 47 ++++---- internal/providers/workbuddy/client_test.go | 89 +++++++++++++++ internal/providers/workbuddy/mapping.go | 80 +++++++++++++ ...t-DX_iH1iV.js => TrafficChart-DTPSvkRu.js} | 2 +- .../{index-CXnPPo3o.js => index-CMCazkl3.js} | 12 +- ...{index-bZP4NZ5x.css => index-DYZ6NhzG.css} | 2 +- internal/webui/static/index.html | 4 +- 31 files changed, 825 insertions(+), 167 deletions(-) create mode 100644 internal/providers/reasoning.go create mode 100644 internal/providers/workbuddy/catalog.go create mode 100644 internal/providers/workbuddy/mapping.go rename internal/webui/static/assets/{TrafficChart-DX_iH1iV.js => TrafficChart-DTPSvkRu.js} (99%) rename internal/webui/static/assets/{index-CXnPPo3o.js => index-CMCazkl3.js} (85%) rename internal/webui/static/assets/{index-bZP4NZ5x.css => index-DYZ6NhzG.css} (93%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5db1ed6a..27d59989 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Write each change in both `### English` and `### 中文` under `## Unreleased`. - Store an empty client-key provider allowlist as `[]` instead of JSON `null` - Keep the v0.2.20 bytes for provider-model settings migration 007, and accept the later tab-indented checksum so existing databases can boot - Explain on System when the host updater is missing, instead of showing the raw Unix socket error +- Show Trae Max-context and per-model reasoning controls, and WorkBuddy reasoning levels, on Models; persist those defaults and send them on chat ### 中文 @@ -30,6 +31,7 @@ Write each change in both `### English` and `### 中文` under `## Unreleased`. - 客户端密钥未限制供应商时写入 `[]`,不再存成 JSON `null` - 007 供应商模型设置迁移保持 v0.2.20 原文,并接受后来误改缩进后的 checksum,已有数据库可以启动 - 系统页在没有宿主机更新器时说明更新条件,不再直接显示 Unix socket 报错 +- 模型页为 Trae 显示 Max 上下文和推理强度,为 WorkBuddy 显示推理档位;默认值会保存,并在对话请求里带上 ## 0.2.20 - 2026-08-29 diff --git a/docs/DESIGN.md b/docs/DESIGN.md index 5d79b373..9a13544f 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -453,7 +453,7 @@ Hard constraints: - Never edit a shipped migration's SQL bytes. Whitespace, comments, quote style, and statement order all change the checksum. - `gofmt` / indent of the surrounding Go is fine. Indenting the text inside the raw string is not. -- New columns, indexes, or tables go in the next numbered file (`008_…`). Do not append to an applied file. +- New columns, indexes, or tables go in the next numbered file (`009_…`). Do not append to an applied file. - Do not `UPDATE schema_migrations` on a live database to make a rewritten file pass. That hides the mismatch and can leave hosts on different schemas. - Do not delete, rename, or reorder applied filenames. @@ -475,7 +475,7 @@ Keep the menu short. Login is a gate, not a nav item. | `/login` | no | Console password | | `/` | Overview | Runtime pulse + request stats | | `/accounts` | Accounts | Qoder login + pool | -| `/providers` | Models | Catalog + per-model context-window defaults; filter by provider and paginate | +| `/providers` | Models | Catalog + per-model defaults (Qoder context window, Trae Max / reasoning, WorkBuddy reasoning); filter by provider and paginate | | `/access` | Access | Base URL + quick chat; account and model dropdowns follow the selected account catalog | | `/logs` | Logs | Request history + runtime process output | | `/keys` | API keys | Named client keys with optional provider allowlists | @@ -597,7 +597,7 @@ After UI edits: | `frontend/src/pages/LoginPage.tsx` | Console gate | | `frontend/src/pages/AccountsPage.tsx` | Qoder login + pool | | `frontend/src/components/account/` | Compact account card, runtime meter, quota fill | -| `frontend/src/pages/ProvidersPage.tsx` | Model catalog + context-window defaults | +| `frontend/src/pages/ProvidersPage.tsx` | Model catalog + per-model context / Max / reasoning defaults | | `frontend/src/pages/LogsPage.tsx` | Request history + runtime logs | | `frontend/src/pages/SystemPage.tsx` | Managed next-version update | | `frontend/src/components/layout/` | Shell / menu | diff --git a/docs/PROVIDERS.md b/docs/PROVIDERS.md index 11e8710e..07fd14bf 100644 --- a/docs/PROVIDERS.md +++ b/docs/PROVIDERS.md @@ -101,7 +101,7 @@ WorkBuddy2API 把 **WorkBuddy CN / CodeBuddy**(`copilot.tencent.com` / `www.co CN:`GET {chatBase}/console/enterprises/personal/models`。国际站这条 console 路径是 OIDC 页面(未登录 302 到 Keycloak,带 Bearer 500 HTML),必须改打 `GET https://www.workbuddy.ai/v2/enterprises/personal/models`。`GET /api/models` 目录失败用 503,不要 502,避免反代把 JSON 换成 HTML 错误页。 -只暴露 CLI agent 的模型 ID(`cli` / `CLI` / `codebuddy` / `workbuddy`),再和 `data.models` 交叉,跳过 `disabled`。上游没有 agents 时,退回全部未禁用模型。字段用 `maxInputTokens` / `maxOutputTokens`,不是 `contextWindow`。按账号拉目录失败时,`GET /api/models?account=` 返回明确错误,不把空列表当成「没有模型」。 +只暴露 CLI agent 的模型 ID(`cli` / `CLI` / `codebuddy` / `workbuddy`),再和 `data.models` 交叉,跳过 `disabled`。上游没有 agents 时,退回全部未禁用模型。字段用 `maxInputTokens` / `maxOutputTokens`,不是 `contextWindow`。推理档位读模型上的 `reasoning`:`supportedEfforts` / `defaultEffort` / `effort` / `canDisableThinking` / `onlyReasoning`。聊天请求发 `reasoning: {effort, summary:"auto"}`;`max` 按官方 CLI 映射成 `xhigh`。WorkBuddy 没有 Trae 那种 Max 开关,大上下文就是目录里的 `maxInputTokens`。按账号拉目录失败时,`GET /api/models?account=` 返回明确错误,不把空列表当成「没有模型」。 参考仓库失败时回退静态表。本仓库对 Qoder 的原则是 **catalog 失败就报错,不猜**。WorkBuddy 应沿用同一原则:动态目录失败返回明确错误,不内置一份会过期的模型白名单。 diff --git a/docs/PROVIDERS_TRAE_SOLO.md b/docs/PROVIDERS_TRAE_SOLO.md index 846958cc..9dae59c2 100644 --- a/docs/PROVIDERS_TRAE_SOLO.md +++ b/docs/PROVIDERS_TRAE_SOLO.md @@ -152,6 +152,7 @@ qoder-anchor: [docs/DESIGN.md](./DESIGN.md) 的控制面 / 执行面边界 - `POST {AgentHost}/api/ide/v1/get_detail_param` - Body 形态:`function`、`config_names: null`、`need_prompt: false`、`poly_prompt: true` - 用 `config_info_list`:`config_name` → native/public id,`display_config.display_name` → 展示名。空列表当错误。 +- live 目录里 `reasoning_effort_config` 和 `context_window_tokens.max` 经常是空的。Max 还要看 `model_extra_config.v2_max_mode_enabled` / `display_config.max_mode` / `is_dollar_max`;推理还要看 `reasoning_effort_options`、`display_contact_config.reasoning.enable`,以及官方客户端实际使用的 `light` / `high` / `extra_high`(发出去映射成 `low` / `high` / `xhigh`)。 - 本仓库原则与 WorkBuddy 相同:**catalog 失败就报错,不回退过期静态表**。`glm-5.2` / `glm-5.3` 只是实测样例,不是白名单。 ### SSE diff --git a/frontend/src/api/overview.ts b/frontend/src/api/overview.ts index 64e01ddb..1049c5fe 100644 --- a/frontend/src/api/overview.ts +++ b/frontend/src/api/overview.ts @@ -64,6 +64,7 @@ export function updateTraeMaxMode(modelKey: string, maxMode: boolean) { model: string provider: string max_mode: boolean + reasoning_effort?: string context_custom: boolean }>(`/api/models/trae/${encodeURIComponent(modelKey)}`, { method: 'PATCH', @@ -71,6 +72,19 @@ export function updateTraeMaxMode(modelKey: string, maxMode: boolean) { }) } +export function updateProviderReasoning(provider: 'trae' | 'workbuddy', modelKey: string, reasoningEffort: string) { + return api<{ + model: string + provider: string + max_mode: boolean + reasoning_effort?: string + context_custom: boolean + }>(`/api/models/${provider}/${encodeURIComponent(modelKey)}`, { + method: 'PATCH', + body: JSON.stringify({ reasoning_effort: reasoningEffort }), + }) +} + export function rewarmWorker(accountId?: string) { if (!accountId) throw new Error('account id required') return api(`/api/accounts/${encodeURIComponent(accountId)}/rewarm`, { method: 'POST', body: '{}' }) diff --git a/frontend/src/api/types.ts b/frontend/src/api/types.ts index 91463965..b96ffc45 100644 --- a/frontend/src/api/types.ts +++ b/frontend/src/api/types.ts @@ -34,7 +34,9 @@ export type ModelInfo = { prompt_max_tokens?: number reasoning_options?: string[] reasoning_default?: string + reasoning_effort?: string reasoning_type?: string + can_disable_thinking?: boolean } export type Overview = { diff --git a/frontend/src/components/ModelDetailsModal.tsx b/frontend/src/components/ModelDetailsModal.tsx index 2e45593a..264a599a 100644 --- a/frontend/src/components/ModelDetailsModal.tsx +++ b/frontend/src/components/ModelDetailsModal.tsx @@ -48,8 +48,8 @@ export function ModelDetailsModal({ model, t, onClose }: Props) { {options.length ? (