From 9b7dcf3a6cf553f893570d6b0ab29d0dbda1595d Mon Sep 17 00:00:00 2001 From: Badri Narayanan S Date: Sat, 27 Dec 2025 12:17:45 +0530 Subject: [PATCH] removing restcting of available models, fixing max tokens issues in test --- src/cloudcode-client.js | 39 ++++++++++------- src/constants.js | 42 ------------------- src/format-converter.js | 19 --------- src/server.js | 30 +++++++++++-- tests/test-caching-streaming.cjs | 4 +- tests/test-images.cjs | 4 +- tests/test-interleaved-thinking.cjs | 4 +- ...est-multiturn-thinking-tools-streaming.cjs | 4 +- tests/test-multiturn-thinking-tools.cjs | 6 +-- tests/test-thinking-signatures.cjs | 4 +- 10 files changed, 63 insertions(+), 93 deletions(-) diff --git a/src/cloudcode-client.js b/src/cloudcode-client.js index d00f840..98f5e5b 100644 --- a/src/cloudcode-client.js +++ b/src/cloudcode-client.js @@ -13,13 +13,11 @@ import crypto from 'crypto'; import { ANTIGRAVITY_ENDPOINT_FALLBACKS, ANTIGRAVITY_HEADERS, - AVAILABLE_MODELS, MAX_RETRIES, MAX_WAIT_BEFORE_ERROR_MS, MIN_SIGNATURE_LENGTH } from './constants.js'; import { - mapModelName, convertAnthropicToGoogle, convertGoogleToAnthropic } from './format-converter.js'; @@ -219,7 +217,7 @@ function parseResetTime(responseOrError, errorText = '') { * Build the wrapped request body for Cloud Code API */ function buildCloudCodeRequest(anthropicRequest, projectId) { - const model = mapModelName(anthropicRequest.model); + const model = anthropicRequest.model; const googleRequest = convertAnthropicToGoogle(anthropicRequest); // Use stable session ID derived from first user message for cache continuity @@ -247,7 +245,7 @@ function buildHeaders(token, model, accept = 'application/json') { }; // Add interleaved thinking header for Claude thinking models - const isThinkingModel = model.toLowerCase().includes('thinking'); + const isThinkingModel = model.toLowerCase().includes('claude') && model.toLowerCase().includes('thinking'); if (isThinkingModel) { headers['anthropic-beta'] = 'interleaved-thinking-2025-05-14'; } @@ -273,8 +271,8 @@ function buildHeaders(token, model, accept = 'application/json') { * @throws {Error} If max retries exceeded or no accounts available */ export async function sendMessage(anthropicRequest, accountManager) { - const model = mapModelName(anthropicRequest.model); - const isThinkingModel = model.toLowerCase().includes('thinking'); + const model = anthropicRequest.model; + const isThinkingModel = model.toLowerCase().includes('claude') && model.toLowerCase().includes('thinking'); // Retry loop with account failover // Ensure we try at least as many times as there are accounts to cycle through everyone @@ -537,7 +535,7 @@ async function parseThinkingSSEResponse(response, originalModel) { * @throws {Error} If max retries exceeded or no accounts available */ export async function* sendMessageStream(anthropicRequest, accountManager) { - const model = mapModelName(anthropicRequest.model); + const model = anthropicRequest.model; // Retry loop with account failover // Ensure we try at least as many times as there are accounts to cycle through everyone @@ -931,19 +929,28 @@ async function* streamSSEResponse(response, originalModel) { /** * List available models in Anthropic API format + * Fetches models dynamically from the Cloud Code API * - * @returns {{object: string, data: Array<{id: string, object: string, created: number, owned_by: string, description: string}>}} List of available models + * @param {string} token - OAuth access token + * @returns {Promise<{object: string, data: Array<{id: string, object: string, created: number, owned_by: string, description: string}>}>} List of available models */ -export function listModels() { +export async function listModels(token) { + const data = await fetchAvailableModels(token); + if (!data || !data.models) { + return { object: 'list', data: [] }; + } + + const modelList = Object.entries(data.models).map(([modelId, modelData]) => ({ + id: modelId, + object: 'model', + created: Math.floor(Date.now() / 1000), + owned_by: 'anthropic', + description: modelData.displayName || modelId + })); + return { object: 'list', - data: AVAILABLE_MODELS.map(m => ({ - id: m.id, - object: 'model', - created: Math.floor(Date.now() / 1000), - owned_by: 'anthropic', - description: m.description - })) + data: modelList }; } diff --git a/src/constants.js b/src/constants.js index 885cd17..1358ea3 100644 --- a/src/constants.js +++ b/src/constants.js @@ -56,44 +56,6 @@ export const ANTIGRAVITY_HEADERS = { }) }; -// Model name mappings: Anthropic format → Antigravity format -export const MODEL_MAPPINGS = { - // Claude models - 'claude-3-opus-20240229': 'claude-opus-4-5-thinking', - 'claude-3-5-opus-20240229': 'claude-opus-4-5-thinking', - 'claude-3-5-sonnet-20241022': 'claude-sonnet-4-5', - 'claude-3-5-sonnet-20240620': 'claude-sonnet-4-5', - 'claude-3-sonnet-20240229': 'claude-sonnet-4-5', - 'claude-sonnet-4-5': 'claude-sonnet-4-5', - 'claude-sonnet-4-5-thinking': 'claude-sonnet-4-5-thinking', - 'claude-opus-4-5-thinking': 'claude-opus-4-5-thinking' -}; - -// Available models exposed by this proxy -export const AVAILABLE_MODELS = [ - { - id: 'claude-sonnet-4-5', - name: 'Claude Sonnet 4.5 (Antigravity)', - description: 'Claude Sonnet 4.5 via Antigravity Cloud Code', - context: 200000, - output: 64000 - }, - { - id: 'claude-sonnet-4-5-thinking', - name: 'Claude Sonnet 4.5 Thinking (Antigravity)', - description: 'Claude Sonnet 4.5 with extended thinking via Antigravity', - context: 200000, - output: 64000 - }, - { - id: 'claude-opus-4-5-thinking', - name: 'Claude Opus 4.5 Thinking (Antigravity)', - description: 'Claude Opus 4.5 with extended thinking via Antigravity', - context: 200000, - output: 64000 - } -]; - // Default project ID if none can be discovered export const DEFAULT_PROJECT_ID = 'rising-fact-p41fc'; @@ -120,7 +82,6 @@ export const MAX_ACCOUNTS = 10; // Maximum number of accounts allowed export const MAX_WAIT_BEFORE_ERROR_MS = 120000; // 2 minutes - throw error if wait exceeds this // Thinking model constants -export const CLAUDE_THINKING_MAX_OUTPUT_TOKENS = 64000; // Max output tokens for thinking models export const MIN_SIGNATURE_LENGTH = 50; // Minimum valid thinking signature length // Google OAuth configuration (from opencode-antigravity-auth) @@ -144,8 +105,6 @@ export const OAUTH_REDIRECT_URI = `http://localhost:${OAUTH_CONFIG.callbackPort} export default { ANTIGRAVITY_ENDPOINT_FALLBACKS, ANTIGRAVITY_HEADERS, - MODEL_MAPPINGS, - AVAILABLE_MODELS, DEFAULT_PROJECT_ID, TOKEN_REFRESH_INTERVAL_MS, REQUEST_BODY_LIMIT, @@ -157,7 +116,6 @@ export default { MAX_RETRIES, MAX_ACCOUNTS, MAX_WAIT_BEFORE_ERROR_MS, - CLAUDE_THINKING_MAX_OUTPUT_TOKENS, MIN_SIGNATURE_LENGTH, OAUTH_CONFIG, OAUTH_REDIRECT_URI diff --git a/src/format-converter.js b/src/format-converter.js index 093edfa..2f274ab 100644 --- a/src/format-converter.js +++ b/src/format-converter.js @@ -9,20 +9,9 @@ import crypto from 'crypto'; import { - MODEL_MAPPINGS, - CLAUDE_THINKING_MAX_OUTPUT_TOKENS, MIN_SIGNATURE_LENGTH } from './constants.js'; -/** - * Map Anthropic model name to Antigravity model name - * @param {string} anthropicModel - Anthropic format model name (e.g., 'claude-3-5-sonnet-20241022') - * @returns {string} Antigravity format model name (e.g., 'claude-sonnet-4-5') - */ -export function mapModelName(anthropicModel) { - return MODEL_MAPPINGS[anthropicModel] || anthropicModel; -} - /** * Check if a part is a thinking block * @param {Object} part - Content part to check @@ -509,13 +498,6 @@ export function convertAnthropicToGoogle(anthropicRequest) { const thinkingBudget = thinking?.budget_tokens; if (thinkingBudget) { thinkingConfig.thinking_budget = thinkingBudget; - - // Ensure maxOutputTokens is large enough when budget is specified - if (!googleRequest.generationConfig.maxOutputTokens || - googleRequest.generationConfig.maxOutputTokens <= thinkingBudget) { - googleRequest.generationConfig.maxOutputTokens = CLAUDE_THINKING_MAX_OUTPUT_TOKENS; - } - console.log('[FormatConverter] Thinking enabled with budget:', thinkingBudget); } else { console.log('[FormatConverter] Thinking enabled (no budget specified)'); @@ -725,7 +707,6 @@ export function convertGoogleToAnthropic(googleResponse, model) { } export default { - mapModelName, convertAnthropicToGoogle, convertGoogleToAnthropic }; diff --git a/src/server.js b/src/server.js index 5484482..8fe7669 100644 --- a/src/server.js +++ b/src/server.js @@ -193,7 +193,7 @@ app.get('/account-limits', async (req, res) => { } } - const sortedModels = Array.from(allModelIds).filter(m => m.includes('claude')).sort(); + const sortedModels = Array.from(allModelIds).sort(); // Return ASCII table format if (format === 'table') { @@ -352,8 +352,32 @@ app.post('/refresh-token', async (req, res) => { /** * List models endpoint (OpenAI-compatible format) */ -app.get('/v1/models', (req, res) => { - res.json(listModels()); +app.get('/v1/models', async (req, res) => { + try { + await ensureInitialized(); + const account = accountManager.pickNext(); + if (!account) { + return res.status(503).json({ + type: 'error', + error: { + type: 'api_error', + message: 'No accounts available' + } + }); + } + const token = await accountManager.getTokenForAccount(account); + const models = await listModels(token); + res.json(models); + } catch (error) { + console.error('[API] Error listing models:', error); + res.status(500).json({ + type: 'error', + error: { + type: 'api_error', + message: error.message + } + }); + } }); /** diff --git a/tests/test-caching-streaming.cjs b/tests/test-caching-streaming.cjs index d9716ae..a0ba865 100644 --- a/tests/test-caching-streaming.cjs +++ b/tests/test-caching-streaming.cjs @@ -36,7 +36,7 @@ async function runTests() { const turn1 = await streamRequest({ model: 'claude-sonnet-4-5-thinking', - max_tokens: 2048, + max_tokens: 16000, stream: true, system: LARGE_SYSTEM_PROMPT, thinking: { type: 'enabled', budget_tokens: 5000 }, @@ -90,7 +90,7 @@ async function runTests() { const turn2 = await streamRequest({ model: 'claude-sonnet-4-5-thinking', - max_tokens: 2048, + max_tokens: 16000, stream: true, system: LARGE_SYSTEM_PROMPT, thinking: { type: 'enabled', budget_tokens: 5000 }, diff --git a/tests/test-images.cjs b/tests/test-images.cjs index 8dcb6d2..10740b9 100644 --- a/tests/test-images.cjs +++ b/tests/test-images.cjs @@ -28,7 +28,7 @@ async function runTests() { const result1 = await streamRequest({ model: 'claude-sonnet-4-5-thinking', - max_tokens: 2048, + max_tokens: 16000, stream: true, thinking: { type: 'enabled', budget_tokens: 8000 }, messages: [{ @@ -79,7 +79,7 @@ async function runTests() { const result2 = await streamRequest({ model: 'claude-sonnet-4-5-thinking', - max_tokens: 2048, + max_tokens: 16000, stream: true, thinking: { type: 'enabled', budget_tokens: 8000 }, messages: [ diff --git a/tests/test-interleaved-thinking.cjs b/tests/test-interleaved-thinking.cjs index 66cf92a..5216c7a 100644 --- a/tests/test-interleaved-thinking.cjs +++ b/tests/test-interleaved-thinking.cjs @@ -30,7 +30,7 @@ async function runTests() { const result = await streamRequest({ model: 'claude-opus-4-5-thinking', - max_tokens: 8192, + max_tokens: 32000, stream: true, tools, thinking: { type: 'enabled', budget_tokens: 16000 }, @@ -93,7 +93,7 @@ Please do this step by step, reading each file before modifying.` const result2 = await streamRequest({ model: 'claude-opus-4-5-thinking', - max_tokens: 8192, + max_tokens: 32000, stream: true, tools, thinking: { type: 'enabled', budget_tokens: 16000 }, diff --git a/tests/test-multiturn-thinking-tools-streaming.cjs b/tests/test-multiturn-thinking-tools-streaming.cjs index 61a7249..2aa53d0 100644 --- a/tests/test-multiturn-thinking-tools-streaming.cjs +++ b/tests/test-multiturn-thinking-tools-streaming.cjs @@ -33,7 +33,7 @@ async function runTests() { const turn1 = await streamRequest({ model: 'claude-sonnet-4-5-thinking', - max_tokens: 4096, + max_tokens: 16000, stream: true, tools, thinking: { type: 'enabled', budget_tokens: 10000 }, @@ -102,7 +102,7 @@ drwxr-xr-x 4 user staff 128 Dec 19 10:00 tests` const turn2 = await streamRequest({ model: 'claude-sonnet-4-5-thinking', - max_tokens: 4096, + max_tokens: 16000, stream: true, tools, thinking: { type: 'enabled', budget_tokens: 10000 }, diff --git a/tests/test-multiturn-thinking-tools.cjs b/tests/test-multiturn-thinking-tools.cjs index a2880be..e479d91 100644 --- a/tests/test-multiturn-thinking-tools.cjs +++ b/tests/test-multiturn-thinking-tools.cjs @@ -38,7 +38,7 @@ async function runTests() { const turn1 = await makeRequest({ model: 'claude-sonnet-4-5-thinking', - max_tokens: 4096, + max_tokens: 16000, stream: false, tools, thinking: { type: 'enabled', budget_tokens: 10000 }, @@ -92,7 +92,7 @@ async function runTests() { const turn2 = await makeRequest({ model: 'claude-sonnet-4-5-thinking', - max_tokens: 4096, + max_tokens: 16000, stream: false, tools, thinking: { type: 'enabled', budget_tokens: 10000 }, @@ -156,7 +156,7 @@ async function runTests() { const turn3 = await makeRequest({ model: 'claude-sonnet-4-5-thinking', - max_tokens: 4096, + max_tokens: 16000, stream: false, tools, thinking: { type: 'enabled', budget_tokens: 10000 }, diff --git a/tests/test-thinking-signatures.cjs b/tests/test-thinking-signatures.cjs index 1adc27d..fb1fcb1 100644 --- a/tests/test-thinking-signatures.cjs +++ b/tests/test-thinking-signatures.cjs @@ -31,7 +31,7 @@ async function runTests() { const turn1Result = await streamRequest({ model: 'claude-sonnet-4-5-thinking', - max_tokens: 4096, + max_tokens: 16000, stream: true, tools, thinking: { type: 'enabled', budget_tokens: 10000 }, @@ -95,7 +95,7 @@ async function runTests() { const turn2Result = await streamRequest({ model: 'claude-sonnet-4-5-thinking', - max_tokens: 4096, + max_tokens: 16000, stream: true, tools, thinking: { type: 'enabled', budget_tokens: 10000 },