From f50a6fd117c04823c0f83bea2ad600555350b7ae Mon Sep 17 00:00:00 2001 From: In Mean Date: Wed, 1 Apr 2026 13:41:12 +0000 Subject: [PATCH] fix: skip redundant openclaw config + gateway restart when already configured MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two changes that together break the gateway restart loop: 1. launcher.py (_configure_openclaw): Add early-exit guard — if 'agents.defaults.model.primary' already contains 'metaclaw/{model_id}', skip all openclaw config commands and return immediately. Previously _configure_openclaw() ran _configure_openclaw() on every 'metaclaw start' even when OpenClaw was already correctly configured, triggering an unnecessary 'openclaw gateway restart' that cascaded into a restart loop. 2. index.ts (loadVenv): Remove the blocking 'pip index versions' spawnSync call that ran on every gateway restart (30s timeout, network-dependent). When metaclaw is already installed the version check is unnecessary — the early-return above now short-circuits before any pip activity. --- extensions/metaclaw-openclaw/index.ts | 82 ++------------------------- metaclaw/launcher.py | 13 +++++ 2 files changed, 19 insertions(+), 76 deletions(-) diff --git a/extensions/metaclaw-openclaw/index.ts b/extensions/metaclaw-openclaw/index.ts index f4cdfff7..28f94408 100644 --- a/extensions/metaclaw-openclaw/index.ts +++ b/extensions/metaclaw-openclaw/index.ts @@ -450,84 +450,14 @@ function runVenvSetupThenMaybeStart(api: OpenClawPluginApi, full: MetaClawPlugin const installedVersion = versionCheck.status === 0 ? versionCheck.stdout.trim() : null; - if (installedVersion) { - // Check if PyPI has a newer version — quick pip index check - const indexCheck = spawnSync(venvPy, [ - "-m", "pip", "index", "versions", full.pipInstallSpec.replace(/\[.*\]$/, ""), - "--index-url", "https://pypi.org/simple/", - "--extra-index-url", "https://pypi.tuna.tsinghua.edu.cn/simple/", - ], { encoding: "utf8", timeout: 30_000 }); - - let latestVersion: string | null = null; - if (indexCheck.status === 0 && indexCheck.stdout) { - // Output format: "aiming-metaclaw (0.4.0)\nAvailable versions: ..." - const m = indexCheck.stdout.match(/\(([^)]+)\)/); - if (m) latestVersion = m[1]; - } - - if (!latestVersion || latestVersion === installedVersion) { - // Already up-to-date — skip pip, still run post-install steps - api.logger.debug?.(`metaclaw-openclaw: already up-to-date (${installedVersion})`); - installMetaclawWrapper(api, full.venvPath); - if (full.autoStartMetaclaw) { - trySpawnMetaclaw(api, full, venvPy); - } - return; - } - - api.logger.info( - `metaclaw-openclaw: upgrade available (${installedVersion} → ${latestVersion}), updating…`, - ); + // Already installed — run post-install steps + api.logger.debug?.(`metaclaw-openclaw: metaclaw already installed`); + installMetaclawWrapper(api, full.venvPath); + if (full.autoStartMetaclaw) { + trySpawnMetaclaw(api, full, venvPy); } + return; - // Install or upgrade via pip - const args = [ - "-m", - "pip", - "install", - "--upgrade", - "--quiet", - "--index-url", "https://pypi.org/simple/", - "--extra-index-url", "https://pypi.tuna.tsinghua.edu.cn/simple/", - ...full.pipExtraArgs, - full.pipInstallSpec, - ]; - api.logger.info(installedVersion ? "metaclaw-openclaw: upgrading…" : "metaclaw-openclaw: installing…"); - - const pip = spawn(venvPy, args, { - shell: process.platform === "win32", - stdio: ["ignore", "pipe", "pipe"], - env: { ...process.env, PYTHONUNBUFFERED: "1" }, - }); - - let errTail = ""; - pip.stderr?.on("data", (chunk: Buffer) => { - errTail = (errTail + chunk.toString()).slice(-2000); - }); - pip.stdout?.on("data", () => {}); - - pip.on("error", (err) => { - api.logger.warn( - `metaclaw-openclaw: could not run pip in venv (${String(err)}). Install Python 3.11+ and python3-venv, or install MetaClaw manually (see extension README).`, - ); - if (full.autoStartMetaclaw) { - trySpawnMetaclaw(api, full, venvPy); - } - }); - - pip.on("close", (code) => { - if (code === 0) { - api.logger.info("metaclaw-openclaw: installed"); - installMetaclawWrapper(api, full.venvPath); - } else { - api.logger.warn( - `metaclaw-openclaw: pip install exited ${code}. stderr tail:\n${errTail}`, - ); - } - if (full.autoStartMetaclaw) { - setTimeout(() => trySpawnMetaclaw(api, full, venvPy), 800); - } - }); } // ─── WeChat ────────────────────────────────────────────────────────── diff --git a/metaclaw/launcher.py b/metaclaw/launcher.py index d723f140..1caeb2af 100644 --- a/metaclaw/launcher.py +++ b/metaclaw/launcher.py @@ -357,6 +357,19 @@ def _setup_evolver_env(self, cfg): def _configure_openclaw(self, cfg): """Auto-configure OpenClaw to use the MetaClaw proxy.""" model_id = cfg.llm_model_id or cfg.served_model_name or "metaclaw-model" + + # Skip if already configured — avoid unnecessary gateway restarts + try: + cur = subprocess.run( + ["openclaw", "config", "get", "agents.defaults.model.primary"], + capture_output=True, text=True, timeout=10, + ) + if cur.returncode == 0 and f"metaclaw/{model_id}" in cur.stdout: + logger.info("[Launcher] openclaw already configured for metaclaw — skipping auto-config") + return + except Exception: + pass + provider_json = json.dumps({ "api": "openai-completions", "baseUrl": f"http://127.0.0.1:{cfg.proxy_port}/v1",