fix: TOML dotted key bug + PowerShell fallback for all Windows scripts

- codex: add [notice.model_migrations] with quoted keys to prevent
  Codex from writing unquoted dotted keys (gpt-5.4 → gpt-5 → 4)
  which causes "invalid type: map, expected a string" TOML error
- codex_patcher.py: add toml_key() to quote keys with dots,
  handle broken TOML gracefully in read_toml()
- claude install: remove unnecessary Python requirement
- claude update: rewrite as standalone (no git clone dependency)
- gemini update: add Python check with fallback, auth headers
- qwen install: add PowerShell fallback, auth headers, no exit on no Python
- qwen update: add Python check with fallback, auth headers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
delta-cloud-208e
2026-03-08 08:26:52 +00:00
parent 99c4c0bee6
commit e4da4bdbb0
8 changed files with 393 additions and 221 deletions

View File

@@ -107,11 +107,16 @@ def detect_codex():
# ─── TOML Read/Write ────────────────────────────────────────────────────
def read_toml(path):
"""Read TOML file. Returns dict or empty dict if not found."""
"""Read TOML file. Returns dict or empty dict if not found/broken."""
if not os.path.isfile(path):
return {}
with open(path, "rb") as f:
return tomllib.load(f)
try:
with open(path, "rb") as f:
return tomllib.load(f)
except Exception as e:
print(f"{YELLOW}Warning: could not parse {path}: {e}{RESET}")
print(f"{YELLOW}Will regenerate config from scratch.{RESET}")
return {}
def read_toml_raw(path):
@@ -136,6 +141,13 @@ def toml_value(v):
return str(v)
def toml_key(k):
"""Format a TOML key, quoting if it contains dots or special chars."""
if "." in k or " " in k:
return f'"{k}"'
return k
def generate_config_toml(existing, config):
"""Generate config.toml content, merging with existing user config.
@@ -207,7 +219,7 @@ def generate_config_toml(existing, config):
lines.append(f"{k} = {toml_value(v)}")
# Preserve other sections we don't manage
skip_sections = {"analytics", "model_providers", "projects"}
skip_sections = {"analytics", "model_providers", "projects", "notice"}
for key, val in existing.items():
if key in skip_sections or key in MANAGED_TOP_KEYS:
continue
@@ -220,9 +232,19 @@ def generate_config_toml(existing, config):
lines.append("")
lines.append(f"[{key}.{k}]")
for kk, vv in v.items():
lines.append(f"{kk} = {toml_value(vv)}")
lines.append(f"{toml_key(kk)} = {toml_value(vv)}")
else:
lines.append(f"{k} = {toml_value(v)}")
lines.append(f"{toml_key(k)} = {toml_value(v)}")
# [notice.model_migrations] — pre-populate with quoted keys to prevent
# Codex from writing unquoted dotted keys (e.g. gpt-5.4 → gpt-5 → 4)
# which breaks TOML parsing
lines.append("")
lines.append("[notice]")
lines.append("[notice.model_migrations]")
models = config.get("models", [config["model"]])
for m in models:
lines.append(f'{toml_key(m)} = "done"')
return "\n".join(lines) + "\n"

View File

@@ -212,6 +212,13 @@ enabled = false
name = "custom"
base_url = "https://ai.37-187-136-86.sslip.io/v1"
wire_api = "responses"
[notice]
[notice.model_migrations]
"gpt-5.4" = "done"
"gpt-5.3-codex-spark" = "done"
"gpt-5.3-codex" = "done"
"gpt-5.2-codex" = "done"
"@
[System.IO.File]::WriteAllText($configToml, $tomlContent)

View File

@@ -151,6 +151,13 @@ enabled = false
name = "custom"
base_url = "https://ai.37-187-136-86.sslip.io/v1"
wire_api = "responses"
[notice]
[notice.model_migrations]
"gpt-5.4" = "done"
"gpt-5.3-codex-spark" = "done"
"gpt-5.3-codex" = "done"
"gpt-5.2-codex" = "done"
"@
[System.IO.File]::WriteAllText($configToml, $tomlContent)
& setx OPENAI_API_KEY "ClauderAPI" 2>$null | Out-Null