Reapply "feat: 更新版本至2.12.3并修复多个问题"

This reverts commit ceff3771ea.
This commit is contained in:
hex2077 2026-04-05 15:23:09 +08:00
parent 02fdc39571
commit 8531343c2b
4 changed files with 131 additions and 68 deletions

View file

@ -2,70 +2,70 @@
$OutputEncoding = [System.Text.Encoding]::UTF8
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " AI Client 2 API 快速安装启动脚本" -ForegroundColor Cyan
Write-Host " AI Client 2 API Quick Setup Script" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
# 处理参数
# Handle parameters
$forcePull = $args -contains "--pull"
# 检查 Git 并拉取
# Check Git and Pull
if ($forcePull) {
Write-Host "[更新] 正在从远程仓库拉取最新代码..."
Write-Host "[UPDATE] Pulling latest code from remote repository..."
if (Get-Command git -ErrorAction SilentlyContinue) {
git pull
if ($LASTEXITCODE -ne 0) {
Write-Warning "Git pull 失败,请检查网络或手动处理冲突。"
Write-Warning "Git pull failed. Please check your network or handle conflicts manually."
} else {
Write-Host "[成功] 代码已更新。" -ForegroundColor Green
Write-Host "[SUCCESS] Code updated." -ForegroundColor Green
}
} else {
Write-Warning "未检测到 Git跳过代码拉取。"
Write-Warning "Git not detected. Skipping code pull."
}
}
# 检查 Node.js
Write-Host "[检查] 正在检查Node.js是否已安装..."
# Check Node.js
Write-Host "[CHECK] Checking if Node.js is installed..."
if (-not (Get-Command node -ErrorAction SilentlyContinue)) {
Write-Host "[错误] 未检测到Node.js请先安装Node.js (https://nodejs.org/)" -ForegroundColor Red
Write-Host "[ERROR] Node.js not detected. Please install Node.js (https://nodejs.org/)" -ForegroundColor Red
Pause
exit 1
}
$nodeVersion = node --version
Write-Host "[成功] Node.js已安装版本: $nodeVersion" -ForegroundColor Green
Write-Host "[SUCCESS] Node.js installed, version: $nodeVersion" -ForegroundColor Green
# 检查 package.json
# Check package.json
if (-not (Test-Path "package.json")) {
Write-Host "[错误] 未找到package.json文件请确保在项目根目录下运行此脚本" -ForegroundColor Red
Write-Host "[ERROR] package.json not found. Please ensure you are running this script from the project root." -ForegroundColor Red
Pause
exit 1
}
# 确定包管理器
# Determine package manager
$pkgManager = if (Get-Command pnpm -ErrorAction SilentlyContinue) { "pnpm" } else { "npm" }
Write-Host "[安装] 正在使用 $pkgManager 安装/更新依赖..." -ForegroundColor Cyan
Write-Host "[INSTALL] Installing/updating dependencies using $pkgManager..." -ForegroundColor Cyan
& $pkgManager install
if ($LASTEXITCODE -ne 0) {
Write-Host "[错误] 依赖安装失败,请检查网络连接。" -ForegroundColor Red
Write-Host "[ERROR] Dependency installation failed. Please check your network connection." -ForegroundColor Red
Pause
exit 1
}
# 检查主文件
# Check master file
if (-not (Test-Path "src\core\master.js")) {
Write-Host "[错误] 未找到 src\core\master.js 文件" -ForegroundColor Red
Write-Host "[ERROR] src\core\master.js not found." -ForegroundColor Red
Pause
exit 1
}
Write-Host ""
Write-Host "========================================" -ForegroundColor Green
Write-Host " 启动 AIClient2API 服务器..." -ForegroundColor Green
Write-Host " Starting AIClient2API Server..." -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Green
Write-Host "服务器将在 http://localhost:3000 启动"
Write-Host "按 Ctrl+C 停止服务器"
Write-Host "Server will start at http://localhost:3000"
Write-Host "Press Ctrl+C to stop the server"
Write-Host ""
node src\core\master.js

View file

