UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

149 lines (148 loc) 6.86 kB
import { t as resolveOpenClawPackageRoot } from "./openclaw-root-CfYY-fyD.js"; import { n as resolveCliName } from "./cli-name-CVj-3DWf.js"; import { t as note } from "./note-DqHk3fA1.js"; import { a as formatCompletionReloadCommand, d as resolveCompletionProfilePath, f as resolveShellFromEnv, i as findCompletionProfileWriteError, l as resolveCompletionCachePath, n as COMPLETION_SKIP_PLUGIN_COMMANDS_ENV, o as installCompletion, p as usesSlowDynamicCompletion, r as completionCacheExists, s as isCompletionInstalled, u as resolveCompletionProfileHint } from "./completion-runtime-CjrvYENP.js"; import path from "node:path"; import { spawnSync } from "node:child_process"; //#region src/commands/doctor-completion.ts /** Doctor checks and repair effects for cached shell completion setup. */ const COMPLETION_CACHE_WRITE_TIMEOUT_MS = 3e4; async function installCompletionForDoctor({ shell, cachePath }, cliName, action) { try { await installCompletion(shell, true, cliName); const reloadCommand = formatCompletionReloadCommand(shell, resolveCompletionProfileHint(shell)); note(`Shell completion ${action}. Restart your shell or run: ${reloadCommand}`, "Shell completion"); } catch (err) { const writeError = findCompletionProfileWriteError(err); if (!writeError) throw err; const failedPath = writeError.path ?? resolveCompletionProfilePath(shell); const command = formatCompletionReloadCommand(shell, cachePath); note(`Shell completion could not be ${action} (permission or read-only error at ${failedPath}). For this ${shell} session only, run:\n${command}`, "Shell completion"); } } /** Generate the completion cache by spawning the CLI. */ async function generateCompletionCache(options) { const root = await resolveOpenClawPackageRoot({ moduleUrl: import.meta.url, argv1: process.argv[1], cwd: process.cwd() }); if (!root) return false; const args = [ path.join(root, "openclaw.mjs"), "completion", "--write-state" ]; if (options.shell) args.push("--shell", options.shell); const env = { ...process.env }; if (options.generationMode === "core-only") env[COMPLETION_SKIP_PLUGIN_COMMANDS_ENV] = "1"; else delete env[COMPLETION_SKIP_PLUGIN_COMMANDS_ENV]; return spawnSync(process.execPath, args, { cwd: root, env, encoding: "utf-8", timeout: COMPLETION_CACHE_WRITE_TIMEOUT_MS }).status === 0; } /** Check the status of shell completion for the current shell. */ async function checkShellCompletionStatus(binName = "openclaw", options = {}) { const shell = options.shell ?? resolveShellFromEnv(); return { shell, profileInstalled: await isCompletionInstalled(shell, binName), cacheExists: await completionCacheExists(shell, binName), cachePath: resolveCompletionCachePath(shell, binName), usesSlowPattern: await usesSlowDynamicCompletion(shell, binName) }; } /** Converts shell completion status into health findings shown by check flows. */ function shellCompletionStatusToHealthFindings(status) { const checkId = "core/doctor/shell-completion"; const pathLocal = `shellCompletion.${status.shell}`; if (status.usesSlowPattern) return [{ checkId, severity: "info", message: `Your ${status.shell} profile uses slow dynamic completion (source <(...)).`, path: pathLocal, fixHint: "Run `openclaw doctor --fix` to upgrade to cached completion." }]; if (status.profileInstalled && !status.cacheExists) return [{ checkId, severity: "info", message: `Shell completion is configured in your ${status.shell} profile but the cache is missing.`, path: pathLocal, fixHint: `Run \`openclaw completion --write-state\` or \`openclaw doctor --fix\` to regenerate ${status.cachePath}.` }]; return []; } /** Converts shell completion status into dry-run repair effects for health check reporting. */ function shellCompletionStatusToRepairEffects(status) { const effects = []; if (status.usesSlowPattern && !status.cacheExists) effects.push({ kind: "state", action: "would-generate-completion-cache", target: status.cachePath, dryRunSafe: true }); if (status.usesSlowPattern) effects.push({ kind: "file", action: "would-upgrade-shell-profile-completion", target: status.shell, dryRunSafe: false }); else if (status.profileInstalled && !status.cacheExists) effects.push({ kind: "state", action: "would-regenerate-completion-cache", target: status.cachePath, dryRunSafe: true }); return effects; } /** * Repairs shell completion setup when doctor runs interactively. * * Slow dynamic profiles are upgraded to cached completion; configured profiles with a missing * cache regenerate it; missing completion prompts unless non-interactive mode is active. */ async function doctorShellCompletion(_runtime, prompter, options = {}) { const cliName = resolveCliName(); const status = await checkShellCompletionStatus(cliName); if (status.usesSlowPattern) { note(`Your ${status.shell} profile uses slow dynamic completion (source <(...)).\nUpgrading to cached completion for faster shell startup...`, "Shell completion"); if (!status.cacheExists) { if (!await generateCompletionCache({ generationMode: "core-only" })) { note(`Failed to generate completion cache. Run \`${cliName} completion --write-state\` manually.`, "Shell completion"); return; } } await installCompletionForDoctor(status, cliName, "upgraded"); return; } if (status.profileInstalled && !status.cacheExists) { note(`Shell completion is configured in your ${status.shell} profile but the cache is missing.\nRegenerating cache...`, "Shell completion"); if (await generateCompletionCache({ generationMode: "core-only" })) note(`Completion cache regenerated at ${status.cachePath}`, "Shell completion"); else note(`Failed to regenerate completion cache. Run \`${cliName} completion --write-state\` manually.`, "Shell completion"); return; } if (!status.profileInstalled) { if (options.nonInteractive) return; if (await prompter.confirm({ message: `Enable ${status.shell} shell completion for ${cliName}?`, initialValue: true })) { if (!await generateCompletionCache({ generationMode: "core-only" })) { note(`Failed to generate completion cache. Run \`${cliName} completion --write-state\` manually.`, "Shell completion"); return; } await installCompletionForDoctor(status, cliName, "installed"); } } } /** Ensures the shell completion cache exists without prompting during setup/update flows. */ async function ensureCompletionCacheExists(binName, options) { const shell = options.shell ?? resolveShellFromEnv(); if (await completionCacheExists(shell, binName)) return true; return generateCompletionCache(options); } //#endregion export { shellCompletionStatusToRepairEffects as a, shellCompletionStatusToHealthFindings as i, doctorShellCompletion as n, ensureCompletionCacheExists as r, checkShellCompletionStatus as t };