diff --git a/cli/planoai/main.py b/cli/planoai/main.py index 5eb43157..86525444 100644 --- a/cli/planoai/main.py +++ b/cli/planoai/main.py @@ -1,3 +1,4 @@ +import json import os import multiprocessing import subprocess @@ -31,6 +32,7 @@ from planoai.trace_cmd import trace as trace_cmd, start_trace_listener_backgroun from planoai.consts import ( DEFAULT_OTEL_TRACING_GRPC_ENDPOINT, DEFAULT_NATIVE_OTEL_TRACING_GRPC_ENDPOINT, + NATIVE_PID_FILE, PLANO_DOCKER_IMAGE, PLANO_DOCKER_NAME, ) @@ -40,6 +42,30 @@ from planoai.versioning import check_version_status, get_latest_version, get_ver log = getLogger(__name__) +def _is_native_plano_running() -> bool: + if not os.path.exists(NATIVE_PID_FILE): + return False + try: + with open(NATIVE_PID_FILE, "r") as f: + pids = json.load(f) + except (OSError, json.JSONDecodeError): + return False + + envoy_pid = pids.get("envoy_pid") + brightstaff_pid = pids.get("brightstaff_pid") + if not isinstance(envoy_pid, int) or not isinstance(brightstaff_pid, int): + return False + + for pid in (envoy_pid, brightstaff_pid): + try: + os.kill(pid, 0) + except ProcessLookupError: + return False + except PermissionError: + continue + return True + + def _is_port_in_use(port: int) -> bool: """Check if a TCP port is already bound on localhost.""" import socket @@ -527,11 +553,16 @@ def cli_agent(type, file, path, settings): CLI_AGENT: The type of CLI agent to start ('claude' or 'codex') """ - # Check if plano docker container is running - plano_status = docker_container_status(PLANO_DOCKER_NAME) - if plano_status != "running": - log.error(f"plano docker container is not running (status: {plano_status})") - log.error("Please start plano using the 'planoai up' command.") + native_running = _is_native_plano_running() + docker_running = False + if not native_running: + docker_running = docker_container_status(PLANO_DOCKER_NAME) == "running" + + if not (native_running or docker_running): + log.error("Plano is not running.") + log.error( + "Start Plano first using 'planoai up ' (native or --docker mode)." + ) sys.exit(1) # Determine plano_config.yaml path