Enhance proxy functionality with Vercel relay support

This commit is contained in:
decolua
2026-04-13 10:08:24 +07:00
parent b3feb96740
commit 89eb26dee2
15 changed files with 331 additions and 9 deletions

View File

@@ -44,7 +44,7 @@ export const PROVIDER_MODELS = {
{ id: "qwen3-coder-plus", name: "Qwen3 Coder Plus" },
{ id: "qwen3-coder-flash", name: "Qwen3 Coder Flash" },
{ id: "vision-model", name: "Qwen3 Vision Model" },
{ id: "coder-model", name: "Qwen3.5 Coder Model" },
{ id: "coder-model", name: "Qwen3.6 Coder Model" },
],
if: [ // iFlow AI
{ id: "qwen3-coder-plus", name: "Qwen3 Coder Plus" },

View File

@@ -215,7 +215,7 @@ export class CursorExecutor extends BaseExecutor {
const transformedBody = this.transformRequest(model, body, stream, credentials);
try {
const shouldForceFetch = proxyOptions?.enabled === true || proxyOptions?.connectionProxyEnabled === true;
const shouldForceFetch = proxyOptions?.enabled === true || proxyOptions?.connectionProxyEnabled === true || !!proxyOptions?.vercelRelayUrl;
const response = (http2 && !shouldForceFetch)
? await this.makeHttp2Request(url, headers, transformedBody, signal)
: await this.makeFetchRequest(url, headers, transformedBody, signal, proxyOptions);

View File

@@ -98,9 +98,14 @@ export async function handleChatCore({ body, modelInfo, credentials, log, onCred
connectionProxyEnabled: credentials?.providerSpecificData?.connectionProxyEnabled === true,
connectionProxyUrl: credentials?.providerSpecificData?.connectionProxyUrl || "",
connectionNoProxy: credentials?.providerSpecificData?.connectionNoProxy || "",
vercelRelayUrl: credentials?.providerSpecificData?.vercelRelayUrl || "",
};
if (proxyOptions.connectionProxyEnabled && proxyOptions.connectionProxyUrl) {
if (proxyOptions.vercelRelayUrl) {
const connectionName = credentials?.connectionName || credentials?.connectionId || "unknown";
const poolId = credentials?.providerSpecificData?.connectionProxyPoolId || "none";
log?.info?.("PROXY", `${provider.toUpperCase()} | ${model} | conn=${connectionName} | pool=${poolId} | vercel-relay=${proxyOptions.vercelRelayUrl}`);
} else if (proxyOptions.connectionProxyEnabled && proxyOptions.connectionProxyUrl) {
let maskedProxyUrl = proxyOptions.connectionProxyUrl;
try {
const parsed = new URL(proxyOptions.connectionProxyUrl);

View File

@@ -198,6 +198,18 @@ async function createBypassRequest(parsedUrl, realIP, options) {
export async function proxyAwareFetch(url, options = {}, proxyOptions = null) {
const targetUrl = typeof url === "string" ? url : url.toString();
// Vercel relay: forward request via relay headers
const vercelRelayUrl = normalizeString(proxyOptions?.vercelRelayUrl);
if (vercelRelayUrl) {
const parsed = new URL(targetUrl);
const relayHeaders = {
...options.headers,
"x-relay-target": `${parsed.protocol}//${parsed.host}`,
"x-relay-path": `${parsed.pathname}${parsed.search}`,
};
return originalFetch(vercelRelayUrl, { ...options, headers: relayHeaders });
}
const connectionProxyUrl = resolveConnectionProxyUrl(targetUrl, proxyOptions);
const envProxyUrl = connectionProxyUrl ? null : normalizeProxyUrl(getEnvProxyUrl(targetUrl));
const proxyUrl = connectionProxyUrl || envProxyUrl;