removing restcting of available models, fixing max tokens issues in test

This commit is contained in:
Badri Narayanan S
2025-12-27 12:17:45 +05:30
parent f86c4f4d32
commit 9b7dcf3a6c
10 changed files with 63 additions and 93 deletions

View File

@@ -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
};
}

View File

@@ -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

View File

@@ -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
};

View File

@@ -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
}
});
}
});
/**

View File

@@ -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 },

View File

@@ -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: [

View File

@@ -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 },

View File

@@ -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 },

View File

@@ -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 },

View File

@@ -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 },