update: use shared completion helpers for shell completion setup
- Replace inline completion logic with `checkShellCompletionStatus` and `ensureCompletionCacheExists` - Auto-upgrade old slow dynamic patterns silently during update - Auto-regenerate cache if profile exists but cache is missing - Prompt to install if no completion is configuredmain
parent
5bd63b012c
commit
dbaf0a8ae2
|
|
@ -4,6 +4,10 @@ import { spawnSync } from "node:child_process";
|
||||||
import fs from "node:fs/promises";
|
import fs from "node:fs/promises";
|
||||||
import os from "node:os";
|
import os from "node:os";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
|
import {
|
||||||
|
checkShellCompletionStatus,
|
||||||
|
ensureCompletionCacheExists,
|
||||||
|
} from "../commands/doctor-completion.js";
|
||||||
import {
|
import {
|
||||||
formatUpdateAvailableHint,
|
formatUpdateAvailableHint,
|
||||||
formatUpdateOneLiner,
|
formatUpdateOneLiner,
|
||||||
|
|
@ -51,7 +55,7 @@ import { renderTable } from "../terminal/table.js";
|
||||||
import { theme } from "../terminal/theme.js";
|
import { theme } from "../terminal/theme.js";
|
||||||
import { replaceCliName, resolveCliName } from "./cli-name.js";
|
import { replaceCliName, resolveCliName } from "./cli-name.js";
|
||||||
import { formatCliCommand } from "./command-format.js";
|
import { formatCliCommand } from "./command-format.js";
|
||||||
import { installCompletion, isCompletionInstalled, resolveShellFromEnv } from "./completion-cli.js";
|
import { installCompletion } from "./completion-cli.js";
|
||||||
import { formatHelpExamples } from "./help-format.js";
|
import { formatHelpExamples } from "./help-format.js";
|
||||||
|
|
||||||
export type UpdateCommandOptions = {
|
export type UpdateCommandOptions = {
|
||||||
|
|
@ -234,32 +238,56 @@ async function tryInstallShellCompletion(opts: {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const shell = resolveShellFromEnv();
|
const status = await checkShellCompletionStatus(CLI_NAME);
|
||||||
const installed = await isCompletionInstalled(shell, CLI_NAME);
|
|
||||||
if (installed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultRuntime.log("");
|
// Profile uses slow dynamic pattern - upgrade to cached version
|
||||||
defaultRuntime.log(theme.heading("Shell completion"));
|
if (status.usesSlowPattern) {
|
||||||
|
defaultRuntime.log(theme.muted("Upgrading shell completion to cached version..."));
|
||||||
const shouldInstall = await confirm({
|
// Ensure cache exists first
|
||||||
message: stylePromptMessage(`Enable ${shell} shell completion for ${CLI_NAME}?`),
|
const cacheGenerated = await ensureCompletionCacheExists(CLI_NAME);
|
||||||
initialValue: true,
|
if (cacheGenerated) {
|
||||||
});
|
await installCompletion(status.shell, true, CLI_NAME);
|
||||||
|
|
||||||
if (isCancel(shouldInstall) || !shouldInstall) {
|
|
||||||
if (!opts.skipPrompt) {
|
|
||||||
defaultRuntime.log(
|
|
||||||
theme.muted(
|
|
||||||
`Skipped. Run \`${replaceCliName(formatCliCommand("openclaw completion --install"), CLI_NAME)}\` later to enable.`,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await installCompletion(shell, opts.skipPrompt, CLI_NAME);
|
// Profile has completion but no cache - auto-fix silently
|
||||||
|
if (status.profileInstalled && !status.cacheExists) {
|
||||||
|
defaultRuntime.log(theme.muted("Regenerating shell completion cache..."));
|
||||||
|
await ensureCompletionCacheExists(CLI_NAME);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No completion at all - prompt to install
|
||||||
|
if (!status.profileInstalled) {
|
||||||
|
defaultRuntime.log("");
|
||||||
|
defaultRuntime.log(theme.heading("Shell completion"));
|
||||||
|
|
||||||
|
const shouldInstall = await confirm({
|
||||||
|
message: stylePromptMessage(`Enable ${status.shell} shell completion for ${CLI_NAME}?`),
|
||||||
|
initialValue: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isCancel(shouldInstall) || !shouldInstall) {
|
||||||
|
if (!opts.skipPrompt) {
|
||||||
|
defaultRuntime.log(
|
||||||
|
theme.muted(
|
||||||
|
`Skipped. Run \`${replaceCliName(formatCliCommand("openclaw completion --install"), CLI_NAME)}\` later to enable.`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate cache first (required for fast shell startup)
|
||||||
|
const cacheGenerated = await ensureCompletionCacheExists(CLI_NAME);
|
||||||
|
if (!cacheGenerated) {
|
||||||
|
defaultRuntime.log(theme.warn("Failed to generate completion cache."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await installCompletion(status.shell, opts.skipPrompt, CLI_NAME);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function isEmptyDir(targetPath: string): Promise<boolean> {
|
async function isEmptyDir(targetPath: string): Promise<boolean> {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue