diff --git a/scripts/postinstall.js b/scripts/postinstall.js index e5adce74e7..1fb82ca99f 100644 --- a/scripts/postinstall.js +++ b/scripts/postinstall.js @@ -293,13 +293,13 @@ function trySetupCompletion(repoRoot) { try { // Run with OPENCLAW_SKIP_POSTINSTALL to avoid any weird recursion, // though distinct from this script. - spawnSync(process.execPath, [binPath, "completion", "--install", "--yes"], { + spawnSync(process.execPath, [binPath, "completion", "--install", "--yes", "--write-state"], { cwd: repoRoot, stdio: "inherit", env: { ...process.env, OPENCLAW_SKIP_POSTINSTALL: "1" }, }); } catch { - // Ignore errors to not break install + // Ignore errors } } diff --git a/src/cli/update-cli.ts b/src/cli/update-cli.ts index d7cd94375e..bf7c9bc4d2 100644 --- a/src/cli/update-cli.ts +++ b/src/cli/update-cli.ts @@ -1,5 +1,6 @@ import type { Command } from "commander"; import { confirm, isCancel, select, spinner } from "@clack/prompts"; +import { spawnSync } from "node:child_process"; import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; @@ -200,6 +201,29 @@ async function pathExists(targetPath: string): Promise { } } +async function tryWriteCompletionCache(root: string, jsonMode: boolean): Promise { + const binPath = path.join(root, "openclaw.mjs"); + if (!(await pathExists(binPath))) { + return; + } + const result = spawnSync(resolveNodeRunner(), [binPath, "completion", "--write-state"], { + cwd: root, + env: { ...process.env, OPENCLAW_SKIP_POSTINSTALL: "1" }, + encoding: "utf-8", + }); + if (result.error) { + if (!jsonMode) { + defaultRuntime.log(theme.warn(`Completion cache update failed: ${String(result.error)}`)); + } + return; + } + if (result.status !== 0 && !jsonMode) { + const stderr = (result.stderr ?? "").toString().trim(); + const detail = stderr ? ` (${stderr})` : ""; + defaultRuntime.log(theme.warn(`Completion cache update failed${detail}.`)); + } +} + async function isEmptyDir(targetPath: string): Promise { try { const entries = await fs.readdir(targetPath); @@ -959,6 +983,8 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise { defaultRuntime.log(theme.warn("Skipping plugin updates: config is invalid.")); } + await tryWriteCompletionCache(root, Boolean(opts.json)); + // Restart service if requested if (shouldRestart) { if (!opts.json) {