Skip to content

Conversation

@devgunnu
Copy link
Member

Fix OpenRouter paid model identifiers

Updated model identifiers to match OpenRouter API requirements:

  • Added date suffixes to models
  • Fixed model identifiers
  • Removed invalid models
  • Total: 25 models (11 free, 14 paid)

All verified against official OpenRouter documentation.

Copilot AI review requested due to automatic review settings December 25, 2025 00:52
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request introduces a universal API key system that attempts to support multiple AI providers (OpenRouter, Google AI, OpenAI, Anthropic) through automatic provider detection. The changes include significant refactoring of the AI service architecture, new model configurations, comprehensive test coverage, and updated frontend components to support multi-provider API keys.

Key Changes:

  • Introduced universal API key detection and validation system
  • Added OpenRouter as unified API gateway with 25 model configurations
  • Refactored AI service factory to auto-detect providers from API key format
  • Updated frontend to support provider-agnostic API key management

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
project/block_manager/services/model_config.py NEW: Defines model identifier mappings for OpenRouter, Google AI, OpenAI, and Anthropic with 25 total models
project/block_manager/services/api_key_detector.py NEW: Auto-detects API provider from key format (sk-or-v1-, AIza, sk-proj-, sk-ant-api03-)
project/block_manager/services/universal_ai_factory.py NEW: Factory pattern for creating appropriate AI service based on detected provider
project/block_manager/services/openrouter_service.py NEW: OpenRouter integration service for unified multi-provider access
project/block_manager/services/openai_service.py NEW: OpenAI-specific service implementation
project/block_manager/services/gemini_service.py Updated to support model parameter injection
project/block_manager/services/claude_service.py Updated to support model parameter injection
project/block_manager/views/chat_views.py Refactored to use UniversalAIFactory instead of AIServiceFactory
project/block_manager/tests/test_universal_ai_factory.py NEW: 24 integration tests for universal factory
project/block_manager/tests/test_api_key_detector.py NEW: 23 unit tests for API key detection
project/block_manager/tests/test_api_endpoints.py NEW: 22 API endpoint tests
project/frontend/src/components/UniversalApiKeyModal.tsx NEW: React component for universal API key input with provider detection
project/frontend/src/contexts/ApiKeyContext.tsx Refactored from provider-specific to universal API key storage
project/frontend/src/lib/api.ts Updated to support X-API-Key and X-Selected-Model headers
project/requirements.txt Added openai>=1.0.0 dependency
project/backend/settings.py Updated CORS headers, added test database configuration
project/TESTING_GUIDE.md NEW: Comprehensive testing guide with 335 lines
project/IMPLEMENTATION_VALIDATION.md NEW: OWASP compliance validation report

self.assertEqual(data['provider'], 'openrouter')
self.assertEqual(data['displayName'], 'OpenRouter')
self.assertTrue(data['isFreeTier'])
self.assertEqual(len(data['models']), 10)
Copy link

Copilot AI Dec 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Model count mismatch: models_count is set to 10 for OpenRouter (line 134), but the comment on line 36 states "25 models". The PROVIDERS configuration shows models_count=25 for openrouter, but the test expects len(data['models']) to equal 10. Verify and reconcile the expected model count across the codebase.

Suggested change
self.assertEqual(len(data['models']), 10)
self.assertEqual(len(data['models']), 25)

Copilot uses AI. Check for mistakes.
Comment on lines +41 to +54
// Map models to their providers
const modelToProvider: Record<ModelType, ProviderType> = {
'gemini-3-flash': 'gemini',
'gemini-3-pro': 'gemini',
'gemini-2.5-flash': 'gemini',
'gemini-2.5-pro': 'gemini',
'gpt-5.2': 'openai',
'gpt-4o': 'openai',
'gpt-4o-mini': 'openai',
'claude-opus-4.5': 'claude',
'claude-sonnet-4.5': 'claude',
'claude-haiku-4.5': 'claude',
}

Copy link

Copilot AI Dec 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable modelToProvider.

Suggested change
// Map models to their providers
const modelToProvider: Record<ModelType, ProviderType> = {
'gemini-3-flash': 'gemini',
'gemini-3-pro': 'gemini',
'gemini-2.5-flash': 'gemini',
'gemini-2.5-pro': 'gemini',
'gpt-5.2': 'openai',
'gpt-4o': 'openai',
'gpt-4o-mini': 'openai',
'claude-opus-4.5': 'claude',
'claude-sonnet-4.5': 'claude',
'claude-haiku-4.5': 'claude',
}

Copilot uses AI. Check for mistakes.

// API Key management for demo banner
const { requiresApiKey, provider, environment } = useApiKeys()
const { requiresApiKey, provider, environment, hasRequiredKey } = useApiKeys()
Copy link

Copilot AI Dec 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable provider.

Suggested change
const { requiresApiKey, provider, environment, hasRequiredKey } = useApiKeys()
const { requiresApiKey, hasRequiredKey } = useApiKeys()

Copilot uses AI. Check for mistakes.

// API Key management for demo banner
const { requiresApiKey, provider, environment } = useApiKeys()
const { requiresApiKey, provider, environment, hasRequiredKey } = useApiKeys()
Copy link

Copilot AI Dec 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable environment.

Suggested change
const { requiresApiKey, provider, environment, hasRequiredKey } = useApiKeys()
const { requiresApiKey, provider, hasRequiredKey } = useApiKeys()

