File size: 6,611 Bytes
6d19910
de5a378
e9e0d7a
 
 
 
f1d70ad
e9e0d7a
6d19910
f1d70ad
 
 
 
 
 
 
 
 
 
 
 
 
b87f698
f1d70ad
 
 
 
 
 
cfaf7b7
 
 
 
4d2fcd9
cfaf7b7
 
 
f2a4625
 
 
 
 
 
 
 
f1d70ad
 
e9e0d7a
de5a378
d988d4d
e9e0d7a
de5a378
 
6d19910
e9e0d7a
 
 
 
 
 
 
 
c1d2b49
ced7c6b
 
de5a378
6d19910
f1d70ad
 
de5a378
6d19910
f1d70ad
 
de5a378
6d19910
f1d70ad
 
de5a378
ced7c6b
f1d70ad
 
 
 
de5a378
6d19910
e9e0d7a
 
 
 
 
 
 
a68f195
6d19910
 
 
 
 
 
 
e9e0d7a
d4b57ad
d988d4d
e9e0d7a
d4b57ad
 
e9e0d7a
 
c74e807
 
e9e0d7a
c74e807
 
d4b57ad
6d19910
 
 
 
 
 
 
f2a4625
 
 
 
 
 
 
a68f195
 
 
 
 
 
 
 
 
 
 
 
 
 
d4b57ad
e9e0d7a
 
 
 
 
de5a378
 
 
 
 
 
 
 
 
 
 
 
cfaf7b7
 
 
4d2fcd9
cfaf7b7
 
 
e9e0d7a
 
a68f195
e9e0d7a
 
 
 
6d19910
e9e0d7a
 
 
de5a378
e9e0d7a
de5a378
 
6d19910
cfaf7b7
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
"""Patch frontend: Replace DEFAULT_MODEL_OPTIONS with OpenRouter models."""

import re
import sys

FILE = "/source/frontend/src/components/Chat/ChatInput.tsx"
MODEL_FILE = "/source/frontend/src/utils/model.ts"

# === Step 1: Patch model.ts ===
with open(MODEL_FILE, "r") as f:
    model_content = f.read()

model_content = model_content.replace(
    "export const KIMI_K27_CODE_MODEL_PATH = 'moonshotai/Kimi-K2.7-Code:novita';",
    "export const KIMI_K27_CODE_MODEL_PATH = 'deepseek-ai/DeepSeek-V4-Pro';"
)
model_content = model_content.replace(
    "export const MINIMAX_M3_MODEL_PATH = 'MiniMaxAI/MiniMax-M3:novita';",
    "export const MINIMAX_M3_MODEL_PATH = 'deepseek-ai/DeepSeek-V4-Flash';"
)
model_content = model_content.replace(
    "export const GLM_52_MODEL_PATH = 'zai-org/GLM-5.2:novita';",
    "export const GLM_52_MODEL_PATH = 'deepseek/deepseek-v4-flash';"
)
model_content = model_content.replace(
    "export const DEEPSEEK_V4_PRO_MODEL_PATH = 'deepseek-ai/DeepSeek-V4-Pro:novita';",
    "export const DEEPSEEK_V4_PRO_MODEL_PATH = 'nvidia/nemotron-3-super-120b-a12b:free';"
)

# Add DeepSeek V4 Flash latest model path
if "DEEPSEEK_V4_FLASH_LATEST_MODEL_PATH" not in model_content:
    model_content = model_content.replace(
        "export const LAGUNA_S21_MODEL_PATH",
        "export const DEEPSEEK_V4_FLASH_LATEST_MODEL_PATH = '~deepseek/deepseek-v4-flash-latest';\n\nexport const LAGUNA_S21_MODEL_PATH"
    )
    print("OK: Added DEEPSEEK_V4_FLASH_LATEST_MODEL_PATH")

# === PATCH: Add Laguna S 2.1 model path ===
if "LAGUNA_S21_MODEL_PATH" not in model_content:
    model_content = model_content.replace(
        "export const LAGUNA_M1_MODEL_PATH",
        "export const LAGUNA_S21_MODEL_PATH = 'openai/poolside/laguna-s-2.1:free';\n\nexport const LAGUNA_M1_MODEL_PATH"
    )
    print("OK: Added LAGUNA_S21_MODEL_PATH")

with open(MODEL_FILE, "w") as f:
    f.write(model_content)
print("OK: model.ts constants updated")

# === Step 2: Patch ChatInput.tsx ===
with open(FILE, "r", encoding="utf-8") as f:
    content = f.read()

# Fix imports
import_pattern = re.compile(
    r'import\s*\{[^}]+\}\s*from\s*[\'"]@/utils/model[\'"];'
)
match = import_pattern.search(content)
if match:
    content = content.replace(match.group(0), "import { isClaudePath } from '@/utils/model';")
    print("OK: Replaced imports")

# Remove Owl Alpha references
content = content.replace("'Owl Alpha'", "'Claude Opus 4.8'")
content = content.replace('"Owl Alpha"', '"Claude Opus 4.8"')

# Row 3: Kimi → DeepSeek V4 Pro
content = content.replace("'Kimi K2.7 Code'", "'DeepSeek V4 Pro'")
content = content.replace('"Kimi K2.7 Code"', '"DeepSeek V4 Pro"')

