feat(mycodex): 对齐 resume options,支持 -r/--resume/--continue/--last/--all
- 新增 _translate_codex_extra,将 -r/--resume 映射为 codex resume - --continue 映射为 codex continue,--last/--all 映射为 resume --last/--all - 更新 help 文案与 README 用法示例 - 补充 5 个 codex resume option 单元测试,50 tests passed
This commit is contained in:
@@ -82,7 +82,8 @@ myagents claude -r <session-id> # 恢复指定 session
|
||||
myagents kimi # 启动 Kimi Code CLI
|
||||
myagents kimi -S <session-id> # 恢复 Kimi session
|
||||
myagents codex # 启动 OpenAI Codex CLI
|
||||
myagents codex resume <id> # 恢复 Codex session
|
||||
myagents codex -r <session-id> # 恢复 Codex session(映射为 resume)
|
||||
myagents codex resume <id> # 原生 resume 子命令
|
||||
myagents update # 重装 myagents 并同步 workspace 链接
|
||||
myagents upgrade # update 别名
|
||||
myagents completion # 安装/查看/卸载 shell 补全
|
||||
@@ -93,10 +94,11 @@ myclaude --cwd . -r <session-id>
|
||||
mykimi
|
||||
mykimi -S <session-id>
|
||||
mycodex
|
||||
mycodex -r <session-id>
|
||||
mycodex resume <session-id>
|
||||
```
|
||||
|
||||
各后端原生参数会原样透传。例如 Kimi npm 版支持 `--session`、`-c`(continue)、`-y`(yolo)等,Codex 支持 `resume`、`continue`、`exec` 等子命令,直接加在命令后即可。
|
||||
各后端原生参数会原样透传。例如 Kimi npm 版支持 `--session`、`-c`(continue)、`-y`(yolo)等,Codex 支持 `resume`、`continue`、`exec` 等子命令;`mycodex` 还会将 `-r` / `--resume` 映射为 `codex resume`,与 `myclaude` 体验保持一致。
|
||||
|
||||
## 配置
|
||||
|
||||
|
||||
+28
-2
@@ -67,6 +67,29 @@ def _resolve_chat_cwd(cwd: str | None) -> Path:
|
||||
return chat_cwd
|
||||
|
||||
|
||||
def _translate_codex_extra(extra: list[str]) -> list[str]:
|
||||
"""Map myagents-style resume options to native codex subcommands.
|
||||
|
||||
Codex CLI uses ``resume`` / ``continue`` subcommands rather than flags.
|
||||
This keeps ``mycodex`` UX consistent with ``myclaude`` / ``mykimi``.
|
||||
"""
|
||||
if not extra:
|
||||
return extra
|
||||
head = extra[0]
|
||||
tail = extra[1:]
|
||||
if head in ("-r", "--resume"):
|
||||
if not tail:
|
||||
return ["resume"]
|
||||
return ["resume", tail[0], *tail[1:]]
|
||||
if head == "--continue":
|
||||
return ["continue", *tail]
|
||||
if head == "--last":
|
||||
return ["resume", "--last", *tail]
|
||||
if head == "--all":
|
||||
return ["resume", "--all", *tail]
|
||||
return extra
|
||||
|
||||
|
||||
def _launch(backend: str, chat_cwd: Path, extra: list[str]) -> None:
|
||||
"""Run backend CLI in chat_cwd, forwarding extra args. Never returns."""
|
||||
config = _BACKENDS[backend]
|
||||
@@ -75,6 +98,9 @@ def _launch(backend: str, chat_cwd: Path, extra: list[str]) -> None:
|
||||
stderr_console.print(config["not_found_msg"])
|
||||
raise SystemExit(127)
|
||||
|
||||
if backend == "codex":
|
||||
extra = _translate_codex_extra(extra)
|
||||
|
||||
cmd = [binary, *config["default_args"], *extra]
|
||||
proc = subprocess.run(cmd, cwd=str(chat_cwd), check=False)
|
||||
raise SystemExit(proc.returncode)
|
||||
@@ -239,11 +265,11 @@ def _first_prompt(backend: str, session_file: Path) -> str:
|
||||
|
||||
|
||||
def _resume_syntax(backend: str) -> str:
|
||||
"""Return the backend's resume flag syntax for use in help text."""
|
||||
"""Return the backend's resume syntax for use in help text."""
|
||||
if backend == "kimi":
|
||||
return "--session, -S <id>"
|
||||
if backend == "codex":
|
||||
return "resume <id>"
|
||||
return "-r, --resume <id> or resume <id>"
|
||||
return "--resume, -r <id>"
|
||||
|
||||
|
||||
|
||||
@@ -301,6 +301,44 @@ class TestCodexPassthrough:
|
||||
assert cmd == ["/usr/bin/codex", "continue"]
|
||||
|
||||
|
||||
class TestCodexResumeOptions:
|
||||
"""Map myagents-style resume flags to codex resume subcommand."""
|
||||
|
||||
def _invoke(self, args: list[str], tmp_path: Path) -> list[str]:
|
||||
runner = CliRunner()
|
||||
with (
|
||||
patch("myagents.launcher.shutil.which", return_value="/usr/bin/codex"),
|
||||
patch("myagents.launcher.subprocess.run") as mock_run,
|
||||
):
|
||||
mock_run.return_value = MagicMock(returncode=0)
|
||||
result = runner.invoke(
|
||||
cli, ["codex", "--cwd", str(tmp_path), *args]
|
||||
)
|
||||
assert result.exit_code == 0, result.output
|
||||
mock_run.assert_called_once()
|
||||
return mock_run.call_args[0][0]
|
||||
|
||||
def test_r_flag_maps_to_resume(self, tmp_path: Path) -> None:
|
||||
cmd = self._invoke(["-r", "abc123"], tmp_path)
|
||||
assert cmd == ["/usr/bin/codex", "resume", "abc123"]
|
||||
|
||||
def test_resume_flag_maps_to_resume(self, tmp_path: Path) -> None:
|
||||
cmd = self._invoke(["--resume", "abc123"], tmp_path)
|
||||
assert cmd == ["/usr/bin/codex", "resume", "abc123"]
|
||||
|
||||
def test_continue_flag_maps_to_continue(self, tmp_path: Path) -> None:
|
||||
cmd = self._invoke(["--continue"], tmp_path)
|
||||
assert cmd == ["/usr/bin/codex", "continue"]
|
||||
|
||||
def test_last_flag_maps_to_resume_last(self, tmp_path: Path) -> None:
|
||||
cmd = self._invoke(["--last"], tmp_path)
|
||||
assert cmd == ["/usr/bin/codex", "resume", "--last"]
|
||||
|
||||
def test_all_flag_maps_to_resume_all(self, tmp_path: Path) -> None:
|
||||
cmd = self._invoke(["--all"], tmp_path)
|
||||
assert cmd == ["/usr/bin/codex", "resume", "--all"]
|
||||
|
||||
|
||||
class TestCodexListSessions:
|
||||
"""``myagents codex --list`` reports resumable sessions."""
|
||||
|
||||
|
||||
@@ -102,7 +102,6 @@ class TestMycodexEntrypoint:
|
||||
patch("myagents.launcher.subprocess.run") as mock_run,
|
||||
):
|
||||
mock_run.return_value = MagicMock(returncode=0)
|
||||
result = runner.invoke(codex_cli, ["--cwd", str(tmp_path), "resume", "abc123"])
|
||||
result = runner.invoke(codex_cli, ["--cwd", str(tmp_path), "-r", "abc123"])
|
||||
assert result.exit_code == 0
|
||||
assert "resume" in mock_run.call_args[0][0]
|
||||
assert "abc123" in mock_run.call_args[0][0]
|
||||
assert mock_run.call_args[0][0] == ["/usr/bin/codex", "resume", "abc123"]
|
||||
|
||||
Reference in New Issue
Block a user