Windows Codex 工具调用 524:切换 PowerShell 7 解决中文编码异常

Windows 上 Codex 调用工具时出现 Reconnecting、HTTP 524 或 responses stream finished without usable output 的排查与修复教程,重点说明 PowerShell 5.1、PowerShell 7、中文编码和流式输出之间的关系。

This page is accessible in English navigation, but the full body has not been translated yet. The original Chinese content is kept below for accuracy.

先给结论

在 Windows 上,如果 Codex 调用文件工具、命令工具或其他 Agent 工具时出现中文乱码、工具输出无法解析、持续重连,最后显示 HTTP 524,优先检查底层 shell 是否仍然是 PowerShell 5.1。一个实用的修复顺序是:

  1. 停止当前重连循环,不要继续堆日志和重复请求。
  2. $PSVersionTable 确认当前 shell;看到 powershell.exe5.1 时,切换到 pwsh.exe
  3. 在 PowerShell 7 中把输入、输出和原生命令编码统一为 UTF-8。
  4. 用中文字符串和 JSON 做本地验证,确认输出没有被截断或改码。
  5. 从这个 PowerShell 7 窗口重新启动 Codex,再做一次最小工具调用。

这是一条基于 Windows shell、中文输出和流式工具调用现象的排查路径,不是“所有 524 都由 PowerShell 造成”的定论。若在全新、极短的 PowerShell 7 会话中仍然失败,需要继续检查 Agent hook、代理线路、上游服务和服务端日志。

你看到的报错意味着什么

terminal-outputtext
Reconnecting... 1/5 (1m 00s · esc to interrupt)
Unexpected status 524 <unknown status code>: responses stream finished without usable output
url: https://<upstream>/v1/responses

这里同时出现了三个信号:Reconnecting 表示客户端正在尝试恢复连接;524 表示请求经过的网关或边缘层没有在预期时间内获得可用的上游响应;responses stream finished without usable output 表示流式响应结束时,客户端没有拿到可以继续处理的有效输出。

所以 524 只是最外层的网络错误表象,不能单凭状态码断定是网络、API Key 或模型本身。对 Agent 工具调用来说,底层命令只要没有按预期退出,或者 JSON / SSE 文本在 shell 与代理之间被截断、改码、混入额外输出,都可能让上游迟迟得不到可解析结果,最后在网关层显示超时或无可用输出。

为什么 PowerShell 5.1 可能触发问题

Windows PowerShell 5.1 是 Windows 自带的旧版 PowerShell,常见启动命令是 powershell.exe;PowerShell 7 是单独安装的跨平台版本,启动命令是 pwsh.exe。两者不是同一个程序,也不会因为你安装了 PowerShell 7 就自动让所有宿主切换过去。

旧 shell 与现代 Agent 工具之间容易出现兼容边界,尤其是以下输出同时存在时:

  • 中文文件名、中文错误信息或中文命令参数;
  • 工具通过标准输入输出传递 JSON、NDJSON 或 SSE 流;
  • 脚本调用原生程序,原生程序的编码与 PowerShell 的编码设置不一致;
  • profile、代理脚本或 hook 在标准输出中额外打印欢迎语、调试信息或乱码;
  • 进程没有正常结束,客户端只能等待、重连,最后被网关判定为无可用响应。

PowerShell 7 通常更适合作为这类工具链的默认 shell,但“安装完成”不等于“Codex 已经使用它”。必须分别验证版本、编码、启动入口和实际子进程。这个区分是本问题最容易被忽略的地方。

准备工作与定义完成

开始前准备以下信息:

  • Windows Terminal 或可打开 PowerShell 的终端;
  • 项目目录和可运行的 git
  • PowerShell 7 安装权限,或能够使用用户级安装方式;
  • 出错时的时间、request id、模型名和脱敏后的终端截图。

满足下面四项,就可以认为本次修复完成:

  1. pwsh --version 返回 PowerShell 7.x。
  2. 中文文本和包含中文的 JSON 能在当前窗口完整输出。
  3. Codex 是从 PowerShell 7 窗口启动,或宿主明确配置了 C:\Program Files\PowerShell\7\pwsh.exe
  4. 最小工具调用能够返回完整结果,不再出现乱码、无输出或持续重连。

最快修复路径

如果你只想先恢复工作,按下面的最短路径执行;后面的章节再解释每一步为什么有效。

  1. 关闭卡在重连的 Agent 进程,保留现有工作区,不要删除项目目录。
  2. 安装 PowerShell 7,并在新窗口执行 pwsh
  3. 在 PowerShell 7 中运行版本和 UTF-8 检查。
  4. 进入项目目录,先执行 git status --short,再启动 Codex。
  5. 让 Codex 先做一个最小的“列出当前目录 / 读取一个小文件”工具调用。
  6. 最小调用成功后,再恢复原任务;不要一开始就重放完整长日志。

如果第 3 步就失败,问题还在 shell 或编码层;如果第 5 步失败但本地编码测试成功,问题更可能在 Agent 的启动方式、hook、代理或上游线路。

确认当前到底是哪个 PowerShell

