feat(gemini): add Target 10-13 — patch model defaults, UI, compression
- Target 10: override DEFAULT_GEMINI_MODEL/FLASH/LITE/AUTO in models.js - Target 11: fix hardcoded model names in ModelDialog.js - Target 12: fix compression config aliases in chatCompressionService.js - Target 13: fix example model name in AgentConfigDialog.js Covers all 16+ locations where gemini-2.5 was used as fallback. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,10 @@ Targets:
|
||||
7. auto_update_registry — redirect registry-url default to npm.sensey24.ru
|
||||
8. auto_update_commands — add --registry to update commands
|
||||
9. auto_permissions — bypass tool approval prompts (YOLO mode via settings)
|
||||
10. default_models — override DEFAULT_GEMINI_MODEL/FLASH/LITE/AUTO in models.js
|
||||
11. model_dialog_desc — fix hardcoded model names in ModelDialog.js
|
||||
12. compression_aliases — fix compression config aliases in chatCompressionService.js
|
||||
13. agent_config_desc — fix example model name in AgentConfigDialog.js
|
||||
"""
|
||||
|
||||
import json
|
||||
@@ -40,6 +44,10 @@ INSTALL_INFO_SUBPATH = "dist/src/utils/installationInfo.js"
|
||||
NPM_CONF_DEFAULTS_SUBPATH = "node_modules/@pnpm/npm-conf/lib/defaults.js"
|
||||
CONFIG_JS_SUBPATH = "dist/src/config/config.js"
|
||||
SETTINGS_SCHEMA_SUBPATH = "dist/src/config/settingsSchema.js"
|
||||
MODELS_JS_SUBPATH = "node_modules/@google/gemini-cli-core/dist/src/config/models.js"
|
||||
MODEL_DIALOG_JS_SUBPATH = "dist/src/ui/components/ModelDialog.js"
|
||||
CHAT_COMPRESSION_SUBPATH = "node_modules/@google/gemini-cli-core/dist/src/services/chatCompressionService.js"
|
||||
AGENT_CONFIG_DIALOG_SUBPATH = "dist/src/ui/components/AgentConfigDialog.js"
|
||||
|
||||
# ANSI colors
|
||||
GREEN = "\033[92m"
|
||||
@@ -756,6 +764,203 @@ def patch_auto_permissions(gemini_root, config):
|
||||
return True, "; ".join(patched_parts)
|
||||
|
||||
|
||||
# ─── Target 10: Patch default model constants in models.js ──────────────
|
||||
|
||||
def patch_default_models(gemini_root, config):
|
||||
"""
|
||||
Target 10: Override DEFAULT_GEMINI_MODEL, DEFAULT_GEMINI_FLASH_MODEL,
|
||||
DEFAULT_GEMINI_FLASH_LITE_MODEL, DEFAULT_GEMINI_MODEL_AUTO and
|
||||
getDisplayString() in models.js to use 3.x models from config.
|
||||
"""
|
||||
default_model = config.get("default_model")
|
||||
flash_model = config.get("internal_flash_model")
|
||||
if not default_model and not flash_model:
|
||||
return True, "Skipped (no default_model/internal_flash_model in config)"
|
||||
|
||||
models_path = os.path.join(gemini_root, MODELS_JS_SUBPATH)
|
||||
if not os.path.isfile(models_path):
|
||||
return False, f"File not found: {models_path}"
|
||||
|
||||
with open(models_path, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
|
||||
changes = 0
|
||||
|
||||
# 10a: DEFAULT_GEMINI_MODEL
|
||||
if default_model:
|
||||
old = "export const DEFAULT_GEMINI_MODEL = 'gemini-2.5-pro';"
|
||||
new = f"export const DEFAULT_GEMINI_MODEL = '{default_model}';"
|
||||
if old in content:
|
||||
content = content.replace(old, new, 1)
|
||||
changes += 1
|
||||
|
||||
# 10b: DEFAULT_GEMINI_FLASH_MODEL
|
||||
if flash_model:
|
||||
old = "export const DEFAULT_GEMINI_FLASH_MODEL = 'gemini-2.5-flash';"
|
||||
new = f"export const DEFAULT_GEMINI_FLASH_MODEL = '{flash_model}';"
|
||||
if old in content:
|
||||
content = content.replace(old, new, 1)
|
||||
changes += 1
|
||||
|
||||
# 10c: DEFAULT_GEMINI_FLASH_LITE_MODEL → same as flash (no 3.x lite)
|
||||
if flash_model:
|
||||
old = "export const DEFAULT_GEMINI_FLASH_LITE_MODEL = 'gemini-2.5-flash-lite';"
|
||||
new = f"export const DEFAULT_GEMINI_FLASH_LITE_MODEL = '{flash_model}';"
|
||||
if old in content:
|
||||
content = content.replace(old, new, 1)
|
||||
changes += 1
|
||||
|
||||
# 10d: DEFAULT_GEMINI_MODEL_AUTO
|
||||
old_auto = "export const DEFAULT_GEMINI_MODEL_AUTO = 'auto-gemini-2.5';"
|
||||
new_auto = "export const DEFAULT_GEMINI_MODEL_AUTO = 'auto-gemini-3';"
|
||||
if old_auto in content:
|
||||
content = content.replace(old_auto, new_auto, 1)
|
||||
changes += 1
|
||||
|
||||
# 10e: getDisplayString() — fix auto display label
|
||||
old_display = "return 'Auto (Gemini 2.5)';"
|
||||
new_display = "return 'Auto (Gemini 3)';"
|
||||
if old_display in content:
|
||||
content = content.replace(old_display, new_display, 1)
|
||||
changes += 1
|
||||
|
||||
if changes == 0:
|
||||
# Check if already patched
|
||||
already = True
|
||||
if default_model and f"= '{default_model}';" not in content:
|
||||
already = False
|
||||
if flash_model and f"DEFAULT_GEMINI_FLASH_MODEL = '{flash_model}';" not in content:
|
||||
already = False
|
||||
if already:
|
||||
return True, "Already patched (models.js)"
|
||||
return False, "No models.js patterns matched — structure may have changed"
|
||||
|
||||
# Backup
|
||||
backup_path = models_path + ".backup"
|
||||
if not os.path.exists(backup_path):
|
||||
shutil.copy2(models_path, backup_path)
|
||||
|
||||
with open(models_path, "w", encoding="utf-8") as f:
|
||||
f.write(content)
|
||||
|
||||
return True, f"Patched {changes} constant(s) in models.js"
|
||||
|
||||
|
||||
# ─── Target 11: Patch ModelDialog.js hardcoded descriptions ────────────
|
||||
|
||||
def patch_model_dialog(gemini_root, config):
|
||||
"""
|
||||
Target 11: Fix hardcoded model names in ModelDialog.js description.
|
||||
"""
|
||||
default_model = config.get("default_model", "gemini-2.5-pro")
|
||||
flash_model = config.get("internal_flash_model", "gemini-2.5-flash")
|
||||
|
||||
dialog_path = os.path.join(gemini_root, MODEL_DIALOG_JS_SUBPATH)
|
||||
if not os.path.isfile(dialog_path):
|
||||
return False, f"File not found: {dialog_path}"
|
||||
|
||||
with open(dialog_path, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
|
||||
old_desc = "gemini-2.5-pro, gemini-2.5-flash"
|
||||
new_desc = f"{default_model}, {flash_model}"
|
||||
|
||||
if old_desc not in content:
|
||||
if new_desc in content:
|
||||
return True, "Already patched (ModelDialog.js)"
|
||||
return False, "No ModelDialog.js pattern matched"
|
||||
|
||||
backup_path = dialog_path + ".backup"
|
||||
if not os.path.exists(backup_path):
|
||||
shutil.copy2(dialog_path, backup_path)
|
||||
|
||||
content = content.replace(old_desc, new_desc)
|
||||
with open(dialog_path, "w", encoding="utf-8") as f:
|
||||
f.write(content)
|
||||
|
||||
return True, "Patched model description in ModelDialog.js"
|
||||
|
||||
|
||||
# ─── Target 12: Patch chatCompressionService.js compression aliases ────
|
||||
|
||||
def patch_compression_aliases(gemini_root, config):
|
||||
"""
|
||||
Target 12: Fix compression config aliases in chatCompressionService.js.
|
||||
After Target 10, DEFAULT_ constants point to 3.x models but switch/case
|
||||
returns 2.5 aliases. Fix to return 3.x aliases.
|
||||
"""
|
||||
compress_path = os.path.join(gemini_root, CHAT_COMPRESSION_SUBPATH)
|
||||
if not os.path.isfile(compress_path):
|
||||
return False, f"File not found: {compress_path}"
|
||||
|
||||
with open(compress_path, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
|
||||
changes = 0
|
||||
replacements = [
|
||||
# (old_return_value, new_return_value)
|
||||
("case DEFAULT_GEMINI_MODEL:\n return 'chat-compression-2.5-pro';",
|
||||
"case DEFAULT_GEMINI_MODEL:\n return 'chat-compression-3-pro';"),
|
||||
("case DEFAULT_GEMINI_FLASH_MODEL:\n return 'chat-compression-2.5-flash';",
|
||||
"case DEFAULT_GEMINI_FLASH_MODEL:\n return 'chat-compression-3-flash';"),
|
||||
("case DEFAULT_GEMINI_FLASH_LITE_MODEL:\n return 'chat-compression-2.5-flash-lite';",
|
||||
"case DEFAULT_GEMINI_FLASH_LITE_MODEL:\n return 'chat-compression-3-flash';"),
|
||||
]
|
||||
|
||||
for old, new in replacements:
|
||||
if old in content:
|
||||
content = content.replace(old, new, 1)
|
||||
changes += 1
|
||||
|
||||
if changes == 0:
|
||||
if "'chat-compression-3-pro'" in content and "'chat-compression-3-flash'" in content:
|
||||
return True, "Already patched (chatCompressionService.js)"
|
||||
return False, "No chatCompressionService.js patterns matched"
|
||||
|
||||
backup_path = compress_path + ".backup"
|
||||
if not os.path.exists(backup_path):
|
||||
shutil.copy2(compress_path, backup_path)
|
||||
|
||||
with open(compress_path, "w", encoding="utf-8") as f:
|
||||
f.write(content)
|
||||
|
||||
return True, f"Patched {changes} compression alias(es)"
|
||||
|
||||
|
||||
# ─── Target 13: Patch AgentConfigDialog.js example model name ──────────
|
||||
|
||||
def patch_agent_config_dialog(gemini_root, config):
|
||||
"""
|
||||
Target 13: Fix example model name in AgentConfigDialog.js description.
|
||||
"""
|
||||
flash_model = config.get("internal_flash_model", "gemini-3-flash-preview")
|
||||
|
||||
dialog_path = os.path.join(gemini_root, AGENT_CONFIG_DIALOG_SUBPATH)
|
||||
if not os.path.isfile(dialog_path):
|
||||
return False, f"File not found: {dialog_path}"
|
||||
|
||||
with open(dialog_path, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
|
||||
old_example = "gemini-2.0-flash"
|
||||
new_example = flash_model
|
||||
|
||||
if old_example not in content:
|
||||
if new_example in content:
|
||||
return True, "Already patched (AgentConfigDialog.js)"
|
||||
return False, "No AgentConfigDialog.js pattern matched"
|
||||
|
||||
backup_path = dialog_path + ".backup"
|
||||
if not os.path.exists(backup_path):
|
||||
shutil.copy2(dialog_path, backup_path)
|
||||
|
||||
content = content.replace(old_example, new_example)
|
||||
with open(dialog_path, "w", encoding="utf-8") as f:
|
||||
f.write(content)
|
||||
|
||||
return True, "Patched example model in AgentConfigDialog.js"
|
||||
|
||||
|
||||
# ─── Rollback ───────────────────────────────────────────────────────────
|
||||
|
||||
def rollback(genai_mjs_path, settings_js_path, gemini_root=None):
|
||||
@@ -769,6 +974,11 @@ def rollback(genai_mjs_path, settings_js_path, gemini_root=None):
|
||||
paths.append(config_js)
|
||||
schema_js = os.path.join(gemini_root, SETTINGS_SCHEMA_SUBPATH)
|
||||
paths.append(schema_js)
|
||||
# Targets 10-13
|
||||
paths.append(os.path.join(gemini_root, MODELS_JS_SUBPATH))
|
||||
paths.append(os.path.join(gemini_root, MODEL_DIALOG_JS_SUBPATH))
|
||||
paths.append(os.path.join(gemini_root, CHAT_COMPRESSION_SUBPATH))
|
||||
paths.append(os.path.join(gemini_root, AGENT_CONFIG_DIALOG_SUBPATH))
|
||||
for p in paths:
|
||||
backup = p + ".backup"
|
||||
if os.path.exists(backup):
|
||||
@@ -876,6 +1086,34 @@ def apply_all_patches(config=None, settings_only=False):
|
||||
if not ok:
|
||||
all_ok = False
|
||||
|
||||
# Target 10: default model constants in models.js
|
||||
ok, msg = patch_default_models(gemini_root, config)
|
||||
results["default_models"] = (ok, msg)
|
||||
print(f" {'[OK]' if ok else '[FAIL]':>8} Target 10: {msg}")
|
||||
if not ok:
|
||||
all_ok = False
|
||||
|
||||
# Target 11: ModelDialog description
|
||||
ok, msg = patch_model_dialog(gemini_root, config)
|
||||
results["model_dialog"] = (ok, msg)
|
||||
print(f" {'[OK]' if ok else '[FAIL]':>8} Target 11: {msg}")
|
||||
if not ok:
|
||||
all_ok = False
|
||||
|
||||
# Target 12: compression aliases
|
||||
ok, msg = patch_compression_aliases(gemini_root, config)
|
||||
results["compression_aliases"] = (ok, msg)
|
||||
print(f" {'[OK]' if ok else '[FAIL]':>8} Target 12: {msg}")
|
||||
if not ok:
|
||||
all_ok = False
|
||||
|
||||
# Target 13: AgentConfigDialog example model
|
||||
ok, msg = patch_agent_config_dialog(gemini_root, config)
|
||||
results["agent_config_dialog"] = (ok, msg)
|
||||
print(f" {'[OK]' if ok else '[FAIL]':>8} Target 13: {msg}")
|
||||
if not ok:
|
||||
all_ok = False
|
||||
|
||||
print()
|
||||
if all_ok:
|
||||
print(f" {color('All patches applied successfully!', GREEN)}")
|
||||
|
||||
Reference in New Issue
Block a user