diff --git a/cc-ci-plan/launch-orchestrator.py b/cc-ci-plan/launch-orchestrator.py index 3d94b76..ac60438 100644 --- a/cc-ci-plan/launch-orchestrator.py +++ b/cc-ci-plan/launch-orchestrator.py @@ -38,7 +38,7 @@ from pathlib import Path # ── config ──────────────────────────────────────────────────────────────────── SESSION = os.environ.get("ORCH_SESSION", "cc-ci-orchestrator-vm") -WORKDIR = os.environ.get("ORCH_DIR", "/srv/cc-ci") +WORKDIR = os.environ.get("ORCH_DIR", "/srv/cc-ci-orch") LOG_DIR = os.environ.get("LOG_DIR", "/srv/cc-ci/.cc-ci-logs") BACKEND = os.environ.get("LOOP_BACKEND", "claude") @@ -79,19 +79,18 @@ def session_alive(): ).returncode == 0 def _ping(session, msg): - """Type a message into the tmux session and submit with Enter.""" + """Type a message into the tmux session and submit it.""" import time subprocess.run(["tmux", "send-keys", "-t", session, "-l", "--", msg], capture_output=True) time.sleep(0.5) - for _ in range(5): - subprocess.run(["tmux", "send-keys", "-t", session, "Enter"], capture_output=True) + submit_key = "C-m" if BACKEND == "opencode" else "Enter" + for _ in range(10): + subprocess.run(["tmux", "send-keys", "-t", session, submit_key], capture_output=True) time.sleep(1) r = subprocess.run(["tmux", "capture-pane", "-pt", session], capture_output=True, text=True) - if msg[:28] not in r.stdout.splitlines()[-4:]: + if msg[:28] not in r.stdout: return - subprocess.run(["tmux", "send-keys", "-t", session, "C-m"], capture_output=True) - time.sleep(0.5) def resume_id(): sid = os.environ.get("ORCH_SESSION_ID") @@ -133,13 +132,11 @@ def start(mode="resume"): elif BACKEND == "opencode": if not Path(OPENCODE_BIN).exists(): die(f"opencode not found at {OPENCODE_BIN}") - # Plain `opencode` TUI stays alive in tmux and auto-connects to the shared server. - # (`opencode attach URL` exits without a real TTY; plain TUI works because tmux - # allocates a PTY for the pane.) The startup prompt is sent via ping_session after - # the TUI initialises. NO_COLOR=1 skips the first-run theme picker. + # Attach the orchestrator TUI to the shared opencode web server so it shows up in the + # same project/session listing as browser-created sessions. cmd = ( f"set -a; . /srv/cc-ci/.testenv; set +a; " - f"NO_COLOR=1 {OPENCODE_BIN} {model_flag}" + f"NO_COLOR=1 {OPENCODE_BIN} attach {OPENCODE_SERVER} --dir {WORKDIR}" ) log(f"starting {SESSION} (backend=opencode, model={LOOP_MODEL or 'default'})") log(f" visible at http://oc.commoninternet.net (tailnet only)") diff --git a/cc-ci-plan/orchestrator-opencode-restart.txt b/cc-ci-plan/orchestrator-opencode-restart.txt new file mode 100644 index 0000000..765b80c --- /dev/null +++ b/cc-ci-plan/orchestrator-opencode-restart.txt @@ -0,0 +1,8 @@ +Stop the existing orchestrator tmux session: +ORCH_SESSION=cc-ci-orchestrator-vm cc-ci-plan/launch-orchestrator.sh stop + +Start a fresh opencode-attached orchestrator session: +LOOP_BACKEND=opencode LOOP_MODEL=openai/gpt-5.4 ORCH_SESSION=cc-ci-orchestrator-vm cc-ci-plan/launch-orchestrator.sh fresh + +Alternative: start it under a separate tmux session name instead of replacing the Claude one: +LOOP_BACKEND=opencode LOOP_MODEL=openai/gpt-5.4 ORCH_SESSION=cc-ci-orchestrator-oc cc-ci-plan/launch-orchestrator.sh fresh diff --git a/nix/hosts/cc-ci-orchestrator-hetzner/configuration.nix b/nix/hosts/cc-ci-orchestrator-hetzner/configuration.nix index 2354dda..53df1de 100644 --- a/nix/hosts/cc-ci-orchestrator-hetzner/configuration.nix +++ b/nix/hosts/cc-ci-orchestrator-hetzner/configuration.nix @@ -129,7 +129,7 @@ SSHCFG serviceConfig = { Type = "simple"; User = "loops"; Group = "users"; - WorkingDirectory = "/srv/cc-ci"; + WorkingDirectory = "/srv/cc-ci-orch/cc-ci"; EnvironmentFile = "/srv/cc-ci/.testenv"; ExecStartPre = "${pkgs.coreutils}/bin/rm -rf /tmp/opencode"; ExecStart = "/home/loops/.local/bin/opencode serve --hostname 127.0.0.1 --port 4096"; @@ -137,7 +137,7 @@ SSHCFG RestartSec = "5s"; }; environment = { HOME = "/home/loops"; }; - path = [ pkgs.bash pkgs.coreutils ]; + path = [ pkgs.bash pkgs.coreutils pkgs.git pkgs.python3 pkgs.openssh pkgs.tmux pkgs.nettools ]; }; # nginx — reverse-proxy oc.commoninternet.net → opencode web server. @@ -165,7 +165,7 @@ SSHCFG serviceConfig = { Type = "oneshot"; RemainAfterExit = true; User = "loops"; Group = "users"; - WorkingDirectory = "/srv/cc-ci"; + WorkingDirectory = "/srv/cc-ci/cc-ci"; # Append one line to REBOOTS.md per genuine reboot (boot_id-gated; not on manual restart). ExecStartPre = "${pkgs.bash}/bin/bash /srv/cc-ci/cc-ci-plan/reboot-log.sh"; };