# Row 4: MiniMax → DeepSeek V4 Flash
content = content.replace("'MiniMax M3'", "'DeepSeek V4 Flash'")
content = content.replace('"MiniMax M3"', '"DeepSeek V4 Flash"')

# Row 5: GLM → DeepSeek V4 Flash
content = content.replace("'GLM 5.2'", "'DeepSeek V4 Flash'")
content = content.replace('"GLM 5.2"', '"DeepSeek V4 Flash"')

# Row 6: DeepSeek V4 Pro → Nemotron
content = content.replace(
    "  {\n    id: 'deepseek-v4-pro',\n    name: 'DeepSeek V4 Pro',\n    modelPath: DEEPSEEK_V4_PRO_MODEL_PATH,\n    avatarUrl: getHfAvatarUrl('deepseek-ai/DeepSeek-V4-Pro'),\n  },",
    "  {\n    id: 'nemotron-120b',\n    name: 'nvidia/nemotron-3-super-120b-a12b:free',\n    modelPath: DEEPSEEK_V4_PRO_MODEL_PATH,\n    avatarUrl: 'https://huggingface.co/api/avatars/nvidia',\n  },"
)

# Replace entire DEFAULT_MODEL_OPTIONS array
pattern = r'const DEFAULT_MODEL_OPTIONS: ModelOption\[\] = \[.*?\];'
match = re.search(pattern, content, re.DOTALL)

if not match:
    print("FAIL: Could not find DEFAULT_MODEL_OPTIONS array!")
    sys.exit(1)

NEW_MODELS = """const DEFAULT_MODEL_OPTIONS: ModelOption[] = [
  {
    id: 'tencent-hy3',
    name: 'Tencent HY3:free',
    modelPath: 'openai/tencent/hy3:free',
    avatarUrl: 'https://huggingface.co/api/avatars/tencent',
    recommended: true,
  },
  {
    id: 'gemma-4-31b',
    name: 'Gemma 4 31B:free',
    modelPath: 'openai/google/gemma-4-31b-it:free',
    avatarUrl: 'https://huggingface.co/api/avatars/google',
    recommended: true,
  },
  {
    id: 'llama-3.3-70b',
    name: 'Llama 3.3 70B:free',
    modelPath: 'openai/meta-llama/llama-3.3-70b-instruct:free',
    avatarUrl: 'https://huggingface.co/api/avatars/meta-llama',
    recommended: true,
  },
  {
    id: 'laguna-m1',
    name: 'Laguna M.1:free',
    modelPath: 'openai/poolside/laguna-m.1:free',
    avatarUrl: 'https://huggingface.co/api/avatars/poolside',
    recommended: true,
  },
  {
    id: 'laguna-s21',
    name: 'Laguna S 2.1:free',
    modelPath: 'openai/poolside/laguna-s-2.1:free',
    avatarUrl: 'https://huggingface.co/api/avatars/poolside',
    recommended: true,
  },
  {
    id: 'nex-n2-mini',
    name: 'nex-agi/nex-n2-mini',
    modelPath: 'openai/nex-agi/nex-n2-mini',
    avatarUrl: 'https://huggingface.co/api/avatars/nex-agi',
    recommended: true,
  },
  {
    id: 'ling-3.0-flash',
    name: 'inclusionai/ling-3.0-flash:free',
    modelPath: 'openai/inclusionai/ling-3.0-flash:free',
    avatarUrl: 'https://huggingface.co/api/avatars/inclusionai',
    recommended: true,
  },
  {
    id: 'llama-3.1-8b',
    name: 'Llama 3.1 8B',
    modelPath: 'openai/meta-llama/llama-3.1-8b-instruct',
    avatarUrl: 'https://huggingface.co/api/avatars/meta-llama',
  },
  {
    id: 'qwen3-coder-next',
    name: 'Qwen3 Coder Next',
    modelPath: 'Qwen/Qwen3-Coder-Next',
    avatarUrl: 'https://huggingface.co/api/avatars/Qwen',
  },
  {
    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-latest',
    name: 'DeepSeek V4 Flash latest',
    modelPath: '~deepseek/deepseek-v4-flash-latest',
    avatarUrl: 'https://huggingface.co/api/avatars/deepseek',
    recommended: true,
  },
];"""

content = content[:match.start()] + NEW_MODELS + content[match.end():]

# Update DEFAULT_MODEL_PATH
dm_path = re.search(r'const DEFAULT_MODEL_PATH\s*=.*?;', content)
if dm_path:
    content = content.replace(dm_path.group(0), "const DEFAULT_MODEL_PATH = 'openai/tencent/hy3:free';")
    print("OK: Replaced DEFAULT_MODEL_PATH")
else:
    print("OK: DEFAULT_MODEL_PATH not found")

with open(FILE, "w", encoding="utf-8") as f:
    f.write(content)

print("OK: Frontend patched - Tencent HY3:free DEFAULT")
print("  Models: HY3:free, Gemma 4 31B:free, Llama 3.3 70B:free, Laguna M.1:free, Laguna S 2.1:free, Nex N2 Mini, Ling 3.0 Flash:free, Llama 3.1 8B, DeepSeek V4 Flash latest")