Spaces:
Sleeping
Sleeping
File size: 1,937 Bytes
c6dedd5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | /**
* proxy-agent.ts - 代理支持模块
*
* 职责:
* 根据 config.proxy 或 PROXY 环境变量创建 undici ProxyAgent,
* 让 Node.js 原生 fetch() 能通过 HTTP/HTTPS 代理发送请求。
*
* Node.js 内置的 fetch (基于 undici) 不会自动读取 HTTP_PROXY / HTTPS_PROXY
* 环境变量,必须显式传入 dispatcher (ProxyAgent) 才能走代理。
*/
import { ProxyAgent } from 'undici';
import { getConfig } from './config.js';
let cachedAgent: ProxyAgent | undefined;
let cachedVisionAgent: ProxyAgent | undefined;
/**
* 获取代理 dispatcher(如果配置了 proxy)
* 返回 undefined 表示不使用代理(直连)
*/
export function getProxyDispatcher(): ProxyAgent | undefined {
const config = getConfig();
const proxyUrl = config.proxy;
if (!proxyUrl) return undefined;
if (!cachedAgent) {
console.log(`[Proxy] 使用全局代理: ${proxyUrl}`);
cachedAgent = new ProxyAgent(proxyUrl);
}
return cachedAgent;
}
/**
* 构建 fetch 的额外选项(包含 dispatcher)
* 用法: fetch(url, { ...options, ...getProxyFetchOptions() })
*/
export function getProxyFetchOptions(): Record<string, unknown> {
const dispatcher = getProxyDispatcher();
return dispatcher ? { dispatcher } : {};
}
/**
* ★ Vision 独立代理:优先使用 vision.proxy,否则回退到全局 proxy
* Cursor API 国内可直连不需要代理,但图片分析 API 可能需要
*/
export function getVisionProxyFetchOptions(): Record<string, unknown> {
const config = getConfig();
const visionProxy = config.vision?.proxy;
if (visionProxy) {
if (!cachedVisionAgent) {
console.log(`[Proxy] Vision 独立代理: ${visionProxy}`);
cachedVisionAgent = new ProxyAgent(visionProxy);
}
return { dispatcher: cachedVisionAgent };
}
// 回退到全局代理
return getProxyFetchOptions();
}
|