From a186f23b37a5b242545c2489c833c2587be24059 Mon Sep 17 00:00:00 2001 From: autonomic-bot Date: Fri, 12 Jun 2026 15:45:09 +0000 Subject: [PATCH] orchestrator: restore opencode web launcher --- cc-ci-plan/JOURNAL.md | 15 ++++++++++ cc-ci-plan/launch-opencode.sh | 29 +++++++++++++++++++ cc-ci-plan/launch-orchestrator.py | 10 +++++-- .../configuration.nix | 22 ++++++-------- 4 files changed, 61 insertions(+), 15 deletions(-) create mode 100755 cc-ci-plan/launch-opencode.sh diff --git a/cc-ci-plan/JOURNAL.md b/cc-ci-plan/JOURNAL.md index fa3ed3b..00f455e 100644 --- a/cc-ci-plan/JOURNAL.md +++ b/cc-ci-plan/JOURNAL.md @@ -543,3 +543,18 @@ session cc-ci-orchestrator-stale can be killed; recipe-mirrors org still private (c) ghost PR debug: plan-ghostpr-debug-fix.md + memory [[ghost-pr-debug]]. - NOT switching the upgrade to sequential (operator: concurrency is fine; the leak is the issue). Duplicate ghost subagent from the interrupt churn — told the upgrader to TaskStop one. + +## 2026-06-12 15:43 UTC — opencode web restored + OpenAI launcher added +- Re-enabled `opencode-web.service` in `nix/hosts/cc-ci-orchestrator-hetzner/configuration.nix` + (`wantedBy = [ "multi-user.target" ]`) and persisted the broader PATH that the old runtime + override had been providing. `nixos-rebuild switch --flake .#cc-ci-orchestrator-hetzner` + brought the service back and it now passes `curl http://127.0.0.1:4096/global/health`. +- Added `cc-ci-plan/launch-opencode.sh` as a separate entrypoint that keeps the default + Claude `launch-orchestrator.sh` untouched. It rebuilds the host flake if `opencode-web` + is not enabled, starts the service if needed, then launches the orchestrator with + `LOOP_BACKEND=opencode`, `LOOP_MODEL=openai/gpt-5.4`, and default session name + `cc-ci-orchestrator-oc`. +- Patched `launch-orchestrator.py` so opencode launches can force the requested model even + though `opencode attach` has no `--model` flag: it now injects `OPENCODE_CONFIG_CONTENT` + for the session. Verified live: `cc-ci-orchestrator-oc` tmux session running on + `backend=opencode model=openai/gpt-5.4`, visible through the shared web server. diff --git a/cc-ci-plan/launch-opencode.sh b/cc-ci-plan/launch-opencode.sh new file mode 100755 index 0000000..acef1c2 --- /dev/null +++ b/cc-ci-plan/launch-opencode.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +set -euo pipefail + +SELF_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" +FLAKE_ROOT="$(readlink -f "$SELF_DIR/..")" +FLAKE_HOST="${FLAKE_HOST:-cc-ci-orchestrator-hetzner}" +DEFAULT_MODEL="${LOOP_MODEL:-openai/gpt-5.4}" + +ensure_opencode_web() { + if ! systemctl is-enabled --quiet opencode-web.service; then + sudo nixos-rebuild switch --flake "$FLAKE_ROOT#$FLAKE_HOST" + fi + + if ! systemctl is-active --quiet opencode-web.service; then + sudo systemctl start opencode-web.service + fi +} + +ensure_opencode_web + +export LOOP_BACKEND=opencode +export LOOP_MODEL="$DEFAULT_MODEL" +export ORCH_SESSION="${ORCH_SESSION:-cc-ci-orchestrator-oc}" + +if [ "$#" -eq 0 ]; then + set -- fresh +fi + +exec python3 "$SELF_DIR/launch-orchestrator.py" "$@" diff --git a/cc-ci-plan/launch-orchestrator.py b/cc-ci-plan/launch-orchestrator.py index ffb5e97..8c38b0f 100644 --- a/cc-ci-plan/launch-orchestrator.py +++ b/cc-ci-plan/launch-orchestrator.py @@ -31,7 +31,7 @@ Env: the session title in the web UI is the SESSION name) """ -import os, sys, subprocess +import json, os, shlex, sys, subprocess from datetime import datetime from pathlib import Path @@ -147,9 +147,15 @@ def start(mode="resume"): die(f"opencode not found at {OPENCODE_BIN}") # Attach the orchestrator TUI to the shared opencode web server so it shows up in the # same project/session listing as browser-created sessions. + model_env = "" + if LOOP_MODEL: + # attach has no --model flag, so inject a one-off config overlay for this session. + model_env = ( + f"OPENCODE_CONFIG_CONTENT={shlex.quote(json.dumps({'model': LOOP_MODEL}))} " + ) cmd = ( f"set -a; . /srv/cc-ci/.testenv; set +a; " - f"NO_COLOR=1 {OPENCODE_BIN} attach {OPENCODE_SERVER} --dir {WORKDIR}" + f"{model_env}NO_COLOR=1 {OPENCODE_BIN} attach {OPENCODE_SERVER} --dir {shlex.quote(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/nix/hosts/cc-ci-orchestrator-hetzner/configuration.nix b/nix/hosts/cc-ci-orchestrator-hetzner/configuration.nix index fd14b5e..900932c 100644 --- a/nix/hosts/cc-ci-orchestrator-hetzner/configuration.nix +++ b/nix/hosts/cc-ci-orchestrator-hetzner/configuration.nix @@ -118,15 +118,12 @@ SSHCFG ''; }; - # opencode web server — one shared instance; all agent sessions attach to it. + # opencode web server — one shared instance; agent sessions attach to it for web visibility. # Serves the web UI at http://oc.commoninternet.net (via nginx below, tailscale-only). - # TINFOIL_API_KEY and other creds are read from /srv/cc-ci/.testenv at startup. + # Provider creds are read from /srv/cc-ci/.testenv at startup. systemd.services.opencode-web = { - description = "opencode web server for cc-ci agents (tinfoil/deepseek backend)"; - # PARKED 2026-06-01: loops run on the claude backend now, so the opencode web server is not - # needed. Definition kept for easy re-enable — restore `wantedBy = [ "multi-user.target" ];` - # and rebuild to bring it back. - wantedBy = [ ]; + description = "opencode web server for cc-ci agents"; + wantedBy = [ "multi-user.target" ]; after = [ "network-online.target" "tailscaled.service" ]; wants = [ "network-online.target" ]; serviceConfig = { @@ -139,17 +136,16 @@ SSHCFG Restart = "on-failure"; RestartSec = "5s"; }; - environment = { HOME = "/home/loops"; }; + environment = { + HOME = "/home/loops"; + PATH = lib.mkForce "/run/wrappers/bin:/home/loops/.local/bin:/run/current-system/sw/bin:/usr/bin:/bin:/home/loops/.nix-profile/bin:/nix/profile/bin:/home/loops/.local/state/nix/profile/bin:/etc/profiles/per-user/loops/bin:/nix/var/nix/profiles/default/bin"; + }; path = [ pkgs.bash pkgs.coreutils pkgs.git pkgs.python3 pkgs.openssh pkgs.tmux pkgs.nettools ]; }; # nginx — reverse-proxy oc.commoninternet.net → opencode web server. # Bound to the tailscale IP so it is only reachable on the tailnet. - # PARKED 2026-06-01 alongside opencode-web (loops are on claude now): this vhost just proxies to - # the now-stopped :4096 server, so it's harmless but dormant. Kept (not deleted) so re-enabling - # opencode-web restores the UI in one step. If opencode is dropped for good, remove this block - # and the DNS step below. - # DNS: add A record oc.commoninternet.net → 100.84.190.30 (operator step; only needed if re-enabled). + # DNS: add A record oc.commoninternet.net → 100.84.190.30 (operator step if hostname access is wanted). services.nginx = { enable = true; recommendedProxySettings = true;