pub(crate) fn container_argv(
argv: Vec<String>,
provider_id: &str,
) -> Vec<String>Expand description
Heal a container agent’s argv IN PLACE when — and only when — it still carries the persistent controller’s flags.
A container agent runs one docker exec per turn: container_spawn.rs
writes the raw message, closes stdin, and reads until EOF. There is no
long-lived stdin and no control channel. The PERSISTENT argv is wrong for
that in three separate ways, and it is what stale blocks carry:
--input-format stream-json— makes the CLI parse every stdin line as a JSON envelope, so it meets the startup markdown and dies withJSON Parse error: Unrecognized token '#'. This is the crash that kept container agents from EVER starting (verified live, 2026-08-31).- missing
-p— the one-shot print flag. Without it the CLI is not in the mode this path drives at all. --permission-prompt-tool stdio(+ a non-bypass--permission-mode) — routes tool permissions through the control protocol, which only the persistent controller speaks. A container turn has nothing to answercan_use_tool, so it rejects or hangs on the first permission check.
An earlier cut of this deleted only --input-format and left the other two
(codex P1 on PR #2867) — that unblocks the immediate crash while leaving the
pane in the wrong CLI mode, which is a worse failure because it looks like
it works.
The cut after THAT rebuilt the argv wholesale from launch_args, which was
worse again (reagent P1 on the same PR): this runs on EVERY container turn,
not once per stale block, so a rebuild also threw away everything
agent-model.ts legitimately appends after the base args —
agent.provider_flags (user-configurable) and --fork-session (gated on
providerId === "claude", not on agentMode, so container agents reach it).
It would have permanently broken both for container agents, on blocks whose
argv this fix had already assembled correctly.
So: subtract, don’t rebuild. Remove the flags the PERSISTENT argv carries
that the one-shot argv does not, restore any one-shot flag that’s missing,
and leave every other token — the user’s --model/--effort, their
provider_flags, --fork-session — exactly where it was. Which flags are
“persistent-only” is derived from the provider catalog rather than hardcoded,
so a future flag moving between the two lists doesn’t silently strand this.
An argv carrying NO persistent-only flag is returned untouched: it was built
by the fixed selectLaunchArgs path and there is nothing to heal.
The root cause is fixed at the source in launch-args.ts; this is the
self-heal for blocks ALREADY persisted with the bad argv, since cmd:args
lives in block meta and would otherwise stay wrong forever. Applied at the
point of use so a block that never re-runs resync_controller can’t bypass
it.