File size: 6,085 Bytes
7888038
3145998
9fca8b2
 
 
 
 
 
 
3145998
62ab37d
 
 
31f1279
62ab37d
 
07599f8
0535ef9
 
 
 
 
 
 
 
 
 
7888038
07599f8
9fca8b2
 
07599f8
9fca8b2
 
 
 
 
 
 
 
 
0535ef9
07599f8
31f1279
 
 
 
9fca8b2
 
 
 
 
31f1279
07599f8
9fca8b2
31f1279
 
 
 
9fca8b2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4b77e8d
31f1279
 
 
 
 
 
9fca8b2
31f1279
 
 
 
 
 
 
 
9fca8b2
 
 
 
31f1279
 
9fca8b2
 
 
 
 
31f1279
 
25c9526
 
 
 
e06f11b
 
34932a2
 
 
dceca0a
34932a2
 
9fca8b2
 
 
 
 
 
 
 
 
 
 
 
 
31f1279
 
 
b449975
31f1279
 
 
9fca8b2
 
 
 
 
 
31f1279
 
 
b449975
31f1279
 
 
 
 
 
b449975
31f1279
 
 
 
 
 
b449975
31f1279
 
 
 
 
 
7888038
9fca8b2
 
 
 
07599f8
 
9fca8b2
 
 
34932a2
62ab37d
 
 
9fca8b2
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
"""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")