/** * AINative Cody SDK Extensions * * Adds dual-provider model routing to the Anthropic SDK. * - AINative models (qwen, gemma, deepseek, nouscoder) → api.ainative.studio * - Claude models (sonnet, haiku, opus) → api.anthropic.com (direct) * * Usage tracking is handled by the existing AIUsageTrackingMiddleware * on the backend — no client-side tracking needed. */ const AINATIVE_MODELS = [ 'qwen-coder-32b', 'qwen-coder-7b', 'nouscoder-14b', 'gemma-2b', 'gemma-9b', 'deepseek-r1-distill-qwen-7b', 'deepseek-r1-distill-llama-8b', 'qwen-7b', ]; const AINATIVE_API_URL = 'https://api.ainative.studio'; const ANTHROPIC_API_URL = 'https://api.anthropic.com'; /** * Determine if a model is an AINative-hosted model */ export function isAINativeModel(model: string): boolean { const lower = model.toLowerCase(); return AINATIVE_MODELS.some((m) => lower.includes(m)); } /** * Determine if a model is a Claude model (routes to Anthropic API) */ export function isClaudeModel(model: string): boolean { const lower = model.toLowerCase(); return ( lower.includes('claude') || lower.includes('sonnet') || lower.includes('haiku') || lower.includes('opus') ); } /** * Get the correct base URL for a given model */ export function getBaseURLForModel(model: string, configuredBaseURL?: string): string { if (configuredBaseURL && configuredBaseURL.includes('ainative.studio') && isClaudeModel(model)) { return ANTHROPIC_API_URL; } return configuredBaseURL || ANTHROPIC_API_URL; } /** * Get the correct API key for a given model */ export function getApiKeyForModel(model: string): string | null { if (isAINativeModel(model)) { return ( (typeof process !== 'undefined' && process.env?.['AINATIVE_API_KEY']) || (typeof process !== 'undefined' && process.env?.['ANTHROPIC_API_KEY']) || null ); } return ( (typeof process !== 'undefined' && process.env?.['ANTHROPIC_API_KEY']) || (typeof process !== 'undefined' && process.env?.['AINATIVE_API_KEY']) || null ); } /** * Wrap fetch to log request metadata (model, provider) for debugging. * Actual usage tracking is handled server-side by AIUsageTrackingMiddleware. */ export function createTrackedFetch( innerFetch: (input: any, init?: any) => Promise, ): (input: any, init?: any) => Promise { return async (input: any, init?: any): Promise => { return innerFetch(input, init); }; }