mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-15 23:50:44 +00:00
fix(cli): clarify operator command errors
This commit is contained in:
@@ -10,6 +10,7 @@ import type {
|
||||
ChannelCapabilitiesDisplayLine,
|
||||
ChannelPlugin,
|
||||
} from "../../channels/plugins/types.public.js";
|
||||
import { formatCliCommand } from "../../cli/command-format.js";
|
||||
import { commitConfigWithPendingPluginInstalls } from "../../cli/plugins-install-record-commit.js";
|
||||
import { refreshPluginRegistryAfterConfigMutation } from "../../cli/plugins-registry-refresh.js";
|
||||
import {
|
||||
@@ -229,12 +230,20 @@ export async function channelsCapabilitiesCommand(
|
||||
const rawTarget = normalizeOptionalString(opts.target) ?? "";
|
||||
|
||||
if (opts.account && (!rawChannel || rawChannel === "all")) {
|
||||
runtime.error(danger("--account requires a specific --channel."));
|
||||
runtime.error(
|
||||
danger(
|
||||
`--account requires a specific --channel. Run ${formatCliCommand("openclaw channels list")} to choose one.`,
|
||||
),
|
||||
);
|
||||
runtime.exit(1);
|
||||
return;
|
||||
}
|
||||
if (rawTarget && (!rawChannel || rawChannel === "all")) {
|
||||
runtime.error(danger("--target requires a specific --channel."));
|
||||
runtime.error(
|
||||
danger(
|
||||
`--target requires a specific --channel. Run ${formatCliCommand("openclaw channels list")} to choose one.`,
|
||||
),
|
||||
);
|
||||
runtime.exit(1);
|
||||
return;
|
||||
}
|
||||
@@ -287,7 +296,11 @@ export async function channelsCapabilitiesCommand(
|
||||
})();
|
||||
|
||||
if (!selected || selected.length === 0) {
|
||||
runtime.error(danger(`Unknown channel "${rawChannel}".`));
|
||||
runtime.error(
|
||||
danger(
|
||||
`Unknown channel "${rawChannel}". Run ${formatCliCommand("openclaw channels list")} to see installed channels.`,
|
||||
),
|
||||
);
|
||||
runtime.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { formatCliCommand } from "../cli/command-format.js";
|
||||
import {
|
||||
listCommitments,
|
||||
markCommitmentsStatus,
|
||||
@@ -35,7 +36,9 @@ function parseStatus(raw: string | undefined, runtime: RuntimeEnv): CommitmentSt
|
||||
if (STATUS_VALUES.has(status as CommitmentStatus)) {
|
||||
return status as CommitmentStatus;
|
||||
}
|
||||
runtime.error(`Unknown commitment status: ${status}`);
|
||||
runtime.error(
|
||||
`Unknown commitment status: ${status}. Use one of: ${Array.from(STATUS_VALUES).join(", ")}.`,
|
||||
);
|
||||
runtime.exit(1);
|
||||
return undefined;
|
||||
}
|
||||
@@ -126,7 +129,9 @@ export async function commitmentsListCommand(
|
||||
runtime.log(info(`Agent filter: ${opts.agent}`));
|
||||
}
|
||||
if (commitments.length === 0) {
|
||||
runtime.log("No commitments found.");
|
||||
runtime.log(
|
||||
`No commitments found. Run ${formatCliCommand("openclaw commitments --all")} to include dismissed and expired commitments.`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
for (const line of formatRows(commitments, isRich())) {
|
||||
@@ -140,7 +145,9 @@ export async function commitmentsDismissCommand(
|
||||
): Promise<void> {
|
||||
const ids = opts.ids.map((id) => id.trim()).filter(Boolean);
|
||||
if (ids.length === 0) {
|
||||
runtime.error("At least one commitment id is required.");
|
||||
runtime.error(
|
||||
`At least one commitment id is required. Run ${formatCliCommand("openclaw commitments list")} to choose one.`,
|
||||
);
|
||||
runtime.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { formatCliCommand } from "../cli/command-format.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
import type { WizardSection } from "./configure.shared.js";
|
||||
@@ -27,7 +28,7 @@ export async function configureCommandFromSectionsArg(
|
||||
|
||||
if (invalid.length > 0) {
|
||||
runtime.error(
|
||||
`Invalid --section: ${invalid.join(", ")}. Expected one of: ${CONFIGURE_WIZARD_SECTIONS.join(", ")}.`,
|
||||
`Invalid --section: ${invalid.join(", ")}. Expected one of: ${CONFIGURE_WIZARD_SECTIONS.join(", ")}. Run ${formatCliCommand("openclaw configure")} without --section to use the full wizard.`,
|
||||
);
|
||||
runtime.exit(1);
|
||||
return;
|
||||
|
||||
@@ -50,13 +50,17 @@ export async function setupWizardCommand(
|
||||
normalizedOpts.secretInputMode !== "plaintext" && // pragma: allowlist secret
|
||||
normalizedOpts.secretInputMode !== "ref" // pragma: allowlist secret
|
||||
) {
|
||||
runtime.error('Invalid --secret-input-mode. Use "plaintext" or "ref".');
|
||||
runtime.error(
|
||||
`Invalid --secret-input-mode. Use "plaintext" or "ref", or run ${formatCliCommand("openclaw onboard")} for the interactive setup.`,
|
||||
);
|
||||
runtime.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (normalizedOpts.resetScope && !VALID_RESET_SCOPES.has(normalizedOpts.resetScope)) {
|
||||
runtime.error('Invalid --reset-scope. Use "config", "config+creds+sessions", or "full".');
|
||||
runtime.error(
|
||||
`Invalid --reset-scope. Use "config", "config+creds+sessions", or "full". Run ${formatCliCommand("openclaw onboard --reset --reset-scope config")} for a config-only reset.`,
|
||||
);
|
||||
runtime.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ import {
|
||||
type SandboxBrowserInfo,
|
||||
type SandboxContainerInfo,
|
||||
} from "../agents/sandbox.js";
|
||||
import { formatCliCommand } from "../cli/command-format.js";
|
||||
import { formatErrorMessage } from "../infra/errors.js";
|
||||
import { type RuntimeEnv, writeRuntimeJson } from "../runtime.js";
|
||||
import {
|
||||
displayBrowsers,
|
||||
@@ -74,7 +76,9 @@ export async function sandboxRecreateCommand(
|
||||
const filtered = await fetchAndFilterContainers(opts);
|
||||
|
||||
if (filtered.containers.length + filtered.browsers.length === 0) {
|
||||
runtime.log("No sandbox runtimes found matching the criteria.");
|
||||
runtime.log(
|
||||
`No sandbox runtimes found matching the criteria. Run ${formatCliCommand("openclaw sandbox list")} to inspect active runtimes.`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -97,14 +101,16 @@ export async function sandboxRecreateCommand(
|
||||
|
||||
function validateRecreateOptions(opts: SandboxRecreateOptions, runtime: RuntimeEnv): boolean {
|
||||
if (!opts.all && !opts.session && !opts.agent) {
|
||||
runtime.error("Please specify --all, --session <key>, or --agent <id>");
|
||||
runtime.error(
|
||||
`Choose the sandbox scope: --all, --session <key>, or --agent <id>. Run ${formatCliCommand("openclaw sandbox list")} to inspect active runtimes first.`,
|
||||
);
|
||||
runtime.exit(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
const exclusiveCount = [opts.all, opts.session, opts.agent].filter(Boolean).length;
|
||||
if (exclusiveCount > 1) {
|
||||
runtime.error("Please specify only one of: --all, --session, --agent");
|
||||
runtime.error("Choose only one sandbox scope: --all, --session, or --agent.");
|
||||
runtime.exit(1);
|
||||
return false;
|
||||
}
|
||||
@@ -194,7 +200,9 @@ async function removeContainer(
|
||||
runtime.log(`✓ Removed ${containerName}`);
|
||||
return { success: true };
|
||||
} catch (err) {
|
||||
runtime.error(`✗ Failed to remove ${containerName}: ${String(err)}`);
|
||||
runtime.error(
|
||||
`Failed to remove ${containerName}: ${formatErrorMessage(err)}. Run ${formatCliCommand("openclaw sandbox list")} to inspect what remains.`,
|
||||
);
|
||||
return { success: false };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { cancel, confirm, isCancel, multiselect } from "@clack/prompts";
|
||||
import { formatCliCommand } from "../cli/command-format.js";
|
||||
import { isNixMode } from "../config/config.js";
|
||||
import { resolveGatewayService } from "../daemon/service.js";
|
||||
import { formatErrorMessage } from "../infra/errors.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { stylePromptHint, stylePromptMessage, stylePromptTitle } from "../terminal/prompt-style.js";
|
||||
import { resolveHomeDir } from "../utils.js";
|
||||
@@ -54,7 +55,9 @@ function buildScopeSelection(opts: UninstallOptions): {
|
||||
|
||||
async function stopAndUninstallService(runtime: RuntimeEnv): Promise<boolean> {
|
||||
if (isNixMode) {
|
||||
runtime.error("Nix mode detected; service uninstall is disabled.");
|
||||
runtime.error(
|
||||
`Nix mode detected; service uninstall is disabled. Manage the service through your Nix profile instead, then run ${formatCliCommand("openclaw status")} to verify.`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
const service = resolveGatewayService();
|
||||
@@ -62,7 +65,9 @@ async function stopAndUninstallService(runtime: RuntimeEnv): Promise<boolean> {
|
||||
try {
|
||||
loaded = await service.isLoaded({ env: process.env });
|
||||
} catch (err) {
|
||||
runtime.error(`Gateway service check failed: ${String(err)}`);
|
||||
runtime.error(
|
||||
`Gateway service check failed: ${formatErrorMessage(err)}. Run ${formatCliCommand("openclaw gateway status --deep")} for service diagnostics.`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (!loaded) {
|
||||
@@ -72,13 +77,17 @@ async function stopAndUninstallService(runtime: RuntimeEnv): Promise<boolean> {
|
||||
try {
|
||||
await service.stop({ env: process.env, stdout: process.stdout });
|
||||
} catch (err) {
|
||||
runtime.error(`Gateway stop failed: ${String(err)}`);
|
||||
runtime.error(
|
||||
`Gateway stop failed: ${formatErrorMessage(err)}. Run ${formatCliCommand("openclaw gateway status --deep")} before retrying uninstall.`,
|
||||
);
|
||||
}
|
||||
try {
|
||||
await service.uninstall({ env: process.env, stdout: process.stdout });
|
||||
return true;
|
||||
} catch (err) {
|
||||
runtime.error(`Gateway uninstall failed: ${String(err)}`);
|
||||
runtime.error(
|
||||
`Gateway uninstall failed: ${formatErrorMessage(err)}. Run ${formatCliCommand("openclaw gateway status --deep")} for the service state.`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -101,14 +110,18 @@ export async function uninstallCommand(runtime: RuntimeEnv, opts: UninstallOptio
|
||||
const { scopes, hadExplicit } = buildScopeSelection(opts);
|
||||
const interactive = !opts.nonInteractive;
|
||||
if (!interactive && !opts.yes) {
|
||||
runtime.error("Non-interactive mode requires --yes.");
|
||||
runtime.error(
|
||||
`Non-interactive uninstall requires --yes. Preview first with ${formatCliCommand("openclaw uninstall --dry-run --all")}.`,
|
||||
);
|
||||
runtime.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hadExplicit) {
|
||||
if (!interactive) {
|
||||
runtime.error("Non-interactive mode requires explicit scopes (use --all).");
|
||||
runtime.error(
|
||||
`Non-interactive uninstall requires explicit scopes. Use --all, or choose scopes such as --service --state.`,
|
||||
);
|
||||
runtime.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user