#!/usr/bin/env npx tsx /** * Quick Provider Test Script * * Tests all available providers using .env credentials * * Usage: * cd v3/@claude-flow/providers * npm run test:quick * * Or directly: * npx tsx src/__tests__/quick-test.ts */ import { config } from 'dotenv'; import { resolve, dirname } from 'path'; import { fileURLToPath } from 'url'; const __dirname = dirname(fileURLToPath(import.meta.url)); // Load .env from project root config({ path: resolve(__dirname, '../../../../../.env') }); import { AnthropicProvider, OpenAIProvider, GoogleProvider, OllamaProvider, RuVectorProvider, createProviderManager, LLMRequest, } from '../index.js'; import { consoleLogger } from '../base-provider.js'; const TEST_PROMPT = 'Say "Hello from Claude Flow V3!" Be brief.'; const createTestRequest = (model?: string): LLMRequest => ({ messages: [{ role: 'user', content: TEST_PROMPT }], model, maxTokens: 50, temperature: 0.1, requestId: `test-${Date.now()}`, }); async function testAnthropic() { const apiKey = process.env.ANTHROPIC_API_KEY; if (!apiKey) { console.log('ā­ļø Skipping Anthropic - no API key'); return null; } console.log('\nšŸ”· Testing Anthropic Claude...'); const provider = new AnthropicProvider({ config: { provider: 'anthropic', apiKey, model: 'claude-3-haiku-20240307', // Use cheaper, widely-available model maxTokens: 100, }, logger: consoleLogger, }); try { await provider.initialize(); const response = await provider.complete(createTestRequest()); console.log('āœ… Anthropic Response:', response.content); console.log(' Tokens:', response.usage); console.log(' Cost:', response.cost); provider.destroy(); return response; } catch (error) { console.error('āŒ Anthropic Error:', error); provider.destroy(); return null; } } async function testGoogle() { const apiKey = process.env.GOOGLE_GEMINI_API_KEY; if (!apiKey) { console.log('ā­ļø Skipping Google - no API key'); return null; } console.log('\nšŸ”· Testing Google Gemini...'); const provider = new GoogleProvider({ config: { provider: 'google', apiKey, model: 'gemini-2.0-flash', maxTokens: 100, }, logger: consoleLogger, }); try { await provider.initialize(); const response = await provider.complete(createTestRequest()); console.log('āœ… Google Response:', response.content); console.log(' Tokens:', response.usage); console.log(' Cost:', response.cost); provider.destroy(); return response; } catch (error) { console.error('āŒ Google Error:', error); provider.destroy(); return null; } } async function testOpenRouter() { const apiKey = process.env.OPENROUTER_API_KEY; if (!apiKey) { console.log('ā­ļø Skipping OpenRouter - no API key'); return null; } console.log('\nšŸ”· Testing OpenRouter (GPT-4o-mini)...'); const provider = new OpenAIProvider({ config: { provider: 'openai', apiKey, apiUrl: 'https://openrouter.ai/api/v1', model: 'openai/gpt-4o-mini', maxTokens: 100, providerOptions: { headers: { 'HTTP-Referer': 'https://claude-flow.dev', 'X-Title': 'Claude Flow V3 Test', }, }, }, logger: consoleLogger, }); try { await provider.initialize(); const response = await provider.complete(createTestRequest('openai/gpt-4o-mini')); console.log('āœ… OpenRouter Response:', response.content); console.log(' Tokens:', response.usage); provider.destroy(); return response; } catch (error) { console.error('āŒ OpenRouter Error:', error); provider.destroy(); return null; } } async function testOllama() { console.log('\nšŸ”· Testing Ollama (local)...'); const provider = new OllamaProvider({ config: { provider: 'ollama', apiUrl: 'http://localhost:11434', model: 'qwen2.5:0.5b', maxTokens: 100, }, logger: consoleLogger, }); try { await provider.initialize(); const response = await provider.complete(createTestRequest('qwen2.5:0.5b')); console.log('āœ… Ollama Response:', response.content); console.log(' Tokens:', response.usage); console.log(' Cost: $0.00 (local)'); provider.destroy(); return response; } catch (error: any) { if (error.message?.includes('ECONNREFUSED') || error.message?.includes('fetch failed')) { console.log('ā­ļø Skipping Ollama - not running locally'); console.log(' To test: ollama pull qwen2.5:0.5b && ollama serve'); } else { console.error('āŒ Ollama Error:', error.message); } provider.destroy(); return null; } } async function testRuVector() { console.log('\nšŸ”· Testing RuVector (SONA + Local Qwen)...'); const provider = new RuVectorProvider({ config: { provider: 'ruvector', model: 'qwen2.5:0.5b', maxTokens: 100, providerOptions: { sonaEnabled: true, hnswEnabled: true, fastgrnnEnabled: true, localModel: 'qwen2.5:0.5b', ollamaUrl: 'http://localhost:11434', }, }, logger: consoleLogger, }); try { await provider.initialize(); const response = await provider.complete(createTestRequest('qwen2.5:0.5b')); console.log('āœ… RuVector Response:', response.content); console.log(' Tokens:', response.usage); // Show SONA metrics try { const sonaMetrics = await provider.getSonaMetrics(); console.log(' SONA Metrics:', sonaMetrics); } catch { console.log(' SONA: Not available (optional)'); } provider.destroy(); return response; } catch (error: any) { if (error.message?.includes('ECONNREFUSED') || error.message?.includes('fetch failed')) { console.log('ā­ļø Skipping RuVector - Ollama not running locally'); console.log(' To test: ollama pull qwen2.5:0.5b && ollama serve'); } else { console.error('āŒ RuVector Error:', error.message); } provider.destroy(); return null; } } async function testProviderManager() { console.log('\nšŸ”· Testing Provider Manager (multi-provider)...'); const providers = []; if (process.env.ANTHROPIC_API_KEY) { providers.push({ provider: 'anthropic' as const, apiKey: process.env.ANTHROPIC_API_KEY, model: 'claude-3-haiku-20240307', maxTokens: 100, }); } // Add OpenRouter as second provider for load balancing/failover if (process.env.OPENROUTER_API_KEY) { providers.push({ provider: 'openai' as const, // OpenRouter uses OpenAI-compatible API apiKey: process.env.OPENROUTER_API_KEY, apiUrl: 'https://openrouter.ai/api/v1', model: 'openai/gpt-4o-mini', maxTokens: 100, } as any); } if (providers.length === 0) { console.log('ā­ļø Skipping Provider Manager - no cloud API keys'); return null; } try { const manager = await createProviderManager({ providers, loadBalancing: { enabled: true, strategy: 'round-robin', }, fallback: { enabled: true, maxAttempts: 2, }, cache: { enabled: true, ttl: 60000, maxSize: 100, }, }, consoleLogger); console.log(' Active providers:', manager.listProviders()); // Make request const response = await manager.complete(createTestRequest()); console.log('āœ… Manager Response:', response.content); console.log(' Used provider:', response.provider); // Test cache console.log(' Testing cache...'); const start = Date.now(); const cached = await manager.complete(createTestRequest()); const cacheTime = Date.now() - start; console.log(` Cache hit time: ${cacheTime}ms`); manager.destroy(); return response; } catch (error) { console.error('āŒ Manager Error:', error); return null; } } async function main() { console.log('╔════════════════════════════════════════════════╗'); console.log('ā•‘ Claude Flow V3 - Provider Test Suite ā•‘'); console.log('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•'); console.log('\nšŸ“‹ Loaded .env from:', resolve(__dirname, '../../../../../.env')); console.log('\nšŸ”‘ Available API Keys:'); console.log(' ANTHROPIC_API_KEY:', process.env.ANTHROPIC_API_KEY ? 'āœ“' : 'āœ—'); console.log(' GOOGLE_GEMINI_API_KEY:', process.env.GOOGLE_GEMINI_API_KEY ? 'āœ“' : 'āœ—'); console.log(' OPENROUTER_API_KEY:', process.env.OPENROUTER_API_KEY ? 'āœ“' : 'āœ—'); const results = { anthropic: await testAnthropic(), google: await testGoogle(), openrouter: await testOpenRouter(), ollama: await testOllama(), ruvector: await testRuVector(), manager: await testProviderManager(), }; // Summary console.log('\n╔════════════════════════════════════════════════╗'); console.log('ā•‘ Test Summary ā•‘'); console.log('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•'); const passed = Object.entries(results).filter(([_, r]) => r !== null).length; const total = Object.keys(results).length; Object.entries(results).forEach(([name, result]) => { const status = result !== null ? 'āœ…' : 'ā­ļø'; console.log(` ${status} ${name}`); }); console.log(`\nšŸ“Š Passed: ${passed}/${total}`); if (results.ollama === null && results.ruvector === null) { console.log('\nšŸ’” To test local models:'); console.log(' 1. Install Ollama: https://ollama.ai'); console.log(' 2. Pull Qwen: ollama pull qwen2.5:0.5b'); console.log(' 3. Start server: ollama serve'); console.log(' 4. Re-run this test'); } } main().catch(console.error);