feat(oauth): zed/trae/windsurf providers + harden callback proxies

- zed live model discovery; codebuddy-intl handler; remove duplicate workbuddy
- split oauth providers.js into per-provider files (facade re-export)
- fold 5 standard refresh providers into config-driven generic
- hide trae/windsurf from registry (no tool calling support)
- fix login-CSRF + SSRF on trae/windsurf/zed local callback proxies
  via loopback-origin guard + strict state validation + apiOrigins allowlist
- move zed RSA private key transit to POST body; redact proxy logs

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
decolua
2026-07-25 17:25:19 +07:00
co-authored by Claude Fable 5
parent 783e271c16
commit 8e04fe1734
46 changed files with 4569 additions and 2203 deletions
+6 -6
View File
@@ -100,10 +100,11 @@ import p97 from "./xiaomi-tokenplan.js";
import p98 from "./youcom.js";
import p99 from "./alims-intl.js";
import p100 from "./codebuddy-intl.js";
import p101 from "./workbuddy.js";
import p102 from "./trae.js";
// Temporarily hidden — no tool calling support (trae SOLO agent / windsurf gRPC skip ToolCallChunk).
// Re-enable by uncommenting both the import and the array entry below.
// import p102 from "./trae.js";
import p103 from "./zed.js";
import p104 from "./windsurf.js";
// import p104 from "./windsurf.js";
export default [
p0,
@@ -207,8 +208,7 @@ export default [
p98,
p99,
p100,
p101,
p102,
// p102, // trae — hidden, no tool calling
p103,
p104,
// p104, // windsurf — hidden, no tool calling
];
+13 -14
View File
@@ -1,7 +1,8 @@
// Trae (ByteDance marscode) provider registry entry.
// Auth + exchange URLs verified from cockpit-tools/src-tauri/src/modules/trae_oauth.rs.
// Region origins verified from trae_account.rs lines 63-66.
// Chat endpoint path /cloudide/api/v3/trae/Chat is GUESSED (TODO verify upstream).
// Chat = SOLO remote agent API:
// POST {base}/chat_sessions → {data:{chat_session_id, message_id}}
// GET {base}/chat_sessions/{id}/events?reply_to_message_id=... → SSE
// Auth: Authorization: Cloud-IDE-JWT <jwt>
export default {
id: "trae",
alias: "tr",
@@ -20,21 +21,19 @@ export default {
notice: { signupUrl: "https://www.trae.ai" },
},
transport: {
// IDE flow (cockpit-tools verified): x-cloudide-token auth, OpenAI-shaped SSE.
baseUrl: "https://api.marscode.com/cloudide/api/v3/trae/Chat",
// SOLO remote agent base — verified working chat endpoint.
baseUrl: "https://core-normal.trae.ai/api/remote/v1",
format: "openai",
headers: {
"x-app-version": "3.5.54",
"x-app-type": "stable",
"x-env": "production",
"client_id": "ono9krqynydwx5",
"User-Agent": "Trae/1.0.0 antigravity-cockpit-tools",
"X-Trae-Client-Type": "web",
"X-Preferenced-Language": "en",
"Referer": "https://solo.trae.ai/",
},
// Auth: x-cloudide-token + Authorization: Bearer — injected by executor buildHeaders.
// Auth: Cloud-IDE-JWT scheme on Authorization — injected by executor buildHeaders.
auth: {
combined: true,
header: "x-cloudide-token",
scheme: "raw",
header: "Authorization",
scheme: "Cloud-IDE-JWT",
},
usage: {
url: "https://api.marscode.com/cloudide/api/v3/trae/GetUserInfo",
@@ -61,7 +60,7 @@ export default {
// Trae refresh uses custom JSON body, not OAuth form — handled by refresh.js, not config-driven.
refresh: { encoding: "json" },
},
// Model catalog sourced from OmniRoute (IDE flow, core-normal.trae.ai).
// Model catalog (IDE flow, core-normal.trae.ai).
models: [
{ id: "auto", name: "Auto (Server Picks)" },
{ id: "work", name: "Work (Fast)" },
+12 -15
View File
@@ -1,6 +1,7 @@
// Windsurf provider registry — Firebase+Codeium+Devin auth chain.
// Chat transport is Codeium protobuf gRPC-Web: endpoint + schema are GUESS,
// the cockpit-tools source only documents auth/quota (SeatManagement) paths.
// Chat = Codeium gRPC-web protobuf:
// POST {base} Content-Type: application/grpc-web+proto
// Service: exa.language_server_pb.LanguageServerService / GetChatMessage
export default {
id: "windsurf",
alias: "ws",
@@ -17,19 +18,16 @@ export default {
hasOAuth: true,
authModes: ["oauth", "apikey"],
// TODO(chat): Codeium ServerService protobuf schema unknown — endpoint is a guess.
transport: {
// GUESS: Codeium chat lives under /exa.server_pb.ServerService/GetChatMessage.
baseUrl: "https://server.codeium.com/exa.server_pb.ServerService/GetChatMessage",
format: "windsurf",
baseUrl: "https://server.codeium.com/exa.language_server_pb.LanguageServerService/GetChatMessage",
format: "openai",
headers: {
"Content-Type": "application/proto",
"Connect-Protocol-Version": "1",
"ideName": "Windsurf",
"extensionName": "codeium.windsurf",
"Content-Type": "application/grpc-web+proto",
"Accept": "application/grpc-web+proto",
"X-Grpc-Web": "1",
},
// Bearer of apiKey (sk-ws-... / Firebase-derived / Devin session) — Connect-Protocol scheme unverified.
auth: { combined: true, header: "Authorization" },
// apiKey (sk-ws-... or Firebase-derived) as Bearer + in protobuf Metadata.api_key.
auth: { combined: true, header: "Authorization", scheme: "Bearer" },
},
// Auth chain (4 terminal paths, all yield apiKey):
@@ -52,9 +50,8 @@ export default {
},
// Catalog verified against model_configs_v2.bin from Devin CLI (2026.5.x).
// Source: OmniRoute registry (guanxiaol/WindsurfPoolAPI). Dot-notation ids; the
// executor MODEL_ALIAS_MAP would map these to Windsurf modelUid once proto chat
// is implemented. contextLength dropped — 9router schema uses id+name only.
// Dot-notation ids; the executor MODEL_ALIAS_MAP maps these to Windsurf modelUid.
// contextLength dropped — 9router schema uses id+name only.
models: [
// Cognition / SWE
{ id: "swe-1.6-fast", name: "SWE-1.6 Fast" },
-73
View File
@@ -1,73 +0,0 @@
export default {
id: "workbuddy",
// Short model prefix (wb/glm-5.2). WorkBuddy is a B2B/enterprise skin of
// CodeBuddy CN (same codebuddy.cn backend), so models mirror codebuddy-cn.
alias: "wb",
uiAlias: "wb",
hidden: false,
priority: 90,
display: {
name: "WorkBuddy",
icon: "smart_toy",
color: "#006EFF",
website: "https://www.codebuddy.cn",
notice: {
signupUrl: "https://www.codebuddy.cn",
},
},
category: "oauth",
authModes: ["oauth", "apikey"],
hasOAuth: true,
transport: {
// Same OpenAI-compatible gateway as codebuddy-cn; platform=workbuddy is
// distinguished at the OAuth layer, not the chat endpoint.
baseUrl: "https://www.codebuddy.cn/v2/chat/completions",
forceStream: true,
thinkingFormat: "openai",
headers: {
"User-Agent": "CLI/2.108.1 CodeBuddy/2.108.1",
"X-Product": "SaaS",
"X-IDE-Type": "CLI",
"X-IDE-Name": "CLI",
"x-requested-with": "XMLHttpRequest",
"x-codebuddy-request": "1",
},
auth: {
combined: true,
header: "Authorization",
scheme: "bearer",
},
},
models: [
{ id: "glm-5.2", name: "GLM-5.2" },
{ id: "glm-5.1", name: "GLM-5.1" },
{ id: "glm-5.0", name: "GLM-5.0" },
{ id: "glm-5.0-turbo", name: "GLM-5.0-Turbo" },
{ id: "glm-5v-turbo", name: "GLM-5v-Turbo" },
{ id: "glm-4.7", name: "GLM-4.7" },
{ id: "minimax-m3", name: "MiniMax-M3" },
{ id: "minimax-m2.7", name: "MiniMax-M2.7" },
{ id: "kimi-k2.7", name: "Kimi-K2.7-Code" },
{ id: "kimi-k2.6", name: "Kimi-K2.6" },
{ id: "kimi-k2.5", name: "Kimi-K2.5" },
{ id: "hy3-preview", name: "Hy3 Preview" },
{ id: "deepseek-v4-pro", name: "DeepSeek-V4-Pro" },
{ id: "deepseek-v4-flash", name: "DeepSeek-V4-Flash" },
{ id: "deepseek-v3-2-volc", name: "DeepSeek-V3.2" },
],
oauth: {
// Same codebuddy.cn host as codebuddy-cn; only platform param differs
// (workbuddy vs CLI). Prefix /v2/plugin matches cockpit-tools Rust.
baseUrl: "https://www.codebuddy.cn",
stateUrl: "https://www.codebuddy.cn/v2/plugin/auth/state",
tokenUrl: "https://www.codebuddy.cn/v2/plugin/auth/token",
refreshUrl: "https://www.codebuddy.cn/v2/plugin/auth/token/refresh",
userAgent: "CLI/2.63.2 CodeBuddy/2.63.2",
platform: "workbuddy",
pollInterval: 5000,
},
features: {
usage: true,
usageApikey: true,
},
};