VS Code Codex 多窗口使用与补丁记录
目标
在同一个 VS Code 窗口中打开多个独立的 Codex 编辑器标签页,并将它们拖到不同编辑器组中并排使用。每个新标签页还应在发送第一条消息前显示历史记录入口。
本文记录当前环境中的实现。它适用于 OpenAI Codex VS Code 扩展 openai.chatgpt,当前验证版本为 26.908.40401。
原始问题
New Codex Agent 总是复用同一标签页
官方扩展创建编辑器面板时使用固定资源 URI:
text
/extension/panel/new
VS Code 根据资源 URI 判断编辑器是否已经打开。重复使用相同 URI 时,它只会激活已有标签页,不会创建第二个标签页。
重载后分栏位置可能丢失
扩展恢复 Codex 标签页时调用 vscode.openWith,但没有传回标签页原来的 viewColumn。因此重载窗口后,原本位于不同编辑器组的标签页可能被集中到当前编辑器组。
专用空白页没有历史记录按钮
/extension/panel/new 使用一个精简的 NewThreadPanelPage。该页面没有通用 Header,所以只有发送第一条消息、生成 conversationId 并进入 /local/<conversationId> 后,历史记录按钮才会出现。
最终实现
补丁将 New Codex Agent 创建的资源改成普通首页,并附加随机查询参数:
text
/?n=<随机值>
这样同时解决两个需求:
/使用插件原生首页,首页本身带有 Chat history 按钮;- 随机查询参数让每个资源 URI 不同,因此 VS Code 会创建多个标签页。
补丁还在恢复标签页时传递:
js
viewColumn: group.viewColumn
从而保留左右分栏布局。
当前补丁状态包含:
multipanel:使用带唯一参数的原生首页,允许多开并显示历史入口;viewcolumn:恢复标签页原来的编辑器分栏;activitybar:显示 Codex 活动栏入口。
使用方法
应用或更新补丁:
bash
python3 ~/.local/share/codex-vscode-patches/patch.py
然后在 VS Code 中执行:
text
Developer: Reload Window
如果重载前存在旧的 Codex 空白标签页,应先关闭旧标签页,再执行:
text
Codex: New Codex Agent
重复执行该命令即可创建多个标签页。将标签页拖到编辑器区域右侧,出现分栏预览后松开,即可并排显示。
按当前路由结构,每个新标签页都会使用带 Chat history 按钮的原生首页,可以分别选择并恢复历史会话。该行为已通过路由、资源唯一性和 JavaScript 语法检查;最终界面仍应在 VS Code 重载后实际确认。
检查补丁状态
bash
python3 ~/.local/share/codex-vscode-patches/patch.py --check
正常结果应为:
text
APPLIED multipanel
APPLIED viewcolumn
APPLIED activitybar
撤销补丁
bash
python3 ~/.local/share/codex-vscode-patches/patch.py --revert
撤销后执行 Developer: Reload Window。原始插件文件保存在对应文件旁边的 .orig 备份中。
安装位置与来源
本地补丁脚本位于:
text
~/.local/share/codex-vscode-patches/patch.py
上游项目:
text
https://github.com/masafykun/codex-vscode-patches
采用的上游提交:
text
999a9f260075c330bb1c6b349990d52296a75419
上游脚本原本面向 macOS。本地版本调整为从 ~/.vscode-server/extensions 查找远程扩展,并使用 PATH 中的 Node.js 做语法检查。
插件升级后的处理
Codex 扩展升级时,新版本会安装到新的版本目录,旧补丁不会自动继承。升级后重新运行:
bash
python3 ~/.local/share/codex-vscode-patches/patch.py
补丁按压缩代码的结构匹配修改位置。如果新版插件重构了相关代码,检查结果会显示 UNKNOWN 并停止修改。这种情况下需要针对新版本重新确认代码结构,不能强行替换。
已放弃的实现
曾尝试直接修改 new-thread-panel-page-*.js,把通用 Header 注入专用空白页面。该修改虽然通过 JavaScript 语法检查,但重载后触发 Webview 运行时错误,页面显示:
text
ChatGPT hit a snag
Something went wrong. Try again to continue
原因是完整 Header 依赖空白页没有准备好的运行时上下文或模块初始化顺序。该修改已经撤销。最终方案只改变新面板的初始路由,不再修改 React Webview 组件。
注意事项
- 多个 Codex 会话操作同一工作区时,会看到并修改相同文件。
- 需要完全隔离代码改动时,应为不同会话创建不同的 Git worktree。
- 补丁属于本地修改,扩展更新后需要重新应用。
- 应保留
.orig文件,以便快速恢复官方版本。