在出问题的同一个终端窗口运行下面的命令。不要只看窗口标题,也不要只凭“我已经安装过 PowerShell 7”来判断。

check-shell.ps1powershell
$PSVersionTable | Format-List PSVersion, PSEdition, OS
$PSVersionTable.PSVersion.ToString()
$PSVersionTable.PSEdition

(Get-Command powershell -ErrorAction SilentlyContinue).Source
(Get-Command pwsh -ErrorAction SilentlyContinue).Source

重点看以下结果:

  • PSEditionCore、版本为 7.x,说明当前是 PowerShell 7。
  • PSEditionDesktop、版本为 5.1,说明当前仍是 Windows PowerShell。
  • 命令路径中出现 powershell.exe,不要把它当成 PowerShell 7。
  • 命令路径中出现 pwsh.exe,才说明该命令入口是 PowerShell 7。

也可以直接执行 $PSHOME 查看当前 PowerShell 的安装目录。PowerShell 7 通常位于 C:\Program Files\PowerShell\7,但实际路径可能因安装方式、版本或用户权限不同而变化,最终以 (Get-Command pwsh).Source 为准。

安装并进入 PowerShell 7

官方推荐的安装方式可以使用 Windows 包管理器。下面的命令只负责安装,不会删除 Windows PowerShell 5.1;两者可以并存。

install-powershell-7.ps1powershell
# 在 Windows Terminal、PowerShell 5.1 或命令提示符中执行
winget install --id Microsoft.PowerShell --source winget

# 安装完成后打开 PowerShell 7
pwsh

安装后必须新开一个终端窗口,或者在当前窗口执行 pwsh 进入 PowerShell 7。然后再次运行 $PSVersionTable.PSVersion$PSVersionTable.PSEdition,确认已经切换成功。

如果系统没有 winget,可以从 Microsoft Learn 的 Windows 安装说明 选择 MSI 或其他官方安装方式。安装方式可以不同,但最终需要能够执行 pwsh.exe

设置并验证 UTF-8 编码

在 PowerShell 7 窗口里先执行一次下面的设置,再做中文和 JSON 输出测试。它只影响当前会话,适合先隔离问题。

check-utf8.ps1powershell
$utf8 = [System.Text.UTF8Encoding]::new($false)
[Console]::InputEncoding = $utf8
[Console]::OutputEncoding = $utf8
$OutputEncoding = $utf8

Write-Output "中文编码测试 / tool-stream-ok"
{ text = "中文"; ok = $true } | ConvertTo-Json -Compress

验证时不要只看屏幕上“看起来正常”。如果 Agent 或代理消费的是标准输出,还要确认输出中没有额外的 profile 欢迎语、调试行或颜色控制字符。对于 JSON,应该能拿到一整行可解析的对象,而不是半截内容或乱码。

如果每次打开 PowerShell 7 都需要设置,可以把四行编码配置写进当前用户的 PowerShell 7 profile。先创建 profile 文件:

create-profile.ps1powershell
$profileDir = Split-Path -Parent $PROFILE
New-Item -ItemType Directory -Force -Path $profileDir | Out-Null
New-Item -ItemType File -Force -Path $PROFILE | Out-Null
notepad $PROFILE

然后把下面内容放入打开的 profile 文件:

$PROFILEpowershell
$utf8 = [System.Text.UTF8Encoding]::new($false)
[Console]::InputEncoding = $utf8
[Console]::OutputEncoding = $utf8
$OutputEncoding = $utf8

更完整的编码背景可参考 Microsoft Learn:about_Character_Encoding。不同版本、原生命令和宿主对编码的处理存在差异,所以要以实际的中文和 JSON 测试结果为准。

确保 Agent 真正从 pwsh.exe 启动

仅仅在系统里安装 PowerShell 7,不能保证 Codex 使用它。最容易验证的方式是:在一个已经确认 PSEdition=Core 的 PowerShell 7 窗口中进入项目目录,再启动 Agent。

launch-from-pwsh.ps1powershell
# 先确认当前目录和工作区,再从 PowerShell 7 启动 Agent
Set-Location C:\path\to\your\project
git status --short
pwsh

# 已进入 PowerShell 7 后启动 Codex CLI(按实际命令替换)
codex

如果你使用的是桌面宿主、IDE 插件或其他启动器,不要根据界面名称猜测 shell。检查它是否提供 shell executable、terminal profile 或 command runner 配置;如果支持,明确填写 pwsh.exe 的绝对路径。不同宿主的设置名称和位置可能不同,本文不假设一个统一的 UI。

在启动 Agent 后,还可以从 PowerShell 7 检查命令解析和 PATH:

check-agent-path.ps1powershell
# 当前 PowerShell 7 窗口中执行
Get-Command codex -ErrorAction SilentlyContinue | Format-List Name,Source,CommandType
where.exe codex
$env:ComSpec
$env:Path -split ";" | Where-Object { $_ -match "PowerShell" }

这里的目标是确认两件事:Agent 命令来自你预期的安装位置,以及启动它的窗口确实是 pwsh.exe。如果 Codex Desktop 自己管理子进程,外部窗口启动方式可能无法改变它的内部 shell,这时应以该宿主支持的配置为准。

