Spaces:
Running
Running
| """Patch frontend ChatInput.tsx: Replace entire DEFAULT_MODEL_OPTIONS array. | |
| OpenRouter model routing on backend: | |
| - Models with openai/google/, openai/deepseek/, openai/nvidia/, openai/poolside/ → OpenRouter | |
| - Models starting with openai/openrouter/ → OpenRouter | |
| - All others → HF Inference Router | |
| Owl Alpha removed (provider Stealth broken on OpenRouter). | |
| Replaced with Gemma 4 9B (free, reliable on OpenRouter). | |
| """ | |
| FILE = "/source/frontend/src/components/Chat/ChatInput.tsx" | |
| with open(FILE) as f: | |
| content = f.read() | |
| # === Step 1: Fix imports - remove unused constants, keep isClaudePath === | |
| old_import = """import { | |
| CLAUDE_OPUS_48_MODEL_PATH, | |
| GPT_55_MODEL_PATH, | |
| KIMI_K26_MODEL_PATH, | |
| isClaudePath, | |
| } from '@/utils/model';""" | |
| new_import = """import { isClaudePath } from '@/utils/model';""" | |
| if old_import in content: | |
| content = content.replace(old_import, new_import) | |
| print("✅ Fixed imports") | |
| else: | |
| # Try single-line format | |
| alt_import = "import { CLAUDE_OPUS_48_MODEL_PATH, GPT_55_MODEL_PATH, KIMI_K26_MODEL_PATH, isClaudePath } from '@/utils/model';" | |
| if alt_import in content: | |
| content = content.replace(alt_import, "import { isClaudePath } from '@/utils/model';") | |
| print("✅ Fixed imports (single-line)") | |
| else: | |
| print("⚠ Could not find import line, checking if already patched...") | |
| if "import { isClaudePath } from '@/utils/model'" in content: | |
| print(" Already patched, skipping") | |
| else: | |
| print("❌ Import line not found!") | |
| raise SystemExit(1) | |
| # === Step 2: Replace DEFAULT_MODEL_OPTIONS array === | |
| marker = "const DEFAULT_MODEL_OPTIONS: ModelOption[] = [" | |
| start = content.find(marker) | |
| if start < 0: | |
| print("❌ DEFAULT_MODEL_OPTIONS not found!") | |
| # Debug: find the actual position | |
| alt = content.find("DEFAULT_MODEL_OPTIONS") | |
| if alt >= 0: | |
| print(f" Found 'DEFAULT_MODEL_OPTIONS' at pos {alt}") | |
| print(f" Context: {repr(content[alt:alt+150])}") | |
| raise SystemExit(1) | |
| # Find the end of the array by counting brackets | |
| end = content.find("];", start) | |
| if end < 0: | |
| print("❌ Array closing ] not found!") | |
| raise SystemExit(1) | |
| # Validate we found the right ] by looking for the pattern | |
| check_segment = content[start:end] | |
| if "];" in check_segment: | |
| # There might be nested arrays - find the outermost ] | |
| depth = 0 | |
| for i, ch in enumerate(content[start:], start): | |
| if ch == '[': | |
| depth += 1 | |
| elif ch == ']': | |
| depth -= 1 | |
| if depth == 0: | |
| end = i + 1 # include the ; | |
| # look for ; after ] | |
| if end < len(content) and content[end] == ';': | |
| end += 1 | |
| break | |
| else: | |
| end = end + 2 | |
| new_array = """const DEFAULT_MODEL_OPTIONS: ModelOption[] = [ | |
| { | |
| id: 'deepseek-v4-pro', | |
| name: 'DeepSeek V4 Pro', | |
| modelPath: 'deepseek-ai/DeepSeek-V4-Pro', | |
| avatarUrl: 'https://huggingface.co/api/avatars/deepseek-ai', | |
| recommended: true, | |
| }, | |
| { | |
| id: 'deepseek-v4-flash', | |
| name: 'DeepSeek V4 Flash', | |
| modelPath: 'deepseek-ai/DeepSeek-V4-Flash', | |
| avatarUrl: 'https://huggingface.co/api/avatars/deepseek-ai', | |
| }, | |
| { | |
| id: 'gpt-5.5', | |
| name: 'GPT-5.5', | |
| modelPath: 'openai/gpt-5.5:fal-ai', | |
| avatarUrl: 'https://huggingface.co/api/avatars/openai', | |
| }, | |
| { | |
| id: 'qwen3-coder-next', | |
| name: 'Qwen3 Coder Next', | |
| modelPath: 'Qwen/Qwen3-Coder-Next', | |
| avatarUrl: 'https://huggingface.co/api/avatars/Qwen', | |
| recommended: true, | |
| }, | |
| { | |
| id: 'gemma-3-1b', | |
| name: 'Gemma 3 1B', | |
| modelPath: 'google/gemma-3-1b-it', | |
| avatarUrl: 'https://huggingface.co/api/avatars/google', | |
| recommended: true, | |
| }, | |
| { | |
| id: 'gemini-2.0-flash', | |
| name: 'Gemini 2.0 Flash', | |
| modelPath: 'openai/google/gemini-2.0-flash-001', | |
| avatarUrl: 'https://huggingface.co/api/avatars/google', | |
| }, | |
| { | |
| id: 'deepseek-v4-flash-or', | |
| name: 'DeepSeek V4 Flash (OR)', | |
| modelPath: 'openai/deepseek/deepseek-v4-flash:free', | |
| avatarUrl: 'https://huggingface.co/api/avatars/deepseek-ai', | |
| }, | |
| { | |
| id: 'gemma-4-9b', | |
| name: 'Gemma 4 9B', | |
| modelPath: 'openai/google/gemma-4-9b-it:free', | |
| avatarUrl: 'https://huggingface.co/api/avatars/google', | |
| recommended: true, | |
| }, | |
| { | |
| id: 'gemma-4-31b', | |
| name: 'Gemma 4 31B', | |
| modelPath: 'openai/google/gemma-4-31b-it:free', | |
| avatarUrl: 'https://huggingface.co/api/avatars/google', | |
| recommended: true, | |
| }, | |
| { | |
| id: 'nemotron-120b', | |
| name: 'Nemotron 3 Super 120B', | |
| modelPath: 'openai/nvidia/nemotron-3-super-120b-a12b:free', | |
| avatarUrl: 'https://huggingface.co/api/avatars/nvidia', | |
| }, | |
| { | |
| id: 'nemotron-3-ultra', | |
| name: 'Nemotron 3 Ultra 550B', | |
| modelPath: 'openai/nvidia/nemotron-3-ultra-550b-a55b:free', | |
| avatarUrl: 'https://huggingface.co/api/avatars/nvidia', | |
| recommended: true, | |
| }, | |
| { | |
| id: 'laguna-m', | |
| name: 'Laguna M.1', | |
| modelPath: 'openai/poolside/laguna-m.1:free', | |
| avatarUrl: 'https://huggingface.co/api/avatars/poolside', | |
| recommended: true, | |
| }, | |
| { | |
| id: 'laguna-xs', | |
| name: 'Laguna XS.2', | |
| modelPath: 'openai/poolside/laguna-xs.2:free', | |
| avatarUrl: 'https://huggingface.co/api/avatars/poolside', | |
| }, | |
| ];""" | |
| content = content[:start] + new_array + content[end:] | |
| # === Step 3: DEFAULT_FREE_MODEL_OPTION_ID === | |
| old_free = "DEFAULT_FREE_MODEL_OPTION_ID = 'kimi-k2.6'" | |
| new_free = "DEFAULT_FREE_MODEL_OPTION_ID = 'deepseek-v4-pro'" | |
| if old_free in content: | |
| content = content.replace(old_free, new_free) | |
| print("✅ Set default free model to DeepSeek V4 Pro") | |
| elif "DEFAULT_FREE_MODEL_OPTION_ID" in content: | |
| print("⚠ DEFAULT_FREE_MODEL_OPTION_ID found, checking value...") | |
| idx = content.find("DEFAULT_FREE_MODEL_OPTION_ID") | |
| print(f" Context: {repr(content[idx:idx+80])}") | |
| with open(FILE, "w") as f: | |
| f.write(content) | |
| print("✅ Frontend patched — 13 models") | |
| print(" Owl Alpha REMOVED (Stealth provider broken)") | |
| print(" Replaced with: Gemma 4 9B (OpenRouter free)") | |
| print(" Default: DeepSeek V4 Pro") |