diff --git a/src/convert.js b/src/convert.js index 69bde9f..b08508d 100644 --- a/src/convert.js +++ b/src/convert.js @@ -2,10 +2,19 @@ import { v4 as uuidv4 } from 'uuid'; import { MODEL_PROTOCOL_PREFIX, getProtocolPrefix } from './common.js'; // 定义默认常量 -const DEFAULT_MAX_TOKENS = 1048576; -const DEFAULT_TEMPERATURE = 0.7; +const DEFAULT_MAX_TOKENS = 8192; +const DEFAULT_GEMINI_MAX_TOKENS = 65536; +const DEFAULT_TEMPERATURE = 1; const DEFAULT_TOP_P = 0.9; +// 辅助函数:判断值是否为 undefined 或 0,并返回默认值 +function checkAndAssignOrDefault(value, defaultValue) { + if (value !== undefined && value !== 0) { + return value; + } + return defaultValue; +} + /** * Generic data conversion function. * @param {object} data - The data to convert (request body or response). @@ -92,9 +101,9 @@ export function toOpenAIRequestFromGemini(geminiRequest) { const openaiRequest = { messages: [], model: geminiRequest.model || "gpt-3.5-turbo", // Default model if not specified in Gemini request - max_tokens: geminiRequest.max_tokens || DEFAULT_MAX_TOKENS, - temperature: geminiRequest.temperature || DEFAULT_TEMPERATURE, - top_p: geminiRequest.top_p || DEFAULT_TOP_P, + max_tokens: checkAndAssignOrDefault(geminiRequest.max_tokens, DEFAULT_MAX_TOKENS), + temperature: checkAndAssignOrDefault(geminiRequest.temperature, DEFAULT_TEMPERATURE), + top_p: checkAndAssignOrDefault(geminiRequest.top_p, DEFAULT_TOP_P), }; // Process system instruction @@ -473,9 +482,9 @@ export function toOpenAIRequestFromClaude(claudeRequest) { const openaiRequest = { model: claudeRequest.model || 'gpt-3.5-turbo', // Default OpenAI model messages: openaiMessages, - max_tokens: claudeRequest.max_tokens || DEFAULT_MAX_TOKENS, - temperature: claudeRequest.temperature || DEFAULT_TEMPERATURE, - top_p: claudeRequest.top_p || DEFAULT_TOP_P, + max_tokens: checkAndAssignOrDefault(claudeRequest.max_tokens, DEFAULT_MAX_TOKENS), + temperature: checkAndAssignOrDefault(claudeRequest.temperature, DEFAULT_TEMPERATURE), + top_p: checkAndAssignOrDefault(claudeRequest.top_p, DEFAULT_TOP_P), // stream: claudeRequest.stream, // Stream mode is handled by different endpoint }; @@ -746,9 +755,9 @@ function buildToolConfig(toolChoice) { function buildGenerationConfig({ temperature, max_tokens, top_p, stop }) { const config = {}; - config.temperature = temperature !== undefined ? temperature : DEFAULT_TEMPERATURE; - config.maxOutputTokens = max_tokens !== undefined ? max_tokens : DEFAULT_MAX_TOKENS; - config.topP = top_p !== undefined ? top_p : DEFAULT_TOP_P; + config.temperature = checkAndAssignOrDefault(temperature, DEFAULT_TEMPERATURE); + config.maxOutputTokens = checkAndAssignOrDefault(max_tokens, DEFAULT_GEMINI_MAX_TOKENS); + config.topP = checkAndAssignOrDefault(top_p, DEFAULT_TOP_P); if (stop !== undefined) config.stopSequences = Array.isArray(stop) ? stop : [stop]; return config; } @@ -848,9 +857,9 @@ export function toClaudeRequestFromOpenAI(openaiRequest) { const claudeRequest = { model: openaiRequest.model || 'claude-3-opus-20240229', messages: claudeMessages, - max_tokens: openaiRequest.max_tokens || DEFAULT_MAX_TOKENS, - temperature: openaiRequest.temperature || DEFAULT_TEMPERATURE, - top_p: openaiRequest.top_p || DEFAULT_TOP_P, + max_tokens: checkAndAssignOrDefault(openaiRequest.max_tokens, DEFAULT_MAX_TOKENS), + temperature: checkAndAssignOrDefault(openaiRequest.temperature, DEFAULT_TEMPERATURE), + top_p: checkAndAssignOrDefault(openaiRequest.top_p, DEFAULT_TOP_P), }; if (systemInstruction) { @@ -1055,21 +1064,9 @@ export function toGeminiRequestFromClaude(claudeRequest) { // Add generation config const generationConfig = {}; - if (claudeRequest.max_tokens !== undefined) { - generationConfig.maxOutputTokens = Number(claudeRequest.max_tokens); - } else { - generationConfig.maxOutputTokens = DEFAULT_MAX_TOKENS; - } - if (claudeRequest.temperature !== undefined) { - generationConfig.temperature = Number(claudeRequest.temperature); - } else { - generationConfig.temperature = DEFAULT_TEMPERATURE; - } - if (claudeRequest.top_p !== undefined) { - generationConfig.topP = Number(claudeRequest.top_p); - } else { - generationConfig.topP = DEFAULT_TOP_P; - } + generationConfig.maxOutputTokens = checkAndAssignOrDefault(claudeRequest.max_tokens, DEFAULT_GEMINI_MAX_TOKENS); + generationConfig.temperature = checkAndAssignOrDefault(claudeRequest.temperature, DEFAULT_TEMPERATURE); + generationConfig.topP = checkAndAssignOrDefault(claudeRequest.top_p, DEFAULT_TOP_P); if (Object.keys(generationConfig).length > 0) { geminiRequest.generationConfig = generationConfig; diff --git a/tests/api-integration.test.js b/tests/api-integration.test.js index 4bbb54d..c06414e 100644 --- a/tests/api-integration.test.js +++ b/tests/api-integration.test.js @@ -78,7 +78,7 @@ const REAL_TEST_DATA = { }; // To run all integration tests: -// npx jest GeminiCli2API/tests/api-integration.test.js +// npx jest ./tests/api-integration.test.js describe('API Integration Tests with HTTP Requests', () => { beforeAll(async () => { // Test server connectivity @@ -97,10 +97,10 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run all OpenAI Compatible Endpoints tests: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "OpenAI Compatible Endpoints" + // npx jest ./tests/api-integration.test.js -t "OpenAI Compatible Endpoints" describe('OpenAI Compatible Endpoints', () => { // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "OpenAI /v1/chat/completions non-streaming Gemini" + // npx jest ./tests/api-integration.test.js -t "OpenAI /v1/chat/completions non-streaming Gemini" test('OpenAI /v1/chat/completions non-streaming Gemini', async () => { const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1/chat/completions`, @@ -122,7 +122,7 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "OpenAI /v1/chat/completions streaming Gemini" + // npx jest ./tests/api-integration.test.js -t "OpenAI /v1/chat/completions streaming Gemini" test('OpenAI /v1/chat/completions streaming Gemini', async () => { const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1/chat/completions`, @@ -160,9 +160,9 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "OpenAI /v1/chat/completions non-streaming with OpenAI provider" + // npx jest ./tests/api-integration.test.js -t "OpenAI /v1/chat/completions non-streaming with OpenAI provider" test('OpenAI /v1/chat/completions non-streaming with OpenAI provider', async () => { - REAL_TEST_DATA.openai.nonStreamRequest.model = "deepseek-chat"; + REAL_TEST_DATA.openai.nonStreamRequest.model = "deepseek-ai/DeepSeek-V3"; const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1/chat/completions`, 'POST', @@ -183,9 +183,9 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "OpenAI /v1/chat/completions streaming with OpenAI provider" + // npx jest ./tests/api-integration.test.js -t "OpenAI /v1/chat/completions streaming with OpenAI provider" test('OpenAI /v1/chat/completions streaming with OpenAI provider', async () => { - REAL_TEST_DATA.openai.streamRequest.model = "deepseek-chat"; + REAL_TEST_DATA.openai.streamRequest.model = "deepseek-ai/DeepSeek-V3"; const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1/chat/completions`, 'POST', @@ -222,7 +222,7 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "OpenAI /v1/chat/completions non-streaming with Claude provider" + // npx jest ./tests/api-integration.test.js -t "OpenAI /v1/chat/completions non-streaming with Claude provider" test('OpenAI /v1/chat/completions non-streaming with Claude provider', async () => { REAL_TEST_DATA.openai.nonStreamRequest.model = "claude-4-sonnet"; const response = await makeRequest( @@ -245,7 +245,7 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "OpenAI /v1/chat/completions streaming with Claude provider" + // npx jest ./tests/api-integration.test.js -t "OpenAI /v1/chat/completions streaming with Claude provider" test('OpenAI /v1/chat/completions streaming with Claude provider', async () => { REAL_TEST_DATA.openai.nonStreamRequest.model = "claude-4-sonnet"; const response = await makeRequest( @@ -285,10 +285,10 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run all Claude Native Endpoints tests: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Claude Native Endpoints" + // npx jest ./tests/api-integration.test.js -t "Claude Native Endpoints" describe('Claude Native Endpoints', () => { // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Claude /v1/messages non-streaming" + // npx jest ./tests/api-integration.test.js -t "Claude /v1/messages non-streaming" test('Claude /v1/messages non-streaming', async () => { const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1/messages`, @@ -309,7 +309,7 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Claude /v1/messages streaming" + // npx jest ./tests/api-integration.test.js -t "Claude /v1/messages streaming" test('Claude /v1/messages streaming', async () => { const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1/messages`, @@ -348,10 +348,10 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run all Claude Kiro Endpoints tests: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Claude Kiro Endpoints" + // npx jest ./tests/api-integration.test.js -t "Claude Kiro Endpoints" describe('Claude Kiro Endpoints', () => { // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Claude Kiro /v1/messages non-streaming" + // npx jest ./tests/api-integration.test.js -t "Claude Kiro /v1/messages non-streaming" test('Claude Kiro /v1/messages non-streaming', async () => { REAL_TEST_DATA.claude.nonStreamRequest.model = "claude-4-sonnet"; const response = await makeRequest( @@ -373,7 +373,7 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Claude Kiro /v1/messages streaming" + // npx jest ./tests/api-integration.test.js -t "Claude Kiro /v1/messages streaming" test('Claude Kiro /v1/messages streaming', async () => { REAL_TEST_DATA.claude.streamRequest.model = "claude-4-sonnet"; const response = await makeRequest( @@ -414,10 +414,10 @@ describe('API Integration Tests with HTTP Requests', () => { // To run all Gemini Native Endpoints tests: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Gemini Native Endpoints" + // npx jest ./tests/api-integration.test.js -t "Gemini Native Endpoints" describe('Gemini Native Endpoints', () => { // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Gemini /v1beta/models/{model}:generateContent" + // npx jest ./tests/api-integration.test.js -t "Gemini /v1beta/models/{model}:generateContent" test('Gemini /v1beta/models/{model}:generateContent', async () => { const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1beta/models/gemini-2.5-flash:generateContent`, @@ -436,7 +436,7 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Gemini /v1beta/models/{model}:streamGenerateContent" + // npx jest ./tests/api-integration.test.js -t "Gemini /v1beta/models/{model}:streamGenerateContent" test('Gemini /v1beta/models/{model}:streamGenerateContent', async () => { const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1beta/models/gemini-2.5-flash:streamGenerateContent`, @@ -475,10 +475,10 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run all Model List Endpoints tests: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Model List Endpoints" + // npx jest ./tests/api-integration.test.js -t "Model List Endpoints" describe('Model List Endpoints', () => { // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "OpenAI /v1/models Gemini" + // npx jest ./tests/api-integration.test.js -t "OpenAI /v1/models Gemini" test('OpenAI /v1/models Gemini', async () => { const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1/models`, @@ -495,7 +495,7 @@ describe('API Integration Tests with HTTP Requests', () => { expect(Array.isArray(responseData.data)).toBe(true); }); - // npx jest GeminiCli2API/tests/api-integration.test.js -t "OpenAI /v1/models OpenAI" + // npx jest ./tests/api-integration.test.js -t "OpenAI /v1/models OpenAI" test('OpenAI /v1/models OpenAI', async () => { const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1/models`, @@ -512,7 +512,7 @@ describe('API Integration Tests with HTTP Requests', () => { expect(Array.isArray(responseData.data)).toBe(true); }); - // npx jest GeminiCli2API/tests/api-integration.test.js -t "OpenAI /v1/models Claude" + // npx jest ./tests/api-integration.test.js -t "OpenAI /v1/models Claude" test('OpenAI /v1/models Claude', async () => { const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1/models`, @@ -530,7 +530,7 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Gemini /v1beta/models modelList" + // npx jest ./tests/api-integration.test.js -t "Gemini /v1beta/models modelList" test('Gemini /v1beta/models modelList', async () => { const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1beta/models`, @@ -549,10 +549,10 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run all Authentication Tests: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Authentication Tests API KEY" + // npx jest ./tests/api-integration.test.js -t "Authentication Tests API KEY" describe('Authentication Tests API KEY', () => { // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Reject requests without API key" + // npx jest ./tests/api-integration.test.js -t "Reject requests without API key" test('Reject requests without API key', async () => { const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1/chat/completions`, @@ -571,7 +571,7 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Accept query parameter authentication" + // npx jest ./tests/api-integration.test.js -t "Accept query parameter authentication" test('Accept query parameter authentication', async () => { const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1/models`, @@ -584,7 +584,7 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Accept Bearer token authentication" + // npx jest ./tests/api-integration.test.js -t "Accept Bearer token authentication" test('Accept Bearer token authentication', async () => { const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1/models`, @@ -597,7 +597,7 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Accept x-goog-api-key authentication" + // npx jest ./tests/api-integration.test.js -t "Accept x-goog-api-key authentication" test('Accept x-goog-api-key authentication', async () => { const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1/models`, @@ -610,7 +610,7 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Accept x-api-key authentication for Claude" + // npx jest ./tests/api-integration.test.js -t "Accept x-api-key authentication for Claude" test('Accept x-api-key authentication for Claude', async () => { const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1/models`, @@ -624,10 +624,10 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run all Error Handling Tests: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Error Handling Tests" + // npx jest ./tests/api-integration.test.js -t "Error Handling Tests" describe('Error Handling Tests', () => { // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Handle invalid JSON in request body" + // npx jest ./tests/api-integration.test.js -t "Handle invalid JSON in request body" test('Handle invalid JSON in request body', async () => { const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1/chat/completions`, @@ -645,7 +645,7 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "Handle unsupported endpoints" + // npx jest ./tests/api-integration.test.js -t "Handle unsupported endpoints" test('Handle unsupported endpoints', async () => { const response = await makeRequest( `${TEST_SERVER_BASE_URL}/unsupported/endpoint`, @@ -665,10 +665,10 @@ describe('API Integration Tests with HTTP Requests', () => { }); // To run all CORS Headers Test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "CORS Headers Test" + // npx jest ./tests/api-integration.test.js -t "CORS Headers Test" describe('CORS Headers Test', () => { // To run this test: - // npx jest GeminiCli2API/tests/api-integration.test.js -t "CORS headers support" + // npx jest ./tests/api-integration.test.js -t "CORS headers support" test('CORS headers support', async () => { const response = await makeRequest( `${TEST_SERVER_BASE_URL}/v1/models`,