【Bug已解决】`/resume` picker does not show CWD filter when Codex is launched with `--remote ... --cd`...
📅 2026/7/18 23:14:26
👁️ 阅读次数
📝 编程学习
【Bug已解决】/resumepicker does not show CWD filter when Codex is launched with--remote ... --cd解决方案
原始报错线索:
/resumepicker does not show CWD filter when Codex is launched with--remote ... --cd(当用--remote ... --cd参数远程启动时,「恢复会话」的选择器没有显示按当前工作目录过滤的选项)。
一、现象长什么样
用户这样启动程序:
codex --remote myhost --cd /projects/foo然后想恢复一个会话,打开/resume选择器,期望能「按当前工作目录/projects/foo过滤」:
- 选择器里没有CWD 过滤选项;
- 选择器把所有目录的会话混在一起,没法按
--cd指定的目录筛; - 但如果不加
--remote,本地启动时 CWD 过滤又是有的; - 说明:
--cd的值在某个环节丢失了,没传到选择器。 根因是启动参数解析后,部分上下文(--cd)没有被保留并传递给后续的会话恢复功能。
二、背景:启动上下文应贯穿全程
程序启动时的关键信息(远程主机、工作目录、用户、环境)构成「启动上下文」,它应当在整个进程生命周期内可被各子功能读取:
- 主对话要用
--cd决定初始目录; /resume选择器要用--cd提供过滤;- 文件操作要用
--cd作为默认根。 若启动参数只被「主对话」消费、--cd用完即弃,后续子功能就缺上下文。
三、为什么 CWD 过滤不显示:根因
3.1 启动参数局部消费后丢弃
--cd在 main 里读出来设了工作目录,但没存进全局「启动上下文」对象,选择器读不到。
3.2 远程模式跳过了上下文传递
--remote分支里,CWD 被当成「远端的事情」没在本地上下文登记,选择器认为「没有 CWD」。
3.3 选择器状态未初始化
选择器组件初始化时没从上下文读 CWD,默认不显示过滤 UI。
3.4 参数解析顺序问题
--cd紧跟--remote,解析器把--cd当成--remote的参数而非独立 flag,值被吞。
四、最小可运行复现(参数未传递到选择器)
下面演示「--cd被主流程消费但没存上下文」:
def parse_args_bad(argv): ctx = {"remote": None, "cwd": None} i = 0 while i < len(argv): if argv[i] == "--remote": ctx["remote"] = argv[i+1]; i += 2 elif argv[i] == "--cd": # 错误:只打印/设了工作目录,没存进 ctx print("设置工作目录:", argv[i+1]) i += 2 else: i += 1 return ctx # cwd 始终是 None if __name__ == "__main__": ctx = parse_args_bad(["--remote", "h1", "--cd", "/projects/foo"]) print("选择器可读到的 cwd:", ctx["cwd"]) # None -> 过滤不显示--cd没存进上下文,选择器读到None,过滤 UI 不显示(根因 3.1)。
五、解决方案一:启动上下文对象贯穿全程
把启动参数解析进一个「上下文对象」,全程共享,绝不局部丢弃:
from dataclasses import dataclass, field from typing import Optional @dataclass class LaunchContext: remote: Optional[str] = None cwd: Optional[str] = None user: Optional[str] = None def has_cwd(self) -> bool: return bool(self.cwd) def parse_args(argv) -> LaunchContext: ctx = LaunchContext() i = 0 while i < len(argv): if argv[i] == "--remote" and i + 1 < len(argv): ctx.remote = argv[i+1]; i += 2 elif argv[i] == "--cd" and i + 1 < len(argv): ctx.cwd = argv[i+1]; i += 2 # 关键:存进上下文 else: i += 1 return ctx if __name__ == "__main__": ctx = parse_args(["--remote", "h1", "--cd", "/projects/foo"]) print("选择器可读到的 cwd:", ctx.cwd) # /projects/foo ✅ 过滤可显示LaunchContext作为单一载体,--cd存进去,选择器随时可读(解决 3.1/3.2)。
六、解决方案二:远程模式下也登记本地 CWD 视图
即便--remote,--cd也应作为「远端的工作目录」登记进上下文,选择器据此过滤远端的会话:
def build_resume_filter(ctx: LaunchContext): """根据启动上下文,决定 /resume 选择器显示哪些过滤。""" filters = [] if ctx.has_cwd(): # 无论本地还是远程,cwd 都作为过滤维度 scope = f"remote:{ctx.remote}" if ctx.remote else "local" filters.append({"type": "cwd", "value": ctx.cwd, "scope": scope}) if ctx.remote: filters.append({"type": "remote", "value": ctx.remote}) return filters if __name__ == "__main__": ctx = parse_args(["--remote", "h1", "--cd", "/projects/foo"]) print("选择器过滤:", build_resume_filter(ctx)) # [{'type':'cwd','value':'/projects/foo','scope':'remote:h1'}, ...]远程模式下 CWD 过滤依然登记(带 remote 作用域),选择器不缺选项(解决 3.2)。
七、解决方案三:选择器初始化时从上下文读取
选择器组件构造时主动从上下文取 CWD,有则渲染过滤 UI:
class ResumePicker: def __init__(self, ctx: LaunchContext, sessions): self.ctx = ctx self.sessions = sessions def visible_filters(self): if self.ctx.has_cwd(): return ["按工作目录过滤", self.ctx.cwd] return ["无 CWD 过滤"] def filter_sessions(self): if not self.ctx.has_cwd(): return self.sessions return [s for s in self.sessions if s.get("cwd") == self.ctx.cwd] if __name__ == "__main__": ctx = parse_args(["--remote", "h1", "--cd", "/projects/foo"]) picker = ResumePicker(ctx, [ {"id": 1, "cwd": "/projects/foo"}, {"id": 2, "cwd": "/projects/bar"}, ]) print("过滤 UI:", picker.visible_filters()) print("过滤后会话:", picker.filter_sessions()) # 只剩 cwd 匹配的选择器从上下文读 CWD,有则显示过滤、按 CWD 筛(解决 3.3)。
八、参数解析健壮性
- 顺序无关:
--remote A --cd B与--cd B --remote A等价; - 不吞值:每个 flag 独立消费自己的下一个参数(第五节已处理);
- 默认值:
--cd缺省时取进程 cwd(如os.getcwd()),选择器仍有过滤; - 可观测:解析后打印上下文。
九、排查清单
「远程启动时恢复选择器不显示 CWD 过滤」,按下面排查:
--cd是否存进启动上下文?还是局部消费即弃(第五节,根因3.1);- 远程模式是否登记 CWD(第六节);
- 选择器是否从上下文读 CWD(第七节);
- 参数解析是否吞值?
--cd是否被当--remote的参数(第四节); --cd缺省是否有默认(第八节);- 多子功能是否共享同一上下文(呼应第133/105篇);
- 日志是否打印解析后的上下文;
- 本地 vs 远程行为是否一致(第六节 scope 区分)。
十、小结
「远程启动时 /resume 选择器不显示 CWD 过滤」的根因是**--cd等启动上下文在解析后被局部消费、未存入可共享的上下文对象,后续子功能读不到**。通用修复:
- 上下文对象贯穿:解析进
LaunchContext,全程共享,绝不局部丢弃(第五节); - 远程也登记 CWD:远程模式下 CWD 带 remote 作用域登记,过滤不缺(第六节);
- 选择器读上下文:构造时取 CWD,有则渲染过滤并按其筛选(第七节);
- 解析健壮:顺序无关、不吞值、缺省有默认(第八节)。 一句话:启动参数不是「被某个功能一次性消费完就扔」的输入,而是「定义整个进程上下文状态」的种子,必须存进可共享对象供所有子功能读取。把启动上下文当成全局状态的第一公民,远程启动后 /resume 也能正确按
--cd过滤——这与第 133 篇配置继承、第 105 篇数据源聚合、第 112 篇跨设备同步,共同体现「上下文必须被完整传递与共享」。
编程学习
技术分享
实战经验