refactor(open-sse): remove dead buildProviderUrl/Headers path (A1)

These translate-path builders had no runtime consumers: the translator route
uses executor.buildUrl/buildHeaders, and the barrel re-exports were unused.
Removing them eliminates the parallel URL/header build path (single source of
truth = executors). Drop their private helpers and the now-unused clineAuth
import. Golden executor snapshots + gate: no regression.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
decolua
2026-06-13 17:34:39 +07:00
parent cc1f4f6c53
commit 3a26d5fb40
5 changed files with 1 additions and 2945 deletions

View File

@@ -31,8 +31,6 @@ export {
export {
detectFormat,
getProviderConfig,
buildProviderUrl,
buildProviderHeaders,
getTargetFormat
} from "./services/provider.js";

View File

@@ -1,5 +1,4 @@
import { PROVIDERS } from "../config/providers.js";
import { buildClineHeaders } from "../shared/clineAuth.js";
const OPENAI_COMPATIBLE_PREFIX = "openai-compatible-";
const OPENAI_COMPATIBLE_DEFAULTS = {
@@ -24,27 +23,6 @@ function getOpenAICompatibleType(provider) {
return provider.includes("responses") ? "responses" : "chat";
}
function buildOpenAICompatibleUrl(baseUrl, apiType) {
const normalized = baseUrl.replace(/\/$/, "");
const path = apiType === "responses" ? "/responses" : "/chat/completions";
return `${normalized}${path}`;
}
function buildAnthropicCompatibleUrl(baseUrl) {
const normalized = baseUrl.replace(/\/$/, "");
return `${normalized}/messages`;
}
function buildQwenBaseUrl(resourceUrl, fallbackBaseUrl) {
const fallback = (fallbackBaseUrl || "").replace(/\/chat\/completions$/, "");
const raw = typeof resourceUrl === "string" ? resourceUrl.trim() : "";
if (!raw) return fallback;
if (raw.startsWith("http://") || raw.startsWith("https://")) {
return raw.replace(/\/$/, "");
}
return `https://${raw.replace(/\/$/, "")}/v1`;
}
// Detect request format from body structure
export function detectFormat(body) {
// OpenAI Responses API: has input (array or string) instead of messages[]
@@ -145,180 +123,6 @@ export function getProviderConfig(provider) {
return PROVIDERS[provider] || PROVIDERS.openai;
}
// Get number of fallback URLs for provider (for retry logic)
export function getProviderFallbackCount(provider) {
const config = getProviderConfig(provider);
return config.baseUrls?.length || 1;
}
// Build provider URL
export function buildProviderUrl(provider, model, stream = true, options = {}) {
if (isOpenAICompatible(provider)) {
const apiType = getOpenAICompatibleType(provider);
const baseUrl = options?.baseUrl || OPENAI_COMPATIBLE_DEFAULTS.baseUrl;
return buildOpenAICompatibleUrl(baseUrl, apiType);
}
if (isAnthropicCompatible(provider)) {
const baseUrl = options?.baseUrl || ANTHROPIC_COMPATIBLE_DEFAULTS.baseUrl;
return buildAnthropicCompatibleUrl(baseUrl);
}
const config = getProviderConfig(provider);
switch (provider) {
case "claude":
return `${config.baseUrl}?beta=true`;
case "gemini": {
const action = stream ? "streamGenerateContent?alt=sse" : "generateContent";
return `${config.baseUrl}/${model}:${action}`;
}
case "gemini-cli": {
const action = stream ? "streamGenerateContent?alt=sse" : "generateContent";
return `${config.baseUrl}:${action}`;
}
case "antigravity": {
// Use baseUrlIndex from options or default to 0
const urlIndex = options?.baseUrlIndex || 0;
const baseUrl = config.baseUrls[urlIndex] || config.baseUrls[0];
const path = stream ? "/v1internal:streamGenerateContent?alt=sse" : "/v1internal:generateContent";
return `${baseUrl}${path}`;
}
case "codex":
return config.baseUrl;
case "qwen": {
const baseUrl = buildQwenBaseUrl(options?.qwenResourceUrl, config.baseUrl);
return `${baseUrl}/chat/completions`;
}
case "github":
return config.baseUrl;
case "glm":
case "kimi":
case "minimax":
// Claude-compatible providers
return `${config.baseUrl}?beta=true`;
default:
return config.baseUrl;
}
}
// Build provider headers
export function buildProviderHeaders(provider, credentials, stream = true, body = null) {
const config = getProviderConfig(provider);
const headers = {
"Content-Type": "application/json",
...config.headers
};
// Add auth header
// Specific override for Anthropic Compatible
if (isAnthropicCompatible(provider)) {
if (credentials.apiKey) {
headers["x-api-key"] = credentials.apiKey;
// Do NOT send Authorization header when apiKey is present for Anthropic Compatible
// as it causes issues with some providers (e.g. opencode.ai)
} else if (credentials.accessToken) {
headers["Authorization"] = `Bearer ${credentials.accessToken}`;
}
// Add default Anthropic version if not present (some proxies require it)
if (!headers["anthropic-version"]) {
headers["anthropic-version"] = "2023-06-01";
}
} else {
switch (provider) {
case "gemini":
if (credentials.apiKey) {
headers["x-goog-api-key"] = credentials.apiKey;
} else if (credentials.accessToken) {
headers["Authorization"] = `Bearer ${credentials.accessToken}`;
}
break;
case "antigravity":
case "gemini-cli":
// Antigravity and Gemini CLI use OAuth access token
headers["Authorization"] = `Bearer ${credentials.accessToken}`;
break;
case "claude":
// Claude uses x-api-key header for API key, or Authorization for OAuth
if (credentials.apiKey) {
headers["x-api-key"] = credentials.apiKey;
} else if (credentials.accessToken) {
headers["Authorization"] = `Bearer ${credentials.accessToken}`;
}
break;
case "github": {
// GitHub Copilot requires special headers to mimic VSCode
// Prioritize copilotToken from providerSpecificData, fallback to accessToken
const githubToken = credentials.copilotToken || credentials.accessToken;
// Add headers in exact same order as test endpoint
headers["Authorization"] = `Bearer ${githubToken}`;
headers["Content-Type"] = "application/json";
headers["copilot-integration-id"] = "vscode-chat";
headers["editor-version"] = "vscode/1.107.1";
headers["editor-plugin-version"] = "copilot-chat/0.26.7";
headers["user-agent"] = "GitHubCopilotChat/0.26.7";
headers["openai-intent"] = "conversation-panel";
headers["x-github-api-version"] = "2025-04-01";
// Generate a UUID for x-request-id (Cloudflare Workers compatible)
headers["x-request-id"] = crypto.randomUUID ? crypto.randomUUID() :
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
headers["x-vscode-user-agent-library-version"] = "electron-fetch";
headers["X-Initiator"] = "user";
headers["Accept"] = "application/json";
break;
}
case "codex":
case "qwen":
case "openai":
case "openrouter":
headers["Authorization"] = `Bearer ${credentials.apiKey || credentials.accessToken}`;
break;
case "cline":
Object.assign(headers, buildClineHeaders(credentials.apiKey || credentials.accessToken));
break;
case "glm":
case "kimi":
case "minimax":
// Claude-compatible API providers use x-api-key
headers["x-api-key"] = credentials.apiKey;
break;
case "vertex":
case "vertex-partner":
// Vertex uses async token minting — headers are set by VertexExecutor._buildHeadersAsync()
// Do NOT set Authorization here; it would leak the raw SA JSON as Bearer token
break;
default:
headers["Authorization"] = `Bearer ${credentials.apiKey || credentials.accessToken}`;
break;
}
}
// Stream accept header
if (stream) {
headers["Accept"] = "text/event-stream";
}
return headers;
}
// Get target format for provider
export function getTargetFormat(provider) {
if (isOpenAICompatible(provider)) {

File diff suppressed because one or more lines are too long

View File

@@ -1,68 +0,0 @@
// A1 GOLDEN: lock OUTPUT của services/provider.js (translate route path) trên code CŨ.
// buildProviderUrl/buildProviderHeaders/getTargetFormat — đường SONG SONG với executor.
// Mục tiêu: trước khi hợp nhất 2 đường, chốt behavior translate-path hiện tại.
import { describe, it, expect } from "vitest";
import { PROVIDERS } from "../../open-sse/config/providers.js";
import {
buildProviderUrl,
buildProviderHeaders,
getTargetFormat,
} from "../../open-sse/services/provider.js";
const API_KEY_CRED = { apiKey: "sk-test-APIKEY", providerSpecificData: {} };
const OAUTH_CRED = { accessToken: "tok-test-ACCESS", providerSpecificData: {} };
// Khử token + field động (github x-request-id uuid, kimi device-id) để snapshot ổn định.
function sanitize(headers) {
const out = {};
for (const [k, v] of Object.entries(headers)) {
out[k] = typeof v === "string"
? v.replace(/Bearer .+/, "Bearer <TOK>")
.replace(/sk-test-APIKEY|tok-test-ACCESS/g, "<CRED>")
.replace(/kimi-\d{10,}/g, "kimi-<TS>")
.replace(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "<UUID>")
: v;
}
return out;
}
const providerIds = Object.keys(PROVIDERS).sort();
function safe(fn) {
try { return fn(); } catch (e) { return `THROW: ${e.message}`; }
}
describe("GOLDEN provider.js buildProviderUrl (translate path)", () => {
for (const pid of providerIds) {
it(`${pid} → url`, () => {
const snap = {
stream: safe(() => buildProviderUrl(pid, "test-model", true, {})),
nonStream: safe(() => buildProviderUrl(pid, "test-model", false, {})),
};
expect(snap).toMatchSnapshot();
});
}
});
describe("GOLDEN provider.js buildProviderHeaders (translate path)", () => {
for (const pid of providerIds) {
it(`${pid} → headers`, () => {
const cred = PROVIDERS[pid].noAuth ? {} : API_KEY_CRED;
const credOauth = PROVIDERS[pid].noAuth ? {} : OAUTH_CRED;
const snap = {
apiKey: safe(() => sanitize(buildProviderHeaders(pid, cred, true))),
oauth: safe(() => sanitize(buildProviderHeaders(pid, credOauth, true))),
nonStream: safe(() => sanitize(buildProviderHeaders(pid, cred, false))),
};
expect(snap).toMatchSnapshot();
});
}
});
describe("GOLDEN provider.js getTargetFormat", () => {
it("all providers → format", () => {
const snap = {};
for (const pid of providerIds) snap[pid] = safe(() => getTargetFormat(pid));
expect(snap).toMatchSnapshot();
});
});