Preserve agent cwd through Codex app server
This commit is contained in:
@@ -204,14 +204,16 @@ prompt_delivery = "exec" # {kickoff}=prompt file, {session}=session name,
|
|||||||
|
|
||||||
For an `"arg"` backend the flag *templates* are configurable (so you can point at a non-claude
|
For an `"arg"` backend the flag *templates* are configurable (so you can point at a non-claude
|
||||||
CLI): `resume_flag` (default `--resume '{id}'`), `model_flag` (default `--model '{model}'`),
|
CLI): `resume_flag` (default `--resume '{id}'`), `model_flag` (default `--model '{model}'`),
|
||||||
`remote_control_flag` (default `--remote-control '{session}'`), and `remote_addr_flag` (default
|
`remote_control_flag` (default `--remote-control '{session}'`), `remote_addr_flag` (default
|
||||||
`--remote '{addr}'`). A backend that sets `process_name`
|
`--remote '{addr}'`), and `remote_cwd_flag` (default `-C {dir}` whenever `remote_addr` is set).
|
||||||
|
A backend that sets `process_name`
|
||||||
participates in backend-mismatch healing; one that doesn't (e.g. `demo`) never does.
|
participates in backend-mismatch healing; one that doesn't (e.g. `demo`) never does.
|
||||||
An optional `preamble` runs first and must succeed before the TUI starts; it supports `{bin}`,
|
An optional `preamble` runs first and must succeed before the TUI starts; it supports `{bin}`,
|
||||||
`{session}`, `{model}`, and `{dir}` templates. The Codex backend uses it to idempotently start the
|
`{session}`, `{model}`, and `{dir}` templates. The Codex backend uses it to idempotently start the
|
||||||
shared Remote Control daemon, then uses `remote_addr = "unix://"` to connect each tmux-hosted Codex
|
shared Remote Control daemon, then uses `remote_addr = "unix://"` to connect each tmux-hosted Codex
|
||||||
TUI to that daemon. This keeps the app-server as the sole thread-store writer while local and
|
TUI to that daemon. The accompanying `-C` is required because the daemon's process directory is
|
||||||
Remote clients share the session.
|
independent of the agent's. This keeps the app-server as the sole thread-store writer while local
|
||||||
|
and Remote clients share the session in the configured project directory.
|
||||||
For an unattended TUI with a deterministic first-run gate, `startup_prompt_re` opts into one
|
For an unattended TUI with a deterministic first-run gate, `startup_prompt_re` opts into one
|
||||||
screen check after `startup_prompt_delay` seconds; on a match, the harness types the explicitly
|
screen check after `startup_prompt_delay` seconds; on a match, the harness types the explicitly
|
||||||
configured `startup_prompt_response` and `submit_key`. Codex uses this to trust the agent's
|
configured `startup_prompt_response` and `submit_key`. Codex uses this to trust the agent's
|
||||||
|
|||||||
@@ -350,10 +350,15 @@ def start_agent(cfg, agent, *, force=False):
|
|||||||
parts.append(_render_template(backend.get("remote_control_flag",
|
parts.append(_render_template(backend.get("remote_control_flag",
|
||||||
"--remote-control '{session}'"), {"session": session}))
|
"--remote-control '{session}'"), {"session": session}))
|
||||||
if backend.get("remote_addr"):
|
if backend.get("remote_addr"):
|
||||||
parts.append(_render_template(backend.get("remote_addr_flag", "--remote '{addr}'"), {
|
remote_values = {
|
||||||
"addr": backend["remote_addr"], "session": session, "model": model,
|
"addr": backend["remote_addr"], "session": session, "model": model,
|
||||||
"dir": shlex.quote(cwd),
|
"dir": shlex.quote(cwd),
|
||||||
}))
|
}
|
||||||
|
parts.append(_render_template(
|
||||||
|
backend.get("remote_addr_flag", "--remote '{addr}'"), remote_values))
|
||||||
|
remote_cwd_flag = backend.get("remote_cwd_flag", "-C {dir}")
|
||||||
|
if remote_cwd_flag:
|
||||||
|
parts.append(_render_template(remote_cwd_flag, remote_values))
|
||||||
if model:
|
if model:
|
||||||
parts.append(_render_template(backend.get("model_flag", "--model '{model}'"), {"model": model}))
|
parts.append(_render_template(backend.get("model_flag", "--model '{model}'"), {"model": model}))
|
||||||
if backend.get("flags"):
|
if backend.get("flags"):
|
||||||
|
|||||||
@@ -96,6 +96,12 @@ else
|
|||||||
fail "Codex probe did not complete (cmd=${cmd}); tail: $(echo "$pane" | grep -vE '^\s*$' | tail -5)"
|
fail "Codex probe did not complete (cmd=${cmd}); tail: $(echo "$pane" | grep -vE '^\s*$' | tail -5)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if echo "$pane" | grep -Fq "$REPO"; then
|
||||||
|
pass "daemon-created Codex thread uses the requested project directory"
|
||||||
|
else
|
||||||
|
fail "Codex thread did not use requested directory $REPO"
|
||||||
|
fi
|
||||||
|
|
||||||
if python3 "$REPO/agents.py" --config "$CFG" status \
|
if python3 "$REPO/agents.py" --config "$CFG" status \
|
||||||
| grep -E '^\s*probe\b' | grep -q RUNNING; then
|
| grep -E '^\s*probe\b' | grep -q RUNNING; then
|
||||||
pass "agents.py status reports probe RUNNING"
|
pass "agents.py status reports probe RUNNING"
|
||||||
|
|||||||
+2
-1
@@ -279,8 +279,9 @@ class TestExampleConfig(unittest.TestCase):
|
|||||||
cmd = launched[0]
|
cmd = launched[0]
|
||||||
self.assertTrue(cmd.startswith(
|
self.assertTrue(cmd.startswith(
|
||||||
"codex remote-control start --json >/dev/null && "
|
"codex remote-control start --json >/dev/null && "
|
||||||
"codex --remote 'unix://' --model 'gpt-test' "))
|
"codex --remote 'unix://' -C "))
|
||||||
self.assertEqual(cmd.count("--remote 'unix://'"), 1)
|
self.assertEqual(cmd.count("--remote 'unix://'"), 1)
|
||||||
|
self.assertIn(f"-C {agents.shlex.quote(cfg['agents']['cx']['dir'])}", cmd)
|
||||||
self.assertIn("--model 'gpt-test'", cmd)
|
self.assertIn("--model 'gpt-test'", cmd)
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
"--dangerously-bypass-approvals-and-sandbox --dangerously-bypass-hook-trust --no-alt-screen",
|
"--dangerously-bypass-approvals-and-sandbox --dangerously-bypass-hook-trust --no-alt-screen",
|
||||||
|
|||||||
Reference in New Issue
Block a user