fix(codex): add env_key to custom provider + model_catalog_json for picker
- Add env_key = "OPENAI_API_KEY" to [model_providers.custom] in PS1 fallback templates (fixes 401 Unauthorized on machines without Python 3.11+) - Add model_catalog_json config + model_catalog.json file generation (fixes empty model picker — all 4 models now visible in interactive mode) - Both fixes applied in: codex_patcher.py, ucodex_install.ps1, ucodex_update.ps1 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -44,6 +44,7 @@ RESET = "\033[0m"
|
|||||||
# Managed config keys (we update these, preserve everything else)
|
# Managed config keys (we update these, preserve everything else)
|
||||||
MANAGED_TOP_KEYS = {
|
MANAGED_TOP_KEYS = {
|
||||||
"model", "model_reasoning_effort", "model_provider",
|
"model", "model_reasoning_effort", "model_provider",
|
||||||
|
"model_catalog_json",
|
||||||
"approval_policy", "sandbox_mode",
|
"approval_policy", "sandbox_mode",
|
||||||
"check_for_update_on_startup", "forced_login_method",
|
"check_for_update_on_startup", "forced_login_method",
|
||||||
}
|
}
|
||||||
@@ -163,6 +164,14 @@ def generate_config_toml(existing, config):
|
|||||||
lines.append(f'model = "{config["model"]}"')
|
lines.append(f'model = "{config["model"]}"')
|
||||||
lines.append(f'model_reasoning_effort = "{config.get("model_reasoning_effort", "high")}"')
|
lines.append(f'model_reasoning_effort = "{config.get("model_reasoning_effort", "high")}"')
|
||||||
lines.append('model_provider = "custom"')
|
lines.append('model_provider = "custom"')
|
||||||
|
|
||||||
|
# Model catalog path (for model picker)
|
||||||
|
codex_dir = os.path.join(os.path.expanduser("~"), ".codex")
|
||||||
|
catalog_path = os.path.join(codex_dir, "model_catalog.json")
|
||||||
|
# Use forward slashes for cross-platform TOML compatibility
|
||||||
|
catalog_path_toml = catalog_path.replace("\\", "/")
|
||||||
|
lines.append(f'model_catalog_json = "{catalog_path_toml}"')
|
||||||
|
|
||||||
lines.append(f'approval_policy = "{config.get("approval_policy", "never")}"')
|
lines.append(f'approval_policy = "{config.get("approval_policy", "never")}"')
|
||||||
lines.append(f'sandbox_mode = "{config.get("sandbox_mode", "danger-full-access")}"')
|
lines.append(f'sandbox_mode = "{config.get("sandbox_mode", "danger-full-access")}"')
|
||||||
lines.append(f'check_for_update_on_startup = {toml_value(config.get("check_for_update", False))}')
|
lines.append(f'check_for_update_on_startup = {toml_value(config.get("check_for_update", False))}')
|
||||||
@@ -464,6 +473,21 @@ def apply_all_patches(config, home_dir=None):
|
|||||||
# Backup before any changes
|
# Backup before any changes
|
||||||
backup_file(config_path)
|
backup_file(config_path)
|
||||||
|
|
||||||
|
# Generate model catalog JSON for model picker
|
||||||
|
catalog_path = os.path.join(codex_dir, "model_catalog.json")
|
||||||
|
models = config.get("models", [config["model"]])
|
||||||
|
catalog_entries = []
|
||||||
|
for m in models:
|
||||||
|
catalog_entries.append({
|
||||||
|
"id": m,
|
||||||
|
"object": "model",
|
||||||
|
"created": 1700000000,
|
||||||
|
"owned_by": "system"
|
||||||
|
})
|
||||||
|
with open(catalog_path, "w", encoding="utf-8") as f:
|
||||||
|
json.dump(catalog_entries, f, indent=2)
|
||||||
|
print(f" {'[OK]':>8} Catalog: {catalog_path} ({len(models)} models)")
|
||||||
|
|
||||||
# Generate new config.toml (merge)
|
# Generate new config.toml (merge)
|
||||||
new_content = generate_config_toml(existing, config)
|
new_content = generate_config_toml(existing, config)
|
||||||
|
|
||||||
@@ -574,6 +598,13 @@ def patch_user(user_home, config):
|
|||||||
existing = read_toml(config_path)
|
existing = read_toml(config_path)
|
||||||
backup_file(config_path)
|
backup_file(config_path)
|
||||||
|
|
||||||
|
# Generate model catalog
|
||||||
|
catalog_path = os.path.join(codex_dir, "model_catalog.json")
|
||||||
|
models = config.get("models", [config["model"]])
|
||||||
|
catalog_entries = [{"id": m, "object": "model", "created": 1700000000, "owned_by": "system"} for m in models]
|
||||||
|
with open(catalog_path, "w", encoding="utf-8") as f:
|
||||||
|
json.dump(catalog_entries, f, indent=2)
|
||||||
|
|
||||||
new_content = generate_config_toml(existing, config)
|
new_content = generate_config_toml(existing, config)
|
||||||
with open(config_path, "w", encoding="utf-8") as f:
|
with open(config_path, "w", encoding="utf-8") as f:
|
||||||
f.write(new_content)
|
f.write(new_content)
|
||||||
|
|||||||
@@ -215,10 +215,12 @@ if (-not $pyCmd) {
|
|||||||
Remove-Item $configToml -Force -ErrorAction SilentlyContinue
|
Remove-Item $configToml -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$catalogPath = "$configDir\model_catalog.json" -replace '\\', '/'
|
||||||
$tomlContent = @"
|
$tomlContent = @"
|
||||||
model = "gpt-5.4"
|
model = "gpt-5.4"
|
||||||
model_reasoning_effort = "high"
|
model_reasoning_effort = "high"
|
||||||
model_provider = "custom"
|
model_provider = "custom"
|
||||||
|
model_catalog_json = "$catalogPath"
|
||||||
approval_policy = "never"
|
approval_policy = "never"
|
||||||
sandbox_mode = "danger-full-access"
|
sandbox_mode = "danger-full-access"
|
||||||
check_for_update_on_startup = false
|
check_for_update_on_startup = false
|
||||||
@@ -230,6 +232,7 @@ enabled = false
|
|||||||
[model_providers.custom]
|
[model_providers.custom]
|
||||||
name = "custom"
|
name = "custom"
|
||||||
base_url = "https://ai.37-187-136-86.sslip.io/v1"
|
base_url = "https://ai.37-187-136-86.sslip.io/v1"
|
||||||
|
env_key = "OPENAI_API_KEY"
|
||||||
wire_api = "responses"
|
wire_api = "responses"
|
||||||
|
|
||||||
[notice]
|
[notice]
|
||||||
@@ -243,6 +246,19 @@ wire_api = "responses"
|
|||||||
[System.IO.File]::WriteAllText($configToml, $tomlContent)
|
[System.IO.File]::WriteAllText($configToml, $tomlContent)
|
||||||
Write-Host " config.toml created: $configToml" -ForegroundColor Green
|
Write-Host " config.toml created: $configToml" -ForegroundColor Green
|
||||||
|
|
||||||
|
# Create model catalog for model picker
|
||||||
|
$catalogFile = Join-Path $configDir "model_catalog.json"
|
||||||
|
$catalogJson = @"
|
||||||
|
[
|
||||||
|
{"id": "gpt-5.4", "object": "model", "created": 1700000000, "owned_by": "system"},
|
||||||
|
{"id": "gpt-5.3-codex-spark", "object": "model", "created": 1700000000, "owned_by": "system"},
|
||||||
|
{"id": "gpt-5.3-codex", "object": "model", "created": 1700000000, "owned_by": "system"},
|
||||||
|
{"id": "gpt-5.2-codex", "object": "model", "created": 1700000000, "owned_by": "system"}
|
||||||
|
]
|
||||||
|
"@
|
||||||
|
[System.IO.File]::WriteAllText($catalogFile, $catalogJson)
|
||||||
|
Write-Host " model_catalog.json created: $catalogFile" -ForegroundColor Green
|
||||||
|
|
||||||
# Set env vars via setx
|
# Set env vars via setx
|
||||||
& setx OPENAI_API_KEY "ClauderAPI" 2>$null | Out-Null
|
& setx OPENAI_API_KEY "ClauderAPI" 2>$null | Out-Null
|
||||||
& setx OPENAI_BASE_URL "https://ai.37-187-136-86.sslip.io/v1" 2>$null | Out-Null
|
& setx OPENAI_BASE_URL "https://ai.37-187-136-86.sslip.io/v1" 2>$null | Out-Null
|
||||||
|
|||||||
@@ -138,10 +138,12 @@ if (-not $pyCmd) {
|
|||||||
$configToml = Join-Path $configDir "config.toml"
|
$configToml = Join-Path $configDir "config.toml"
|
||||||
# Remove old broken config
|
# Remove old broken config
|
||||||
if (Test-Path $configToml) { Remove-Item $configToml -Force -ErrorAction SilentlyContinue }
|
if (Test-Path $configToml) { Remove-Item $configToml -Force -ErrorAction SilentlyContinue }
|
||||||
|
$catalogPath = "$configDir\model_catalog.json" -replace '\\', '/'
|
||||||
$tomlContent = @"
|
$tomlContent = @"
|
||||||
model = "gpt-5.4"
|
model = "gpt-5.4"
|
||||||
model_reasoning_effort = "high"
|
model_reasoning_effort = "high"
|
||||||
model_provider = "custom"
|
model_provider = "custom"
|
||||||
|
model_catalog_json = "$catalogPath"
|
||||||
approval_policy = "never"
|
approval_policy = "never"
|
||||||
sandbox_mode = "danger-full-access"
|
sandbox_mode = "danger-full-access"
|
||||||
check_for_update_on_startup = false
|
check_for_update_on_startup = false
|
||||||
@@ -153,6 +155,7 @@ enabled = false
|
|||||||
[model_providers.custom]
|
[model_providers.custom]
|
||||||
name = "custom"
|
name = "custom"
|
||||||
base_url = "https://ai.37-187-136-86.sslip.io/v1"
|
base_url = "https://ai.37-187-136-86.sslip.io/v1"
|
||||||
|
env_key = "OPENAI_API_KEY"
|
||||||
wire_api = "responses"
|
wire_api = "responses"
|
||||||
|
|
||||||
[notice]
|
[notice]
|
||||||
@@ -163,6 +166,19 @@ wire_api = "responses"
|
|||||||
"gpt-5.2-codex" = "done"
|
"gpt-5.2-codex" = "done"
|
||||||
"@
|
"@
|
||||||
[System.IO.File]::WriteAllText($configToml, $tomlContent)
|
[System.IO.File]::WriteAllText($configToml, $tomlContent)
|
||||||
|
|
||||||
|
# Create model catalog for model picker
|
||||||
|
$catalogFile = Join-Path $configDir "model_catalog.json"
|
||||||
|
$catalogJson = @"
|
||||||
|
[
|
||||||
|
{"id": "gpt-5.4", "object": "model", "created": 1700000000, "owned_by": "system"},
|
||||||
|
{"id": "gpt-5.3-codex-spark", "object": "model", "created": 1700000000, "owned_by": "system"},
|
||||||
|
{"id": "gpt-5.3-codex", "object": "model", "created": 1700000000, "owned_by": "system"},
|
||||||
|
{"id": "gpt-5.2-codex", "object": "model", "created": 1700000000, "owned_by": "system"}
|
||||||
|
]
|
||||||
|
"@
|
||||||
|
[System.IO.File]::WriteAllText($catalogFile, $catalogJson)
|
||||||
|
|
||||||
& setx OPENAI_API_KEY "ClauderAPI" 2>$null | Out-Null
|
& setx OPENAI_API_KEY "ClauderAPI" 2>$null | Out-Null
|
||||||
& setx OPENAI_BASE_URL "https://ai.37-187-136-86.sslip.io/v1" 2>$null | Out-Null
|
& setx OPENAI_BASE_URL "https://ai.37-187-136-86.sslip.io/v1" 2>$null | Out-Null
|
||||||
$env:OPENAI_API_KEY = "ClauderAPI"
|
$env:OPENAI_API_KEY = "ClauderAPI"
|
||||||
|
|||||||
Reference in New Issue
Block a user