AIClient-2-API/src/proxy-utils.js
Yoahoug 10146e3cf0 fix: Kiro长上下文400错误修复 & 添加自定义代理支持
## Kiro 长上下文修复
- 添加请求体大小限制(默认240KB),避免超过Kiro API限制导致400错误
- 添加 cleanIncompleteToolCalls 方法,清理不完整的工具调用
- 确保截断后第一条消息是user类型
- 新增配置项 KIRO_MAX_REQUEST_SIZE_KB

## 自定义代理支持
- 为各Provider添加独立的代理配置选项
- 支持 USE_SYSTEM_PROXY_* 配置
- UI界面添加代理配置入口
- 新增 proxy-utils.js 代理工具模块
2026-01-02 23:32:10 +08:00

128 lines
3.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 代理工具模块
* 支持 HTTP、HTTPS 和 SOCKS5 代理
*/
import { HttpsProxyAgent } from 'https-proxy-agent';
import { HttpProxyAgent } from 'http-proxy-agent';
import { SocksProxyAgent } from 'socks-proxy-agent';
/**
* 解析代理URL并返回相应的代理配置
* @param {string} proxyUrl - 代理URL如 http://127.0.0.1:7890 或 socks5://127.0.0.1:1080
* @returns {Object|null} 代理配置对象,包含 httpAgent 和 httpsAgent
*/
export function parseProxyUrl(proxyUrl) {
if (!proxyUrl || typeof proxyUrl !== 'string') {
return null;
}
const trimmedUrl = proxyUrl.trim();
if (!trimmedUrl) {
return null;
}
try {
const url = new URL(trimmedUrl);
const protocol = url.protocol.toLowerCase();
if (protocol === 'socks5:' || protocol === 'socks4:' || protocol === 'socks:') {
// SOCKS 代理
const socksAgent = new SocksProxyAgent(trimmedUrl);
return {
httpAgent: socksAgent,
httpsAgent: socksAgent,
proxyType: 'socks'
};
} else if (protocol === 'http:' || protocol === 'https:') {
// HTTP/HTTPS 代理
return {
httpAgent: new HttpProxyAgent(trimmedUrl),
httpsAgent: new HttpsProxyAgent(trimmedUrl),
proxyType: 'http'
};
} else {
console.warn(`[Proxy] Unsupported proxy protocol: ${protocol}`);
return null;
}
} catch (error) {
console.error(`[Proxy] Failed to parse proxy URL: ${error.message}`);
return null;
}
}
/**
* 检查指定的提供商是否启用了代理
* @param {Object} config - 配置对象
* @param {string} providerType - 提供商类型
* @returns {boolean} 是否启用代理
*/
export function isProxyEnabledForProvider(config, providerType) {
if (!config || !config.PROXY_URL || !config.PROXY_ENABLED_PROVIDERS) {
return false;
}
const enabledProviders = config.PROXY_ENABLED_PROVIDERS;
if (!Array.isArray(enabledProviders)) {
return false;
}
return enabledProviders.includes(providerType);
}
/**
* 获取指定提供商的代理配置
* @param {Object} config - 配置对象
* @param {string} providerType - 提供商类型
* @returns {Object|null} 代理配置对象或 null
*/
export function getProxyConfigForProvider(config, providerType) {
if (!isProxyEnabledForProvider(config, providerType)) {
return null;
}
const proxyConfig = parseProxyUrl(config.PROXY_URL);
if (proxyConfig) {
console.log(`[Proxy] Using ${proxyConfig.proxyType} proxy for ${providerType}: ${config.PROXY_URL}`);
}
return proxyConfig;
}
/**
* 为 axios 配置代理
* @param {Object} axiosConfig - axios 配置对象
* @param {Object} config - 应用配置对象
* @param {string} providerType - 提供商类型
* @returns {Object} 更新后的 axios 配置
*/
export function configureAxiosProxy(axiosConfig, config, providerType) {
const proxyConfig = getProxyConfigForProvider(config, providerType);
if (proxyConfig) {
// 使用代理 agent
axiosConfig.httpAgent = proxyConfig.httpAgent;
axiosConfig.httpsAgent = proxyConfig.httpsAgent;
// 禁用 axios 内置的代理配置,使用我们的 agent
axiosConfig.proxy = false;
}
return axiosConfig;
}
/**
* 为 google-auth-library 配置代理
* @param {Object} config - 应用配置对象
* @param {string} providerType - 提供商类型
* @returns {Object|null} transporter 配置对象或 null
*/
export function getGoogleAuthProxyConfig(config, providerType) {
const proxyConfig = getProxyConfigForProvider(config, providerType);
if (proxyConfig) {
return {
agent: proxyConfig.httpsAgent
};
}
return null;
}