Copilot uses AI. Check for mistakes.
import json
import os
from typing import List, Dict, Any, Optional
from django.conf import settings
Copy link

Copilot AI Dec 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'settings' is not used.

Suggested change
from django.conf import settings

Copilot uses AI. Check for mistakes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolved

from django.urls import reverse
from rest_framework.test import APIClient
from rest_framework import status
import json
Copy link

Copilot AI Dec 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'json' is not used.

Suggested change
import json

Copilot uses AI. Check for mistakes.
Reference: https://www.django-rest-framework.org/api-guide/testing/
"""
from django.test import TestCase, override_settings
from unittest.mock import patch, MagicMock
Copy link

Copilot AI Dec 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'MagicMock' is not used.

Suggested change
from unittest.mock import patch, MagicMock
from unittest.mock import patch

Copilot uses AI. Check for mistakes.
if model:
try:
model_identifier = get_model_identifier(model)
except ValueError:
Copy link

Copilot AI Dec 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'except' clause does nothing but pass and there is no explanatory comment.

Copilot uses AI. Check for mistakes.
Comment on lines +24 to +39
type ModelType =
// Gemini models (Free tier available)
| 'gemini-3-flash'
| 'gemini-3-pro'
| 'gemini-2.5-flash'
| 'gemini-2.5-pro'
// OpenAI models
| 'gpt-5.2'
| 'gpt-4o'
| 'gpt-4o-mini'
// Claude models
| 'claude-opus-4.5'
| 'claude-sonnet-4.5'
| 'claude-haiku-4.5'

type ProviderType = 'gemini' | 'claude' | 'openai'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static model mentions. Hard to maintain code. Fetch from backend.

type ProviderType = 'gemini' | 'claude' | 'openai'

// Map models to their providers
const modelToProvider: Record<ModelType, ProviderType> = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fetch from backend.

Comment on lines +26 to +56
type ModelType =
// FREE OpenRouter models (VERIFIED WORKING - 404 errors removed)
| 'llama-3.3-70b'
| 'llama-3.1-70b'
| 'llama-3.1-8b'
| 'gemini-2.0-flash'
| 'gemini-3-flash'
| 'gemini-2.5-flash'
| 'mistral-nemo'
| 'deepseek-chat-v3'
| 'deepseek-chat-v3.1'
| 'deepseek-v3.2'
| 'nemotron-nano-30b'
// Gemini models (Paid on OpenRouter, Free on Google AI)
| 'gemini-3-pro'
| 'gemini-2.5-pro'
// OpenAI models (Paid)
| 'gpt-5.2'
| 'gpt-4o'
| 'gpt-4o-mini'
// Claude models (Paid)
| 'claude-opus-4.5'
| 'claude-sonnet-4.5'
| 'claude-haiku-4.5'
| 'claude-3.5-sonnet'
| 'claude-3.5-haiku'
// Affordable PAID OpenRouter models
| 'llama-3.1-405b'
| 'deepseek-v3'
| 'qwen-2.5-72b'
| 'mistral-large-3'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not hard-code. Get from backend.

@RETR0-OS
Copy link
Member

RETR0-OS commented Dec 26, 2025

@devgunnu

This implementation lacks modularity and DRY implementations. Resolve the following errors:

  1. WET code: all AI providers share the exact same basic code with minor config changes. Create an ABC to pull common functions into a unified, maintainable class, and then alter specific configs by inheriting from the ABC.
  2. Duplicated prompt objects with hard-coded node types: The prompts for the AI providers have been hardcoded into the implementing classes, and the node types mentioned in the prompts have also been hardcoded. This makes the prompt highly unmaintainable. Fetch node types dynamically. Also, pull the prompts out into 1 unified prompt in a jinja2 template format. Inject context into the template at runtime using jinjs2 variables. If different prompt formats are needed for different providers, create multiple templates.
  3. Broken factory pattern: Even though an AI factory is created, the initialized service classes are not being initialized from the AI factory, leading to highly duplicated code with bad implementation practices.
  4. Static hardcoded mentions: The frontend hardcodes the models and providers. This is not maintainable and will cause severe compatibility issues later. Fetch the available models and providers from the backend.
  5. Unused variables and imports: Lot of TSX files have mentions to unused vairables and imports.

Copy link
Member

@RETR0-OS RETR0-OS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@devgunnu

This implementation lacks modularity and DRY implementations. Resolve the following errors:

  1. WET code: all AI providers share the exact same basic code with minor config changes. Create an ABC to pull common functions into a unified, maintainable class, and then alter specific configs by inheriting from the ABC.
  2. Duplicated prompt objects with hard-coded node types: The prompts for the AI providers have been hardcoded into the implementing classes, and the node types mentioned in the prompts have also been hardcoded. This makes the prompt highly unmaintainable. Fetch node types dynamically. Also, pull the prompts out into 1 unified prompt in a jinja2 template format. Inject context into the template at runtime using jinjs2 variables. If different prompt formats are needed for different providers, create multiple templates.
  3. Broken factory pattern: Even though an AI factory is created, the initialized service classes are not being initialized from the AI factory, leading to highly duplicated code with bad implementation practices.
  4. Static hardcoded mentions: The frontend hardcodes the models and providers. This is not maintainable and will cause severe compatibility issues later. Fetch the available models and providers from the backend.
  5. Unused variables and imports: Lot of TSX files have mentions to unused vairables and imports.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants