feat(operator): runner registry — spawn any agent CLI, not just Claude (P3)
Generalize the three Claude-hardcoded spots in bootstrap (launch argv,
install plan, creds/config-dir) behind a Runner registry so a nested
operator can be spawned with any agent CLI. The Claude path stays the
default and byte-identical.
- bootstrap.Runner + RUNNERS{claude,codex,gemini,cmd} + get_runner/runner_present
- build_run_argv / install_plan / creds_source / plan_creds / child_env all
take an optional `runner` (default claude → unchanged behaviour)
- claude validated end-to-end; codex/gemini are best-effort defaults
overridable via $HH_<RUNNER>_INSTALL etc.; generic `cmd` runner reads a
full launch template from $HH_OPERATOR_CMD ({directive} placeholder)
- bridge _op_spawn resolves req["runner"], rejects unknown; plan now carries
runner/runner_present (was claude_present)
- CLI: `spawn --runner {claude|codex|gemini|cmd}`
- 7 new unit tests; full suite 132 passed
Note: compose_directive still emits the Claude-flavoured ("hh-operator
skill") directive — the portable Layer-1 prompt is P4.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -87,11 +87,15 @@ def _build_parser() -> argparse.ArgumentParser:
|
||||
gt.add_argument("--out", default=None, help="write to this local path (else stdout)")
|
||||
gt.add_argument("--session", default=None)
|
||||
|
||||
sp = sub.add_parser("spawn", help="spawn a nested Claude operator (budgeted)")
|
||||
sp = sub.add_parser("spawn", help="spawn a nested operator (budgeted)")
|
||||
sp.add_argument("objective", help="what the nested operator should achieve")
|
||||
sp.add_argument("--room-host", required=True)
|
||||
sp.add_argument("--room-port", type=int, required=True)
|
||||
sp.add_argument("--room-name", default="operator")
|
||||
sp.add_argument("--runner", default="claude",
|
||||
choices=["claude", "codex", "gemini", "cmd"],
|
||||
help="which agent CLI to spawn as the child operator "
|
||||
"(default: claude; 'cmd' reads $HH_OPERATOR_CMD)")
|
||||
sp.add_argument("--stop", action="append", default=None,
|
||||
help="a stop condition (repeatable)")
|
||||
sp.add_argument("--target", choices=["host"], default="host")
|
||||
@@ -366,6 +370,7 @@ def _run_spawn(args) -> int:
|
||||
"op": "spawn", "objective": args.objective,
|
||||
"room": {"host": args.room_host, "port": args.room_port,
|
||||
"name": args.room_name},
|
||||
"runner": args.runner,
|
||||
"stop": args.stop, "target": args.target,
|
||||
"config_dir": args.config_dir, "allow_creds": args.allow_creds,
|
||||
"skip_permissions": args.skip_permissions, "dry_run": not args.go})
|
||||
|
||||
Reference in New Issue
Block a user