Spaces:
Running
Running
Fix critical bug: func_start.start() is char index, not line index. Use line number properly.
Browse files- patch_models.py +36 -37
patch_models.py
CHANGED
|
@@ -59,29 +59,34 @@ def replace_available_models(content):
|
|
| 59 |
# Strategy 1: Find the function via regex and replace its body
|
| 60 |
func_start = re.search(r'def _available_models\(', content)
|
| 61 |
if func_start:
|
| 62 |
-
# Find 'return models' at the same indent level
|
| 63 |
-
func_def_line = content[:func_start.start()].count('\n')
|
| 64 |
lines = content.split('\n')
|
| 65 |
-
#
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
for i in
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
end_line = i - 1
|
| 73 |
break
|
| 74 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
end_line = i - 1
|
| 76 |
break
|
| 77 |
-
else:
|
| 78 |
-
end_line = len(lines) - 1
|
| 79 |
|
| 80 |
-
old_func_text = '\n'.join(lines[
|
| 81 |
-
if old_func_text:
|
| 82 |
content = content.replace(old_func_text, NEW_FUNC_BODY)
|
| 83 |
-
print(f"OK: Replaced _available_models() via line-based search (lines {
|
| 84 |
return content
|
|
|
|
|
|
|
| 85 |
|
| 86 |
# Strategy 2: Try exact string match (various known patterns)
|
| 87 |
known_old_funcs = [
|
|
@@ -174,20 +179,17 @@ def replace_available_models(content):
|
|
| 174 |
print("OK: Used extend approach")
|
| 175 |
return content
|
| 176 |
|
| 177 |
-
# Strategy 5: Last resort — just
|
| 178 |
-
print("WARN:
|
| 179 |
-
# Find where AVAILABLE_MODELS is defined and replace
|
| 180 |
avail_match = re.search(r'AVAILABLE_MODELS\s*=\s*_available_models\(\)', content)
|
| 181 |
if avail_match:
|
| 182 |
content = content[:avail_match.start()] + "AVAILABLE_MODELS = []\n" + NEW_MODELS_CODE + content[avail_match.end():]
|
| 183 |
-
content = content.replace("AVAILABLE_MODELS = []\nAVAILABLE_MODELS = _available_models()\n", "")
|
| 184 |
print("OK: Used regex fallback")
|
| 185 |
return content
|
| 186 |
|
| 187 |
print("FAIL: Cannot patch agent.py — none of 5 strategies matched!")
|
| 188 |
-
|
| 189 |
-
print(
|
| 190 |
-
print(content[:3000])
|
| 191 |
print("--- END ---")
|
| 192 |
raise RuntimeError("Could not patch _available_models")
|
| 193 |
|
|
@@ -262,15 +264,12 @@ def patch_llm_params(llm_content):
|
|
| 262 |
# Strategy 3: Find HF_ROUTER_BASE_URL in params and inject before it
|
| 263 |
idx = llm_content.find('"api_base": HF_ROUTER_BASE_URL')
|
| 264 |
if idx >= 0:
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
insert_point = llm_content.find('\n', insert_point + 1) # skip api_key line too
|
| 272 |
-
patch_code = """
|
| 273 |
-
|
| 274 |
# === PATCH: Route ALL openai/-prefixed models to OpenRouter ===
|
| 275 |
if normalized_model.startswith("openai/"):
|
| 276 |
return {
|
|
@@ -280,9 +279,9 @@ def patch_llm_params(llm_content):
|
|
| 280 |
}
|
| 281 |
# === END PATCH ===
|
| 282 |
"""
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
|
| 286 |
|
| 287 |
# Strategy 4: Check if already patched
|
| 288 |
if "normalized_model.startswith(\"openai/\")" in llm_content:
|
|
@@ -305,7 +304,8 @@ def patch_llm_params(llm_content):
|
|
| 305 |
print("OK: Already correctly routed")
|
| 306 |
return llm_content
|
| 307 |
|
| 308 |
-
print("FAIL: Cannot patch llm_params.py!
|
|
|
|
| 309 |
print(llm_content[:1000])
|
| 310 |
print("--- END ---")
|
| 311 |
raise RuntimeError("Could not patch _resolve_llm_params")
|
|
@@ -321,7 +321,6 @@ try:
|
|
| 321 |
ast.parse(content)
|
| 322 |
except SyntaxError as e:
|
| 323 |
print(f"FAIL: Syntax error in agent.py after patch: {e}")
|
| 324 |
-
# Dump the relevant section for debugging
|
| 325 |
lines = content.split('\n')
|
| 326 |
err_line = e.lineno or 0
|
| 327 |
for i in range(max(0, err_line - 5), min(len(lines), err_line + 5)):
|
|
|
|
| 59 |
# Strategy 1: Find the function via regex and replace its body
|
| 60 |
func_start = re.search(r'def _available_models\(', content)
|
| 61 |
if func_start:
|
|
|
|
|
|
|
| 62 |
lines = content.split('\n')
|
| 63 |
+
# Convert char position to line number
|
| 64 |
+
func_line_num = 0
|
| 65 |
+
pos = 0
|
| 66 |
+
for i, line in enumerate(lines):
|
| 67 |
+
pos += len(line) + 1 # +1 for newline
|
| 68 |
+
if pos > func_start.start():
|
| 69 |
+
func_line_num = i
|
|
|
|
| 70 |
break
|
| 71 |
+
|
| 72 |
+
func_indent = len(lines[func_line_num]) - len(lines[func_line_num].lstrip())
|
| 73 |
+
|
| 74 |
+
# Find function end: next `def ` at same or lesser indent, or end of file
|
| 75 |
+
end_line = len(lines) - 1
|
| 76 |
+
for i in range(func_line_num + 1, len(lines)):
|
| 77 |
+
stripped = lines[i].lstrip()
|
| 78 |
+
line_indent = len(lines[i]) - len(stripped)
|
| 79 |
+
if stripped and line_indent <= func_indent and (stripped.startswith('def ') or stripped.startswith('class ')):
|
| 80 |
end_line = i - 1
|
| 81 |
break
|
|
|
|
|
|
|
| 82 |
|
| 83 |
+
old_func_text = '\n'.join(lines[func_line_num:end_line + 1])
|
| 84 |
+
if old_func_text and len(old_func_text) > 50:
|
| 85 |
content = content.replace(old_func_text, NEW_FUNC_BODY)
|
| 86 |
+
print(f"OK: Replaced _available_models() via line-based search (lines {func_line_num + 1}-{end_line + 1})")
|
| 87 |
return content
|
| 88 |
+
else:
|
| 89 |
+
print(f"WARN: Line-based search found function but body too short ({len(old_func_text)} chars), trying other strategies")
|
| 90 |
|
| 91 |
# Strategy 2: Try exact string match (various known patterns)
|
| 92 |
known_old_funcs = [
|
|
|
|
| 179 |
print("OK: Used extend approach")
|
| 180 |
return content
|
| 181 |
|
| 182 |
+
# Strategy 5: Last resort — just find AVAILABLE_MODELS assignment
|
| 183 |
+
print("WARN: Trying AVAILABLE_MODELS regex...")
|
|
|
|
| 184 |
avail_match = re.search(r'AVAILABLE_MODELS\s*=\s*_available_models\(\)', content)
|
| 185 |
if avail_match:
|
| 186 |
content = content[:avail_match.start()] + "AVAILABLE_MODELS = []\n" + NEW_MODELS_CODE + content[avail_match.end():]
|
|
|
|
| 187 |
print("OK: Used regex fallback")
|
| 188 |
return content
|
| 189 |
|
| 190 |
print("FAIL: Cannot patch agent.py — none of 5 strategies matched!")
|
| 191 |
+
print("--- First 2000 chars of agent.py ---")
|
| 192 |
+
print(content[:2000])
|
|
|
|
| 193 |
print("--- END ---")
|
| 194 |
raise RuntimeError("Could not patch _available_models")
|
| 195 |
|
|
|
|
| 264 |
# Strategy 3: Find HF_ROUTER_BASE_URL in params and inject before it
|
| 265 |
idx = llm_content.find('"api_base": HF_ROUTER_BASE_URL')
|
| 266 |
if idx >= 0:
|
| 267 |
+
hf_model_line = llm_content.rfind('hf_model = normalized_model', 0, idx)
|
| 268 |
+
if hf_model_line >= 0:
|
| 269 |
+
# Find the line end after hf_model and api_key lines
|
| 270 |
+
after_hf = llm_content.find('\n', hf_model_line) + 1
|
| 271 |
+
after_key = llm_content.find('\n', after_hf) + 1
|
| 272 |
+
patch_code = """
|
|
|
|
|
|
|
|
|
|
| 273 |
# === PATCH: Route ALL openai/-prefixed models to OpenRouter ===
|
| 274 |
if normalized_model.startswith("openai/"):
|
| 275 |
return {
|
|
|
|
| 279 |
}
|
| 280 |
# === END PATCH ===
|
| 281 |
"""
|
| 282 |
+
llm_content = llm_content[:after_key] + patch_code + llm_content[after_key:]
|
| 283 |
+
print("OK: Patched _resolve_llm_params (inject before HF_ROUTER_BASE_URL)")
|
| 284 |
+
return llm_content
|
| 285 |
|
| 286 |
# Strategy 4: Check if already patched
|
| 287 |
if "normalized_model.startswith(\"openai/\")" in llm_content:
|
|
|
|
| 304 |
print("OK: Already correctly routed")
|
| 305 |
return llm_content
|
| 306 |
|
| 307 |
+
print("FAIL: Cannot patch llm_params.py!")
|
| 308 |
+
print("--- First 1000 chars of llm_params.py ---")
|
| 309 |
print(llm_content[:1000])
|
| 310 |
print("--- END ---")
|
| 311 |
raise RuntimeError("Could not patch _resolve_llm_params")
|
|
|
|
| 321 |
ast.parse(content)
|
| 322 |
except SyntaxError as e:
|
| 323 |
print(f"FAIL: Syntax error in agent.py after patch: {e}")
|
|
|
|
| 324 |
lines = content.split('\n')
|
| 325 |
err_line = e.lineno or 0
|
| 326 |
for i in range(max(0, err_line - 5), min(len(lines), err_line + 5)):
|