如果仍然 524:分层排查

PowerShell 7 仍失败时,按下面的顺序隔离变量,不要同时修改多个配置:

现象优先检查下一步
中文测试就乱码或 JSON 不完整当前 shell、profile、Console 编码使用 pwsh -NoProfile 重测,修复编码后再启动 Agent
中文测试正常,最小工具调用失败Agent 启动器、hook、MCP 或插件子进程关闭非必要 hook,用最小工具调用逐个恢复
只有一个项目失败项目脚本、环境变量、路径和依赖换空目录或最小项目做对照,再比较项目配置
所有项目都失败,且短请求也 524代理线路、上游服务、模型可用性记录时间、request id、URL、模型和脱敏日志,联系服务端排查

如果可以执行普通 HTTP 请求,建议先验证最小请求,再验证流式请求,最后再验证工具调用。三者不要混在一次长任务里:普通请求失败说明线路或认证还没通;普通请求成功而流式失败,重点检查流代理和输出处理;流式成功而工具失败,重点检查 shell、hook、MCP 和子进程。

失败时的恢复策略

1. 先保存工作区状态

Agent 卡住不代表已经回滚了文件。先停止重连,再在 PowerShell 7 中确认代码是否已经落盘:

check-worktree.ps1powershell
Set-Location C:\path\to\your\project
git status --short
git diff --stat
git diff --name-only

会话恢复、shell 切换和 Git 回滚是三个不同动作。不要因为工具调用失败,就直接删除工作区或执行破坏性 Git 命令。

2. 从最小任务重新验证

不要立刻重放原来的大任务。先让 Agent 完成以下一个动作:

  • 列出当前目录一级文件;
  • 读取一个不超过几十行的文本文件;
  • 执行一个不产生大段输出的版本命令;
  • 写入一个临时文件,再读取并删除它。

每一步都要确认“命令退出、输出完整、中文可读、文件状态正确”后再进入下一步。

3. 仍失败时切换到无 profile 对照

如果你怀疑 profile、别名或自动加载脚本,打开一个干净的 PowerShell 7 进程:

clean-pwsh.ps1powershell
pwsh -NoLogo -NoProfile

在这个干净窗口再次设置 UTF-8、进入项目并启动 Agent。若无 profile 成功,说明问题在 profile、启动脚本或环境变量;若仍失败,继续检查 Agent、代理和上游。

常见误区

  1. 只执行 chcp 65001 就认为问题解决。代码页只是一个变量,PowerShell、原生命令、Console 编码、标准输入输出和 Agent 协议仍可能不一致;必须用真实中文和 JSON 输出验证。
  2. 装了 PowerShell 7,却仍从 powershell.exe 启动。安装不会替换 Windows PowerShell 5.1,命令入口必须确认是 pwsh.exe
  3. 把 524 直接当成 API Key 错误。认证问题更常见于 401 / 403;524 更像网关未获得及时的可用上游响应,但仍需结合完整错误和 request id 判断。
  4. 不断按重连或重复执行同一个工具。如果进程被编码、hook 或协议输出卡住,重复重试只会增加请求和日志,不会修复根因。
  5. profile 中打印调试信息。Agent 如果解析标准输出,欢迎语、调试日志和颜色控制字符都可能污染工具协议。
  6. 把切换 shell 当成回滚代码。shell 只改变命令执行环境;已修改的代码仍然以文件和 git status 为准。

验收清单

完成修复后,逐项确认:

  • $PSVersionTable.PSEdition 返回 Core
  • $PSVersionTable.PSVersion 返回 7.x,而不是 5.1。
  • (Get-Command pwsh).Source 能解析到实际的 pwsh.exe
  • 中文字符串在终端中完整显示,没有问号、乱码或截断。
  • 包含中文的 JSON 能作为一条完整输出被读取。
  • profile 没有向标准输出写入无关文本;必要时已用 -NoProfile 对照。
  • Codex 的实际启动方式已经确认,不只是系统 PATH 看起来正确。
  • 最小工具调用成功后,才恢复原来的长任务。
  • 如果仍然 524,已记录 request id、时间、URL、模型和对照结果,并提交给线路或服务端维护者。

可复用的故障交接模板

需要在新会话、工单或团队群里继续排查时,使用短交接信息,不要粘贴完整历史:

windows-tool-timeout-handoff.txttext
Windows 工具调用排查结果:
- 当前 shell:PowerShell 7 / pwsh.exe
- PSVersion:<填入版本>
- 编码测试:中文文本和 JSON 均能完整输出 / 仍失败
- Agent 启动方式:<命令或宿主设置>
- 524 是否只发生在本项目:<是 / 否>
- 工作区状态:<git status 摘要>
- 下一步:先检查 <shell / hook / 上游线路 / 服务端日志>

这个模板的重点是保留可比较的事实:失败时的 shell、成功或失败的 UTF-8 测试、Agent 的真实启动方式,以及问题是否只发生在一个项目。它比“Windows 调工具报 524”更容易让下一位维护者快速定位边界。

参考资料