最近给 Codex 配置 gpt-5.6-sol 时,我遇到了一个有点奇怪的问题:同一台电脑、同一个 Codex,其他模型都能正常调用终端,只有这个模型一直提示“当前会话未提供终端调用工具”。
一开始我怀疑过 PowerShell、环境变量,甚至重新检查了 shell_type。最后才发现,问题并不在终端本身,而是在自定义模型 catalog 里。
这篇文章记录的是自定义模型 catalog 和中继服务环境下的实测结果。
tool_mode、use_responses_lite等字段并不是 Codex 公开配置文档承诺的稳定接口,不同供应端或版本的行为可能不同。
问题出在哪里
当时 gpt-5.6-sol 的配置里同时存在下面几个字段:
{
"shell_type": "shell_command",
"tool_mode": "code_mode_only",
"use_responses_lite": true
}
虽然已经声明了 shell_type,实际请求仍然进入了没有注入本地终端工具的路径。我的处理方式是保留 shell_type,关闭 lite 请求,并删除 tool_mode:
{
"shell_type": "shell_command",
"use_responses_lite": false
}
修改后还需要新建一个 Codex 任务。已有任务的工具列表不会随 catalog 文件动态刷新。
找到当前生效的 catalog
Codex 的个人配置通常在:
%USERPROFILE%\.codex\config.toml
自定义 catalog 的路径由 model_catalog_json 指定。不要根据文件名猜,也不要照搬别人电脑上的完整路径,可以直接从配置中读取:
$codexHome = Join-Path $HOME '.codex'
$config = Join-Path $codexHome 'config.toml'
$match = Select-String `
-Path $config `
-Pattern '^model_catalog_json\s*=\s*"([^"]+)"$'
if (-not $match) {
throw 'config.toml 中没有找到 model_catalog_json'
}
$catalogRelative = $match.Matches[0].Groups[1].Value
$catalog = Join-Path $codexHome $catalogRelative
$catalog
官方配置文档也将 model_catalog_json 描述为启动时加载的可选模型目录覆盖项。因为配置是在启动时读取的,所以改完后新建任务是很重要的一步。
先检查,不要直接修改
找到文件后,先看看目标模型当前有哪些字段:
$json = Get-Content -Raw -LiteralPath $catalog | ConvertFrom-Json
$json.models |
Where-Object { $_.slug -eq 'gpt-5.6-sol' } |
Select-Object slug, shell_type, tool_mode, use_responses_lite
我当时看到的是:
slug : gpt-5.6-sol
shell_type : shell_command
tool_mode : code_mode_only
use_responses_lite : True
这也解释了为什么单纯补上 shell_type 没有解决问题。
备份并修复
下面这段脚本只修改 gpt-5.6-sol 对象,并在原目录生成一份带时间戳的备份:
$timestamp = Get-Date -Format 'yyyyMMdd-HHmmss'
$backup = "$catalog.bak-5.6sol-terminal-$timestamp"
Copy-Item -LiteralPath $catalog -Destination $backup
$json = Get-Content -Raw -LiteralPath $catalog | ConvertFrom-Json
$model = $json.models |
Where-Object { $_.slug -eq 'gpt-5.6-sol' } |
Select-Object -First 1
if (-not $model) {
throw "没有在 $catalog 中找到 gpt-5.6-sol"
}
$model | Add-Member `
-NotePropertyName shell_type `
-NotePropertyValue shell_command `
-Force
$model | Add-Member `
-NotePropertyName use_responses_lite `
-NotePropertyValue $false `
-Force
$model.PSObject.Properties.Remove('tool_mode')
$json |
ConvertTo-Json -Depth 100 |
Set-Content -LiteralPath $catalog -Encoding UTF8
Write-Host "已修复:$catalog"
Write-Host "备份位置:$backup"
ConvertTo-Json 会重新排版整个文件,但不会改变 JSON 的数据结构。如果很在意原文件格式,也可以只手工修改目标模型对象。
验证修改结果
先确认 JSON 仍能正常解析,再查看目标字段:
$verified = Get-Content -Raw -LiteralPath $catalog | ConvertFrom-Json
$verified.models |
Where-Object { $_.slug -eq 'gpt-5.6-sol' } |
Select-Object slug, shell_type, tool_mode, use_responses_lite
预期结果是:
shell_type : shell_command
tool_mode :
use_responses_lite : False
一定要用新任务实测
关闭旧任务,新建一个使用 gpt-5.6-sol 的任务,然后发送:
请调用终端运行 Get-Location,然后只返回终端输出。
也可以用 CLI 单独验证:
codex exec -m gpt-5.6-sol --skip-git-repo-check `
"请调用终端运行 Get-Location,然后只返回终端输出。"
成功时,日志中应该能看到类似内容:
model: gpt-5.6-sol
exec
pwsh.exe -Command Get-Location
succeeded
如果 codex.exe 命中了 WindowsApps 入口并提示拒绝访问,可以先检查自己的配置是否记录了实际 CLI 路径,再使用那个完整路径执行命令。
为什么旧任务还是不能用
这是这次排障里最容易让人误判的一点。
模型 catalog 在任务启动时读取,可用工具也在那时确定。修改文件只能影响之后创建的任务,不能给已经存在的任务动态补上 shell_command。
因此可以这样判断:
- CLI 新会话能调用终端,说明 catalog 修改已经生效。
- 旧任务仍然提示没有终端工具,并不代表修复失败。
- 新建任务后恢复正常,问题就算真正解决了。
如果以后再次出现
Codex 更新、中继服务或 catalog 同步程序都可能重新生成模型目录。问题复发时,我会按下面的顺序检查:
- 重新读取
config.toml中当前生效的model_catalog_json。 - 检查
gpt-5.6-sol的shell_type、tool_mode和use_responses_lite。 - 修复后新建任务,不在旧任务里反复测试。
- 最后做一次真实的终端调用,而不只是检查 JSON。
如果修改后引发了其他问题,直接把之前生成的备份复制回原 catalog 即可。回滚之后同样需要新建任务。
最后
这次问题最迷惑的地方,是配置里明明已经有 shell_type = shell_command,看起来终端能力应该存在。真正影响行为的却是另外两个不太显眼的字段。
所以遇到“某个模型没有终端工具”时,不必先重装 PowerShell 或 Codex。先确认问题是否只发生在单个模型,再检查当前实际生效的 catalog,通常能少走不少弯路。