@ -40,6 +40,7 @@ const ANTIGRAVITY_SYSTEM_PROMPT = `You are Antigravity, a powerful agentic AI co
// Thinking 配置相关常量
const DEFAULT_THINKING_MIN = 1024;
const DEFAULT_THINKING_MAX = 100000;
const FALLBACK_THINKING_SIGNATURE = "skip_thought_signature_validator_fallback";
// 获取 Antigravity 模型列表
const ANTIGRAVITY_MODELS = getProviderModels(MODEL_PROVIDER.ANTIGRAVITY);
@ -199,16 +200,16 @@ function normalizeAntigravityThinking(modelName, payload, isClaudeModel) {
let normalizedBudget = normalizeThinkingBudget(modelName, budget);
// 对于 Claude 模型,确保 thinking budget < max_tokens
// 确保 thinking budget < max_tokens (对所有模型生效,不仅是 Claude)
const maxTokens = payload?.request?.generationConfig?.maxOutputTokens || payload?.request?.generationConfig?.max_output_tokens;
if (maxTokens && maxTokens > 0 && normalizedBudget >= maxTokens) {
normalizedBudget = Math.max(0, maxTokens - 1);
}
// 如果是 Claude 模型,检查最小 budget
if (isClaudeModel) {
const maxTokens = payload?.request?.generationConfig?.maxOutputTokens;
if (maxTokens && maxTokens > 0 && normalizedBudget >= maxTokens) {
normalizedBudget = maxTokens - 1;
}
// 检查最小 budget
const minBudget = DEFAULT_THINKING_MIN;
if (normalizedBudget >= 0 && normalizedBudget < minBudget) {
if (normalizedBudget >= 0 && normalizedBudget < minBudget && normalizedBudget !== -1) {
// Budget 低于最小值,移除 thinking 配置
delete payload.request.generationConfig.thinkingConfig;
return payload;
@ -599,7 +600,7 @@ function toGeminiApiResponse(antigravityResponse) {
}
/**
* 确保请求体中的内容部分都有角色属性
* 确保请求体中的内容部分都有角色属性并修复历史记录中的思考签名
* @param {Object} requestBody - 请求体
* @returns {Object} 处理后的请求体
*/
@ -674,6 +675,24 @@ function ensureRolesInContents(requestBody, modelName) {
if (!content.role) {
content.role = 'user';
}
// [FIX] 修复历史记录中的思考块,确保有签名 (messages.1.content.0.thinking.signature 报错修复)
if (content.parts && Array.isArray(content.parts)) {
content.parts.forEach(part => {
if (part && part.thought === true) {
if (!part.thoughtSignature && !part.thought_signature) {
part.thoughtSignature = FALLBACK_THINKING_SIGNATURE;
}
// [FIX] 额外增加一个 'thinking' 对象以适配某些 Antigravity 内部验证逻辑
if (!part.thinking) {
part.thinking = {
signature: part.thoughtSignature || part.thought_signature || FALLBACK_THINKING_SIGNATURE
};
}
}
});
}
});
}
@ -696,25 +715,6 @@ export class AntigravityApiService {
timeout: 120000,
});
// 检查是否需要使用代理
const proxyConfig = getGoogleAuthProxyConfig(config, config.MODEL_PROVIDER || MODEL_PROVIDER.ANTIGRAVITY);
// 配置 OAuth2Client 使用自定义的 HTTP agent
const oauth2Options = {
clientId: OAUTH_CLIENT_ID,
clientSecret: OAUTH_CLIENT_SECRET,
};
if (proxyConfig) {
oauth2Options.transporterOptions = proxyConfig;
logger.info('[Antigravity] Using proxy for OAuth2Client');
} else {
oauth2Options.transporterOptions = {
agent: this.httpsAgent,
};
}
this.authClient = new OAuth2Client(oauth2Options);
this.availableModels = [];
this.isInitialized = false;
@ -730,6 +730,32 @@ export class AntigravityApiService {
// 保存代理配置供后续使用
this.proxyConfig = getProxyConfigForProvider(config, config.MODEL_PROVIDER || MODEL_PROVIDER.ANTIGRAVITY);
// 检查是否需要使用代理
const proxyConfig = getGoogleAuthProxyConfig(config, config.MODEL_PROVIDER || MODEL_PROVIDER.ANTIGRAVITY);
// 配置 OAuth2Client 使用自定义的 HTTP agent
const oauth2Options = {
clientId: OAUTH_CLIENT_ID,
clientSecret: OAUTH_CLIENT_SECRET,
};
if (proxyConfig) {
oauth2Options.transporterOptions = proxyConfig;
logger.info('[Antigravity] Using proxy for OAuth2Client');
} else {
// 根据 base URL 判断使用 http 还是 https agent
const firstBaseURL = this.baseURLs && this.baseURLs.length > 0 ? this.baseURLs[0] : '';
const useHttp = firstBaseURL.startsWith('http://');
oauth2Options.transporterOptions = {
agent: useHttp ? this.httpAgent : this.httpsAgent,
};
if (useHttp) {
logger.info('[Antigravity] Using HTTP agent for OAuth2Client');
}
}
this.authClient = new OAuth2Client(oauth2Options);
}
_applySidecar(requestOptions) {

View file

@ -287,24 +287,6 @@ export class GeminiApiService {
maxFreeSockets: 5,
timeout: 120000,
});
// 检查是否需要使用代理
const proxyConfig = getGoogleAuthProxyConfig(config, config.MODEL_PROVIDER || MODEL_PROVIDER.GEMINI_CLI);
// 配置 OAuth2Client 使用自定义的 HTTP agent
const oauth2Options = {
clientId: OAUTH_CLIENT_ID,
clientSecret: OAUTH_CLIENT_SECRET,
};
if (proxyConfig) {
oauth2Options.transporterOptions = proxyConfig;
logger.info('[Gemini] Using proxy for OAuth2Client');
} else {
oauth2Options.transporterOptions = {
agent: this.httpsAgent,
};
}
this.authClient = new OAuth2Client(oauth2Options);
this.availableModels = [];
@ -322,6 +304,29 @@ export class GeminiApiService {
// 保存代理配置供后续使用
this.proxyConfig = getProxyConfigForProvider(config, config.MODEL_PROVIDER || MODEL_PROVIDER.GEMINI_CLI);
// 检查是否需要使用代理
const proxyConfig = getGoogleAuthProxyConfig(config, config.MODEL_PROVIDER || MODEL_PROVIDER.GEMINI_CLI);
// 配置 OAuth2Client 使用自定义的 HTTP agent
const oauth2Options = {
clientId: OAUTH_CLIENT_ID,
clientSecret: OAUTH_CLIENT_SECRET,
};
if (proxyConfig) {
oauth2Options.transporterOptions = proxyConfig;
logger.info('[Gemini] Using proxy for OAuth2Client');
} else {
// 根据 base URL 判断使用 http 还是 https agent
const useHttp = this.codeAssistEndpoint && this.codeAssistEndpoint.startsWith('http://');
oauth2Options.transporterOptions = {
agent: useHttp ? this.httpAgent : this.httpsAgent,
};
if (useHttp) {
logger.info('[Gemini] Using HTTP agent for OAuth2Client');
}
}
}
async initialize() {

View file

@ -50,6 +50,38 @@ export const qwenOAuth2Events = new EventEmitter();
// --- Helper Functions ---
/**
* Qwen 默认系统提示词
*/
const QWEN_DEFAULT_SYSTEM_PROMPT = "You are a helpful assistant. You are Qwen, a large language model trained by Alibaba.";
/**
* 应用 Qwen 默认系统提示词逻辑
* @param {Object} requestBody - OpenAI 格式的请求体
* @returns {Object} 处理后的请求体
*/
function applyQwenDefaultSystemPrompt(requestBody) {
if (!requestBody || !requestBody.messages || !Array.isArray(requestBody.messages)) {
return requestBody;
}
// 检查是否已有系统提示词 (role 为 system 或 developer)
const hasSystemPrompt = requestBody.messages.some(msg =>
msg.role === 'system' || msg.role === 'developer'
);
// 如果没有系统提示词,则在消息列表最前面插入默认提示词
if (!hasSystemPrompt) {
requestBody.messages.unshift({
role: 'system',
content: QWEN_DEFAULT_SYSTEM_PROMPT
});
logger.info('[Qwen Auth] 已应用默认系统提示词');
}
return requestBody;
}
// 封装公共的 await fetch 方法
async function commonFetch(url, options = {}, useSystemProxy = false) {
const defaultOptions = {
@ -580,7 +612,7 @@ export class QwenApiService {
this.currentAxiosInstance = axios.create(axiosConfig);
// Process message content before sending the request
const processedBody = body;//this.processMessageContent(body);
const processedBody = applyQwenDefaultSystemPrompt(body);
// Check if model in body is in QWEN_MODEL_LIST, if not, use the first model's id
if (processedBody.model && !QWEN_MODEL_LIST.some(model => model.id === processedBody.model)) {